Database restructure: use protobuf to save battery information fields.

This patch only updates the existing fields.
There will be 2 following patches to:
1. Expose the new fields (foreground / foreground service / background x
   usage time / power consumption) to UI.
2. Get the full charge cycle start time from Database and remove the
   SharedPreference.

Test: make RunSettingsRoboTests + manual
Bug: 253553141
Change-Id: Iee02dc7e671f97899cb1495323acfa0173e31df2
This commit is contained in:
Kuan Wang
2022-11-09 16:24:23 +08:00
parent 45c9b11655
commit 1493fa2fea
19 changed files with 528 additions and 513 deletions

View File

@@ -80,6 +80,7 @@ android_library {
"settings-log-bridge-protos-lite", "settings-log-bridge-protos-lite",
"settings-telephony-protos-lite", "settings-telephony-protos-lite",
"fuelgauge-log-protos-lite", "fuelgauge-log-protos-lite",
"fuelgauge-usage-state-protos-lite",
"contextualcards", "contextualcards",
"settings-logtags", "settings-logtags",
"statslog-settings", "statslog-settings",

View File

@@ -41,3 +41,11 @@ java_library {
}, },
srcs: ["fuelgauge_log.proto"], srcs: ["fuelgauge_log.proto"],
} }
java_library {
name: "fuelgauge-usage-state-protos-lite",
proto: {
type: "lite",
},
srcs: ["fuelgauge_usage_state.proto"],
}

View File

@@ -0,0 +1,41 @@
syntax = "proto2";
package com.android.settings.intelligence;
option java_multiple_files = true;
option java_package = "com.android.settings.fuelgauge.batteryusage";
option java_outer_classname = "FuelgaugeUsageStateProto";
// Stores device battery relative information.
message DeviceBatteryState {
optional int32 battery_level = 1;
optional int32 battery_status = 2;
optional int32 battery_health = 3;
}
message BatteryInformation {
// Records device battery relative information.
optional DeviceBatteryState device_battery_state = 1;
// Whether the data is represented as a system component or not?
optional bool is_hidden = 2;
// Records the timestamp relative information.
optional int64 boot_timestamp = 3;
optional string zone_id = 4;
// Records app relative information.
optional string app_label = 7;
// Records the battery usage relative information.
optional double total_power = 10;
optional double consume_power = 11;
optional double percent_of_total = 12;
optional int32 drain_type = 13;
optional int64 foreground_usage_time_in_ms = 14;
optional int64 foreground_service_usage_time_in_ms = 15;
optional int64 background_usage_time_in_ms = 16;
optional double foreground_usage_consume_power = 17;
optional double foreground_service_usage_consume_power = 18;
optional double background_usage_consume_power = 19;
optional double cached_usage_consume_power = 20;
}

View File

