blob: 0ecf50ead1805625eb2885e0ab54e8a06a8313b0 [file] [log] [blame]
/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.fuelgauge.batteryusage;
import static com.google.common.truth.Truth.assertThat;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.anyLong;
import static org.mockito.Mockito.anyString;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.isA;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.when;
import android.app.usage.IUsageStatsManager;
import android.app.usage.UsageEvents;
import android.app.usage.UsageEvents.Event;
import android.content.BroadcastReceiver;
import android.content.ContentValues;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.UserInfo;
import android.os.BatteryConsumer;
import android.os.BatteryManager;
import android.os.BatteryUsageStats;
import android.os.Parcel;
import android.os.RemoteException;
import android.os.UserManager;
import android.text.format.DateUtils;
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
import com.android.settings.testutils.FakeFeatureFactory;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.mockito.MockitoAnnotations;
import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
@RunWith(RobolectricTestRunner.class)
public final class DataProcessorTest {
private static final String FAKE_ENTRY_KEY = "fake_entry_key";
private Context mContext;
private FakeFeatureFactory mFeatureFactory;
private PowerUsageFeatureProvider mPowerUsageFeatureProvider;
@Mock private Intent mIntent;
@Mock private BatteryUsageStats mBatteryUsageStats;
@Mock private UserManager mUserManager;
@Mock private IUsageStatsManager mUsageStatsManager;
@Mock private BatteryEntry mMockBatteryEntry1;
@Mock private BatteryEntry mMockBatteryEntry2;
@Mock private BatteryEntry mMockBatteryEntry3;
@Mock private BatteryEntry mMockBatteryEntry4;
@Mock private UsageEvents mUsageEvents1;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
TimeZone.setDefault(TimeZone.getTimeZone("GMT+8"));
mContext = spy(RuntimeEnvironment.application);
mFeatureFactory = FakeFeatureFactory.setupForTest();
mPowerUsageFeatureProvider = mFeatureFactory.powerUsageFeatureProvider;
DataProcessor.sTestSystemAppsSet = Set.of();
DataProcessor.sUsageStatsManager = mUsageStatsManager;
doReturn(mIntent).when(mContext).registerReceiver(
isA(BroadcastReceiver.class), isA(IntentFilter.class));
doReturn(100).when(mIntent).getIntExtra(eq(BatteryManager.EXTRA_SCALE), anyInt());
doReturn(66).when(mIntent).getIntExtra(eq(BatteryManager.EXTRA_LEVEL), anyInt());
doReturn(mContext).when(mContext).getApplicationContext();
doReturn(mUserManager).when(mContext).getSystemService(UserManager.class);
doReturn(new int[]{0}).when(mUserManager).getProfileIdsWithDisabled(anyInt());
}
@Test
public void getAppUsageEvents_returnExpectedResult() throws RemoteException {
UserInfo userInfo = new UserInfo(/*id=*/ 0, "user_0", /*flags=*/ 0);
final List<UserInfo> userInfoList = new ArrayList<>();
userInfoList.add(userInfo);
doReturn(userInfoList).when(mUserManager).getAliveUsers();
doReturn(true).when(mUserManager).isUserUnlocked(userInfo.id);
doReturn(mUsageEvents1)
.when(mUsageStatsManager)
.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString());
final Map<Long, UsageEvents> resultMap = DataProcessor.getAppUsageEvents(mContext);
assertThat(resultMap).hasSize(1);
assertThat(resultMap.get(Long.valueOf(userInfo.id))).isEqualTo(mUsageEvents1);
}
@Test
public void getAppUsageEvents_lockedUser_returnNull() {
UserInfo userInfo = new UserInfo(/*id=*/ 0, "user_0", /*flags=*/ 0);
final List<UserInfo> userInfoList = new ArrayList<>();
userInfoList.add(userInfo);
doReturn(userInfoList).when(mUserManager).getAliveUsers();
// Test locked user.
doReturn(false).when(mUserManager).isUserUnlocked(userInfo.id);
final Map<Long, UsageEvents> resultMap = DataProcessor.getAppUsageEvents(mContext);
assertThat(resultMap).isNull();
}
@Test
public void getAppUsageEvents_nullUsageEvents_returnNull() throws RemoteException {
UserInfo userInfo = new UserInfo(/*id=*/ 0, "user_0", /*flags=*/ 0);
final List<UserInfo> userInfoList = new ArrayList<>();
userInfoList.add(userInfo);
doReturn(userInfoList).when(mUserManager).getAliveUsers();
doReturn(true).when(mUserManager).isUserUnlocked(userInfo.id);
doReturn(null).when(mUsageStatsManager)
.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString());
final Map<Long, UsageEvents> resultMap = DataProcessor.getAppUsageEvents(mContext);
assertThat(resultMap).isNull();
}
@Test
public void getAppUsageEventsForUser_returnExpectedResult() throws RemoteException {
final int userId = 1;
doReturn(true).when(mUserManager).isUserUnlocked(userId);
doReturn(mUsageEvents1)
.when(mUsageStatsManager)
.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString());
assertThat(DataProcessor.getAppUsageEventsForUser(mContext, userId, 0))
.isEqualTo(mUsageEvents1);
}
@Test
public void getAppUsageEventsForUser_lockedUser_returnNull() {
final int userId = 1;
// Test locked user.
doReturn(false).when(mUserManager).isUserUnlocked(userId);
assertThat(DataProcessor.getAppUsageEventsForUser(mContext, userId, 0)).isNull();
}
@Test
public void getAppUsageEventsForUser_nullUsageEvents_returnNull() throws RemoteException {
final int userId = 1;
doReturn(true).when(mUserManager).isUserUnlocked(userId);
doReturn(null).when(mUsageStatsManager)
.queryEventsForUser(anyLong(), anyLong(), anyInt(), anyString());
assertThat(DataProcessor.getAppUsageEventsForUser(mContext, userId, 0)).isNull();
}
@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(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(45200000L, 48800000L);
final List<Integer> levels2 = List.of(100, 100);
hourlyBatteryLevelsPerDay.add(
new BatteryLevelData.PeriodBatteryLevelData(timestamps2, levels2));
final List<AppUsageEvent> appUsageEventList = new ArrayList<>();
// Adds some events before the start timestamp.
appUsageEventList.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 1, /*userId=*/ 1,
/*instanceId=*/ 2, packageName));
appUsageEventList.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 2, /*userId=*/ 1,
/*instanceId=*/ 2, packageName));
// Adds the valid app usage events.
appUsageEventList.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 4200000L, /*userId=*/ 1,
/*instanceId=*/ 2, packageName));
appUsageEventList.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 4500000L, /*userId=*/ 1,
/*instanceId=*/ 2, packageName));
appUsageEventList.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 12600000L, /*userId=*/ 2,
/*instanceId=*/ 3, packageName));
appUsageEventList.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 15600000L, /*userId=*/ 2,
/*instanceId=*/ 3, packageName));
appUsageEventList.add(buildAppUsageEvent(
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=*/ 17800000L, /*userId=*/ 1,
/*instanceId=*/ 2, packageName));
appUsageEventList.add(buildAppUsageEvent(
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=*/ 61200000L, /*userId=*/ 1,
/*instanceId=*/ 4, packageName));
final Map<Integer, Map<Integer, Map<Long, Map<String, List<AppUsagePeriod>>>>> periodMap =
DataProcessor.generateAppUsagePeriodMap(
hourlyBatteryLevelsPerDay, appUsageEventList);
assertThat(periodMap).hasSize(3);
// Day 1
assertThat(periodMap.get(0)).hasSize(2);
Map<Long, Map<String, List<AppUsagePeriod>>> hourlyMap = periodMap.get(0).get(0);
assertThat(hourlyMap).hasSize(2);
Map<String, List<AppUsagePeriod>> userMap = hourlyMap.get(1L);
assertThat(userMap).hasSize(1);
assertThat(userMap.get(packageName)).hasSize(1);
assertAppUsagePeriod(userMap.get(packageName).get(0), 17200000L, 17800000L);
userMap = hourlyMap.get(2L);
assertThat(userMap).hasSize(1);
assertThat(userMap.get(packageName)).hasSize(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
assertThat(periodMap.get(1)).hasSize(0);
// Day 3
assertThat(periodMap.get(2)).hasSize(1);
hourlyMap = periodMap.get(2).get(0);
assertThat(hourlyMap).hasSize(1);
userMap = hourlyMap.get(1L);
assertThat(userMap).hasSize(1);
assertThat(userMap.get(packageName)).hasSize(2);
assertAppUsagePeriod(userMap.get(packageName).get(0), 45970000L, 46000000L);
assertAppUsagePeriod(userMap.get(packageName).get(1), 47800000L, 48800000L);
}
@Test
public void generateAppUsagePeriodMap_emptyEventList_returnNull() {
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
new ArrayList<>();
hourlyBatteryLevelsPerDay.add(
new BatteryLevelData.PeriodBatteryLevelData(new ArrayList<>(), new ArrayList<>()));
assertThat(DataProcessor.generateAppUsagePeriodMap(
hourlyBatteryLevelsPerDay, new ArrayList<>())).isNull();
}
@Test
public void generateAppUsageEventListFromUsageEvents_returnExpectedResult() {
Event event1 = getUsageEvent(Event.NOTIFICATION_INTERRUPTION, /*timestamp=*/ 1);
Event event2 = getUsageEvent(Event.ACTIVITY_RESUMED, /*timestamp=*/ 2);
Event event3 = getUsageEvent(Event.ACTIVITY_STOPPED, /*timestamp=*/ 3);
Event event4 = getUsageEvent(Event.DEVICE_SHUTDOWN, /*timestamp=*/ 4);
Event event5 = getUsageEvent(Event.ACTIVITY_RESUMED, /*timestamp=*/ 5);
event5.mPackage = null;
List<Event> events1 = new ArrayList<>();
events1.add(event1);
events1.add(event2);
List<Event> events2 = new ArrayList<>();
events2.add(event3);
events2.add(event4);
events2.add(event5);
final long userId1 = 101L;
final long userId2 = 102L;
final long userId3 = 103L;
final Map<Long, UsageEvents> appUsageEvents = new HashMap();
appUsageEvents.put(userId1, getUsageEvents(events1));
appUsageEvents.put(userId2, getUsageEvents(events2));
appUsageEvents.put(userId3, getUsageEvents(new ArrayList<>()));
final List<AppUsageEvent> appUsageEventList =
DataProcessor.generateAppUsageEventListFromUsageEvents(mContext, appUsageEvents);
assertThat(appUsageEventList).hasSize(3);
assertAppUsageEvent(
appUsageEventList.get(0), AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 2);
assertAppUsageEvent(
appUsageEventList.get(1), AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 3);
assertAppUsageEvent(
appUsageEventList.get(2), AppUsageEventType.DEVICE_SHUTDOWN, /*timestamp=*/ 4);
}
@Test
public void getDeviceScreenOnTime_returnExpectedResult() {
final Map<Integer, Map<Integer, Map<Long, Map<String, List<AppUsagePeriod>>>>>
appUsagePeriodMap = new HashMap<>();
appUsagePeriodMap.put(0, new HashMap<>());
appUsagePeriodMap.put(1, new HashMap<>());
appUsagePeriodMap.put(2, null);
final long userId1 = 1;
final long userId2 = 2;
// Adds the index [0][0].
Map<Long, Map<String, List<AppUsagePeriod>>> appUsageMap = new HashMap<>();
Map<String, List<AppUsagePeriod>> userPeriodMap = new HashMap<>();
appUsageMap.put(userId1, userPeriodMap);
userPeriodMap.put(
"package1", List.of(buildAppUsagePeriod(0, 5), buildAppUsagePeriod(5, 7)));
userPeriodMap.put("package2", List.of(buildAppUsagePeriod(10, 25)));
userPeriodMap = new HashMap<>();
appUsageMap.put(userId2, userPeriodMap);
userPeriodMap.put("package3", List.of(buildAppUsagePeriod(15, 45)));
appUsagePeriodMap.get(0).put(0, appUsageMap);
// Adds the index [0][1].
appUsageMap = new HashMap<>();
userPeriodMap = new HashMap<>();
appUsageMap.put(userId1, userPeriodMap);
userPeriodMap.put(
"package1", List.of(buildAppUsagePeriod(50, 60), buildAppUsagePeriod(70, 80)));
appUsagePeriodMap.get(0).put(1, appUsageMap);
// Adds the index [1][0].
appUsageMap = new HashMap<>();
userPeriodMap = new HashMap<>();
appUsageMap.put(userId1, userPeriodMap);
userPeriodMap.put("package2", List.of(buildAppUsagePeriod(0, 8000000L)));
userPeriodMap.put("package3",
List.of(buildAppUsagePeriod(10, 15), buildAppUsagePeriod(25, 29)));
appUsagePeriodMap.get(1).put(0, appUsageMap);
final Map<Integer, Map<Integer, Long>> deviceScreenOnTime =
DataProcessor.getDeviceScreenOnTime(appUsagePeriodMap);
assertThat(deviceScreenOnTime.get(0).get(0)).isEqualTo(42);
assertThat(deviceScreenOnTime.get(0).get(1)).isEqualTo(20);
assertThat(deviceScreenOnTime.get(1).get(0)).isEqualTo(7200000);
assertThat(deviceScreenOnTime.get(0).get(DataProcessor.SELECTED_INDEX_ALL)).isEqualTo(62);
assertThat(deviceScreenOnTime.get(1).get(DataProcessor.SELECTED_INDEX_ALL))
.isEqualTo(7200000);
assertThat(deviceScreenOnTime
.get(DataProcessor.SELECTED_INDEX_ALL)
.get(DataProcessor.SELECTED_INDEX_ALL))
.isEqualTo(7200062);
}
@Test
public void getDeviceScreenOnTime_nullUsageMap_returnNull() {
assertThat(DataProcessor.getDeviceScreenOnTime(null)).isNull();
}
@Test
public void getHistoryMapWithExpectedTimestamps_emptyHistoryMap_returnEmptyMap() {
assertThat(DataProcessor
.getHistoryMapWithExpectedTimestamps(mContext, new HashMap<>()))
.isEmpty();
}
@Test
public void getHistoryMapWithExpectedTimestamps_returnExpectedMap() {
// Timezone GMT+8
final long[] timestamps = {
1640966700000L, // 2022-01-01 00:05:00
1640970180000L, // 2022-01-01 01:03:00
1640973840000L, // 2022-01-01 02:04:00
1640978100000L, // 2022-01-01 03:15:00
1640981400000L // 2022-01-01 04:10:00
};
final int[] levels = {100, 94, 90, 82, 50};
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap =
createHistoryMap(timestamps, levels);
DataProcessor.sTestCurrentTimeMillis = timestamps[timestamps.length - 1];
final Map<Long, Map<String, BatteryHistEntry>> resultMap =
DataProcessor.getHistoryMapWithExpectedTimestamps(mContext, batteryHistoryMap);
// Timezone GMT+8
final long[] expectedTimestamps = {
1640966400000L, // 2022-01-01 00:00:00
1640970000000L, // 2022-01-01 01:00:00
1640973600000L, // 2022-01-01 02:00:00
1640977200000L, // 2022-01-01 03:00:00
1640980800000L, // 2022-01-01 04:00:00
1640984400000L, // 2022-01-01 05:00:00
1640988000000L // 2022-01-01 06:00:00
};
final int[] expectedLevels = {100, 94, 90, 84, 56, 98, 98};
assertThat(resultMap).hasSize(expectedLevels.length);
for (int index = 0; index < 5; index++) {
assertThat(resultMap.get(expectedTimestamps[index]).get(FAKE_ENTRY_KEY).mBatteryLevel)
.isEqualTo(expectedLevels[index]);
}
for (int index = 5; index < 7; index++) {
assertThat(resultMap.get(expectedTimestamps[index]).containsKey(
DataProcessor.CURRENT_TIME_BATTERY_HISTORY_PLACEHOLDER)).isTrue();
}
}
@Test
public void getLevelDataThroughProcessedHistoryMap_notEnoughData_returnNull() {
final long[] timestamps = {100L};
final int[] levels = {100};
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap =
createHistoryMap(timestamps, levels);
DataProcessor.sTestCurrentTimeMillis = timestamps[timestamps.length - 1];
assertThat(
DataProcessor.getLevelDataThroughProcessedHistoryMap(mContext, batteryHistoryMap))
.isNull();
}
@Test
public void getLevelDataThroughProcessedHistoryMap_OneDayData_returnExpectedResult() {
// Timezone GMT+8
final long[] timestamps = {
1640966400000L, // 2022-01-01 00:00:00
1640970000000L, // 2022-01-01 01:00:00
1640973600000L, // 2022-01-01 02:00:00
1640977200000L, // 2022-01-01 03:00:00
1640980800000L // 2022-01-01 04:00:00
};
final int[] levels = {100, 94, 90, 82, 50};
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap =
createHistoryMap(timestamps, levels);
DataProcessor.sTestCurrentTimeMillis = timestamps[timestamps.length - 1];
final BatteryLevelData resultData =
DataProcessor.getLevelDataThroughProcessedHistoryMap(mContext, batteryHistoryMap);
final List<Long> expectedDailyTimestamps = List.of(timestamps[0], timestamps[4]);
final List<Integer> expectedDailyLevels = List.of(levels[0], levels[4]);
final List<List<Long>> expectedHourlyTimestamps = List.of(
List.of(timestamps[0], timestamps[2], timestamps[4])
);
final List<List<Integer>> expectedHourlyLevels = List.of(
List.of(levels[0], levels[2], levels[4])
);
verifyExpectedBatteryLevelData(
resultData,
expectedDailyTimestamps,
expectedDailyLevels,
expectedHourlyTimestamps,
expectedHourlyLevels);
}
@Test
public void getLevelDataThroughProcessedHistoryMap_MultipleDaysData_returnExpectedResult() {
// Timezone GMT+8
final long[] timestamps = {
1641038400000L, // 2022-01-01 20:00:00
1641060000000L, // 2022-01-02 02:00:00
1641067200000L, // 2022-01-02 04:00:00
1641081600000L, // 2022-01-02 08:00:00
};
final int[] levels = {100, 94, 90, 82};
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap =
createHistoryMap(timestamps, levels);
DataProcessor.sTestCurrentTimeMillis = timestamps[timestamps.length - 1];
final BatteryLevelData resultData =
DataProcessor.getLevelDataThroughProcessedHistoryMap(mContext, batteryHistoryMap);
final List<Long> expectedDailyTimestamps = List.of(
1641038400000L, // 2022-01-01 20:00:00
1641052800000L, // 2022-01-02 00:00:00
1641081600000L // 2022-01-02 08:00:00
);
final List<Integer> expectedDailyLevels = new ArrayList<>();
expectedDailyLevels.add(100);
expectedDailyLevels.add(null);
expectedDailyLevels.add(82);
final List<List<Long>> expectedHourlyTimestamps = List.of(
List.of(
1641038400000L, // 2022-01-01 20:00:00
1641045600000L, // 2022-01-01 22:00:00
1641052800000L // 2022-01-02 00:00:00
),
List.of(
1641052800000L, // 2022-01-02 00:00:00
1641060000000L, // 2022-01-02 02:00:00
1641067200000L, // 2022-01-02 04:00:00
1641074400000L, // 2022-01-02 06:00:00
1641081600000L // 2022-01-02 08:00:00
)
);
final List<Integer> expectedHourlyLevels1 = new ArrayList<>();
expectedHourlyLevels1.add(100);
expectedHourlyLevels1.add(null);
expectedHourlyLevels1.add(null);
final List<Integer> expectedHourlyLevels2 = new ArrayList<>();
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(94);
expectedHourlyLevels2.add(90);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(82);
final List<List<Integer>> expectedHourlyLevels = List.of(
expectedHourlyLevels1,
expectedHourlyLevels2
);
verifyExpectedBatteryLevelData(
resultData,
expectedDailyTimestamps,
expectedDailyLevels,
expectedHourlyTimestamps,
expectedHourlyLevels);
}
@Test
public void getLevelDataThroughProcessedHistoryMap_daylightSaving25Hour_returnExpectedResult() {
// Timezone PST 2022-11-06 has an extra 01:00:00 - 01:59:59 for daylight saving.
TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
final long[] timestamps = {
1667667600000L, // 2022-11-05 10:00:00
1667829600000L // 2022-11-07 06:00:00
};
final int[] levels = {100, 88};
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap =
createHistoryMap(timestamps, levels);
DataProcessor.sTestCurrentTimeMillis = timestamps[timestamps.length - 1];
final BatteryLevelData resultData =
DataProcessor.getLevelDataThroughProcessedHistoryMap(mContext, batteryHistoryMap);
final List<Long> expectedDailyTimestamps = List.of(
1667667600000L, // 2022-11-05 10:00:00
1667718000000L, // 2022-11-06 00:00:00
1667808000000L, // 2022-11-07 00:00:00
1667829600000L // 2022-11-07 06:00:00
);
final List<Integer> expectedDailyLevels = new ArrayList<>();
expectedDailyLevels.add(100);
expectedDailyLevels.add(null);
expectedDailyLevels.add(null);
expectedDailyLevels.add(88);
final List<List<Long>> expectedHourlyTimestamps = List.of(
List.of(
1667667600000L, // 2022-11-05 10:00:00
1667674800000L, // 2022-11-05 12:00:00
1667682000000L, // 2022-11-05 14:00:00
1667689200000L, // 2022-11-05 16:00:00
1667696400000L, // 2022-11-05 18:00:00
1667703600000L, // 2022-11-05 20:00:00
1667710800000L, // 2022-11-05 22:00:00
1667718000000L // 2022-11-06 00:00:00
),
List.of(
1667718000000L, // 2022-11-06 00:00:00
1667725200000L, // 2022-11-06 01:00:00 after daylight saving change
1667732400000L, // 2022-11-06 03:00:00
1667739600000L, // 2022-11-06 05:00:00
1667746800000L, // 2022-11-06 07:00:00
1667754000000L, // 2022-11-06 09:00:00
1667761200000L, // 2022-11-06 11:00:00
1667768400000L, // 2022-11-06 13:00:00
1667775600000L, // 2022-11-06 15:00:00
1667782800000L, // 2022-11-06 17:00:00
1667790000000L, // 2022-11-06 19:00:00
1667797200000L, // 2022-11-06 21:00:00
1667804400000L // 2022-11-06 23:00:00
),
List.of(
1667808000000L, // 2022-11-07 00:00:00
1667815200000L, // 2022-11-07 02:00:00
1667822400000L, // 2022-11-07 04:00:00
1667829600000L // 2022-11-07 06:00:00
)
);
final List<Integer> expectedHourlyLevels1 = new ArrayList<>();
expectedHourlyLevels1.add(100);
expectedHourlyLevels1.add(null);
expectedHourlyLevels1.add(null);
expectedHourlyLevels1.add(null);
expectedHourlyLevels1.add(null);
expectedHourlyLevels1.add(null);
expectedHourlyLevels1.add(null);
expectedHourlyLevels1.add(null);
final List<Integer> expectedHourlyLevels2 = new ArrayList<>();
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
final List<Integer> expectedHourlyLevels3 = new ArrayList<>();
expectedHourlyLevels3.add(null);
expectedHourlyLevels3.add(null);
expectedHourlyLevels3.add(null);
expectedHourlyLevels3.add(88);
final List<List<Integer>> expectedHourlyLevels = List.of(
expectedHourlyLevels1,
expectedHourlyLevels2,
expectedHourlyLevels3
);
verifyExpectedBatteryLevelData(
resultData,
expectedDailyTimestamps,
expectedDailyLevels,
expectedHourlyTimestamps,
expectedHourlyLevels);
}
@Test
public void getLevelDataThroughProcessedHistoryMap_daylightSaving23Hour_returnExpectedResult() {
// Timezone PST 2022-03-13 has no 02:00:00 - 02:59:59 for daylight saving.
TimeZone.setDefault(TimeZone.getTimeZone("America/Los_Angeles"));
final long[] timestamps = {
1647151200000L, // 2022-03-12 22:00:00
1647262800000L // 2022-03-14 06:00:00
};
final int[] levels = {100, 88};
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap =
createHistoryMap(timestamps, levels);
DataProcessor.sTestCurrentTimeMillis = timestamps[timestamps.length - 1];
final BatteryLevelData resultData =
DataProcessor.getLevelDataThroughProcessedHistoryMap(mContext, batteryHistoryMap);
final List<Long> expectedDailyTimestamps = List.of(
1647151200000L, // 2022-03-12 22:00:00
1647158400000L, // 2022-03-13 00:00:00
1647241200000L, // 2022-03-14 00:00:00
1647262800000L // 2022-03-14 06:00:00
);
final List<Integer> expectedDailyLevels = new ArrayList<>();
expectedDailyLevels.add(100);
expectedDailyLevels.add(null);
expectedDailyLevels.add(null);
expectedDailyLevels.add(88);
final List<List<Long>> expectedHourlyTimestamps = List.of(
List.of(
1647151200000L, // 2022-03-12 22:00:00
1647158400000L // 2022-03-13 00:00:00
),
List.of(
1647158400000L, // 2022-03-13 00:00:00
1647165600000L, // 2022-03-13 03:00:00 after daylight saving change
1647172800000L, // 2022-03-13 05:00:00
1647180000000L, // 2022-03-13 07:00:00
1647187200000L, // 2022-03-13 09:00:00
1647194400000L, // 2022-03-13 11:00:00
1647201600000L, // 2022-03-13 13:00:00
1647208800000L, // 2022-03-13 15:00:00
1647216000000L, // 2022-03-13 17:00:00
1647223200000L, // 2022-03-13 19:00:00
1647230400000L, // 2022-03-13 21:00:00
1647237600000L // 2022-03-13 23:00:00
),
List.of(
1647241200000L, // 2022-03-14 00:00:00
1647248400000L, // 2022-03-14 02:00:00
1647255600000L, // 2022-03-14 04:00:00
1647262800000L // 2022-03-14 06:00:00
)
);
final List<Integer> expectedHourlyLevels1 = new ArrayList<>();
expectedHourlyLevels1.add(100);
expectedHourlyLevels1.add(null);
final List<Integer> expectedHourlyLevels2 = new ArrayList<>();
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
expectedHourlyLevels2.add(null);
final List<Integer> expectedHourlyLevels3 = new ArrayList<>();
expectedHourlyLevels3.add(null);
expectedHourlyLevels3.add(null);
expectedHourlyLevels3.add(null);
expectedHourlyLevels3.add(88);
final List<List<Integer>> expectedHourlyLevels = List.of(
expectedHourlyLevels1,
expectedHourlyLevels2,
expectedHourlyLevels3
);
verifyExpectedBatteryLevelData(
resultData,
expectedDailyTimestamps,
expectedDailyLevels,
expectedHourlyTimestamps,
expectedHourlyLevels);
}
@Test
public void getTimestampSlots_emptyRawList_returnEmptyList() {
final List<Long> resultList = DataProcessor.getTimestampSlots(
new ArrayList<>(), 1641038400000L); // 2022-01-01 20:00:00
assertThat(resultList).isEmpty();
}
@Test
public void getTimestampSlots_startWithEvenHour_returnExpectedResult() {
final Calendar startCalendar = Calendar.getInstance();
startCalendar.set(2022, 6, 5, 6, 30, 50); // 2022-07-05 06:30:50
final Calendar endCalendar = Calendar.getInstance();
endCalendar.set(2022, 6, 5, 22, 30, 50); // 2022-07-05 22:30:50
final Calendar expectedStartCalendar = Calendar.getInstance();
expectedStartCalendar.set(2022, 6, 5, 6, 0, 0); // 2022-07-05 06:00:00
final Calendar expectedEndCalendar = Calendar.getInstance();
expectedEndCalendar.set(2022, 6, 6, 0, 0, 0); // 2022-07-05 22:00:00
verifyExpectedTimestampSlots(
startCalendar, endCalendar, expectedStartCalendar, expectedEndCalendar);
}
@Test
public void getTimestampSlots_startWithOddHour_returnExpectedResult() {
final Calendar startCalendar = Calendar.getInstance();
startCalendar.set(2022, 6, 5, 5, 0, 50); // 2022-07-05 05:00:50
final Calendar endCalendar = Calendar.getInstance();
endCalendar.set(2022, 6, 6, 21, 0, 50); // 2022-07-06 21:00:50
final Calendar expectedStartCalendar = Calendar.getInstance();
expectedStartCalendar.set(2022, 6, 5, 6, 0, 0); // 2022-07-05 06:00:00
final Calendar expectedEndCalendar = Calendar.getInstance();
expectedEndCalendar.set(2022, 6, 6, 22, 0, 0); // 2022-07-06 20:00:00
verifyExpectedTimestampSlots(
startCalendar, endCalendar, expectedStartCalendar, expectedEndCalendar);
}
@Test
public void getDailyTimestamps_notEnoughData_returnEmptyList() {
assertThat(DataProcessor.getDailyTimestamps(new ArrayList<>())).isEmpty();
assertThat(DataProcessor.getDailyTimestamps(List.of(100L))).isEmpty();
assertThat(DataProcessor.getDailyTimestamps(List.of(100L, 5400000L))).isEmpty();
}
@Test
public void getDailyTimestamps_OneHourDataPerDay_returnEmptyList() {
// Timezone GMT+8
final List<Long> timestamps = List.of(
1641049200000L, // 2022-01-01 23:00:00
1641052800000L, // 2022-01-02 00:00:00
1641056400000L // 2022-01-02 01:00:00
);
assertThat(DataProcessor.getDailyTimestamps(timestamps)).isEmpty();
}
@Test
public void getDailyTimestamps_OneDayData_returnExpectedList() {
// Timezone GMT+8
final List<Long> timestamps = List.of(
1640966400000L, // 2022-01-01 00:00:00
1640970000000L, // 2022-01-01 01:00:00
1640973600000L, // 2022-01-01 02:00:00
1640977200000L, // 2022-01-01 03:00:00
1640980800000L // 2022-01-01 04:00:00
);
final List<Long> expectedTimestamps = List.of(
1640966400000L, // 2022-01-01 00:00:00
1640980800000L // 2022-01-01 04:00:00
);
assertThat(DataProcessor.getDailyTimestamps(timestamps)).isEqualTo(expectedTimestamps);
}
@Test
public void getDailyTimestamps_MultipleDaysData_returnExpectedList() {
// Timezone GMT+8
final List<Long> timestamps = List.of(
1641045600000L, // 2022-01-01 22:00:00
1641060000000L, // 2022-01-02 02:00:00
1641160800000L, // 2022-01-03 06:00:00
1641232800000L // 2022-01-04 02:00:00
);
final List<Long> expectedTimestamps = List.of(
1641045600000L, // 2022-01-01 22:00:00
1641052800000L, // 2022-01-02 00:00:00
1641139200000L, // 2022-01-03 00:00:00
1641225600000L, // 2022-01-04 00:00:00
1641232800000L // 2022-01-04 02:00:00
);
assertThat(DataProcessor.getDailyTimestamps(timestamps)).isEqualTo(expectedTimestamps);
}
@Test
public void getDailyTimestamps_FirstDayOneHourData_returnExpectedList() {
// Timezone GMT+8
final List<Long> timestamps = List.of(
1641049200000L, // 2022-01-01 23:00:00
1641060000000L, // 2022-01-02 02:00:00
1641160800000L, // 2022-01-03 06:00:00
1641254400000L // 2022-01-04 08:00:00
);
final List<Long> expectedTimestamps = List.of(
1641052800000L, // 2022-01-02 00:00:00
1641139200000L, // 2022-01-03 00:00:00
1641225600000L, // 2022-01-04 00:00:00
1641254400000L // 2022-01-04 08:00:00
);
assertThat(DataProcessor.getDailyTimestamps(timestamps)).isEqualTo(expectedTimestamps);
}
@Test
public void getDailyTimestamps_LastDayNoData_returnExpectedList() {
// Timezone GMT+8
final List<Long> timestamps = List.of(
1640988000000L, // 2022-01-01 06:00:00
1641060000000L, // 2022-01-02 02:00:00
1641160800000L, // 2022-01-03 06:00:00
1641225600000L // 2022-01-04 00:00:00
);
final List<Long> expectedTimestamps = List.of(
1640988000000L, // 2022-01-01 06:00:00
1641052800000L, // 2022-01-02 00:00:00
1641139200000L, // 2022-01-03 00:00:00
1641225600000L // 2022-01-04 00:00:00
);
assertThat(DataProcessor.getDailyTimestamps(timestamps)).isEqualTo(expectedTimestamps);
}
@Test
public void getDailyTimestamps_LastDayOneHourData_returnExpectedList() {
// Timezone GMT+8
final List<Long> timestamps = List.of(
1640988000000L, // 2022-01-01 06:00:00
1641060000000L, // 2022-01-02 02:00:00
1641160800000L, // 2022-01-03 06:00:00
1641229200000L // 2022-01-04 01:00:00
);
final List<Long> expectedTimestamps = List.of(
1640988000000L, // 2022-01-01 06:00:00
1641052800000L, // 2022-01-02 00:00:00
1641139200000L, // 2022-01-03 00:00:00
1641225600000L // 2022-01-04 00:00:00
);
assertThat(DataProcessor.getDailyTimestamps(timestamps)).isEqualTo(expectedTimestamps);
}
@Test
public void isFromFullCharge_emptyData_returnFalse() {
assertThat(DataProcessor.isFromFullCharge(null)).isFalse();
assertThat(DataProcessor.isFromFullCharge(new HashMap<>())).isFalse();
}
@Test
public void isFromFullCharge_notChargedData_returnFalse() {
final Map<String, BatteryHistEntry> entryMap = new HashMap<>();
final ContentValues values = new ContentValues();
values.put("batteryLevel", 98);
final BatteryHistEntry entry = new BatteryHistEntry(values);
entryMap.put(FAKE_ENTRY_KEY, entry);
assertThat(DataProcessor.isFromFullCharge(entryMap)).isFalse();
}
@Test
public void isFromFullCharge_chargedData_returnTrue() {
final Map<String, BatteryHistEntry> entryMap = new HashMap<>();
final ContentValues values = getContentValuesWithBatteryLevel(100);
final BatteryHistEntry entry = new BatteryHistEntry(values);
entryMap.put(FAKE_ENTRY_KEY, entry);
assertThat(DataProcessor.isFromFullCharge(entryMap)).isTrue();
}
@Test
public void findNearestTimestamp_returnExpectedResult() {
long[] results = DataProcessor.findNearestTimestamp(
Arrays.asList(10L, 20L, 30L, 40L), /*target=*/ 15L);
assertThat(results).isEqualTo(new long[] {10L, 20L});
results = DataProcessor.findNearestTimestamp(
Arrays.asList(10L, 20L, 30L, 40L), /*target=*/ 10L);
assertThat(results).isEqualTo(new long[] {10L, 10L});
results = DataProcessor.findNearestTimestamp(
Arrays.asList(10L, 20L, 30L, 40L), /*target=*/ 5L);
assertThat(results).isEqualTo(new long[] {0L, 10L});
results = DataProcessor.findNearestTimestamp(
Arrays.asList(10L, 20L, 30L, 40L), /*target=*/ 50L);
assertThat(results).isEqualTo(new long[] {40L, 0L});
}
@Test
public void getTimestampOfNextDay_returnExpectedResult() {
// 2021-02-28 06:00:00 => 2021-03-01 00:00:00
assertThat(DataProcessor.getTimestampOfNextDay(1614463200000L))
.isEqualTo(1614528000000L);
// 2021-12-31 16:00:00 => 2022-01-01 00:00:00
assertThat(DataProcessor.getTimestampOfNextDay(1640937600000L))
.isEqualTo(1640966400000L);
}
@Test
public void isForDailyChart_returnExpectedResult() {
assertThat(DataProcessor.isForDailyChart(/*isStartOrEnd=*/ true, 0L)).isTrue();
// 2022-01-01 00:00:00
assertThat(DataProcessor.isForDailyChart(/*isStartOrEnd=*/ false, 1640966400000L))
.isTrue();
// 2022-01-01 01:00:05
assertThat(DataProcessor.isForDailyChart(/*isStartOrEnd=*/ false, 1640970005000L))
.isFalse();
}
@Test
public void getBatteryUsageMap_emptyHistoryMap_returnNull() {
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
new ArrayList<>();
hourlyBatteryLevelsPerDay.add(
new BatteryLevelData.PeriodBatteryLevelData(new ArrayList<>(), new ArrayList<>()));
assertThat(DataProcessor.getBatteryUsageMap(
mContext, hourlyBatteryLevelsPerDay, new HashMap<>(), /*appUsagePeriodMap=*/ null))
.isNull();
}
@Test
public void getBatteryUsageMap_returnsExpectedResult() {
final long[] batteryHistoryKeys = new long[]{
1641045600000L, // 2022-01-01 22:00:00
1641049200000L, // 2022-01-01 23:00:00
1641052800000L, // 2022-01-02 00:00:00
1641056400000L, // 2022-01-02 01:00:00
1641060000000L, // 2022-01-02 02:00:00
};
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
final int currentUserId = mContext.getUserId();
final BatteryHistEntry fakeEntry = createBatteryHistEntry(
ConvertUtils.FAKE_PACKAGE_NAME, "fake_label", /*consumePower=*/ 0,
/*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 0L, currentUserId, ConvertUtils.CONSUMER_TYPE_UID_BATTERY,
/*foregroundUsageTimeInMs=*/ 0L, /*backgroundUsageTimeInMs=*/ 0L,
/*isHidden=*/ false);
// Adds the index = 0 data.
Map<String, BatteryHistEntry> entryMap = new HashMap<>();
BatteryHistEntry entry = createBatteryHistEntry(
"package1", "label1", /*consumePower=*/ 5.0,
/*foregroundUsageConsumePower=*/ 2, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 3, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
/*backgroundUsageTimeInMs=*/ 20L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
entryMap.put(fakeEntry.getKey(), fakeEntry);
batteryHistoryMap.put(batteryHistoryKeys[0], entryMap);
// Adds the index = 1 data.
entryMap = new HashMap<>();
entryMap.put(fakeEntry.getKey(), fakeEntry);
batteryHistoryMap.put(batteryHistoryKeys[1], entryMap);
// Adds the index = 2 data.
entryMap = new HashMap<>();
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 20.0,
/*foregroundUsageConsumePower=*/ 5, /*foregroundServiceUsageConsumePower=*/ 5,
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
/*uid=*/ 2L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 15L,
/*backgroundUsageTimeInMs=*/ 25L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
entryMap.put(fakeEntry.getKey(), fakeEntry);
batteryHistoryMap.put(batteryHistoryKeys[2], entryMap);
// Adds the index = 3 data.
entryMap = new HashMap<>();
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 40.0,
/*foregroundUsageConsumePower=*/ 8, /*foregroundServiceUsageConsumePower=*/ 8,
/*backgroundUsageConsumePower=*/ 8, /*cachedUsageConsumePower=*/ 8,
/*uid=*/ 2L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 25L,
/*backgroundUsageTimeInMs=*/ 35L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package3", "label3", /*consumePower=*/ 10.0,
/*foregroundUsageConsumePower=*/ 4, /*foregroundServiceUsageConsumePower=*/ 2,
/*backgroundUsageConsumePower=*/ 2, /*cachedUsageConsumePower=*/ 2,
/*uid=*/ 3L, currentUserId,
ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, /*foregroundUsageTimeInMs=*/ 40L,
/*backgroundUsageTimeInMs=*/ 50L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package4", "label3", /*consumePower=*/ 15.0,
/*foregroundUsageConsumePower=*/ 6, /*foregroundServiceUsageConsumePower=*/ 3,
/*backgroundUsageConsumePower=*/ 3, /*cachedUsageConsumePower=*/ 3,
/*uid=*/ 4L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 5L,
/*backgroundUsageTimeInMs=*/ 5L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
entryMap.put(fakeEntry.getKey(), fakeEntry);
batteryHistoryMap.put(batteryHistoryKeys[3], entryMap);
// Adds the index = 4 data.
entryMap = new HashMap<>();
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 40.0,
/*foregroundUsageConsumePower=*/ 14, /*foregroundServiceUsageConsumePower=*/ 9,
/*backgroundUsageConsumePower=*/ 9, /*cachedUsageConsumePower=*/ 8,
/*uid=*/ 2L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 30L,
/*backgroundUsageTimeInMs=*/ 40L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package3", "label3", /*consumePower=*/ 20.0,
/*foregroundUsageConsumePower=*/ 5, /*foregroundServiceUsageConsumePower=*/ 5,
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
/*uid=*/ 3L, currentUserId,
ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, /*foregroundUsageTimeInMs=*/ 50L,
/*backgroundUsageTimeInMs=*/ 60L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package4", "label4", /*consumePower=*/ 40.0,
/*foregroundUsageConsumePower=*/ 8, /*foregroundServiceUsageConsumePower=*/ 8,
/*backgroundUsageConsumePower=*/ 8, /*cachedUsageConsumePower=*/ 8,
/*uid=*/ 4L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 5L,
/*backgroundUsageTimeInMs=*/ 5L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
entryMap.put(fakeEntry.getKey(), fakeEntry);
batteryHistoryMap.put(batteryHistoryKeys[4], entryMap);
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
new ArrayList<>();
// Adds the day 1 data.
List<Long> timestamps =
List.of(batteryHistoryKeys[0], batteryHistoryKeys[2]);
final List<Integer> levels = List.of(100, 100);
hourlyBatteryLevelsPerDay.add(
new BatteryLevelData.PeriodBatteryLevelData(timestamps, levels));
// Adds the day 2 data.
timestamps = List.of(batteryHistoryKeys[2], batteryHistoryKeys[4]);
hourlyBatteryLevelsPerDay.add(
new BatteryLevelData.PeriodBatteryLevelData(timestamps, levels));
// Adds app usage data to test screen on time.
final Map<Integer, Map<Integer, Map<Long, Map<String, List<AppUsagePeriod>>>>>
appUsagePeriodMap = new HashMap<>();
appUsagePeriodMap.put(0, new HashMap<>());
appUsagePeriodMap.put(1, new HashMap<>());
// Adds the index [0][0].
Map<Long, Map<String, List<AppUsagePeriod>>> appUsageMap = new HashMap<>();
Map<String, List<AppUsagePeriod>> userPeriodMap = new HashMap<>();
appUsageMap.put(Long.valueOf(currentUserId), userPeriodMap);
userPeriodMap.put("package2", List.of(buildAppUsagePeriod(0, 5)));
userPeriodMap.put("package3", List.of(buildAppUsagePeriod(10, 25)));
appUsagePeriodMap.get(0).put(0, appUsageMap);
// Adds the index [1][0].
appUsageMap = new HashMap<>();
userPeriodMap = new HashMap<>();
appUsageMap.put(Long.valueOf(currentUserId), userPeriodMap);
userPeriodMap.put("package2",
List.of(buildAppUsagePeriod(2, 7), buildAppUsagePeriod(5, 9)));
userPeriodMap.put("package3",
List.of(buildAppUsagePeriod(10, 15), buildAppUsagePeriod(25, 29)));
appUsagePeriodMap.get(1).put(0, appUsageMap);
final Map<Integer, Map<Integer, BatteryDiffData>> resultMap =
DataProcessor.getBatteryUsageMap(
mContext, hourlyBatteryLevelsPerDay, batteryHistoryMap, appUsagePeriodMap);
BatteryDiffData resultDiffData =
resultMap
.get(DataProcessor.SELECTED_INDEX_ALL)
.get(DataProcessor.SELECTED_INDEX_ALL);
assertBatteryDiffEntry(
resultDiffData.getAppDiffEntryList().get(0), currentUserId, /*uid=*/ 2L,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 50.0,
/*foregroundUsageConsumePower=*/ 14, /*foregroundServiceUsageConsumePower=*/ 9,
/*backgroundUsageConsumePower=*/ 9, /*cachedUsageConsumePower=*/ 8,
/*foregroundUsageTimeInMs=*/ 30, /*backgroundUsageTimeInMs=*/ 40,
/*screenOnTimeInMs=*/ 12);
assertBatteryDiffEntry(
resultDiffData.getAppDiffEntryList().get(1), currentUserId, /*uid=*/ 4L,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 50.0,
/*foregroundUsageConsumePower=*/ 8, /*foregroundServiceUsageConsumePower=*/ 8,
/*backgroundUsageConsumePower=*/ 8, /*cachedUsageConsumePower=*/ 8,
/*foregroundUsageTimeInMs=*/ 5, /*backgroundUsageTimeInMs=*/ 5,
/*screenOnTimeInMs=*/ 0);
assertBatteryDiffEntry(
resultDiffData.getSystemDiffEntryList().get(0), currentUserId, /*uid=*/ 3L,
ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, /*consumePercentage=*/ 100.0,
/*foregroundUsageConsumePower=*/ 5, /*foregroundServiceUsageConsumePower=*/ 5,
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
/*foregroundUsageTimeInMs=*/ 50, /*backgroundUsageTimeInMs=*/ 60,
/*screenOnTimeInMs=*/ 9);
resultDiffData = resultMap.get(0).get(DataProcessor.SELECTED_INDEX_ALL);
assertBatteryDiffEntry(
resultDiffData.getAppDiffEntryList().get(0), currentUserId, /*uid=*/ 2L,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 100.0,
/*foregroundUsageConsumePower=*/ 5, /*foregroundServiceUsageConsumePower=*/ 5,
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
/*foregroundUsageTimeInMs=*/ 15, /*backgroundUsageTimeInMs=*/ 25,
/*screenOnTimeInMs=*/ 5);
resultDiffData = resultMap.get(1).get(DataProcessor.SELECTED_INDEX_ALL);
assertBatteryDiffEntry(
resultDiffData.getAppDiffEntryList().get(0), currentUserId, /*uid=*/ 4L,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 66.66666666666666,
/*foregroundUsageConsumePower=*/ 8, /*foregroundServiceUsageConsumePower=*/ 8,
/*backgroundUsageConsumePower=*/ 8, /*cachedUsageConsumePower=*/ 8,
/*foregroundUsageTimeInMs=*/ 5, /*backgroundUsageTimeInMs=*/ 5,
/*screenOnTimeInMs=*/ 0);
assertBatteryDiffEntry(
resultDiffData.getAppDiffEntryList().get(1), currentUserId, /*uid=*/ 2L,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 33.33333333333333,
/*foregroundUsageConsumePower=*/ 9, /*foregroundServiceUsageConsumePower=*/ 4,
/*backgroundUsageConsumePower=*/ 4, /*cachedUsageConsumePower=*/ 3,
/*foregroundUsageTimeInMs=*/ 15, /*backgroundUsageTimeInMs=*/ 15,
/*screenOnTimeInMs=*/ 7);
assertBatteryDiffEntry(
resultDiffData.getSystemDiffEntryList().get(0), currentUserId, /*uid=*/ 3L,
ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, /*consumePercentage=*/ 100.0,
/*foregroundUsageConsumePower=*/ 5, /*foregroundServiceUsageConsumePower=*/ 5,
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
/*foregroundUsageTimeInMs=*/ 50, /*backgroundUsageTimeInMs=*/ 60,
/*screenOnTimeInMs=*/ 9);
}
@Test
public void getBatteryUsageMap_multipleUsers_returnsExpectedResult() {
final long[] batteryHistoryKeys = new long[]{
1641052800000L, // 2022-01-02 00:00:00
1641056400000L, // 2022-01-02 01:00:00
1641060000000L // 2022-01-02 02:00:00
};
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
final int currentUserId = mContext.getUserId();
// Adds the index = 0 data.
Map<String, BatteryHistEntry> entryMap = new HashMap<>();
BatteryHistEntry entry = createBatteryHistEntry(
"package1", "label1", /*consumePower=*/ 5.0,
/*foregroundUsageConsumePower=*/ 5, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
/*backgroundUsageTimeInMs=*/ 20L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package1", "label1", /*consumePower=*/ 10.0,
/*foregroundUsageConsumePower=*/ 7, /*foregroundServiceUsageConsumePower=*/ 1,
/*backgroundUsageConsumePower=*/ 1, /*cachedUsageConsumePower=*/ 1,
/*uid=*/ 2L, currentUserId + 1,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
/*backgroundUsageTimeInMs=*/ 20L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 5.0,
/*foregroundUsageConsumePower=*/ 5, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 3L, currentUserId + 2,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 20L,
/*backgroundUsageTimeInMs=*/ 30L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[0], entryMap);
// Adds the index = 1 data.
entryMap = new HashMap<>();
entry = createBatteryHistEntry(
"package1", "label1", /*consumePower=*/ 15.0,
/*foregroundUsageConsumePower=*/ 9, /*foregroundServiceUsageConsumePower=*/ 2,
/*backgroundUsageConsumePower=*/ 2, /*cachedUsageConsumePower=*/ 2,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 20L,
/*backgroundUsageTimeInMs=*/ 30L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package1", "label1", /*consumePower=*/ 30.0,
/*foregroundUsageConsumePower=*/ 20, /*foregroundServiceUsageConsumePower=*/ 6,
/*backgroundUsageConsumePower=*/ 2, /*cachedUsageConsumePower=*/ 2,
/*uid=*/ 2L, currentUserId + 1,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
/*backgroundUsageTimeInMs=*/ 20L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 15.0,
/*foregroundUsageConsumePower=*/ 10, /*foregroundServiceUsageConsumePower=*/ 5,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 3L, currentUserId + 2,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 30L,
/*backgroundUsageTimeInMs=*/ 30L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[1], entryMap);
// Adds the index = 2 data.
entryMap = new HashMap<>();
entry = createBatteryHistEntry(
"package1", "label1", /*consumePower=*/ 25.0,
/*foregroundUsageConsumePower=*/ 10, /*foregroundServiceUsageConsumePower=*/ 5,
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 20L,
/*backgroundUsageTimeInMs=*/ 30L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package1", "label1", /*consumePower=*/ 50.0,
/*foregroundUsageConsumePower=*/ 20, /*foregroundServiceUsageConsumePower=*/ 10,
/*backgroundUsageConsumePower=*/ 10, /*cachedUsageConsumePower=*/ 10,
/*uid=*/ 2L, currentUserId + 1,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 20L,
/*backgroundUsageTimeInMs=*/ 20L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 25.0,
/*foregroundUsageConsumePower=*/ 10, /*foregroundServiceUsageConsumePower=*/ 10,
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 3L, currentUserId + 2,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 30L,
/*backgroundUsageTimeInMs=*/ 30L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[2], entryMap);
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
new ArrayList<>();
List<Long> timestamps = List.of(batteryHistoryKeys[0], batteryHistoryKeys[2]);
final List<Integer> levels = List.of(100, 100);
hourlyBatteryLevelsPerDay.add(
new BatteryLevelData.PeriodBatteryLevelData(timestamps, levels));
final Map<Integer, Map<Integer, BatteryDiffData>> resultMap =
DataProcessor.getBatteryUsageMap(
mContext, hourlyBatteryLevelsPerDay, batteryHistoryMap,
/*appUsagePeriodMap=*/ null);
final BatteryDiffData resultDiffData =
resultMap
.get(DataProcessor.SELECTED_INDEX_ALL)
.get(DataProcessor.SELECTED_INDEX_ALL);
assertBatteryDiffEntry(
resultDiffData.getAppDiffEntryList().get(0), currentUserId, /*uid=*/ 1L,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 100.0,
/*foregroundUsageConsumePower=*/ 5, /*foregroundServiceUsageConsumePower=*/ 5,
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
/*foregroundUsageTimeInMs=*/ 10, /*backgroundUsageTimeInMs=*/ 10,
/*screenOnTimeInMs=*/ 0);
assertThat(resultDiffData.getSystemDiffEntryList()).isEmpty();
assertThat(resultMap.get(0).get(0)).isNotNull();
assertThat(resultMap.get(0).get(DataProcessor.SELECTED_INDEX_ALL)).isNotNull();
}
@Test
public void getBatteryUsageMap_usageTimeExceed_returnsExpectedResult() {
final long[] batteryHistoryKeys = new long[]{
1641052800000L, // 2022-01-02 00:00:00
1641056400000L, // 2022-01-02 01:00:00
1641060000000L // 2022-01-02 02:00:00
};
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
final int currentUserId = mContext.getUserId();
// Adds the index = 0 data.
Map<String, BatteryHistEntry> entryMap = new HashMap<>();
BatteryHistEntry entry = createBatteryHistEntry(
"package1", "label1", /*consumePower=*/ 0,
/*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
/*backgroundUsageTimeInMs=*/ 0L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[0], entryMap);
// Adds the index = 1 data.
entryMap = new HashMap<>();
entry = createBatteryHistEntry(
"package1", "label1", /*consumePower=*/ 0,
/*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
/*backgroundUsageTimeInMs=*/ 0L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[1], entryMap);
// Adds the index = 2 data.
entryMap = new HashMap<>();
entry = createBatteryHistEntry(
"package1", "label1", /*consumePower=*/ 500.0,
/*foregroundUsageConsumePower=*/ 200, /*foregroundServiceUsageConsumePower=*/ 100,
/*backgroundUsageConsumePower=*/ 100, /*cachedUsageConsumePower=*/ 100,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 3600000L,
/*backgroundUsageTimeInMs=*/ 7200000L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[2], entryMap);
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
new ArrayList<>();
List<Long> timestamps = List.of(batteryHistoryKeys[0], batteryHistoryKeys[2]);
final List<Integer> levels = List.of(100, 100);
hourlyBatteryLevelsPerDay.add(
new BatteryLevelData.PeriodBatteryLevelData(timestamps, levels));
// Adds app usage data to test screen on time.
final Map<Integer, Map<Integer, Map<Long, Map<String, List<AppUsagePeriod>>>>>
appUsagePeriodMap = new HashMap<>();
appUsagePeriodMap.put(0, new HashMap<>());
// Adds the index [0][0].
final Map<Long, Map<String, List<AppUsagePeriod>>> appUsageMap = new HashMap<>();
final Map<String, List<AppUsagePeriod>> userPeriodMap = new HashMap<>();
appUsageMap.put(Long.valueOf(currentUserId), userPeriodMap);
userPeriodMap.put("package1", List.of(buildAppUsagePeriod(0, 8000000)));
appUsagePeriodMap.get(0).put(0, appUsageMap);
final Map<Integer, Map<Integer, BatteryDiffData>> resultMap =
DataProcessor.getBatteryUsageMap(
mContext, hourlyBatteryLevelsPerDay, batteryHistoryMap, appUsagePeriodMap);
final BatteryDiffData resultDiffData =
resultMap
.get(DataProcessor.SELECTED_INDEX_ALL)
.get(DataProcessor.SELECTED_INDEX_ALL);
// Verifies the clipped usage time.
final float ratio = (float) (7200) / (float) (3600 + 7200);
final BatteryDiffEntry resultEntry = resultDiffData.getAppDiffEntryList().get(0);
assertThat(resultEntry.mForegroundUsageTimeInMs)
.isEqualTo(Math.round(entry.mForegroundUsageTimeInMs * ratio));
assertThat(resultEntry.mBackgroundUsageTimeInMs)
.isEqualTo(0);
assertThat(resultEntry.mConsumePower)
.isEqualTo(entry.mConsumePower * ratio);
assertThat(resultEntry.mForegroundUsageConsumePower)
.isEqualTo(entry.mForegroundUsageConsumePower * ratio);
assertThat(resultEntry.mForegroundServiceUsageConsumePower)
.isEqualTo(entry.mForegroundServiceUsageConsumePower * ratio);
assertThat(resultEntry.mBackgroundUsageConsumePower)
.isEqualTo(entry.mBackgroundUsageConsumePower * ratio);
assertThat(resultEntry.mCachedUsageConsumePower)
.isEqualTo(entry.mCachedUsageConsumePower * ratio);
assertThat(resultEntry.mScreenOnTimeInMs).isEqualTo(7200000L);
assertThat(resultMap.get(0).get(0)).isNotNull();
assertThat(resultMap.get(0).get(DataProcessor.SELECTED_INDEX_ALL)).isNotNull();
}
@Test
public void getBatteryUsageMap_hideApplicationEntries_returnsExpectedResult() {
final long[] batteryHistoryKeys = new long[]{
1641052800000L, // 2022-01-02 00:00:00
1641056400000L, // 2022-01-02 01:00:00
1641060000000L // 2022-01-02 02:00:00
};
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
final int currentUserId = mContext.getUserId();
// Adds the index = 0 data.
Map<String, BatteryHistEntry> entryMap = new HashMap<>();
BatteryHistEntry entry = createBatteryHistEntry(
"package1", "label1", /*consumePower=*/ 0,
/*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
/*backgroundUsageTimeInMs=*/ 0L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 0,
/*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 2L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
/*backgroundUsageTimeInMs=*/ 0L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[0], entryMap);
// Adds the index = 1 data.
entryMap = new HashMap<>();
entry = createBatteryHistEntry(
"package1", "label1", /*consumePower=*/ 0,
/*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
/*backgroundUsageTimeInMs=*/ 0L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 0,
/*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 2L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
/*backgroundUsageTimeInMs=*/ 0L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[1], entryMap);
// Adds the index = 2 data.
entryMap = new HashMap<>();
entry = createBatteryHistEntry(
"package1", "label1", /*consumePower=*/ 10.0,
/*foregroundUsageConsumePower=*/ 5, /*foregroundServiceUsageConsumePower=*/ 5,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
/*backgroundUsageTimeInMs=*/ 20L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 10.0,
/*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
/*uid=*/ 2L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
/*backgroundUsageTimeInMs=*/ 20L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[2], entryMap);
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
new ArrayList<>();
List<Long> timestamps = List.of(batteryHistoryKeys[0], batteryHistoryKeys[2]);
final List<Integer> levels = List.of(100, 100);
hourlyBatteryLevelsPerDay.add(
new BatteryLevelData.PeriodBatteryLevelData(timestamps, levels));
when(mPowerUsageFeatureProvider.getHideApplicationSet())
.thenReturn(Set.of("package1"));
final Map<Integer, Map<Integer, BatteryDiffData>> resultMap =
DataProcessor.getBatteryUsageMap(
mContext, hourlyBatteryLevelsPerDay, batteryHistoryMap,
/*appUsagePeriodMap=*/ null);
final BatteryDiffData resultDiffData =
resultMap
.get(DataProcessor.SELECTED_INDEX_ALL)
.get(DataProcessor.SELECTED_INDEX_ALL);
assertBatteryDiffEntry(
resultDiffData.getAppDiffEntryList().get(0), currentUserId, /*uid=*/ 2L,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 100.0,
/*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
/*foregroundUsageTimeInMs=*/ 10, /*backgroundUsageTimeInMs=*/ 20,
/*screenOnTimeInMs=*/ 0);
}
@Test
public void getBatteryUsageMap_hideBackgroundUsageTime_returnsExpectedResult() {
final long[] batteryHistoryKeys = new long[]{
1641052800000L, // 2022-01-02 00:00:00
1641056400000L, // 2022-01-02 01:00:00
1641060000000L // 2022-01-02 02:00:00
};
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
final int currentUserId = mContext.getUserId();
// Adds the index = 0 data.
Map<String, BatteryHistEntry> entryMap = new HashMap<>();
BatteryHistEntry entry = createBatteryHistEntry(
"package1", "label1", /*consumePower=*/ 0,
/*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
/*backgroundUsageTimeInMs=*/ 0L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 0,
/*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 2L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
/*backgroundUsageTimeInMs=*/ 0L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[0], entryMap);
// Adds the index = 1 data.
entryMap = new HashMap<>();
entry = createBatteryHistEntry(
"package1", "label1", /*consumePower=*/ 0,
/*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
/*backgroundUsageTimeInMs=*/ 0L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 0,
/*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 2L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 0L,
/*backgroundUsageTimeInMs=*/ 0L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[1], entryMap);
// Adds the index = 2 data.
entryMap = new HashMap<>();
entry = createBatteryHistEntry(
"package1", "label1", /*consumePower=*/ 10.0,
/*foregroundUsageConsumePower=*/ 5, /*foregroundServiceUsageConsumePower=*/ 5,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*uid=*/ 1L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
/*backgroundUsageTimeInMs=*/ 20L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
entry = createBatteryHistEntry(
"package2", "label2", /*consumePower=*/ 10.0,
/*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 5, /*cachedUsageConsumePower=*/ 5,
/*uid=*/ 2L, currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*foregroundUsageTimeInMs=*/ 10L,
/*backgroundUsageTimeInMs=*/ 20L, /*isHidden=*/ false);
entryMap.put(entry.getKey(), entry);
batteryHistoryMap.put(batteryHistoryKeys[2], entryMap);
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyBatteryLevelsPerDay =
new ArrayList<>();
List<Long> timestamps = List.of(batteryHistoryKeys[0], batteryHistoryKeys[2]);
final List<Integer> levels = List.of(100, 100);
hourlyBatteryLevelsPerDay.add(
new BatteryLevelData.PeriodBatteryLevelData(timestamps, levels));
when(mPowerUsageFeatureProvider.getHideBackgroundUsageTimeSet())
.thenReturn(new HashSet(Arrays.asList((CharSequence) "package2")));
final Map<Integer, Map<Integer, BatteryDiffData>> resultMap =
DataProcessor.getBatteryUsageMap(
mContext, hourlyBatteryLevelsPerDay, batteryHistoryMap,
/*appUsagePeriodMap=*/ null);
final BatteryDiffData resultDiffData =
resultMap
.get(DataProcessor.SELECTED_INDEX_ALL)
.get(DataProcessor.SELECTED_INDEX_ALL);
BatteryDiffEntry resultEntry = resultDiffData.getAppDiffEntryList().get(0);
assertThat(resultEntry.mBackgroundUsageTimeInMs).isEqualTo(20);
resultEntry = resultDiffData.getAppDiffEntryList().get(1);
assertThat(resultEntry.mBackgroundUsageTimeInMs).isEqualTo(0);
}
@Test
public void generateBatteryDiffData_emptyBatteryEntryList_returnNull() {
assertThat(DataProcessor.generateBatteryDiffData(mContext,
DataProcessor.convertToBatteryHistEntry(null, mBatteryUsageStats))).isNull();
}
@Test
public void generateBatteryDiffData_returnsExpectedResult() {
final List<BatteryEntry> batteryEntryList = new ArrayList<>();
batteryEntryList.add(mMockBatteryEntry1);
batteryEntryList.add(mMockBatteryEntry2);
batteryEntryList.add(mMockBatteryEntry3);
batteryEntryList.add(mMockBatteryEntry4);
doReturn(0.0).when(mMockBatteryEntry1).getConsumedPower();
doReturn(0.0).when(mMockBatteryEntry1).getConsumedPowerInForeground();
doReturn(0.0).when(mMockBatteryEntry1).getConsumedPowerInForegroundService();
doReturn(0.0).when(mMockBatteryEntry1).getConsumedPowerInBackground();
doReturn(0.0).when(mMockBatteryEntry1).getConsumedPowerInCached();
doReturn(30L).when(mMockBatteryEntry1).getTimeInForegroundMs();
doReturn(40L).when(mMockBatteryEntry1).getTimeInBackgroundMs();
doReturn(1).when(mMockBatteryEntry1).getUid();
doReturn(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).when(mMockBatteryEntry1).getConsumerType();
doReturn(0.5).when(mMockBatteryEntry2).getConsumedPower();
doReturn(0.5).when(mMockBatteryEntry2).getConsumedPowerInForeground();
doReturn(0.0).when(mMockBatteryEntry2).getConsumedPowerInForegroundService();
doReturn(0.0).when(mMockBatteryEntry2).getConsumedPowerInBackground();
doReturn(0.0).when(mMockBatteryEntry2).getConsumedPowerInCached();
doReturn(20L).when(mMockBatteryEntry2).getTimeInForegroundMs();
doReturn(20L).when(mMockBatteryEntry2).getTimeInBackgroundMs();
doReturn(2).when(mMockBatteryEntry2).getUid();
doReturn(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).when(mMockBatteryEntry2).getConsumerType();
doReturn(0.0).when(mMockBatteryEntry3).getConsumedPower();
doReturn(0.0).when(mMockBatteryEntry3).getConsumedPowerInForeground();
doReturn(0.0).when(mMockBatteryEntry3).getConsumedPowerInForegroundService();
doReturn(0.0).when(mMockBatteryEntry3).getConsumedPowerInBackground();
doReturn(0.0).when(mMockBatteryEntry3).getConsumedPowerInCached();
doReturn(0L).when(mMockBatteryEntry3).getTimeInForegroundMs();
doReturn(0L).when(mMockBatteryEntry3).getTimeInBackgroundMs();
doReturn(3).when(mMockBatteryEntry3).getUid();
doReturn(ConvertUtils.CONSUMER_TYPE_UID_BATTERY).when(mMockBatteryEntry3).getConsumerType();
doReturn(1.5).when(mMockBatteryEntry4).getConsumedPower();
doReturn(0.9).when(mMockBatteryEntry4).getConsumedPowerInForeground();
doReturn(0.2).when(mMockBatteryEntry4).getConsumedPowerInForegroundService();
doReturn(0.3).when(mMockBatteryEntry4).getConsumedPowerInBackground();
doReturn(0.1).when(mMockBatteryEntry4).getConsumedPowerInCached();
doReturn(10L).when(mMockBatteryEntry4).getTimeInForegroundMs();
doReturn(10L).when(mMockBatteryEntry4).getTimeInBackgroundMs();
doReturn(4).when(mMockBatteryEntry4).getUid();
doReturn(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY)
.when(mMockBatteryEntry4).getConsumerType();
doReturn(BatteryConsumer.POWER_COMPONENT_CAMERA)
.when(mMockBatteryEntry4).getPowerComponentId();
final BatteryDiffData batteryDiffData = DataProcessor.generateBatteryDiffData(mContext,
DataProcessor.convertToBatteryHistEntry(batteryEntryList, mBatteryUsageStats));
assertBatteryDiffEntry(
batteryDiffData.getAppDiffEntryList().get(0), 0, /*uid=*/ 2L,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 100.0,
/*foregroundUsageConsumePower=*/ 0.5, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*foregroundUsageTimeInMs=*/ 20, /*backgroundUsageTimeInMs=*/ 20,
/*screenOnTimeInMs=*/ 0);
assertBatteryDiffEntry(
batteryDiffData.getAppDiffEntryList().get(1), 0, /*uid=*/ 1L,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY, /*consumePercentage=*/ 0.0,
/*foregroundUsageConsumePower=*/ 0, /*foregroundServiceUsageConsumePower=*/ 0,
/*backgroundUsageConsumePower=*/ 0, /*cachedUsageConsumePower=*/ 0,
/*foregroundUsageTimeInMs=*/ 30, /*backgroundUsageTimeInMs=*/ 40,
/*screenOnTimeInMs=*/ 0);
assertBatteryDiffEntry(
batteryDiffData.getSystemDiffEntryList().get(0), 0, /*uid=*/ 4L,
ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY, /*consumePercentage=*/ 100.0,
/*foregroundUsageConsumePower=*/ 0.9, /*foregroundServiceUsageConsumePower=*/ 0.2,
/*backgroundUsageConsumePower=*/ 0.3, /*cachedUsageConsumePower=*/ 0.1,
/*foregroundUsageTimeInMs=*/ 10, /*backgroundUsageTimeInMs=*/ 10,
/*screenOnTimeInMs=*/ 0);
}
@Test
public void buildAppUsagePeriodList_returnExpectedResult() {
final List<AppUsageEvent> appUsageEvents = new ArrayList<>();
final String packageName1 = "com.android.settings1";
final String packageName2 = "com.android.settings2";
// Fake multiple instances in one package.
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 1, /*userId=*/ 1,
/*instanceId=*/ 2, packageName1));
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 2, /*userId=*/ 1,
/*instanceId=*/ 2, packageName1));
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 3, /*userId=*/ 1,
/*instanceId=*/ 2, packageName1));
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 4, /*userId=*/ 1,
/*instanceId=*/ 2, packageName1));
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 2, /*userId=*/ 1,
/*instanceId=*/ 3, packageName1));
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 4, /*userId=*/ 1,
/*instanceId=*/ 3, packageName1));
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 2, /*userId=*/ 1,
/*instanceId=*/ 5, packageName2));
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 4, /*userId=*/ 1,
/*instanceId=*/ 5, packageName2));
// Fake one instance in one package.
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 1, /*userId=*/ 2,
/*instanceId=*/ 4, packageName2));
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 2, /*userId=*/ 2,
/*instanceId=*/ 4, packageName2));
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 3, /*userId=*/ 2,
/*instanceId=*/ 4, packageName2));
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 4, /*userId=*/ 2,
/*instanceId=*/ 4, packageName2));
final Map<Long, Map<String, List<AppUsagePeriod>>> appUsagePeriodMap =
DataProcessor.buildAppUsagePeriodList(appUsageEvents, 0, 5);
assertThat(appUsagePeriodMap).hasSize(2);
final Map<String, List<AppUsagePeriod>> userMap1 = appUsagePeriodMap.get(1L);
assertThat(userMap1).hasSize(2);
List<AppUsagePeriod> appUsagePeriodList = userMap1.get(packageName1);
assertThat(appUsagePeriodList).hasSize(3);
assertAppUsagePeriod(appUsagePeriodList.get(0), 1, 2);
assertAppUsagePeriod(appUsagePeriodList.get(1), 2, 4);
assertAppUsagePeriod(appUsagePeriodList.get(2), 3, 4);
appUsagePeriodList = userMap1.get(packageName2);
assertThat(appUsagePeriodList).hasSize(1);
assertAppUsagePeriod(appUsagePeriodList.get(0), 2, 4);
final Map<String, List<AppUsagePeriod>> userMap2 = appUsagePeriodMap.get(2L);
assertThat(userMap2).hasSize(1);
appUsagePeriodList = userMap2.get(packageName2);
assertThat(appUsagePeriodList).hasSize(2);
assertAppUsagePeriod(appUsagePeriodList.get(0), 1, 2);
assertAppUsagePeriod(appUsagePeriodList.get(1), 3, 4);
}
@Test
public void buildAppUsagePeriodList_emptyEventList_returnNull() {
assertThat(DataProcessor.buildAppUsagePeriodList(
new ArrayList<>(), 0, 1)).isNull();
}
@Test
public void buildAppUsagePeriodList_emptyActivityList_returnNull() {
final List<AppUsageEvent> appUsageEvents = new ArrayList<>();
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.DEVICE_SHUTDOWN, /*timestamp=*/ 1));
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.DEVICE_SHUTDOWN, /*timestamp=*/ 2));
assertThat(DataProcessor.buildAppUsagePeriodList(
appUsageEvents, 0, 3)).isNull();
}
@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=*/ 150000));
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 200000));
// Fake two adjacent resume events.
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 300000));
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 400000));
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 500000));
// Fake no start event when stop event happens.
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_STOPPED, /*timestamp=*/ 600000));
// There exists start event when device shutdown event happens. Shutdown is later than
// default complete time.
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 700000));
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.DEVICE_SHUTDOWN, /*timestamp=*/ 800000));
// There exists start event when device shutdown event happens. Shutdown is earlier than
// default complete time.
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 900000));
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.DEVICE_SHUTDOWN, /*timestamp=*/ 910000));
// There exists start event when the period ends.
appUsageEvents.add(buildAppUsageEvent(
AppUsageEventType.ACTIVITY_RESUMED, /*timestamp=*/ 1000000));
final List<AppUsagePeriod> appUsagePeriodList =
DataProcessor.buildAppUsagePeriodListPerInstance(appUsageEvents, 100000, 1100000);
assertThat(appUsagePeriodList).hasSize(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
public void getScreenOnTime_returnExpectedResult() {
final long userId = 1;
final String packageName = "com.android.settings";
final Map<Long, Map<String, List<AppUsagePeriod>>> appUsageMap = new HashMap<>();
final List<AppUsagePeriod> appUsagePeriodList = new ArrayList<>();
appUsageMap.put(userId, new HashMap<>());
appUsageMap.get(userId).put(packageName, appUsagePeriodList);
// Fake overlapped case.
appUsagePeriodList.add(buildAppUsagePeriod(0, 5));
appUsagePeriodList.add(buildAppUsagePeriod(2, 3));
appUsagePeriodList.add(buildAppUsagePeriod(2, 4));
appUsagePeriodList.add(buildAppUsagePeriod(5, 7));
// Fake same case.
appUsagePeriodList.add(buildAppUsagePeriod(10, 12));
appUsagePeriodList.add(buildAppUsagePeriod(10, 12));
appUsagePeriodList.add(buildAppUsagePeriod(10, 12));
// Fake normal case.
appUsagePeriodList.add(buildAppUsagePeriod(15, 20));
appUsagePeriodList.add(buildAppUsagePeriod(35, 40));
appUsagePeriodList.add(buildAppUsagePeriod(25, 30));
assertThat(DataProcessor.getScreenOnTime(appUsageMap, userId, packageName)).isEqualTo(24);
}
@Test
public void getScreenOnTime_nullInput_returnZero() {
final long userId = 1;
final String packageName = "com.android.settings";
final Map<Long, Map<String, List<AppUsagePeriod>>> appUsageMap = new HashMap<>();
appUsageMap.put(userId, new HashMap<>());
assertThat(DataProcessor.getScreenOnTime(null, userId, packageName)).isEqualTo(0);
assertThat(DataProcessor.getScreenOnTime(new HashMap<>(), userId, packageName))
.isEqualTo(0);
assertThat(DataProcessor.getScreenOnTime(appUsageMap, userId, packageName)).isEqualTo(0);
}
private static Map<Long, Map<String, BatteryHistEntry>> createHistoryMap(
final long[] timestamps, final int[] levels) {
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
for (int index = 0; index < timestamps.length; index++) {
final Map<String, BatteryHistEntry> entryMap = new HashMap<>();
final ContentValues values = getContentValuesWithBatteryLevel(levels[index]);
final BatteryHistEntry entry = new BatteryHistEntry(values);
entryMap.put(FAKE_ENTRY_KEY, entry);
batteryHistoryMap.put(timestamps[index], entryMap);
}
return batteryHistoryMap;
}
private static ContentValues getContentValuesWithBatteryLevel(final int level) {
final ContentValues values = new ContentValues();
final DeviceBatteryState deviceBatteryState =
DeviceBatteryState
.newBuilder()
.setBatteryLevel(level)
.build();
final BatteryInformation batteryInformation =
BatteryInformation
.newBuilder()
.setDeviceBatteryState(deviceBatteryState)
.build();
values.put(BatteryHistEntry.KEY_BATTERY_INFORMATION,
ConvertUtils.convertBatteryInformationToString(batteryInformation));
return values;
}
private static BatteryHistEntry createBatteryHistEntry(
final String packageName, final String appLabel, final double consumePower,
final double foregroundUsageConsumePower,
final double foregroundServiceUsageConsumePower,
final double backgroundUsageConsumePower, final double cachedUsageConsumePower,
final long uid, final long userId, final int consumerType,
final long foregroundUsageTimeInMs, final long backgroundUsageTimeInMs,
final boolean isHidden) {
// Only insert required fields.
final BatteryInformation batteryInformation =
BatteryInformation
.newBuilder()
.setAppLabel(appLabel)
.setConsumePower(consumePower)
.setForegroundUsageConsumePower(foregroundUsageConsumePower)
.setForegroundServiceUsageConsumePower(foregroundServiceUsageConsumePower)
.setBackgroundUsageConsumePower(backgroundUsageConsumePower)
.setCachedUsageConsumePower(cachedUsageConsumePower)
.setForegroundUsageTimeInMs(foregroundUsageTimeInMs)
.setBackgroundUsageTimeInMs(backgroundUsageTimeInMs)
.setIsHidden(isHidden)
.build();
final ContentValues values = new ContentValues();
values.put(BatteryHistEntry.KEY_PACKAGE_NAME, packageName);
values.put(BatteryHistEntry.KEY_UID, uid);
values.put(BatteryHistEntry.KEY_USER_ID, userId);
values.put(BatteryHistEntry.KEY_CONSUMER_TYPE, consumerType);
values.put(BatteryHistEntry.KEY_BATTERY_INFORMATION,
ConvertUtils.convertBatteryInformationToString(batteryInformation));
return new BatteryHistEntry(values);
}
private UsageEvents getUsageEvents(final List<Event> events) {
UsageEvents usageEvents = new UsageEvents(events, new String[] {"package"});
Parcel parcel = Parcel.obtain();
parcel.setDataPosition(0);
usageEvents.writeToParcel(parcel, 0);
parcel.setDataPosition(0);
return UsageEvents.CREATOR.createFromParcel(parcel);
}
private Event getUsageEvent(
final int eventType, final long timestamp) {
final Event event = new Event();
event.mEventType = eventType;
event.mPackage = "package";
event.mTimeStamp = timestamp;
return event;
}
private AppUsageEvent buildAppUsageEvent(final AppUsageEventType type, final long timestamp) {
return buildAppUsageEvent(
type, timestamp, /*userId=*/ 1, /*instanceId=*/ 2,
"com.android.settings");
}
private AppUsageEvent buildAppUsageEvent(
final AppUsageEventType type,
final long timestamp,
final long userId,
final int instanceId,
final String packageName) {
return AppUsageEvent.newBuilder()
.setType(type)
.setTimestamp(timestamp)
.setUserId(userId)
.setPackageName(packageName)
.setInstanceId(instanceId)
.build();
}
private AppUsagePeriod buildAppUsagePeriod(final long start, final long end) {
return AppUsagePeriod.newBuilder()
.setStartTime(start)
.setEndTime(end)
.build();
}
private void assertAppUsageEvent(
final AppUsageEvent event, final AppUsageEventType eventType, final long timestamp) {
assertThat(event.getType()).isEqualTo(eventType);
assertThat(event.getTimestamp()).isEqualTo(timestamp);
}
private void assertAppUsagePeriod(
final AppUsagePeriod period, final long startTime, final long endTime) {
assertThat(period.getStartTime()).isEqualTo(startTime);
assertThat(period.getEndTime()).isEqualTo(endTime);
}
private static void verifyExpectedBatteryLevelData(
final BatteryLevelData resultData,
final List<Long> expectedDailyTimestamps,
final List<Integer> expectedDailyLevels,
final List<List<Long>> expectedHourlyTimestamps,
final List<List<Integer>> expectedHourlyLevels) {
final BatteryLevelData.PeriodBatteryLevelData dailyResultData =
resultData.getDailyBatteryLevels();
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyResultData =
resultData.getHourlyBatteryLevelsPerDay();
verifyExpectedDailyBatteryLevelData(
dailyResultData, expectedDailyTimestamps, expectedDailyLevels);
verifyExpectedHourlyBatteryLevelData(
hourlyResultData, expectedHourlyTimestamps, expectedHourlyLevels);
}
private static void verifyExpectedDailyBatteryLevelData(
final BatteryLevelData.PeriodBatteryLevelData dailyResultData,
final List<Long> expectedDailyTimestamps,
final List<Integer> expectedDailyLevels) {
assertThat(dailyResultData.getTimestamps()).isEqualTo(expectedDailyTimestamps);
assertThat(dailyResultData.getLevels()).isEqualTo(expectedDailyLevels);
}
private static void verifyExpectedHourlyBatteryLevelData(
final List<BatteryLevelData.PeriodBatteryLevelData> hourlyResultData,
final List<List<Long>> expectedHourlyTimestamps,
final List<List<Integer>> expectedHourlyLevels) {
final int expectedHourlySize = expectedHourlyTimestamps.size();
assertThat(hourlyResultData).hasSize(expectedHourlySize);
for (int dailyIndex = 0; dailyIndex < expectedHourlySize; dailyIndex++) {
assertThat(hourlyResultData.get(dailyIndex).getTimestamps())
.isEqualTo(expectedHourlyTimestamps.get(dailyIndex));
assertThat(hourlyResultData.get(dailyIndex).getLevels())
.isEqualTo(expectedHourlyLevels.get(dailyIndex));
}
}
private static void verifyExpectedTimestampSlots(
final Calendar start,
final Calendar current,
final Calendar expectedStart,
final Calendar expectedEnd) {
expectedStart.set(Calendar.MILLISECOND, 0);
expectedEnd.set(Calendar.MILLISECOND, 0);
final ArrayList<Long> timestampSlots = new ArrayList<>();
timestampSlots.add(start.getTimeInMillis());
final List<Long> resultList =
DataProcessor.getTimestampSlots(timestampSlots, current.getTimeInMillis());
for (int index = 0; index < resultList.size(); index++) {
final long expectedTimestamp =
expectedStart.getTimeInMillis() + index * DateUtils.HOUR_IN_MILLIS;
assertThat(resultList.get(index)).isEqualTo(expectedTimestamp);
}
assertThat(resultList.get(resultList.size() - 1))
.isEqualTo(expectedEnd.getTimeInMillis());
}
private static void assertBatteryDiffEntry(
final BatteryDiffEntry entry, final long userId, final long uid,
final int consumerType, final double consumePercentage,
final double foregroundUsageConsumePower,
final double foregroundServiceUsageConsumePower,
final double backgroundUsageConsumePower, final double cachedUsageConsumePower,
final long foregroundUsageTimeInMs, final long backgroundUsageTimeInMs,
final long screenOnTimeInMs) {
assertThat(entry.mBatteryHistEntry.mUserId).isEqualTo(userId);
assertThat(entry.mBatteryHistEntry.mUid).isEqualTo(uid);
assertThat(entry.mBatteryHistEntry.mConsumerType).isEqualTo(consumerType);
assertThat(entry.getPercentOfTotal()).isEqualTo(consumePercentage);
assertThat(entry.mForegroundUsageConsumePower).isEqualTo(foregroundUsageConsumePower);
assertThat(entry.mForegroundServiceUsageConsumePower)
.isEqualTo(foregroundServiceUsageConsumePower);
assertThat(entry.mBackgroundUsageConsumePower).isEqualTo(backgroundUsageConsumePower);
assertThat(entry.mCachedUsageConsumePower).isEqualTo(cachedUsageConsumePower);
assertThat(entry.mForegroundUsageTimeInMs).isEqualTo(foregroundUsageTimeInMs);
assertThat(entry.mBackgroundUsageTimeInMs).isEqualTo(backgroundUsageTimeInMs);
assertThat(entry.mScreenOnTimeInMs).isEqualTo(screenOnTimeInMs);
}
}