Support multi-user privacy for battery usage chart

When there are multiple accounts in the devices, the battery usage list
is shared in the current design. We will aggregate other users usage
data into a single item to support multi-user privacy requirements

Screenshot: https://screenshot.googleplex.com/AkFTUtNvnoxcuGR

Bug: 202119550
Test: make RunSettingsRoboTests
Change-Id: I6cb55f0d50a4caca83212a0a54410530a032c089
This commit is contained in:
ykhung
2022-07-10 23:47:42 +08:00
parent 9447ec6d81
commit 764d513d00
7 changed files with 191 additions and 16 deletions

View File

@@ -70,6 +70,7 @@ import org.robolectric.annotation.Resetter;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
@RunWith(RobolectricTestRunner.class)
@@ -343,9 +344,17 @@ public final class BatteryBackupHelperTest {
private void verifyBackupData(String expectedResult) throws Exception {
final byte[] expectedBytes = expectedResult.getBytes();
final ArgumentCaptor<byte[]> captor = ArgumentCaptor.forClass(byte[].class);
final Set<String> expectedResultSet =
Set.of(expectedResult.split(BatteryBackupHelper.DELIMITER));
verify(mBackupDataOutput).writeEntityHeader(
BatteryBackupHelper.KEY_OPTIMIZATION_LIST, expectedBytes.length);
verify(mBackupDataOutput).writeEntityData(expectedBytes, expectedBytes.length);
verify(mBackupDataOutput).writeEntityData(captor.capture(), eq(expectedBytes.length));
final String actualResult = new String(captor.getValue());
final Set<String> actualResultSet =
Set.of(actualResult.split(BatteryBackupHelper.DELIMITER));
assertThat(actualResultSet).isEqualTo(expectedResultSet);
}
private void createTestingData(

View File

@@ -138,7 +138,7 @@ public final class BatteryDiffEntryTest {
// Generates fake testing data.
final ContentValues values = getContentValuesWithType(
ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
values.put("drainType",
values.put(BatteryHistEntry.KEY_DRAIN_TYPE,
Integer.valueOf(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY));
final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
@@ -164,7 +164,7 @@ public final class BatteryDiffEntryTest {
// Generates fake testing data.
final ContentValues values = getContentValuesWithType(
ConvertUtils.CONSUMER_TYPE_USER_BATTERY);
values.put("userId", Integer.valueOf(1001));
values.put(BatteryHistEntry.KEY_USER_ID, Integer.valueOf(1001));
final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry);
@@ -189,8 +189,8 @@ public final class BatteryDiffEntryTest {
final String fakePackageName = "com.fake.google.com";
final ContentValues values = getContentValuesWithType(
ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
values.put("uid", /*invalid uid*/ 10001);
values.put("packageName", fakePackageName);
values.put(BatteryHistEntry.KEY_UID, /*invalid uid*/ 10001);
values.put(BatteryHistEntry.KEY_PACKAGE_NAME, fakePackageName);
doReturn(mMockAppInfo).when(mMockPackageManager)
.getApplicationInfo(fakePackageName, 0);
doReturn(expectedAppLabel).when(mMockPackageManager)
@@ -233,7 +233,7 @@ public final class BatteryDiffEntryTest {
final String expectedAppLabel = "fake app label";
final ContentValues values = getContentValuesWithType(
ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
values.put("appLabel", expectedAppLabel);
values.put(BatteryHistEntry.KEY_APP_LABEL, expectedAppLabel);
final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry);
@@ -391,8 +391,8 @@ public final class BatteryDiffEntryTest {
final String fakePackageName = "com.fake.google.com";
final ContentValues values = getContentValuesWithType(
ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
values.put("uid", /*invalid uid*/ 10001);
values.put("packageName", fakePackageName);
values.put(BatteryHistEntry.KEY_UID, /*invalid uid*/ 10001);
values.put(BatteryHistEntry.KEY_PACKAGE_NAME, fakePackageName);
final BatteryDiffEntry entry =
createBatteryDiffEntry(10, new BatteryHistEntry(values));
@@ -424,7 +424,7 @@ public final class BatteryDiffEntryTest {
final String expectedPackageName = "com.fake.google.com";
final ContentValues values = getContentValuesWithType(
ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
values.put("packageName", expectedPackageName);
values.put(BatteryHistEntry.KEY_PACKAGE_NAME, expectedPackageName);
final BatteryDiffEntry entry =
createBatteryDiffEntry(10, new BatteryHistEntry(values));
@@ -437,7 +437,7 @@ public final class BatteryDiffEntryTest {
final ContentValues values = getContentValuesWithType(
ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
values.put(
"packageName",
BatteryHistEntry.KEY_PACKAGE_NAME,
expectedPackageName + ":privileged_process0");
final BatteryDiffEntry entry =
createBatteryDiffEntry(10, new BatteryHistEntry(values));
@@ -445,11 +445,24 @@ public final class BatteryDiffEntryTest {
assertThat(entry.getPackageName()).isEqualTo(expectedPackageName);
}
@Test
public void getAppLabel_withOtherUsersUid_returnExpectedLabel() {
final ContentValues values = getContentValuesWithType(
ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
values.put(BatteryHistEntry.KEY_UID, BatteryUtils.UID_OTHER_USERS);
final BatteryDiffEntry batteryDiffEntry = createBatteryDiffEntry(
/*consumePower=*/ 0, new BatteryHistEntry(values));
assertThat(batteryDiffEntry.getAppLabel())
.isEqualTo(mContext.getString(R.string.battery_usage_other_users));
}
private BatteryDiffEntry createBatteryDiffEntry(
int consumerType, long uid, boolean isHidden) {
final ContentValues values = getContentValuesWithType(consumerType);
values.put("isHidden", isHidden);
values.put("uid", uid);
values.put(BatteryHistEntry.KEY_IS_HIDDEN, isHidden);
values.put(BatteryHistEntry.KEY_UID, uid);
return new BatteryDiffEntry(
mContext,
/*foregroundUsageTimeInMs=*/ 0,
@@ -472,15 +485,15 @@ public final class BatteryDiffEntryTest {
private static ContentValues getContentValuesWithType(int consumerType) {
final ContentValues values = new ContentValues();
values.put("consumerType", Integer.valueOf(consumerType));
values.put(BatteryHistEntry.KEY_CONSUMER_TYPE, Integer.valueOf(consumerType));
return values;
}
private BatteryDiffEntry createBatteryDiffEntry(Drawable drawable) throws Exception {
final ContentValues values = getContentValuesWithType(
ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
values.put("uid", 1001);
values.put("packageName", "com.a.b.c");
values.put(BatteryHistEntry.KEY_UID, 1001);
values.put(BatteryHistEntry.KEY_PACKAGE_NAME, "com.a.b.c");
final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
doReturn(drawable).when(mMockPackageManager).getDefaultActivityIcon();
doReturn(null).when(mMockPackageManager).getApplicationInfo("com.a.b.c", 0);

View File

@@ -27,6 +27,7 @@ import android.os.BatteryUsageStats;
import android.os.LocaleList;
import android.os.UserHandle;
import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.fuelgauge.PowerUsageFeatureProvider;
import com.android.settings.testutils.FakeFeatureFactory;
@@ -39,6 +40,7 @@ import org.robolectric.RobolectricTestRunner;
import org.robolectric.RuntimeEnvironment;
import java.util.Arrays;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
@@ -371,6 +373,71 @@ public final class ConvertUtilsTest {
assertThat(ConvertUtils.getLocale(mContext)).isEqualTo(Locale.getDefault());
}
@Test
public void resolveMultiUsersData_replaceOtherUsersItemWithExpectedEntry() {
final int currentUserId = mContext.getUserId();
final Map<Integer, List<BatteryDiffEntry>> entryMap = new HashMap<>();
// Without other users time slot.
entryMap.put(0, Arrays.asList(
createBatteryDiffEntry(
currentUserId,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY,
/*consumePercentage=*/ 50)));
// With other users time slot.
final List<BatteryDiffEntry> withOtherUsersList = new ArrayList<>();
entryMap.put(1, withOtherUsersList);
withOtherUsersList.add(
createBatteryDiffEntry(
currentUserId + 1,
ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY,
/*consumePercentage=*/ 20));
withOtherUsersList.add(
createBatteryDiffEntry(
currentUserId + 2,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY,
/*consumePercentage=*/ 30));
withOtherUsersList.add(
createBatteryDiffEntry(
currentUserId + 3,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY,
/*consumePercentage=*/ 40));
ConvertUtils.resolveMultiUsersData(mContext, entryMap);
assertThat(entryMap.get(0).get(0).getPercentOfTotal()).isEqualTo(50);
// Asserts with other users items.
final List<BatteryDiffEntry> entryList = entryMap.get(1);
assertThat(entryList).hasSize(2);
assertBatteryDiffEntry(
entryList.get(0),
currentUserId + 1,
/*uid=*/ 0,
ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY,
/*consumePercentage=*/ 20);
assertBatteryDiffEntry(
entryList.get(1),
BatteryUtils.UID_OTHER_USERS,
BatteryUtils.UID_OTHER_USERS,
ConvertUtils.CONSUMER_TYPE_UID_BATTERY,
/*consumePercentage=*/ 70);
}
private BatteryDiffEntry createBatteryDiffEntry(
long userId, int counsumerType, double consumePercentage) {
final ContentValues values = new ContentValues();
values.put(BatteryHistEntry.KEY_USER_ID, userId);
values.put(BatteryHistEntry.KEY_CONSUMER_TYPE, counsumerType);
final BatteryDiffEntry batteryDiffEntry =
new BatteryDiffEntry(
mContext,
/*foregroundUsageTimeInMs=*/ 0,
/*backgroundUsageTimeInMs=*/ 0,
/*consumePower=*/ consumePercentage,
new BatteryHistEntry(values));
batteryDiffEntry.setTotalConsumePower(100f);
return batteryDiffEntry;
}
private static BatteryHistEntry createBatteryHistEntry(
String packageName, String appLabel, double consumePower,
long uid, long foregroundUsageTimeInMs, long backgroundUsageTimeInMs) {
@@ -389,6 +456,15 @@ public final class ConvertUtilsTest {
return new BatteryHistEntry(values);
}
private static void assertBatteryDiffEntry(
BatteryDiffEntry entry, long userId, long uid, int counsumerType,
double consumePercentage) {
assertThat(entry.mBatteryHistEntry.mUid).isEqualTo(uid);
assertThat(entry.mBatteryHistEntry.mUserId).isEqualTo(userId);
assertThat(entry.mBatteryHistEntry.mConsumerType).isEqualTo(counsumerType);
assertThat(entry.getPercentOfTotal()).isEqualTo(consumePercentage);
}
private static void assertBatteryDiffEntry(
BatteryDiffEntry entry, int percentOfTotal,
long foregroundUsageTimeInMs, long backgroundUsageTimeInMs) {