@@ -19,13 +19,10 @@ package com.android.settings.fuelgauge;
import android.content.Context; import android.content.Context;
import android.content.SharedPreferences; import android.content.SharedPreferences;
import android.util.Base64; import android.util.Base64;
import android.util.Log;
import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action; import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.MessageLite;
import java.io.PrintWriter; import java.io.PrintWriter;
import java.util.List; import java.util.List;
@@ -76,22 +73,8 @@ public final class BatteryHistoricalLogUtil {
} }
private static BatteryOptimizeHistoricalLog parseLogFromString(String storedLogs) { private static BatteryOptimizeHistoricalLog parseLogFromString(String storedLogs) {
return parseProtoFromString(storedLogs, BatteryOptimizeHistoricalLog.getDefaultInstance()); return BatteryUtils.parseProtoFromString(
} storedLogs, BatteryOptimizeHistoricalLog.getDefaultInstance());
@SuppressWarnings("unchecked")
private static <T extends MessageLite> T parseProtoFromString(
String serializedProto, T protoClass) {
if (serializedProto.isEmpty()) {
return (T) protoClass.getDefaultInstanceForType();
}
try {
return (T) protoClass.getParserForType()
.parseFrom(Base64.decode(serializedProto, Base64.DEFAULT));
} catch (InvalidProtocolBufferException e) {
Log.e(TAG, "Failed to deserialize proto class", e);
return (T) protoClass.getDefaultInstanceForType();
}
} }
/** /**

View File

@@ -32,6 +32,7 @@ import android.os.Process;
import android.os.SystemClock; import android.os.SystemClock;
import android.os.UidBatteryConsumer; import android.os.UidBatteryConsumer;
import android.os.UserHandle; import android.os.UserHandle;
import android.util.Base64;
import android.util.Log; import android.util.Log;
import androidx.annotation.IntDef; import androidx.annotation.IntDef;
@@ -52,6 +53,9 @@ import com.android.settingslib.fuelgauge.PowerAllowlistBackend;
import com.android.settingslib.utils.PowerUtil; import com.android.settingslib.utils.PowerUtil;
import com.android.settingslib.utils.ThreadUtils; import com.android.settingslib.utils.ThreadUtils;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.MessageLite;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.time.Duration; import java.time.Duration;
@@ -316,6 +320,28 @@ public class BatteryUtils {
} }
} }
/**
* Parses proto object from string.
*
* @param serializedProto the serialized proto string
* @param protoClass class of the proto
* @return instance of the proto class parsed from the string
*/
@SuppressWarnings("unchecked")
public static <T extends MessageLite> T parseProtoFromString(
String serializedProto, T protoClass) {
if (serializedProto.isEmpty()) {
return (T) protoClass.getDefaultInstanceForType();
}
try {
return (T) protoClass.getParserForType()
.parseFrom(Base64.decode(serializedProto, Base64.DEFAULT));
} catch (InvalidProtocolBufferException e) {
Log.e(TAG, "Failed to deserialize proto class", e);
return (T) protoClass.getDefaultInstanceForType();
}
}
public void setForceAppStandby(int uid, String packageName, public void setForceAppStandby(int uid, String packageName,
int mode) { int mode) {
final boolean isPreOApp = isPreOApp(packageName); final boolean isPreOApp = isPreOApp(packageName);

View File

@@ -30,23 +30,12 @@ public class BatteryHistEntry {
/** Keys for accessing {@link ContentValues} or {@link Cursor}. */ /** Keys for accessing {@link ContentValues} or {@link Cursor}. */
public static final String KEY_UID = "uid"; public static final String KEY_UID = "uid";
public static final String KEY_USER_ID = "userId"; public static final String KEY_USER_ID = "userId";
public static final String KEY_APP_LABEL = "appLabel";
public static final String KEY_PACKAGE_NAME = "packageName"; public static final String KEY_PACKAGE_NAME = "packageName";
public static final String KEY_IS_HIDDEN = "isHidden";
// Device booting elapsed time from SystemClock.elapsedRealtime().
public static final String KEY_BOOT_TIMESTAMP = "bootTimestamp";
public static final String KEY_TIMESTAMP = "timestamp"; public static final String KEY_TIMESTAMP = "timestamp";
public static final String KEY_ZONE_ID = "zoneId";
public static final String KEY_TOTAL_POWER = "totalPower";
public static final String KEY_CONSUME_POWER = "consumePower";
public static final String KEY_PERCENT_OF_TOTAL = "percentOfTotal";
public static final String KEY_FOREGROUND_USAGE_TIME = "foregroundUsageTimeInMs";
public static final String KEY_BACKGROUND_USAGE_TIME = "backgroundUsageTimeInMs";
public static final String KEY_DRAIN_TYPE = "drainType";
public static final String KEY_CONSUMER_TYPE = "consumerType"; public static final String KEY_CONSUMER_TYPE = "consumerType";
public static final String KEY_BATTERY_LEVEL = "batteryLevel"; public static final String KEY_IS_FULL_CHARGE_CYCLE_START = "isFullChargeCycleStart";
public static final String KEY_BATTERY_STATUS = "batteryStatus"; public static final String KEY_BATTERY_INFORMATION = "batteryInformation";
public static final String KEY_BATTERY_HEALTH = "batteryHealth"; public static final String KEY_BATTERY_INFORMATION_DEBUG = "batteryInformationDebug";
public final long mUid; public final long mUid;
public final long mUserId; public final long mUserId;
@@ -79,43 +68,49 @@ public class BatteryHistEntry {
public BatteryHistEntry(ContentValues values) { public BatteryHistEntry(ContentValues values) {
mUid = getLong(values, KEY_UID); mUid = getLong(values, KEY_UID);
mUserId = getLong(values, KEY_USER_ID); mUserId = getLong(values, KEY_USER_ID);
mAppLabel = getString(values, KEY_APP_LABEL);
mPackageName = getString(values, KEY_PACKAGE_NAME); mPackageName = getString(values, KEY_PACKAGE_NAME);
mIsHidden = getBoolean(values, KEY_IS_HIDDEN);
mBootTimestamp = getLong(values, KEY_BOOT_TIMESTAMP);
mTimestamp = getLong(values, KEY_TIMESTAMP); mTimestamp = getLong(values, KEY_TIMESTAMP);
mZoneId = getString(values, KEY_ZONE_ID);
mTotalPower = getDouble(values, KEY_TOTAL_POWER);
mConsumePower = getDouble(values, KEY_CONSUME_POWER);
mPercentOfTotal = getDouble(values, KEY_PERCENT_OF_TOTAL);
mForegroundUsageTimeInMs = getLong(values, KEY_FOREGROUND_USAGE_TIME);
mBackgroundUsageTimeInMs = getLong(values, KEY_BACKGROUND_USAGE_TIME);
mDrainType = getInteger(values, KEY_DRAIN_TYPE);
mConsumerType = getInteger(values, KEY_CONSUMER_TYPE); mConsumerType = getInteger(values, KEY_CONSUMER_TYPE);
mBatteryLevel = getInteger(values, KEY_BATTERY_LEVEL); final BatteryInformation batteryInformation =
mBatteryStatus = getInteger(values, KEY_BATTERY_STATUS); ConvertUtils.getBatteryInformation(values, KEY_BATTERY_INFORMATION);
mBatteryHealth = getInteger(values, KEY_BATTERY_HEALTH); mAppLabel = batteryInformation.getAppLabel();
mIsHidden = batteryInformation.getIsHidden();
mBootTimestamp = batteryInformation.getBootTimestamp();
mZoneId = batteryInformation.getZoneId();
mTotalPower = batteryInformation.getTotalPower();
mConsumePower = batteryInformation.getConsumePower();
mPercentOfTotal = batteryInformation.getPercentOfTotal();
mForegroundUsageTimeInMs = batteryInformation.getForegroundUsageTimeInMs();
mBackgroundUsageTimeInMs = batteryInformation.getBackgroundUsageTimeInMs();
mDrainType = batteryInformation.getDrainType();
final DeviceBatteryState deviceBatteryState = batteryInformation.getDeviceBatteryState();
mBatteryLevel = deviceBatteryState.getBatteryLevel();
mBatteryStatus = deviceBatteryState.getBatteryStatus();
mBatteryHealth = deviceBatteryState.getBatteryHealth();
} }
public BatteryHistEntry(Cursor cursor) { public BatteryHistEntry(Cursor cursor) {
mUid = getLong(cursor, KEY_UID); mUid = getLong(cursor, KEY_UID);
mUserId = getLong(cursor, KEY_USER_ID); mUserId = getLong(cursor, KEY_USER_ID);
mAppLabel = getString(cursor, KEY_APP_LABEL);
mPackageName = getString(cursor, KEY_PACKAGE_NAME); mPackageName = getString(cursor, KEY_PACKAGE_NAME);
mIsHidden = getBoolean(cursor, KEY_IS_HIDDEN);
mBootTimestamp = getLong(cursor, KEY_BOOT_TIMESTAMP);
mTimestamp = getLong(cursor, KEY_TIMESTAMP); mTimestamp = getLong(cursor, KEY_TIMESTAMP);
mZoneId = getString(cursor, KEY_ZONE_ID);
mTotalPower = getDouble(cursor, KEY_TOTAL_POWER);
mConsumePower = getDouble(cursor, KEY_CONSUME_POWER);
mPercentOfTotal = getDouble(cursor, KEY_PERCENT_OF_TOTAL);
mForegroundUsageTimeInMs = getLong(cursor, KEY_FOREGROUND_USAGE_TIME);
mBackgroundUsageTimeInMs = getLong(cursor, KEY_BACKGROUND_USAGE_TIME);
mDrainType = getInteger(cursor, KEY_DRAIN_TYPE);
mConsumerType = getInteger(cursor, KEY_CONSUMER_TYPE); mConsumerType = getInteger(cursor, KEY_CONSUMER_TYPE);
mBatteryLevel = getInteger(cursor, KEY_BATTERY_LEVEL); final BatteryInformation batteryInformation =
mBatteryStatus = getInteger(cursor, KEY_BATTERY_STATUS); ConvertUtils.getBatteryInformation(cursor, KEY_BATTERY_INFORMATION);
mBatteryHealth = getInteger(cursor, KEY_BATTERY_HEALTH); mAppLabel = batteryInformation.getAppLabel();
mIsHidden = batteryInformation.getIsHidden();
mBootTimestamp = batteryInformation.getBootTimestamp();
mZoneId = batteryInformation.getZoneId();
mTotalPower = batteryInformation.getTotalPower();
mConsumePower = batteryInformation.getConsumePower();
mPercentOfTotal = batteryInformation.getPercentOfTotal();
mForegroundUsageTimeInMs = batteryInformation.getForegroundUsageTimeInMs();
mBackgroundUsageTimeInMs = batteryInformation.getBackgroundUsageTimeInMs();
mDrainType = batteryInformation.getDrainType();
final DeviceBatteryState deviceBatteryState = batteryInformation.getDeviceBatteryState();
mBatteryLevel = deviceBatteryState.getBatteryLevel();
mBatteryStatus = deviceBatteryState.getBatteryStatus();
mBatteryHealth = deviceBatteryState.getBatteryHealth();
} }
private BatteryHistEntry( private BatteryHistEntry(
@@ -240,23 +235,6 @@ public class BatteryHistEntry {
return 0L; return 0L;
} }
private double getDouble(ContentValues values, String key) {
if (values != null && values.containsKey(key)) {
return values.getAsDouble(key);
}
mIsValidEntry = false;
return 0f;
}
private double getDouble(Cursor cursor, String key) {
final int columnIndex = cursor.getColumnIndex(key);
if (columnIndex >= 0) {
return cursor.getDouble(columnIndex);
}
mIsValidEntry = false;
return 0f;
}
private String getString(ContentValues values, String key) { private String getString(ContentValues values, String key) {
if (values != null && values.containsKey(key)) { if (values != null && values.containsKey(key)) {
return values.getAsString(key); return values.getAsString(key);
@@ -274,24 +252,6 @@ public class BatteryHistEntry {
return null; return null;
} }
private boolean getBoolean(ContentValues values, String key) {
if (values != null && values.containsKey(key)) {
return values.getAsBoolean(key);
}
mIsValidEntry = false;
return false;
}
private boolean getBoolean(Cursor cursor, String key) {
final int columnIndex = cursor.getColumnIndex(key);
if (columnIndex >= 0) {
// Use value == 1 to represent boolean value in the database.
return cursor.getInt(columnIndex) == 1;
}
mIsValidEntry = false;
return false;
}
/** Creates new {@link BatteryHistEntry} from interpolation. */ /** Creates new {@link BatteryHistEntry} from interpolation. */
public static BatteryHistEntry interpolate( public static BatteryHistEntry interpolate(
long slotTimestamp, long slotTimestamp,
@@ -315,7 +275,7 @@ public class BatteryHistEntry {
lowerHistEntry == null ? 0 : lowerHistEntry.mBackgroundUsageTimeInMs, lowerHistEntry == null ? 0 : lowerHistEntry.mBackgroundUsageTimeInMs,
upperHistEntry.mBackgroundUsageTimeInMs, upperHistEntry.mBackgroundUsageTimeInMs,
ratio); ratio);
// Checks whether there is any abnoaml cases! // Checks whether there is any abnormal cases!
if (upperHistEntry.mConsumePower < consumePower if (upperHistEntry.mConsumePower < consumePower
|| upperHistEntry.mForegroundUsageTimeInMs < foregroundUsageTimeInMs || upperHistEntry.mForegroundUsageTimeInMs < foregroundUsageTimeInMs
|| upperHistEntry.mBackgroundUsageTimeInMs < backgroundUsageTimeInMs) { || upperHistEntry.mBackgroundUsageTimeInMs < backgroundUsageTimeInMs) {

View File

@@ -18,13 +18,16 @@ package com.android.settings.fuelgauge.batteryusage;
import android.annotation.IntDef; import android.annotation.IntDef;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Context; import android.content.Context;
import android.database.Cursor;
import android.os.BatteryUsageStats; import android.os.BatteryUsageStats;
import android.os.Build;
import android.os.LocaleList; import android.os.LocaleList;
import android.os.UserHandle; import android.os.UserHandle;
import android.os.UserManager; import android.os.UserManager;
import android.text.format.DateFormat; import android.text.format.DateFormat;
import android.text.format.DateUtils; import android.text.format.DateUtils;
import android.util.ArraySet; import android.util.ArraySet;
import android.util.Base64;
import android.util.Log; import android.util.Log;
import androidx.annotation.VisibleForTesting; import androidx.annotation.VisibleForTesting;
@@ -83,48 +86,71 @@ public final class ConvertUtils {
/** Converts to content values */ /** Converts to content values */
public static ContentValues convertToContentValues( public static ContentValues convertToContentValues(
BatteryEntry entry, final BatteryEntry entry,
BatteryUsageStats batteryUsageStats, final BatteryUsageStats batteryUsageStats,
int batteryLevel, final int batteryLevel,
int batteryStatus, final int batteryStatus,
int batteryHealth, final int batteryHealth,
long bootTimestamp, final long bootTimestamp,
long timestamp) { final long timestamp) {
final ContentValues values = new ContentValues(); final ContentValues values = new ContentValues();
if (entry != null && batteryUsageStats != null) { if (entry != null && batteryUsageStats != null) {
values.put(BatteryHistEntry.KEY_UID, Long.valueOf(entry.getUid())); values.put(BatteryHistEntry.KEY_UID, Long.valueOf(entry.getUid()));
values.put(BatteryHistEntry.KEY_USER_ID, values.put(BatteryHistEntry.KEY_USER_ID,
Long.valueOf(UserHandle.getUserId(entry.getUid()))); Long.valueOf(UserHandle.getUserId(entry.getUid())));
values.put(BatteryHistEntry.KEY_APP_LABEL, entry.getLabel());
values.put(BatteryHistEntry.KEY_PACKAGE_NAME, values.put(BatteryHistEntry.KEY_PACKAGE_NAME,
entry.getDefaultPackageName()); entry.getDefaultPackageName());
values.put(BatteryHistEntry.KEY_IS_HIDDEN, Boolean.valueOf(entry.isHidden()));
values.put(BatteryHistEntry.KEY_TOTAL_POWER,
Double.valueOf(batteryUsageStats.getConsumedPower()));
values.put(BatteryHistEntry.KEY_CONSUME_POWER,
Double.valueOf(entry.getConsumedPower()));
values.put(BatteryHistEntry.KEY_PERCENT_OF_TOTAL,
Double.valueOf(entry.mPercent));
values.put(BatteryHistEntry.KEY_FOREGROUND_USAGE_TIME,
Long.valueOf(entry.getTimeInForegroundMs()));
values.put(BatteryHistEntry.KEY_BACKGROUND_USAGE_TIME,
Long.valueOf(entry.getTimeInBackgroundMs()));
values.put(BatteryHistEntry.KEY_DRAIN_TYPE,
Integer.valueOf(entry.getPowerComponentId()));
values.put(BatteryHistEntry.KEY_CONSUMER_TYPE, values.put(BatteryHistEntry.KEY_CONSUMER_TYPE,
Integer.valueOf(entry.getConsumerType())); Integer.valueOf(entry.getConsumerType()));
} else { } else {
values.put(BatteryHistEntry.KEY_PACKAGE_NAME, FAKE_PACKAGE_NAME); values.put(BatteryHistEntry.KEY_PACKAGE_NAME, FAKE_PACKAGE_NAME);
} }
values.put(BatteryHistEntry.KEY_BOOT_TIMESTAMP, Long.valueOf(bootTimestamp));
values.put(BatteryHistEntry.KEY_TIMESTAMP, Long.valueOf(timestamp)); values.put(BatteryHistEntry.KEY_TIMESTAMP, Long.valueOf(timestamp));
values.put(BatteryHistEntry.KEY_ZONE_ID, TimeZone.getDefault().getID()); final BatteryInformation batteryInformation =
values.put(BatteryHistEntry.KEY_BATTERY_LEVEL, Integer.valueOf(batteryLevel)); constructBatteryInformation(
values.put(BatteryHistEntry.KEY_BATTERY_STATUS, Integer.valueOf(batteryStatus)); entry,
values.put(BatteryHistEntry.KEY_BATTERY_HEALTH, Integer.valueOf(batteryHealth)); batteryUsageStats,
batteryLevel,
batteryStatus,
batteryHealth,
bootTimestamp);
values.put(BatteryHistEntry.KEY_BATTERY_INFORMATION,
convertBatteryInformationToString(batteryInformation));
// Save the BatteryInformation unencoded string into database for debugging.
if (Build.TYPE.equals("userdebug")) {
values.put(
BatteryHistEntry.KEY_BATTERY_INFORMATION_DEBUG, batteryInformation.toString());
}
return values; return values;
} }
/** Gets the encoded string from {@link BatteryInformation} instance. */
public static String convertBatteryInformationToString(
final BatteryInformation batteryInformation) {
return Base64.encodeToString(batteryInformation.toByteArray(), Base64.DEFAULT);
}
/** Gets the {@link BatteryInformation} instance from {@link ContentValues}. */
public static BatteryInformation getBatteryInformation(
final ContentValues values, final String key) {
final BatteryInformation defaultInstance = BatteryInformation.getDefaultInstance();
if (values != null && values.containsKey(key)) {
return BatteryUtils.parseProtoFromString(values.getAsString(key), defaultInstance);
}
return defaultInstance;
}
/** Gets the {@link BatteryInformation} instance from {@link Cursor}. */
public static BatteryInformation getBatteryInformation(final Cursor cursor, final String key) {
final BatteryInformation defaultInstance = BatteryInformation.getDefaultInstance();
final int columnIndex = cursor.getColumnIndex(key);
if (columnIndex >= 0) {
return BatteryUtils.parseProtoFromString(
cursor.getString(columnIndex), defaultInstance);
}
return defaultInstance;
}
/** Converts to {@link BatteryHistEntry} */ /** Converts to {@link BatteryHistEntry} */
public static BatteryHistEntry convertToBatteryHistEntry( public static BatteryHistEntry convertToBatteryHistEntry(
BatteryEntry entry, BatteryEntry entry,
@@ -331,6 +357,41 @@ public final class ConvertUtils {
} }
} }
private static BatteryInformation constructBatteryInformation(
final BatteryEntry entry,
final BatteryUsageStats batteryUsageStats,
final int batteryLevel,
final int batteryStatus,
final int batteryHealth,
final long bootTimestamp) {
final DeviceBatteryState deviceBatteryState =
DeviceBatteryState
.newBuilder()
.setBatteryLevel(batteryLevel)
.setBatteryStatus(batteryStatus)
.setBatteryHealth(batteryHealth)
.build();
final BatteryInformation.Builder batteryInformationBuilder =
BatteryInformation
.newBuilder()
.setDeviceBatteryState(deviceBatteryState)
.setBootTimestamp(bootTimestamp)
.setZoneId(TimeZone.getDefault().getID());
if (entry != null && batteryUsageStats != null) {
batteryInformationBuilder
.setIsHidden(entry.isHidden())
.setAppLabel(entry.getLabel() != null ? entry.getLabel() : "")
.setTotalPower(batteryUsageStats.getConsumedPower())
.setConsumePower(entry.getConsumedPower())
.setPercentOfTotal(entry.mPercent)
.setDrainType(entry.getPowerComponentId())
.setForegroundUsageTimeInMs(entry.getTimeInForegroundMs())
.setBackgroundUsageTimeInMs(entry.getTimeInBackgroundMs());
}
return batteryInformationBuilder.build();
}
private static void insert24HoursData( private static void insert24HoursData(
final int desiredIndex, final int desiredIndex,
final Map<Integer, List<BatteryDiffEntry>> indexedUsageMap) { final Map<Integer, List<BatteryDiffEntry>> indexedUsageMap) {

View File

@@ -17,16 +17,16 @@
package com.android.settings.fuelgauge.batteryusage.db; package com.android.settings.fuelgauge.batteryusage.db;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.Intent;
import android.os.BatteryManager;
import androidx.room.Entity; import androidx.room.Entity;
import androidx.room.PrimaryKey; import androidx.room.PrimaryKey;
import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.fuelgauge.batteryusage.BatteryInformation;
import com.google.errorprone.annotations.CanIgnoreReturnValue; import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.Date; import java.util.Date;
import java.util.Locale; import java.util.Locale;
import java.util.TimeZone; import java.util.TimeZone;
@@ -43,68 +43,41 @@ public class BatteryState {
// Records the app relative information. // Records the app relative information.
public final long uid; public final long uid;
public final long userId; public final long userId;
public final String appLabel;
public final String packageName; public final String packageName;
// Whether the data is represented as system component or not?
public final boolean isHidden;
// Records the timestamp relative information.
public final long bootTimestamp;
public final long timestamp; public final long timestamp;
public final String zoneId;
// Records the battery usage relative information.
public final double totalPower;
public final double consumePower;
public final double percentOfTotal;
public final long foregroundUsageTimeInMs;
public final long backgroundUsageTimeInMs;
public final int drainType;
public final int consumerType; public final int consumerType;
// Records the battery intent relative information. public final boolean isFullChargeCycleStart;
public final int batteryLevel; public final String batteryInformation;
public final int batteryStatus; /**
public final int batteryHealth; * This field is filled only when build type is "userdebug".
* For now, Java Proto Lite is recommended by the Android team as the more lightweight solution
* designed specifically for mobile apps to process protobuf.
* However, converting protobuf to string through Java Proto Lite needs to parse it into a bytes
* field first, which leads to the strings saved in our database are encoded and hard to
* understand.
* To make it easier to debug in our daily development, this field is added.
* It will not be filled for the real users.
*/
public final String batteryInformationDebug;
public BatteryState( public BatteryState(
long uid, long uid,
long userId, long userId,
String appLabel,
String packageName, String packageName,
boolean isHidden,
long bootTimestamp,
long timestamp, long timestamp,
String zoneId,
double totalPower,
double consumePower,
double percentOfTotal,
long foregroundUsageTimeInMs,
long backgroundUsageTimeInMs,
int drainType,
int consumerType, int consumerType,
int batteryLevel, boolean isFullChargeCycleStart,
int batteryStatus, String batteryInformation,
int batteryHealth) { String batteryInformationDebug) {
// Records the app relative information. // Records the app relative information.
this.uid = uid; this.uid = uid;
this.userId = userId; this.userId = userId;
this.appLabel = appLabel;
this.packageName = packageName; this.packageName = packageName;
this.isHidden = isHidden;
// Records the timestamp relative information.
this.bootTimestamp = bootTimestamp;
this.timestamp = timestamp; this.timestamp = timestamp;
this.zoneId = zoneId;
// Records the battery usage relative information.
this.totalPower = totalPower;
this.consumePower = consumePower;
this.percentOfTotal = percentOfTotal;
this.foregroundUsageTimeInMs = foregroundUsageTimeInMs;
this.backgroundUsageTimeInMs = backgroundUsageTimeInMs;
this.drainType = drainType;
this.consumerType = consumerType; this.consumerType = consumerType;
// Records the battery intent relative information. this.isFullChargeCycleStart = isFullChargeCycleStart;
this.batteryLevel = batteryLevel; this.batteryInformation = batteryInformation;
this.batteryStatus = batteryStatus; this.batteryInformationDebug = batteryInformationDebug;
this.batteryHealth = batteryHealth;
} }
/** Sets the auto-generated content ID. */ /** Sets the auto-generated content ID. */
@@ -126,22 +99,17 @@ public class BatteryState {
sCacheSimpleDateFormat = new SimpleDateFormat("MMM dd,yyyy HH:mm:ss", Locale.US); sCacheSimpleDateFormat = new SimpleDateFormat("MMM dd,yyyy HH:mm:ss", Locale.US);
} }
final String recordAtDateTime = sCacheSimpleDateFormat.format(new Date(timestamp)); final String recordAtDateTime = sCacheSimpleDateFormat.format(new Date(timestamp));
final BatteryInformation batteryInformationInstance =
BatteryUtils.parseProtoFromString(
batteryInformation, BatteryInformation.getDefaultInstance());
final StringBuilder builder = new StringBuilder() final StringBuilder builder = new StringBuilder()
.append("\nBatteryState{") .append("\nBatteryState{")
.append(String.format(Locale.US, .append(String.format(Locale.US,
"\n\tpackage=%s|label=%s|uid=%d|userId=%d|isHidden=%b", "\n\tpackage=%s|uid=%d|userId=%d", packageName, uid, userId))
packageName, appLabel, uid, userId, isHidden)) .append(String.format(Locale.US, "\n\ttimestamp=%s|consumer=%d|isStart=%b",
.append(String.format(Locale.US, "\n\ttimestamp=%s|zoneId=%s|bootTimestamp=%d", recordAtDateTime, consumerType, isFullChargeCycleStart))
recordAtDateTime, zoneId, Duration.ofMillis(bootTimestamp).getSeconds())) .append(String.format(Locale.US, "\n\tbatteryInfo="))
.append(String.format(Locale.US, .append(batteryInformationInstance.toString());
"\n\tusage=%f|total=%f|consume=%f|elapsedTime=%d|%d",
percentOfTotal, totalPower, consumePower,
Duration.ofMillis(foregroundUsageTimeInMs).getSeconds(),
Duration.ofMillis(backgroundUsageTimeInMs).getSeconds()))
.append(String.format(Locale.US,
"\n\tdrain=%d|consumer=%d", drainType, consumerType))
.append(String.format(Locale.US, "\n\tbattery=%d|status=%d|health=%d\n}",
batteryLevel, batteryStatus, batteryHealth));
return builder.toString(); return builder.toString();
} }
@@ -155,52 +123,25 @@ public class BatteryState {
if (contentValues.containsKey("userId")) { if (contentValues.containsKey("userId")) {
builder.setUserId(contentValues.getAsLong("userId")); builder.setUserId(contentValues.getAsLong("userId"));
} }
if (contentValues.containsKey("appLabel")) {
builder.setAppLabel(contentValues.getAsString("appLabel"));
}
if (contentValues.containsKey("packageName")) { if (contentValues.containsKey("packageName")) {
builder.setPackageName(contentValues.getAsString("packageName")); builder.setPackageName(contentValues.getAsString("packageName"));
} }
if (contentValues.containsKey("isHidden")) {
builder.setIsHidden(contentValues.getAsBoolean("isHidden"));
}
if (contentValues.containsKey("bootTimestamp")) {
builder.setBootTimestamp(contentValues.getAsLong("bootTimestamp"));
}
if (contentValues.containsKey("timestamp")) { if (contentValues.containsKey("timestamp")) {
builder.setTimestamp(contentValues.getAsLong("timestamp")); builder.setTimestamp(contentValues.getAsLong("timestamp"));
} }
if (contentValues.containsKey("consumePower")) {
builder.setConsumePower(contentValues.getAsDouble("consumePower"));
}
if (contentValues.containsKey("totalPower")) {
builder.setTotalPower(contentValues.getAsDouble("totalPower"));
}
if (contentValues.containsKey("percentOfTotal")) {
builder.setPercentOfTotal(contentValues.getAsDouble("percentOfTotal"));
}
if (contentValues.containsKey("foregroundUsageTimeInMs")) {
builder.setForegroundUsageTimeInMs(
contentValues.getAsLong("foregroundUsageTimeInMs"));
}
if (contentValues.containsKey("backgroundUsageTimeInMs")) {
builder.setBackgroundUsageTimeInMs(
contentValues.getAsLong("backgroundUsageTimeInMs"));
}
if (contentValues.containsKey("drainType")) {
builder.setDrainType(contentValues.getAsInteger("drainType"));
}
if (contentValues.containsKey("consumerType")) { if (contentValues.containsKey("consumerType")) {
builder.setConsumerType(contentValues.getAsInteger("consumerType")); builder.setConsumerType(contentValues.getAsInteger("consumerType"));
} }
if (contentValues.containsKey("batteryLevel")) { if (contentValues.containsKey("isFullChargeCycleStart")) {
builder.setBatteryLevel(contentValues.getAsInteger("batteryLevel")); builder.setIsFullChargeCycleStart(
contentValues.getAsBoolean("isFullChargeCycleStart"));
} }
if (contentValues.containsKey("batteryStatus")) { if (contentValues.containsKey("batteryInformation")) {
builder.setBatteryStatus(contentValues.getAsInteger("batteryStatus")); builder.setBatteryInformation(contentValues.getAsString("batteryInformation"));
} }
if (contentValues.containsKey("batteryHealth")) { if (contentValues.containsKey("batteryInformationDebug")) {
builder.setBatteryHealth(contentValues.getAsInteger("batteryHealth")); builder.setBatteryInformationDebug(
contentValues.getAsString("batteryInformationDebug"));
} }
return builder.build(); return builder.build();
} }
@@ -214,21 +155,12 @@ public class BatteryState {
public static class Builder { public static class Builder {
private long mUid; private long mUid;
private long mUserId; private long mUserId;
private String mAppLabel;
private String mPackageName; private String mPackageName;
private boolean mIsHidden;
private long mBootTimestamp;
private long mTimestamp; private long mTimestamp;
private double mTotalPower;
private double mConsumePower;
private double mPercentOfTotal;
private long mForegroundUsageTimeInMs;
private long mBackgroundUsageTimeInMs;
private int mDrainType;
private int mConsumerType; private int mConsumerType;
private int mBatteryLevel; private boolean mIsFullChargeCycleStart;
private int mBatteryStatus; private String mBatteryInformation;
private int mBatteryHealth; private String mBatteryInformationDebug;
/** Sets the uid. */ /** Sets the uid. */
@CanIgnoreReturnValue @CanIgnoreReturnValue
@@ -244,13 +176,6 @@ public class BatteryState {
return this; return this;
} }
/** Sets the app label. */
@CanIgnoreReturnValue
public Builder setAppLabel(String appLabel) {
this.mAppLabel = appLabel;
return this;
}
/** Sets the package name. */ /** Sets the package name. */
@CanIgnoreReturnValue @CanIgnoreReturnValue
public Builder setPackageName(String packageName) { public Builder setPackageName(String packageName) {
@@ -258,20 +183,6 @@ public class BatteryState {
return this; return this;
} }
/** Sets the is hidden value. */
@CanIgnoreReturnValue
public Builder setIsHidden(boolean isHidden) {
this.mIsHidden = isHidden;
return this;
}
/** Sets the boot timestamp. */
@CanIgnoreReturnValue
public Builder setBootTimestamp(long bootTimestamp) {
this.mBootTimestamp = bootTimestamp;
return this;
}
/** Sets the timestamp. */ /** Sets the timestamp. */
@CanIgnoreReturnValue @CanIgnoreReturnValue
public Builder setTimestamp(long timestamp) { public Builder setTimestamp(long timestamp) {
@@ -279,48 +190,6 @@ public class BatteryState {
return this; return this;
} }
/** Sets the total power. */
@CanIgnoreReturnValue
public Builder setTotalPower(double totalPower) {
this.mTotalPower = totalPower;
return this;
}
/** Sets the consumed power. */
@CanIgnoreReturnValue
public Builder setConsumePower(double consumePower) {
this.mConsumePower = consumePower;
return this;
}
/** Sets the percentage of total. */
@CanIgnoreReturnValue
public Builder setPercentOfTotal(double percentOfTotal) {
this.mPercentOfTotal = percentOfTotal;
return this;
}
/** Sets the foreground usage time. */
@CanIgnoreReturnValue
public Builder setForegroundUsageTimeInMs(long foregroundUsageTimeInMs) {
this.mForegroundUsageTimeInMs = foregroundUsageTimeInMs;
return this;
}
/** Sets the background usage time. */
@CanIgnoreReturnValue
public Builder setBackgroundUsageTimeInMs(long backgroundUsageTimeInMs) {
this.mBackgroundUsageTimeInMs = backgroundUsageTimeInMs;
return this;
}
/** Sets the drain type. */
@CanIgnoreReturnValue
public Builder setDrainType(int drainType) {
this.mDrainType = drainType;
return this;
}
/** Sets the consumer type. */ /** Sets the consumer type. */
@CanIgnoreReturnValue @CanIgnoreReturnValue
public Builder setConsumerType(int consumerType) { public Builder setConsumerType(int consumerType) {
@@ -328,44 +197,24 @@ public class BatteryState {
return this; return this;
} }
/** Sets the battery level. */ /** Sets whether is the full charge cycle start. */
@CanIgnoreReturnValue @CanIgnoreReturnValue
public Builder setBatteryLevel(int batteryLevel) { public Builder setIsFullChargeCycleStart(boolean isFullChargeCycleStart) {
this.mBatteryLevel = batteryLevel; this.mIsFullChargeCycleStart = isFullChargeCycleStart;
return this; return this;
} }
/** Sets the battery status. */ /** Sets the consumer type. */
@CanIgnoreReturnValue @CanIgnoreReturnValue
public Builder setBatteryStatus(int batteryStatus) { public Builder setBatteryInformation(String batteryInformation) {
this.mBatteryStatus = batteryStatus; this.mBatteryInformation = batteryInformation;
return this; return this;
} }
/** Sets the battery health. */ /** Sets the consumer type. */
@CanIgnoreReturnValue @CanIgnoreReturnValue
public Builder setBatteryHealth(int batteryHealth) { public Builder setBatteryInformationDebug(String batteryInformationDebug) {
this.mBatteryHealth = batteryHealth; this.mBatteryInformationDebug = batteryInformationDebug;
return this;
}
/** Sets the battery intent. */
@CanIgnoreReturnValue
public Builder setBatteryIntent(Intent batteryIntent) {
final int level = batteryIntent.getIntExtra(BatteryManager.EXTRA_LEVEL, -1);
final int scale = batteryIntent.getIntExtra(BatteryManager.EXTRA_SCALE, 0);
this.mBatteryLevel =
scale == 0
? -1 /*invalid battery level*/
: Math.round((level / (float) scale) * 100f);
this.mBatteryStatus =
batteryIntent.getIntExtra(
BatteryManager.EXTRA_STATUS,
BatteryManager.BATTERY_STATUS_UNKNOWN);
this.mBatteryHealth =
batteryIntent.getIntExtra(
BatteryManager.EXTRA_HEALTH,
BatteryManager.BATTERY_HEALTH_UNKNOWN);
return this; return this;
} }
@@ -374,22 +223,12 @@ public class BatteryState {
return new BatteryState( return new BatteryState(
mUid, mUid,
mUserId, mUserId,
mAppLabel,
mPackageName, mPackageName,
mIsHidden,
mBootTimestamp,
mTimestamp, mTimestamp,
/*zoneId=*/ TimeZone.getDefault().getID(),
mTotalPower,
mConsumePower,
mPercentOfTotal,
mForegroundUsageTimeInMs,
mBackgroundUsageTimeInMs,
mDrainType,
mConsumerType, mConsumerType,
mBatteryLevel, mIsFullChargeCycleStart,
mBatteryStatus, mBatteryInformation,
mBatteryHealth); mBatteryInformationDebug);
} }
private Builder() {} private Builder() {}

View File

@@ -40,7 +40,7 @@ public abstract class BatteryStateDatabase extends RoomDatabase {
if (sBatteryStateDatabase == null) { if (sBatteryStateDatabase == null) {
sBatteryStateDatabase = sBatteryStateDatabase =
Room.databaseBuilder( Room.databaseBuilder(
context, BatteryStateDatabase.class, "battery-usage-db-v5") context, BatteryStateDatabase.class, "battery-usage-db-v6")
// Allows accessing data in the main thread for dumping bugreport. // Allows accessing data in the main thread for dumping bugreport.
.allowMainThreadQueries() .allowMainThreadQueries()
.fallbackToDestructiveMigration() .fallbackToDestructiveMigration()

View File

@@ -679,8 +679,19 @@ public final class BatteryChartPreferenceControllerTest {
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>(); final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
for (int index = 0; index < numOfHours; index++) { for (int index = 0; index < numOfHours; index++) {
final ContentValues values = new ContentValues(); final ContentValues values = new ContentValues();
values.put("batteryLevel", Integer.valueOf(100 - index)); final DeviceBatteryState deviceBatteryState =
values.put("consumePower", Integer.valueOf(100 - index)); DeviceBatteryState
.newBuilder()
.setBatteryLevel(100 - index)
.build();
final BatteryInformation batteryInformation =
BatteryInformation
.newBuilder()
.setDeviceBatteryState(deviceBatteryState)
.setConsumePower(100 - index)
.build();
values.put(BatteryHistEntry.KEY_BATTERY_INFORMATION,
ConvertUtils.convertBatteryInformationToString(batteryInformation));
final BatteryHistEntry entry = new BatteryHistEntry(values); final BatteryHistEntry entry = new BatteryHistEntry(values);
final Map<String, BatteryHistEntry> entryMap = new HashMap<>(); final Map<String, BatteryHistEntry> entryMap = new HashMap<>();
entryMap.put("fake_entry_key" + index, entry); entryMap.put("fake_entry_key" + index, entry);

View File

@@ -138,8 +138,13 @@ public final class BatteryDiffEntryTest {
// Generates fake testing data. // Generates fake testing data.
final ContentValues values = getContentValuesWithType( final ContentValues values = getContentValuesWithType(
ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY); ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
values.put(BatteryHistEntry.KEY_DRAIN_TYPE, final BatteryInformation batteryInformation =
Integer.valueOf(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY)); BatteryInformation
.newBuilder()
.setDrainType(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY)
.build();
values.put(BatteryHistEntry.KEY_BATTERY_INFORMATION,
ConvertUtils.convertBatteryInformationToString(batteryInformation));
final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values); final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry); final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry);
@@ -233,7 +238,13 @@ public final class BatteryDiffEntryTest {
final String expectedAppLabel = "fake app label"; final String expectedAppLabel = "fake app label";
final ContentValues values = getContentValuesWithType( final ContentValues values = getContentValuesWithType(
ConvertUtils.CONSUMER_TYPE_UID_BATTERY); ConvertUtils.CONSUMER_TYPE_UID_BATTERY);
values.put(BatteryHistEntry.KEY_APP_LABEL, expectedAppLabel); final BatteryInformation batteryInformation =
BatteryInformation
.newBuilder()
.setAppLabel(expectedAppLabel)
.build();
values.put(BatteryHistEntry.KEY_BATTERY_INFORMATION,
ConvertUtils.convertBatteryInformationToString(batteryInformation));
final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values); final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry); final BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry);
@@ -461,7 +472,13 @@ public final class BatteryDiffEntryTest {
private BatteryDiffEntry createBatteryDiffEntry( private BatteryDiffEntry createBatteryDiffEntry(
int consumerType, long uid, boolean isHidden) { int consumerType, long uid, boolean isHidden) {
final ContentValues values = getContentValuesWithType(consumerType); final ContentValues values = getContentValuesWithType(consumerType);
values.put(BatteryHistEntry.KEY_IS_HIDDEN, isHidden); final BatteryInformation batteryInformation =
BatteryInformation
.newBuilder()
.setIsHidden(isHidden)
.build();
values.put(BatteryHistEntry.KEY_BATTERY_INFORMATION,
ConvertUtils.convertBatteryInformationToString(batteryInformation));
values.put(BatteryHistEntry.KEY_UID, uid); values.put(BatteryHistEntry.KEY_UID, uid);
return new BatteryDiffEntry( return new BatteryDiffEntry(
mContext, mContext,

View File

@@ -124,7 +124,13 @@ public final class BatteryHistEntryTest {
public void testGetKey_consumerSystemType_returnExpectedString() { public void testGetKey_consumerSystemType_returnExpectedString() {
final ContentValues values = getContentValuesWithType( final ContentValues values = getContentValuesWithType(
ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY); ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
values.put(BatteryHistEntry.KEY_DRAIN_TYPE, 1); final BatteryInformation batteryInformation =
BatteryInformation
.newBuilder()
.setDrainType(1)
.build();
values.put(BatteryHistEntry.KEY_BATTERY_INFORMATION,
ConvertUtils.convertBatteryInformationToString(batteryInformation));
final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values); final BatteryHistEntry batteryHistEntry = new BatteryHistEntry(values);
assertThat(batteryHistEntry.getKey()).isEqualTo("S|1"); assertThat(batteryHistEntry.getKey()).isEqualTo("S|1");
@@ -308,42 +314,40 @@ public final class BatteryHistEntryTest {
new String[]{ new String[]{
BatteryHistEntry.KEY_UID, BatteryHistEntry.KEY_UID,
BatteryHistEntry.KEY_USER_ID, BatteryHistEntry.KEY_USER_ID,
BatteryHistEntry.KEY_APP_LABEL,
BatteryHistEntry.KEY_PACKAGE_NAME, BatteryHistEntry.KEY_PACKAGE_NAME,
BatteryHistEntry.KEY_IS_HIDDEN,
BatteryHistEntry.KEY_BOOT_TIMESTAMP,
BatteryHistEntry.KEY_TIMESTAMP, BatteryHistEntry.KEY_TIMESTAMP,
BatteryHistEntry.KEY_ZONE_ID,
BatteryHistEntry.KEY_TOTAL_POWER,
BatteryHistEntry.KEY_CONSUME_POWER,
BatteryHistEntry.KEY_PERCENT_OF_TOTAL,
BatteryHistEntry.KEY_FOREGROUND_USAGE_TIME,
BatteryHistEntry.KEY_BACKGROUND_USAGE_TIME,
BatteryHistEntry.KEY_DRAIN_TYPE,
BatteryHistEntry.KEY_CONSUMER_TYPE, BatteryHistEntry.KEY_CONSUMER_TYPE,
BatteryHistEntry.KEY_BATTERY_LEVEL, BatteryHistEntry.KEY_BATTERY_INFORMATION});
BatteryHistEntry.KEY_BATTERY_STATUS, DeviceBatteryState deviceBatteryState =
BatteryHistEntry.KEY_BATTERY_HEALTH}); DeviceBatteryState
.newBuilder()
.setBatteryLevel(batteryLevel)
.setBatteryStatus(BatteryManager.BATTERY_STATUS_FULL)
.setBatteryHealth(BatteryManager.BATTERY_HEALTH_COLD)
.build();
BatteryInformation batteryInformation =
BatteryInformation
.newBuilder()
.setDeviceBatteryState(deviceBatteryState)
.setIsHidden(true)
.setBootTimestamp(bootTimestamp)
.setZoneId(TimeZone.getDefault().getID())
.setAppLabel("Settings")
.setTotalPower(totalPower)
.setConsumePower(consumePower)
.setPercentOfTotal(0.3)
.setDrainType(3)
.setForegroundUsageTimeInMs(foregroundUsageTimeInMs)
.setBackgroundUsageTimeInMs(backgroundUsageTimeInMs)
.build();
cursor.addRow( cursor.addRow(
new Object[]{ new Object[]{
Long.valueOf(1001), Long.valueOf(1001),
Long.valueOf(UserHandle.getUserId(1001)), Long.valueOf(UserHandle.getUserId(1001)),
"Settings",
"com.google.android.settings.battery", "com.google.android.settings.battery",
Integer.valueOf(1),
Long.valueOf(bootTimestamp),
Long.valueOf(timestamp), Long.valueOf(timestamp),
TimeZone.getDefault().getID(),
Double.valueOf(totalPower),
Double.valueOf(consumePower),
Double.valueOf(0.3),
Long.valueOf(foregroundUsageTimeInMs),
Long.valueOf(backgroundUsageTimeInMs),
Integer.valueOf(3),
Integer.valueOf(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY), Integer.valueOf(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY),
Integer.valueOf(batteryLevel), ConvertUtils.convertBatteryInformationToString(batteryInformation)});
Integer.valueOf(BatteryManager.BATTERY_STATUS_FULL),
Integer.valueOf(BatteryManager.BATTERY_HEALTH_COLD)});
cursor.moveToFirst(); cursor.moveToFirst();
return new BatteryHistEntry(cursor); return new BatteryHistEntry(cursor);
} }

View File

@@ -148,23 +148,37 @@ public final class BatteryUsageContentProviderTest {
@Test @Test
public void insert_batteryState_returnsExpectedResult() { public void insert_batteryState_returnsExpectedResult() {
mProvider.onCreate(); mProvider.onCreate();
final DeviceBatteryState deviceBatteryState =
DeviceBatteryState
.newBuilder()
.setBatteryLevel(51)
.setBatteryStatus(2)
.setBatteryHealth(3)
.build();
final BatteryInformation batteryInformation =
BatteryInformation
.newBuilder()
.setDeviceBatteryState(deviceBatteryState)
.setAppLabel("Settings")
.setIsHidden(true)
.setBootTimestamp(101L)
.setTotalPower(99)
.setConsumePower(9)
.setPercentOfTotal(0.9)
.setForegroundUsageTimeInMs(1000)
.setBackgroundUsageTimeInMs(2000)
.setDrainType(1)
.build();
final String expectedBatteryInformationString =
ConvertUtils.convertBatteryInformationToString(batteryInformation);
ContentValues values = new ContentValues(); ContentValues values = new ContentValues();
values.put("uid", Long.valueOf(101L)); values.put(BatteryHistEntry.KEY_UID, Long.valueOf(101L));
values.put("userId", Long.valueOf(1001L)); values.put(BatteryHistEntry.KEY_USER_ID, Long.valueOf(1001L));
values.put("appLabel", new String("Settings")); values.put(BatteryHistEntry.KEY_PACKAGE_NAME, new String("com.android.settings"));
values.put("packageName", new String("com.android.settings")); values.put(BatteryHistEntry.KEY_TIMESTAMP, Long.valueOf(2100021L));
values.put("timestamp", Long.valueOf(2100021L)); values.put(BatteryHistEntry.KEY_CONSUMER_TYPE, Integer.valueOf(2));
values.put("isHidden", Boolean.valueOf(true)); values.put(BatteryHistEntry.KEY_IS_FULL_CHARGE_CYCLE_START, true);
values.put("totalPower", Double.valueOf(99.0)); values.put(BatteryHistEntry.KEY_BATTERY_INFORMATION, expectedBatteryInformationString);
values.put("consumePower", Double.valueOf(9.0));
values.put("percentOfTotal", Double.valueOf(0.9));
values.put("foregroundUsageTimeInMs", Long.valueOf(1000));
values.put("backgroundUsageTimeInMs", Long.valueOf(2000));
values.put("drainType", Integer.valueOf(1));
values.put("consumerType", Integer.valueOf(2));
values.put("batteryLevel", Integer.valueOf(51));
values.put("batteryStatus", Integer.valueOf(2));
values.put("batteryHealth", Integer.valueOf(3));
final Uri uri = mProvider.insert(VALID_BATTERY_STATE_CONTENT_URI, values); final Uri uri = mProvider.insert(VALID_BATTERY_STATE_CONTENT_URI, values);
@@ -175,31 +189,34 @@ public final class BatteryUsageContentProviderTest {
assertThat(states).hasSize(1); assertThat(states).hasSize(1);
assertThat(states.get(0).uid).isEqualTo(101L); assertThat(states.get(0).uid).isEqualTo(101L);
assertThat(states.get(0).userId).isEqualTo(1001L); assertThat(states.get(0).userId).isEqualTo(1001L);
assertThat(states.get(0).appLabel).isEqualTo("Settings");
assertThat(states.get(0).packageName).isEqualTo("com.android.settings"); assertThat(states.get(0).packageName).isEqualTo("com.android.settings");
assertThat(states.get(0).isHidden).isTrue();
assertThat(states.get(0).timestamp).isEqualTo(2100021L); assertThat(states.get(0).timestamp).isEqualTo(2100021L);
assertThat(states.get(0).totalPower).isEqualTo(99.0);
assertThat(states.get(0).consumePower).isEqualTo(9.0);
assertThat(states.get(0).percentOfTotal).isEqualTo(0.9);
assertThat(states.get(0).foregroundUsageTimeInMs).isEqualTo(1000);
assertThat(states.get(0).backgroundUsageTimeInMs).isEqualTo(2000);
assertThat(states.get(0).drainType).isEqualTo(1);
assertThat(states.get(0).consumerType).isEqualTo(2); assertThat(states.get(0).consumerType).isEqualTo(2);
assertThat(states.get(0).batteryLevel).isEqualTo(51); assertThat(states.get(0).isFullChargeCycleStart).isTrue();
assertThat(states.get(0).batteryStatus).isEqualTo(2); assertThat(states.get(0).batteryInformation).isEqualTo(expectedBatteryInformationString);
assertThat(states.get(0).batteryHealth).isEqualTo(3);
} }
@Test @Test
public void insert_partialFieldsContentValues_returnsExpectedResult() { public void insert_partialFieldsContentValues_returnsExpectedResult() {
mProvider.onCreate(); mProvider.onCreate();
final DeviceBatteryState deviceBatteryState =
DeviceBatteryState
.newBuilder()
.setBatteryLevel(52)
.setBatteryStatus(3)
.setBatteryHealth(2)
.build();
final BatteryInformation batteryInformation =
BatteryInformation
.newBuilder()
.setDeviceBatteryState(deviceBatteryState)
.build();
final String expectedBatteryInformationString =
ConvertUtils.convertBatteryInformationToString(batteryInformation);
final ContentValues values = new ContentValues(); final ContentValues values = new ContentValues();
values.put("packageName", new String("fake_data")); values.put(BatteryHistEntry.KEY_PACKAGE_NAME, new String("fake_data"));
values.put("timestamp", Long.valueOf(2100022L)); values.put(BatteryHistEntry.KEY_TIMESTAMP, Long.valueOf(2100022L));
values.put("batteryLevel", Integer.valueOf(52)); values.put(BatteryHistEntry.KEY_BATTERY_INFORMATION, expectedBatteryInformationString);
values.put("batteryStatus", Integer.valueOf(3));
values.put("batteryHealth", Integer.valueOf(2));
final Uri uri = mProvider.insert(VALID_BATTERY_STATE_CONTENT_URI, values); final Uri uri = mProvider.insert(VALID_BATTERY_STATE_CONTENT_URI, values);
@@ -210,9 +227,7 @@ public final class BatteryUsageContentProviderTest {
assertThat(states).hasSize(1); assertThat(states).hasSize(1);
assertThat(states.get(0).packageName).isEqualTo("fake_data"); assertThat(states.get(0).packageName).isEqualTo("fake_data");
assertThat(states.get(0).timestamp).isEqualTo(2100022L); assertThat(states.get(0).timestamp).isEqualTo(2100022L);
assertThat(states.get(0).batteryLevel).isEqualTo(52); assertThat(states.get(0).batteryInformation).isEqualTo(expectedBatteryInformationString);
assertThat(states.get(0).batteryStatus).isEqualTo(3);
assertThat(states.get(0).batteryHealth).isEqualTo(2);
} }
@Test @Test

View File

@@ -96,34 +96,33 @@ public final class ConvertUtilsTest {
/*batteryHealth=*/ BatteryManager.BATTERY_HEALTH_COLD, /*batteryHealth=*/ BatteryManager.BATTERY_HEALTH_COLD,
/*bootTimestamp=*/ 101L, /*bootTimestamp=*/ 101L,
/*timestamp=*/ 10001L); /*timestamp=*/ 10001L);
final BatteryInformation batteryInformation =
ConvertUtils.getBatteryInformation(
values, BatteryHistEntry.KEY_BATTERY_INFORMATION);
final DeviceBatteryState deviceBatteryState = batteryInformation.getDeviceBatteryState();
assertThat(values.getAsLong(BatteryHistEntry.KEY_UID)).isEqualTo(1001L); assertThat(values.getAsLong(BatteryHistEntry.KEY_UID)).isEqualTo(1001L);
assertThat(values.getAsLong(BatteryHistEntry.KEY_USER_ID)) assertThat(values.getAsLong(BatteryHistEntry.KEY_USER_ID))
.isEqualTo(UserHandle.getUserId(1001)); .isEqualTo(UserHandle.getUserId(1001));
assertThat(values.getAsString(BatteryHistEntry.KEY_APP_LABEL))
.isEqualTo("Settings");
assertThat(values.getAsString(BatteryHistEntry.KEY_PACKAGE_NAME)) assertThat(values.getAsString(BatteryHistEntry.KEY_PACKAGE_NAME))
.isEqualTo("com.google.android.settings.battery"); .isEqualTo("com.google.android.settings.battery");
assertThat(values.getAsBoolean(BatteryHistEntry.KEY_IS_HIDDEN)).isTrue();
assertThat(values.getAsLong(BatteryHistEntry.KEY_BOOT_TIMESTAMP))
.isEqualTo(101L);
assertThat(values.getAsLong(BatteryHistEntry.KEY_TIMESTAMP)).isEqualTo(10001L); assertThat(values.getAsLong(BatteryHistEntry.KEY_TIMESTAMP)).isEqualTo(10001L);
assertThat(values.getAsString(BatteryHistEntry.KEY_ZONE_ID))
.isEqualTo(TimeZone.getDefault().getID());
assertThat(values.getAsDouble(BatteryHistEntry.KEY_TOTAL_POWER)).isEqualTo(5.1);
assertThat(values.getAsDouble(BatteryHistEntry.KEY_CONSUME_POWER)).isEqualTo(1.1);
assertThat(values.getAsDouble(BatteryHistEntry.KEY_PERCENT_OF_TOTAL)).isEqualTo(0.3);
assertThat(values.getAsLong(BatteryHistEntry.KEY_FOREGROUND_USAGE_TIME))
.isEqualTo(1234L);
assertThat(values.getAsLong(BatteryHistEntry.KEY_BACKGROUND_USAGE_TIME))
.isEqualTo(5689L);
assertThat(values.getAsInteger(BatteryHistEntry.KEY_DRAIN_TYPE)).isEqualTo(expectedType);
assertThat(values.getAsInteger(BatteryHistEntry.KEY_CONSUMER_TYPE)) assertThat(values.getAsInteger(BatteryHistEntry.KEY_CONSUMER_TYPE))
.isEqualTo(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY); .isEqualTo(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
assertThat(values.getAsInteger(BatteryHistEntry.KEY_BATTERY_LEVEL)).isEqualTo(12); assertThat(batteryInformation.getAppLabel()).isEqualTo("Settings");
assertThat(values.getAsInteger(BatteryHistEntry.KEY_BATTERY_STATUS)) assertThat(batteryInformation.getIsHidden()).isTrue();
assertThat(batteryInformation.getBootTimestamp()).isEqualTo(101L);
assertThat(batteryInformation.getZoneId()).isEqualTo(TimeZone.getDefault().getID());
assertThat(batteryInformation.getTotalPower()).isEqualTo(5.1);
assertThat(batteryInformation.getConsumePower()).isEqualTo(1.1);
assertThat(batteryInformation.getPercentOfTotal()).isEqualTo(0.3);
assertThat(batteryInformation.getForegroundUsageTimeInMs()).isEqualTo(1234L);
assertThat(batteryInformation.getBackgroundUsageTimeInMs()).isEqualTo(5689L);
assertThat(batteryInformation.getDrainType()).isEqualTo(expectedType);
assertThat(deviceBatteryState.getBatteryLevel()).isEqualTo(12);
assertThat(deviceBatteryState.getBatteryStatus())
.isEqualTo(BatteryManager.BATTERY_STATUS_FULL); .isEqualTo(BatteryManager.BATTERY_STATUS_FULL);
assertThat(values.getAsInteger(BatteryHistEntry.KEY_BATTERY_HEALTH)) assertThat(deviceBatteryState.getBatteryHealth())
.isEqualTo(BatteryManager.BATTERY_HEALTH_COLD); .isEqualTo(BatteryManager.BATTERY_HEALTH_COLD);
} }
@@ -139,17 +138,19 @@ public final class ConvertUtilsTest {
/*bootTimestamp=*/ 101L, /*bootTimestamp=*/ 101L,
/*timestamp=*/ 10001L); /*timestamp=*/ 10001L);
assertThat(values.getAsLong(BatteryHistEntry.KEY_BOOT_TIMESTAMP)) final BatteryInformation batteryInformation =
.isEqualTo(101L); ConvertUtils.getBatteryInformation(
values, BatteryHistEntry.KEY_BATTERY_INFORMATION);
final DeviceBatteryState deviceBatteryState = batteryInformation.getDeviceBatteryState();
assertThat(batteryInformation.getBootTimestamp()).isEqualTo(101L);
assertThat(batteryInformation.getZoneId()).isEqualTo(TimeZone.getDefault().getID());
assertThat(deviceBatteryState.getBatteryLevel()).isEqualTo(12);
assertThat(deviceBatteryState.getBatteryStatus())
.isEqualTo(BatteryManager.BATTERY_STATUS_FULL);
assertThat(deviceBatteryState.getBatteryHealth())
.isEqualTo(BatteryManager.BATTERY_HEALTH_COLD);
assertThat(values.getAsLong(BatteryHistEntry.KEY_TIMESTAMP)) assertThat(values.getAsLong(BatteryHistEntry.KEY_TIMESTAMP))
.isEqualTo(10001L); .isEqualTo(10001L);
assertThat(values.getAsString(BatteryHistEntry.KEY_ZONE_ID))
.isEqualTo(TimeZone.getDefault().getID());
assertThat(values.getAsInteger(BatteryHistEntry.KEY_BATTERY_LEVEL)).isEqualTo(12);
assertThat(values.getAsInteger(BatteryHistEntry.KEY_BATTERY_STATUS))
.isEqualTo(BatteryManager.BATTERY_STATUS_FULL);
assertThat(values.getAsInteger(BatteryHistEntry.KEY_BATTERY_HEALTH))
.isEqualTo(BatteryManager.BATTERY_HEALTH_COLD);
assertThat(values.getAsString(BatteryHistEntry.KEY_PACKAGE_NAME)) assertThat(values.getAsString(BatteryHistEntry.KEY_PACKAGE_NAME))
.isEqualTo(ConvertUtils.FAKE_PACKAGE_NAME); .isEqualTo(ConvertUtils.FAKE_PACKAGE_NAME);
} }
@@ -499,17 +500,21 @@ public final class ConvertUtilsTest {
String packageName, String appLabel, double consumePower, String packageName, String appLabel, double consumePower,
long uid, long foregroundUsageTimeInMs, long backgroundUsageTimeInMs) { long uid, long foregroundUsageTimeInMs, long backgroundUsageTimeInMs) {
// Only insert required fields. // Only insert required fields.
final BatteryInformation batteryInformation =
BatteryInformation
.newBuilder()
.setAppLabel(appLabel)
.setConsumePower(consumePower)
.setForegroundUsageTimeInMs(foregroundUsageTimeInMs)
.setBackgroundUsageTimeInMs(backgroundUsageTimeInMs)
.build();
final ContentValues values = new ContentValues(); final ContentValues values = new ContentValues();
values.put(BatteryHistEntry.KEY_PACKAGE_NAME, packageName); values.put(BatteryHistEntry.KEY_PACKAGE_NAME, packageName);
values.put(BatteryHistEntry.KEY_APP_LABEL, appLabel);
values.put(BatteryHistEntry.KEY_UID, Long.valueOf(uid)); values.put(BatteryHistEntry.KEY_UID, Long.valueOf(uid));
values.put(BatteryHistEntry.KEY_CONSUMER_TYPE, values.put(BatteryHistEntry.KEY_CONSUMER_TYPE,
Integer.valueOf(ConvertUtils.CONSUMER_TYPE_UID_BATTERY)); Integer.valueOf(ConvertUtils.CONSUMER_TYPE_UID_BATTERY));
values.put(BatteryHistEntry.KEY_CONSUME_POWER, consumePower); values.put(BatteryHistEntry.KEY_BATTERY_INFORMATION,
values.put(BatteryHistEntry.KEY_FOREGROUND_USAGE_TIME, ConvertUtils.convertBatteryInformationToString(batteryInformation));
Long.valueOf(foregroundUsageTimeInMs));
values.put(BatteryHistEntry.KEY_BACKGROUND_USAGE_TIME,
Long.valueOf(backgroundUsageTimeInMs));
return new BatteryHistEntry(values); return new BatteryHistEntry(values);
} }

View File

@@ -458,8 +458,7 @@ public class DataProcessorTest {
@Test @Test
public void isFromFullCharge_chargedData_returnTrue() { public void isFromFullCharge_chargedData_returnTrue() {
final Map<String, BatteryHistEntry> entryMap = new HashMap<>(); final Map<String, BatteryHistEntry> entryMap = new HashMap<>();
final ContentValues values = new ContentValues(); final ContentValues values = getContentValuesWithBatteryLevel(100);
values.put("batteryLevel", 100);
final BatteryHistEntry entry = new BatteryHistEntry(values); final BatteryHistEntry entry = new BatteryHistEntry(values);
entryMap.put(FAKE_ENTRY_KEY, entry); entryMap.put(FAKE_ENTRY_KEY, entry);
@@ -1042,8 +1041,7 @@ public class DataProcessorTest {
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>(); final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
for (int index = 0; index < timestamps.length; index++) { for (int index = 0; index < timestamps.length; index++) {
final Map<String, BatteryHistEntry> entryMap = new HashMap<>(); final Map<String, BatteryHistEntry> entryMap = new HashMap<>();
final ContentValues values = new ContentValues(); final ContentValues values = getContentValuesWithBatteryLevel(levels[index]);
values.put(BatteryHistEntry.KEY_BATTERY_LEVEL, levels[index]);
final BatteryHistEntry entry = new BatteryHistEntry(values); final BatteryHistEntry entry = new BatteryHistEntry(values);
entryMap.put(FAKE_ENTRY_KEY, entry); entryMap.put(FAKE_ENTRY_KEY, entry);
batteryHistoryMap.put(timestamps[index], entryMap); batteryHistoryMap.put(timestamps[index], entryMap);
@@ -1051,20 +1049,43 @@ public class DataProcessorTest {
return batteryHistoryMap; 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( private static BatteryHistEntry createBatteryHistEntry(
final String packageName, final String appLabel, final double consumePower, final String packageName, final String appLabel, final double consumePower,
final long uid, final long userId, final int consumerType, final long uid, final long userId, final int consumerType,
final long foregroundUsageTimeInMs, final long backgroundUsageTimeInMs) { final long foregroundUsageTimeInMs, final long backgroundUsageTimeInMs) {
// Only insert required fields. // Only insert required fields.
final BatteryInformation batteryInformation =
BatteryInformation
.newBuilder()
.setAppLabel(appLabel)
.setConsumePower(consumePower)
.setForegroundUsageTimeInMs(foregroundUsageTimeInMs)
.setBackgroundUsageTimeInMs(backgroundUsageTimeInMs)
.build();
final ContentValues values = new ContentValues(); final ContentValues values = new ContentValues();
values.put(BatteryHistEntry.KEY_PACKAGE_NAME, packageName); values.put(BatteryHistEntry.KEY_PACKAGE_NAME, packageName);
values.put(BatteryHistEntry.KEY_APP_LABEL, appLabel);
values.put(BatteryHistEntry.KEY_UID, uid); values.put(BatteryHistEntry.KEY_UID, uid);
values.put(BatteryHistEntry.KEY_USER_ID, userId); values.put(BatteryHistEntry.KEY_USER_ID, userId);
values.put(BatteryHistEntry.KEY_CONSUMER_TYPE, consumerType); values.put(BatteryHistEntry.KEY_CONSUMER_TYPE, consumerType);
values.put(BatteryHistEntry.KEY_CONSUME_POWER, consumePower); values.put(BatteryHistEntry.KEY_BATTERY_INFORMATION,
values.put(BatteryHistEntry.KEY_FOREGROUND_USAGE_TIME, foregroundUsageTimeInMs); ConvertUtils.convertBatteryInformationToString(batteryInformation));
values.put(BatteryHistEntry.KEY_BACKGROUND_USAGE_TIME, backgroundUsageTimeInMs);
return new BatteryHistEntry(values); return new BatteryHistEntry(values);
} }

View File

@@ -231,13 +231,13 @@ public final class DatabaseUtilsTest {
// Verifies the BatteryHistEntry data for timestamp1. // Verifies the BatteryHistEntry data for timestamp1.
Map<String, BatteryHistEntry> batteryMap = batteryHistMap.get(timestamp1); Map<String, BatteryHistEntry> batteryMap = batteryHistMap.get(timestamp1);
assertThat(batteryMap).hasSize(1); assertThat(batteryMap).hasSize(1);
assertThat(batteryMap.get("1").mAppLabel).isEqualTo("app name1"); assertThat(batteryMap.get("1").mPackageName).isEqualTo("app name1");
// Verifies the BatteryHistEntry data for timestamp2. // Verifies the BatteryHistEntry data for timestamp2.
batteryMap = batteryHistMap.get(timestamp2); batteryMap = batteryHistMap.get(timestamp2);
assertThat(batteryMap).hasSize(3); assertThat(batteryMap).hasSize(3);
assertThat(batteryMap.get("2").mAppLabel).isEqualTo("app name2"); assertThat(batteryMap.get("2").mPackageName).isEqualTo("app name2");
assertThat(batteryMap.get("3").mAppLabel).isEqualTo("app name3"); assertThat(batteryMap.get("3").mPackageName).isEqualTo("app name3");
assertThat(batteryMap.get("4").mAppLabel).isEqualTo("app name4"); assertThat(batteryMap.get("4").mPackageName).isEqualTo("app name4");
} }
@Test @Test
@@ -341,20 +341,27 @@ public final class DatabaseUtilsTest {
} }
private static void verifyContentValues(double consumedPower, ContentValues values) { private static void verifyContentValues(double consumedPower, ContentValues values) {
assertThat(values.getAsDouble(BatteryHistEntry.KEY_CONSUME_POWER)) final BatteryInformation batteryInformation =
.isEqualTo(consumedPower); ConvertUtils.getBatteryInformation(
assertThat(values.getAsInteger(BatteryHistEntry.KEY_BATTERY_LEVEL)).isEqualTo(20); values, BatteryHistEntry.KEY_BATTERY_INFORMATION);
assertThat(values.getAsInteger(BatteryHistEntry.KEY_BATTERY_STATUS)) final DeviceBatteryState deviceBatteryState = batteryInformation.getDeviceBatteryState();
assertThat(batteryInformation.getConsumePower()).isEqualTo(consumedPower);
assertThat(deviceBatteryState.getBatteryLevel()).isEqualTo(20);
assertThat(deviceBatteryState.getBatteryStatus())
.isEqualTo(BatteryManager.BATTERY_STATUS_FULL); .isEqualTo(BatteryManager.BATTERY_STATUS_FULL);
assertThat(values.getAsInteger(BatteryHistEntry.KEY_BATTERY_HEALTH)) assertThat(deviceBatteryState.getBatteryHealth())
.isEqualTo(BatteryManager.BATTERY_HEALTH_COLD); .isEqualTo(BatteryManager.BATTERY_HEALTH_COLD);
} }
private static void verifyFakeContentValues(ContentValues values) { private static void verifyFakeContentValues(ContentValues values) {
assertThat(values.getAsInteger("batteryLevel")).isEqualTo(20); final BatteryInformation batteryInformation =
assertThat(values.getAsInteger("batteryStatus")) ConvertUtils.getBatteryInformation(
values, BatteryHistEntry.KEY_BATTERY_INFORMATION);
final DeviceBatteryState deviceBatteryState = batteryInformation.getDeviceBatteryState();
assertThat(deviceBatteryState.getBatteryLevel()).isEqualTo(20);
assertThat(deviceBatteryState.getBatteryStatus())
.isEqualTo(BatteryManager.BATTERY_STATUS_FULL); .isEqualTo(BatteryManager.BATTERY_STATUS_FULL);
assertThat(values.getAsInteger("batteryHealth")) assertThat(deviceBatteryState.getBatteryHealth())
.isEqualTo(BatteryManager.BATTERY_HEALTH_COLD); .isEqualTo(BatteryManager.BATTERY_HEALTH_COLD);
assertThat(values.getAsString("packageName")) assertThat(values.getAsString("packageName"))
.isEqualTo(ConvertUtils.FAKE_PACKAGE_NAME); .isEqualTo(ConvertUtils.FAKE_PACKAGE_NAME);
@@ -372,7 +379,7 @@ public final class DatabaseUtilsTest {
private static MatrixCursor getMatrixCursor() { private static MatrixCursor getMatrixCursor() {
return new MatrixCursor( return new MatrixCursor(
new String[] { new String[] {
BatteryHistEntry.KEY_APP_LABEL, BatteryHistEntry.KEY_PACKAGE_NAME,
BatteryHistEntry.KEY_TIMESTAMP, BatteryHistEntry.KEY_TIMESTAMP,
BatteryHistEntry.KEY_UID, BatteryHistEntry.KEY_UID,
BatteryHistEntry.KEY_CONSUMER_TYPE}); BatteryHistEntry.KEY_CONSUMER_TYPE});

View File

@@ -36,7 +36,7 @@ import java.util.List;
/** Tests for {@link BatteryStateDao}. */ /** Tests for {@link BatteryStateDao}. */
@RunWith(RobolectricTestRunner.class) @RunWith(RobolectricTestRunner.class)
public final class BatteryStateDaoTest { public final class BatteryStateDaoTest {
private static final int CURSOR_COLUMN_SIZE = 19; private static final int CURSOR_COLUMN_SIZE = 9;
private static final long TIMESTAMP1 = System.currentTimeMillis(); private static final long TIMESTAMP1 = System.currentTimeMillis();
private static final long TIMESTAMP2 = System.currentTimeMillis() + 2; private static final long TIMESTAMP2 = System.currentTimeMillis() + 2;
private static final long TIMESTAMP3 = System.currentTimeMillis() + 4; private static final long TIMESTAMP3 = System.currentTimeMillis() + 4;
@@ -81,10 +81,10 @@ public final class BatteryStateDaoTest {
assertThat(cursor.getColumnCount()).isEqualTo(CURSOR_COLUMN_SIZE); assertThat(cursor.getColumnCount()).isEqualTo(CURSOR_COLUMN_SIZE);
// Verifies the queried first battery state. // Verifies the queried first battery state.
cursor.moveToFirst(); cursor.moveToFirst();
assertThat(cursor.getString(4 /*packageName*/)).isEqualTo(PACKAGE_NAME3); assertThat(cursor.getString(3 /*packageName*/)).isEqualTo(PACKAGE_NAME3);
// Verifies the queried second battery state. // Verifies the queried second battery state.
cursor.moveToNext(); cursor.moveToNext();
assertThat(cursor.getString(4 /*packageName*/)).isEqualTo(PACKAGE_NAME2); assertThat(cursor.getString(3 /*packageName*/)).isEqualTo(PACKAGE_NAME2);
} }
@Test @Test

View File

@@ -18,9 +18,12 @@ package com.android.settings.fuelgauge.batteryusage.db;
import static com.google.common.truth.Truth.assertThat; import static com.google.common.truth.Truth.assertThat;
import android.content.Intent;
import android.os.BatteryManager; import android.os.BatteryManager;
import com.android.settings.fuelgauge.batteryusage.BatteryInformation;
import com.android.settings.fuelgauge.batteryusage.ConvertUtils;
import com.android.settings.fuelgauge.batteryusage.DeviceBatteryState;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import org.junit.runner.RunWith; import org.junit.runner.RunWith;
@@ -33,66 +36,58 @@ public final class BatteryStateTest {
private static final int BATTERY_STATUS = BatteryManager.BATTERY_STATUS_FULL; private static final int BATTERY_STATUS = BatteryManager.BATTERY_STATUS_FULL;
private static final int BATTERY_HEALTH = BatteryManager.BATTERY_HEALTH_COLD; private static final int BATTERY_HEALTH = BatteryManager.BATTERY_HEALTH_COLD;
private Intent mBatteryIntent; private BatteryInformation mBatteryInformation;
@Before @Before
public void setUp() { public void setUp() {
mBatteryIntent = new Intent(Intent.ACTION_BATTERY_CHANGED); final DeviceBatteryState deviceBatteryState =
// Inserts the battery states into intent. DeviceBatteryState
mBatteryIntent.putExtra(BatteryManager.EXTRA_LEVEL, BATTERY_LEVEL); .newBuilder()
mBatteryIntent.putExtra(BatteryManager.EXTRA_STATUS, BATTERY_STATUS); .setBatteryLevel(BATTERY_LEVEL)
mBatteryIntent.putExtra(BatteryManager.EXTRA_HEALTH, BATTERY_HEALTH); .setBatteryStatus(BATTERY_STATUS)
.setBatteryHealth(BATTERY_HEALTH)
.build();
mBatteryInformation =
BatteryInformation
.newBuilder()
.setDeviceBatteryState(deviceBatteryState)
.setBootTimestamp(101L)
.setIsHidden(true)
.setAppLabel("Settings")
.setTotalPower(100)
.setConsumePower(3)
.setPercentOfTotal(10)
.setDrainType(1)
.setForegroundUsageTimeInMs(60000)
.setBackgroundUsageTimeInMs(10000)
.build();
} }
@Test @Test
public void testBuilder_returnsExpectedResult() { public void testBuilder_returnsExpectedResult() {
mBatteryIntent.putExtra(BatteryManager.EXTRA_SCALE, 100); BatteryState state = create(mBatteryInformation);
BatteryState state = create(mBatteryIntent);
// Verifies the app relative information. // Verifies the app relative information.
assertThat(state.uid).isEqualTo(1001L); assertThat(state.uid).isEqualTo(1001L);
assertThat(state.userId).isEqualTo(100L); assertThat(state.userId).isEqualTo(100L);
assertThat(state.appLabel).isEqualTo("Settings");
assertThat(state.packageName).isEqualTo("com.android.settings"); assertThat(state.packageName).isEqualTo("com.android.settings");
assertThat(state.isHidden).isTrue();
assertThat(state.bootTimestamp).isEqualTo(101L);
assertThat(state.timestamp).isEqualTo(100001L); assertThat(state.timestamp).isEqualTo(100001L);
// Verifies the battery relative information.
assertThat(state.totalPower).isEqualTo(100);
assertThat(state.consumePower).isEqualTo(3);
assertThat(state.percentOfTotal).isEqualTo(10);
assertThat(state.foregroundUsageTimeInMs).isEqualTo(60000);
assertThat(state.backgroundUsageTimeInMs).isEqualTo(10000);
assertThat(state.drainType).isEqualTo(1);
assertThat(state.consumerType).isEqualTo(2); assertThat(state.consumerType).isEqualTo(2);
assertThat(state.batteryLevel).isEqualTo(BATTERY_LEVEL); assertThat(state.isFullChargeCycleStart).isTrue();
assertThat(state.batteryStatus).isEqualTo(BATTERY_STATUS); assertThat(state.batteryInformation).isEqualTo(
assertThat(state.batteryHealth).isEqualTo(BATTERY_HEALTH); ConvertUtils.convertBatteryInformationToString(mBatteryInformation));
} }
@Test private static BatteryState create(BatteryInformation batteryInformation) {
public void create_withoutBatteryScale_returnsStateWithInvalidLevel() {
BatteryState state = create(mBatteryIntent);
assertThat(state.batteryLevel).isEqualTo(-1);
}
private static BatteryState create(Intent intent) {
return BatteryState.newBuilder() return BatteryState.newBuilder()
.setUid(1001L) .setUid(1001L)
.setUserId(100L) .setUserId(100L)
.setAppLabel("Settings")
.setPackageName("com.android.settings") .setPackageName("com.android.settings")
.setIsHidden(true)
.setBootTimestamp(101L)
.setTimestamp(100001L) .setTimestamp(100001L)
.setTotalPower(100f)
.setConsumePower(3f)
.setPercentOfTotal(10f)
.setForegroundUsageTimeInMs(60000)
.setBackgroundUsageTimeInMs(10000)
.setDrainType(1)
.setConsumerType(2) .setConsumerType(2)
.setBatteryIntent(intent) .setIsFullChargeCycleStart(true)
.setBatteryInformation(
ConvertUtils.convertBatteryInformationToString(batteryInformation))
.build(); .build();
} }
} }

View File

@@ -23,6 +23,9 @@ import android.os.UserManager;
import androidx.room.Room; import androidx.room.Room;
import com.android.settings.fuelgauge.batteryusage.BatteryInformation;
import com.android.settings.fuelgauge.batteryusage.ConvertUtils;
import com.android.settings.fuelgauge.batteryusage.DeviceBatteryState;
import com.android.settings.fuelgauge.batteryusage.db.BatteryState; import com.android.settings.fuelgauge.batteryusage.db.BatteryState;
import com.android.settings.fuelgauge.batteryusage.db.BatteryStateDao; import com.android.settings.fuelgauge.batteryusage.db.BatteryStateDao;
import com.android.settings.fuelgauge.batteryusage.db.BatteryStateDatabase; import com.android.settings.fuelgauge.batteryusage.db.BatteryStateDatabase;
@@ -75,26 +78,44 @@ public class BatteryTestUtils {
/** Inserts a fake data into the database for testing. */ /** Inserts a fake data into the database for testing. */
public static void insertDataToBatteryStateDatabase( public static void insertDataToBatteryStateDatabase(
Context context, long timestamp, String packageName, boolean multiple) { Context context, long timestamp, String packageName, boolean multiple) {
DeviceBatteryState deviceBatteryState =
DeviceBatteryState
.newBuilder()
.setBatteryLevel(31)
.setBatteryStatus(0)
.setBatteryHealth(0)
.build();
BatteryInformation batteryInformation =
BatteryInformation
.newBuilder()
.setDeviceBatteryState(deviceBatteryState)
.setIsHidden(true)
.setBootTimestamp(timestamp - 1)
.setZoneId("Europe/Paris")
.setAppLabel("Settings")
.setTotalPower(100f)
.setConsumePower(0.3f)
.setPercentOfTotal(10f)
.setDrainType(1)
.setForegroundUsageTimeInMs(60000)
.setForegroundServiceUsageTimeInMs(30000)
.setBackgroundUsageTimeInMs(10000)
.setForegroundUsageConsumePower(0.1f)
.setForegroundServiceUsageConsumePower(0.05f)
.setBackgroundUsageConsumePower(0.1f)
.setCachedUsageConsumePower(0.05f)
.build();
final BatteryState state = final BatteryState state =
new BatteryState( new BatteryState(
/*uid=*/ 1001L, /*uid=*/ 1001L,
/*userId=*/ 100L, /*userId=*/ 100L,
/*appLabel=*/ "Settings",
packageName, packageName,
/*isHidden=*/ true,
/*bootTimestamp=*/ timestamp - 1,
timestamp, timestamp,
/*zoneId=*/ "Europe/Paris",
/*totalPower=*/ 100f,
/*consumePower=*/ 0.3f,
/*percentOfTotal=*/ 10f,
/*foregroundUsageTimeInMs=*/ 60000,
/*backgroundUsageTimeInMs=*/ 10000,
/*drainType=*/ 1,
/*consumerType=*/ 2, /*consumerType=*/ 2,
/*batteryLevel=*/ 31, /*isFullChargeCycleStart=*/ false,
/*batteryStatus=*/ 0, ConvertUtils.convertBatteryInformationToString(batteryInformation),
/*batteryHealth=*/ 0); "");
BatteryStateDao dao = BatteryStateDao dao =
BatteryStateDatabase.getInstance(context).batteryStateDao(); BatteryStateDatabase.getInstance(context).batteryStateDao();
if (multiple) { if (multiple) {