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-telephony-protos-lite",
"fuelgauge-log-protos-lite",
"fuelgauge-usage-state-protos-lite",
"contextualcards",
"settings-logtags",
"statslog-settings",

View File

@@ -41,3 +41,11 @@ java_library {
},
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.SharedPreferences;
import android.util.Base64;
import android.util.Log;
import com.android.settings.fuelgauge.BatteryOptimizeHistoricalLogEntry.Action;
import com.google.common.annotations.VisibleForTesting;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.MessageLite;
import java.io.PrintWriter;
import java.util.List;
@@ -76,22 +73,8 @@ public final class BatteryHistoricalLogUtil {
}
private static BatteryOptimizeHistoricalLog parseLogFromString(String storedLogs) {
return 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();
}
return BatteryUtils.parseProtoFromString(
storedLogs, BatteryOptimizeHistoricalLog.getDefaultInstance());
}
/**

View File

@@ -32,6 +32,7 @@ import android.os.Process;
import android.os.SystemClock;
import android.os.UidBatteryConsumer;
import android.os.UserHandle;
import android.util.Base64;
import android.util.Log;
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.ThreadUtils;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.MessageLite;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
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,
int mode) {
final boolean isPreOApp = isPreOApp(packageName);

View File

@@ -30,23 +30,12 @@ public class BatteryHistEntry {
/** Keys for accessing {@link ContentValues} or {@link Cursor}. */
public static final String KEY_UID = "uid";
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_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_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_BATTERY_LEVEL = "batteryLevel";
public static final String KEY_BATTERY_STATUS = "batteryStatus";
public static final String KEY_BATTERY_HEALTH = "batteryHealth";
public static final String KEY_IS_FULL_CHARGE_CYCLE_START = "isFullChargeCycleStart";
public static final String KEY_BATTERY_INFORMATION = "batteryInformation";
public static final String KEY_BATTERY_INFORMATION_DEBUG = "batteryInformationDebug";
public final long mUid;
public final long mUserId;
@@ -79,43 +68,49 @@ public class BatteryHistEntry {
public BatteryHistEntry(ContentValues values) {
mUid = getLong(values, KEY_UID);
mUserId = getLong(values, KEY_USER_ID);
mAppLabel = getString(values, KEY_APP_LABEL);
mPackageName = getString(values, KEY_PACKAGE_NAME);
mIsHidden = getBoolean(values, KEY_IS_HIDDEN);
mBootTimestamp = getLong(values, KEY_BOOT_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);
mBatteryLevel = getInteger(values, KEY_BATTERY_LEVEL);
mBatteryStatus = getInteger(values, KEY_BATTERY_STATUS);
mBatteryHealth = getInteger(values, KEY_BATTERY_HEALTH);
final BatteryInformation batteryInformation =
ConvertUtils.getBatteryInformation(values, KEY_BATTERY_INFORMATION);
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) {
mUid = getLong(cursor, KEY_UID);
mUserId = getLong(cursor, KEY_USER_ID);
mAppLabel = getString(cursor, KEY_APP_LABEL);
mPackageName = getString(cursor, KEY_PACKAGE_NAME);
mIsHidden = getBoolean(cursor, KEY_IS_HIDDEN);
mBootTimestamp = getLong(cursor, KEY_BOOT_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);
mBatteryLevel = getInteger(cursor, KEY_BATTERY_LEVEL);
mBatteryStatus = getInteger(cursor, KEY_BATTERY_STATUS);
mBatteryHealth = getInteger(cursor, KEY_BATTERY_HEALTH);
final BatteryInformation batteryInformation =
ConvertUtils.getBatteryInformation(cursor, KEY_BATTERY_INFORMATION);
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(
@@ -240,23 +235,6 @@ public class BatteryHistEntry {
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) {
if (values != null && values.containsKey(key)) {
return values.getAsString(key);
@@ -274,24 +252,6 @@ public class BatteryHistEntry {
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. */
public static BatteryHistEntry interpolate(
long slotTimestamp,
@@ -315,7 +275,7 @@ public class BatteryHistEntry {
lowerHistEntry == null ? 0 : lowerHistEntry.mBackgroundUsageTimeInMs,
upperHistEntry.mBackgroundUsageTimeInMs,
ratio);
// Checks whether there is any abnoaml cases!
// Checks whether there is any abnormal cases!
if (upperHistEntry.mConsumePower < consumePower
|| upperHistEntry.mForegroundUsageTimeInMs < foregroundUsageTimeInMs
|| upperHistEntry.mBackgroundUsageTimeInMs < backgroundUsageTimeInMs) {

View File

@@ -18,13 +18,16 @@ package com.android.settings.fuelgauge.batteryusage;
import android.annotation.IntDef;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.os.BatteryUsageStats;
import android.os.Build;
import android.os.LocaleList;
import android.os.UserHandle;
import android.os.UserManager;
import android.text.format.DateFormat;
import android.text.format.DateUtils;
import android.util.ArraySet;
import android.util.Base64;
import android.util.Log;
import androidx.annotation.VisibleForTesting;
@@ -83,48 +86,71 @@ public final class ConvertUtils {
/** Converts to content values */
public static ContentValues convertToContentValues(
BatteryEntry entry,
BatteryUsageStats batteryUsageStats,
int batteryLevel,
int batteryStatus,
int batteryHealth,
long bootTimestamp,
long timestamp) {
final BatteryEntry entry,
final BatteryUsageStats batteryUsageStats,
final int batteryLevel,
final int batteryStatus,
final int batteryHealth,
final long bootTimestamp,
final long timestamp) {
final ContentValues values = new ContentValues();
if (entry != null && batteryUsageStats != null) {
values.put(BatteryHistEntry.KEY_UID, Long.valueOf(entry.getUid()));
values.put(BatteryHistEntry.KEY_USER_ID,
Long.valueOf(UserHandle.getUserId(entry.getUid())));
values.put(BatteryHistEntry.KEY_APP_LABEL, entry.getLabel());
values.put(BatteryHistEntry.KEY_PACKAGE_NAME,
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,
Integer.valueOf(entry.getConsumerType()));
} else {
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_ZONE_ID, TimeZone.getDefault().getID());
values.put(BatteryHistEntry.KEY_BATTERY_LEVEL, Integer.valueOf(batteryLevel));
values.put(BatteryHistEntry.KEY_BATTERY_STATUS, Integer.valueOf(batteryStatus));
values.put(BatteryHistEntry.KEY_BATTERY_HEALTH, Integer.valueOf(batteryHealth));
final BatteryInformation batteryInformation =
constructBatteryInformation(
entry,
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;
}
/** 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} */
public static BatteryHistEntry convertToBatteryHistEntry(
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(
final int desiredIndex,
final Map<Integer, List<BatteryDiffEntry>> indexedUsageMap) {

View File

@@ -17,16 +17,16 @@
package com.android.settings.fuelgauge.batteryusage.db;
import android.content.ContentValues;
import android.content.Intent;
import android.os.BatteryManager;
import androidx.room.Entity;
import androidx.room.PrimaryKey;
import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.fuelgauge.batteryusage.BatteryInformation;
import com.google.errorprone.annotations.CanIgnoreReturnValue;
import java.text.SimpleDateFormat;
import java.time.Duration;
import java.util.Date;
import java.util.Locale;
import java.util.TimeZone;
@@ -43,68 +43,41 @@ public class BatteryState {
// Records the app relative information.
public final long uid;
public final long userId;
public final String appLabel;
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 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;
// Records the battery intent relative information.
public final int batteryLevel;
public final int batteryStatus;
public final int batteryHealth;
public final boolean isFullChargeCycleStart;
public final String batteryInformation;
/**
* 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(
long uid,
long userId,
String appLabel,
String packageName,
boolean isHidden,
long bootTimestamp,
long timestamp,
String zoneId,
double totalPower,
double consumePower,
double percentOfTotal,
long foregroundUsageTimeInMs,
long backgroundUsageTimeInMs,
int drainType,
int consumerType,
int batteryLevel,
int batteryStatus,
int batteryHealth) {
boolean isFullChargeCycleStart,
String batteryInformation,
String batteryInformationDebug) {
// Records the app relative information.
this.uid = uid;
this.userId = userId;
this.appLabel = appLabel;
this.packageName = packageName;
this.isHidden = isHidden;
// Records the timestamp relative information.
this.bootTimestamp = bootTimestamp;
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;
// Records the battery intent relative information.
this.batteryLevel = batteryLevel;
this.batteryStatus = batteryStatus;
this.batteryHealth = batteryHealth;
this.isFullChargeCycleStart = isFullChargeCycleStart;
this.batteryInformation = batteryInformation;
this.batteryInformationDebug = batteryInformationDebug;
}
/** Sets the auto-generated content ID. */
@@ -126,22 +99,17 @@ public class BatteryState {
sCacheSimpleDateFormat = new SimpleDateFormat("MMM dd,yyyy HH:mm:ss", Locale.US);
}
final String recordAtDateTime = sCacheSimpleDateFormat.format(new Date(timestamp));
final BatteryInformation batteryInformationInstance =
BatteryUtils.parseProtoFromString(
batteryInformation, BatteryInformation.getDefaultInstance());
final StringBuilder builder = new StringBuilder()
.append("\nBatteryState{")
.append(String.format(Locale.US,
"\n\tpackage=%s|label=%s|uid=%d|userId=%d|isHidden=%b",
packageName, appLabel, uid, userId, isHidden))
.append(String.format(Locale.US, "\n\ttimestamp=%s|zoneId=%s|bootTimestamp=%d",
recordAtDateTime, zoneId, Duration.ofMillis(bootTimestamp).getSeconds()))
.append(String.format(Locale.US,
"\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));
"\n\tpackage=%s|uid=%d|userId=%d", packageName, uid, userId))
.append(String.format(Locale.US, "\n\ttimestamp=%s|consumer=%d|isStart=%b",
recordAtDateTime, consumerType, isFullChargeCycleStart))
.append(String.format(Locale.US, "\n\tbatteryInfo="))
.append(batteryInformationInstance.toString());
return builder.toString();
}
@@ -155,52 +123,25 @@ public class BatteryState {
if (contentValues.containsKey("userId")) {
builder.setUserId(contentValues.getAsLong("userId"));
}
if (contentValues.containsKey("appLabel")) {
builder.setAppLabel(contentValues.getAsString("appLabel"));
}
if (contentValues.containsKey("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")) {
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")) {
builder.setConsumerType(contentValues.getAsInteger("consumerType"));
}
if (contentValues.containsKey("batteryLevel")) {
builder.setBatteryLevel(contentValues.getAsInteger("batteryLevel"));
if (contentValues.containsKey("isFullChargeCycleStart")) {
builder.setIsFullChargeCycleStart(
contentValues.getAsBoolean("isFullChargeCycleStart"));
}
if (contentValues.containsKey("batteryStatus")) {
builder.setBatteryStatus(contentValues.getAsInteger("batteryStatus"));
if (contentValues.containsKey("batteryInformation")) {
builder.setBatteryInformation(contentValues.getAsString("batteryInformation"));
}
if (contentValues.containsKey("batteryHealth")) {
builder.setBatteryHealth(contentValues.getAsInteger("batteryHealth"));
if (contentValues.containsKey("batteryInformationDebug")) {
builder.setBatteryInformationDebug(
contentValues.getAsString("batteryInformationDebug"));
}
return builder.build();
}
@@ -214,21 +155,12 @@ public class BatteryState {
public static class Builder {
private long mUid;
private long mUserId;
private String mAppLabel;
private String mPackageName;
private boolean mIsHidden;
private long mBootTimestamp;
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 mBatteryLevel;
private int mBatteryStatus;
private int mBatteryHealth;
private boolean mIsFullChargeCycleStart;
private String mBatteryInformation;
private String mBatteryInformationDebug;
/** Sets the uid. */
@CanIgnoreReturnValue
@@ -244,13 +176,6 @@ public class BatteryState {
return this;
}
/** Sets the app label. */
@CanIgnoreReturnValue
public Builder setAppLabel(String appLabel) {
this.mAppLabel = appLabel;
return this;
}
/** Sets the package name. */
@CanIgnoreReturnValue
public Builder setPackageName(String packageName) {
@@ -258,20 +183,6 @@ public class BatteryState {
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. */
@CanIgnoreReturnValue
public Builder setTimestamp(long timestamp) {
@@ -279,48 +190,6 @@ public class BatteryState {
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. */
@CanIgnoreReturnValue
public Builder setConsumerType(int consumerType) {
@@ -328,44 +197,24 @@ public class BatteryState {
return this;
}
/** Sets the battery level. */
/** Sets whether is the full charge cycle start. */
@CanIgnoreReturnValue
public Builder setBatteryLevel(int batteryLevel) {
this.mBatteryLevel = batteryLevel;
public Builder setIsFullChargeCycleStart(boolean isFullChargeCycleStart) {
this.mIsFullChargeCycleStart = isFullChargeCycleStart;
return this;
}
/** Sets the battery status. */
/** Sets the consumer type. */
@CanIgnoreReturnValue
public Builder setBatteryStatus(int batteryStatus) {
this.mBatteryStatus = batteryStatus;
public Builder setBatteryInformation(String batteryInformation) {
this.mBatteryInformation = batteryInformation;
return this;
}
/** Sets the battery health. */
/** Sets the consumer type. */
@CanIgnoreReturnValue
public Builder setBatteryHealth(int batteryHealth) {
this.mBatteryHealth = batteryHealth;
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);
public Builder setBatteryInformationDebug(String batteryInformationDebug) {
this.mBatteryInformationDebug = batteryInformationDebug;
return this;
}
@@ -374,22 +223,12 @@ public class BatteryState {
return new BatteryState(
mUid,
mUserId,
mAppLabel,
mPackageName,
mIsHidden,
mBootTimestamp,
mTimestamp,
/*zoneId=*/ TimeZone.getDefault().getID(),
mTotalPower,
mConsumePower,
mPercentOfTotal,
mForegroundUsageTimeInMs,
mBackgroundUsageTimeInMs,
mDrainType,
mConsumerType,
mBatteryLevel,
mBatteryStatus,
mBatteryHealth);
mIsFullChargeCycleStart,
mBatteryInformation,
mBatteryInformationDebug);
}
private Builder() {}

View File

@@ -40,7 +40,7 @@ public abstract class BatteryStateDatabase extends RoomDatabase {
if (sBatteryStateDatabase == null) {
sBatteryStateDatabase =
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.
.allowMainThreadQueries()
.fallbackToDestructiveMigration()

View File

@@ -679,8 +679,19 @@ public final class BatteryChartPreferenceControllerTest {
final Map<Long, Map<String, BatteryHistEntry>> batteryHistoryMap = new HashMap<>();
for (int index = 0; index < numOfHours; index++) {
final ContentValues values = new ContentValues();
values.put("batteryLevel", Integer.valueOf(100 - index));
values.put("consumePower", Integer.valueOf(100 - index));
final DeviceBatteryState deviceBatteryState =
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 Map<String, BatteryHistEntry> entryMap = new HashMap<>();
entryMap.put("fake_entry_key" + index, entry);

View File

@@ -138,8 +138,13 @@ public final class BatteryDiffEntryTest {
// Generates fake testing data.
final ContentValues values = getContentValuesWithType(
ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
values.put(BatteryHistEntry.KEY_DRAIN_TYPE,
Integer.valueOf(BatteryConsumer.POWER_COMPONENT_AMBIENT_DISPLAY));
final BatteryInformation batteryInformation =
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 BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry);
@@ -233,7 +238,13 @@ public final class BatteryDiffEntryTest {
final String expectedAppLabel = "fake app label";
final ContentValues values = getContentValuesWithType(
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 BatteryDiffEntry entry = createBatteryDiffEntry(10, batteryHistEntry);
@@ -461,7 +472,13 @@ public final class BatteryDiffEntryTest {
private BatteryDiffEntry createBatteryDiffEntry(
int consumerType, long uid, boolean isHidden) {
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);
return new BatteryDiffEntry(
mContext,

View File

@@ -124,7 +124,13 @@ public final class BatteryHistEntryTest {
public void testGetKey_consumerSystemType_returnExpectedString() {
final ContentValues values = getContentValuesWithType(
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);
assertThat(batteryHistEntry.getKey()).isEqualTo("S|1");
@@ -308,42 +314,40 @@ public final class BatteryHistEntryTest {
new String[]{
BatteryHistEntry.KEY_UID,
BatteryHistEntry.KEY_USER_ID,
BatteryHistEntry.KEY_APP_LABEL,
BatteryHistEntry.KEY_PACKAGE_NAME,
BatteryHistEntry.KEY_IS_HIDDEN,
BatteryHistEntry.KEY_BOOT_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_BATTERY_LEVEL,
BatteryHistEntry.KEY_BATTERY_STATUS,
BatteryHistEntry.KEY_BATTERY_HEALTH});
BatteryHistEntry.KEY_BATTERY_INFORMATION});
DeviceBatteryState deviceBatteryState =
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(
new Object[]{
Long.valueOf(1001),
Long.valueOf(UserHandle.getUserId(1001)),
"Settings",
"com.google.android.settings.battery",
Integer.valueOf(1),
Long.valueOf(bootTimestamp),
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(batteryLevel),
Integer.valueOf(BatteryManager.BATTERY_STATUS_FULL),
Integer.valueOf(BatteryManager.BATTERY_HEALTH_COLD)});
ConvertUtils.convertBatteryInformationToString(batteryInformation)});
cursor.moveToFirst();
return new BatteryHistEntry(cursor);
}

View File

@@ -148,23 +148,37 @@ public final class BatteryUsageContentProviderTest {
@Test
public void insert_batteryState_returnsExpectedResult() {
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();
values.put("uid", Long.valueOf(101L));
values.put("userId", Long.valueOf(1001L));
values.put("appLabel", new String("Settings"));
values.put("packageName", new String("com.android.settings"));
values.put("timestamp", Long.valueOf(2100021L));
values.put("isHidden", Boolean.valueOf(true));
values.put("totalPower", Double.valueOf(99.0));
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));
values.put(BatteryHistEntry.KEY_UID, Long.valueOf(101L));
values.put(BatteryHistEntry.KEY_USER_ID, Long.valueOf(1001L));
values.put(BatteryHistEntry.KEY_PACKAGE_NAME, new String("com.android.settings"));
values.put(BatteryHistEntry.KEY_TIMESTAMP, Long.valueOf(2100021L));
values.put(BatteryHistEntry.KEY_CONSUMER_TYPE, Integer.valueOf(2));
values.put(BatteryHistEntry.KEY_IS_FULL_CHARGE_CYCLE_START, true);
values.put(BatteryHistEntry.KEY_BATTERY_INFORMATION, expectedBatteryInformationString);
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.get(0).uid).isEqualTo(101L);
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).isHidden).isTrue();
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).batteryLevel).isEqualTo(51);
assertThat(states.get(0).batteryStatus).isEqualTo(2);
assertThat(states.get(0).batteryHealth).isEqualTo(3);
assertThat(states.get(0).isFullChargeCycleStart).isTrue();
assertThat(states.get(0).batteryInformation).isEqualTo(expectedBatteryInformationString);
}
@Test
public void insert_partialFieldsContentValues_returnsExpectedResult() {
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();
values.put("packageName", new String("fake_data"));
values.put("timestamp", Long.valueOf(2100022L));
values.put("batteryLevel", Integer.valueOf(52));
values.put("batteryStatus", Integer.valueOf(3));
values.put("batteryHealth", Integer.valueOf(2));
values.put(BatteryHistEntry.KEY_PACKAGE_NAME, new String("fake_data"));
values.put(BatteryHistEntry.KEY_TIMESTAMP, Long.valueOf(2100022L));
values.put(BatteryHistEntry.KEY_BATTERY_INFORMATION, expectedBatteryInformationString);
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.get(0).packageName).isEqualTo("fake_data");
assertThat(states.get(0).timestamp).isEqualTo(2100022L);
assertThat(states.get(0).batteryLevel).isEqualTo(52);
assertThat(states.get(0).batteryStatus).isEqualTo(3);
assertThat(states.get(0).batteryHealth).isEqualTo(2);
assertThat(states.get(0).batteryInformation).isEqualTo(expectedBatteryInformationString);
}
@Test

View File

@@ -96,34 +96,33 @@ public final class ConvertUtilsTest {
/*batteryHealth=*/ BatteryManager.BATTERY_HEALTH_COLD,
/*bootTimestamp=*/ 101L,
/*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_USER_ID))
.isEqualTo(UserHandle.getUserId(1001));
assertThat(values.getAsString(BatteryHistEntry.KEY_APP_LABEL))
.isEqualTo("Settings");
assertThat(values.getAsString(BatteryHistEntry.KEY_PACKAGE_NAME))
.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.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))
.isEqualTo(ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY);
assertThat(values.getAsInteger(BatteryHistEntry.KEY_BATTERY_LEVEL)).isEqualTo(12);
assertThat(values.getAsInteger(BatteryHistEntry.KEY_BATTERY_STATUS))
assertThat(batteryInformation.getAppLabel()).isEqualTo("Settings");
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);
assertThat(values.getAsInteger(BatteryHistEntry.KEY_BATTERY_HEALTH))
assertThat(deviceBatteryState.getBatteryHealth())
.isEqualTo(BatteryManager.BATTERY_HEALTH_COLD);
}
@@ -139,17 +138,19 @@ public final class ConvertUtilsTest {
/*bootTimestamp=*/ 101L,
/*timestamp=*/ 10001L);
assertThat(values.getAsLong(BatteryHistEntry.KEY_BOOT_TIMESTAMP))
.isEqualTo(101L);
final BatteryInformation batteryInformation =
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))
.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))
.isEqualTo(ConvertUtils.FAKE_PACKAGE_NAME);
}
@@ -499,17 +500,21 @@ public final class ConvertUtilsTest {
String packageName, String appLabel, double consumePower,
long uid, long foregroundUsageTimeInMs, long backgroundUsageTimeInMs) {
// Only insert required fields.
final BatteryInformation batteryInformation =
BatteryInformation
.newBuilder()
.setAppLabel(appLabel)
.setConsumePower(consumePower)
.setForegroundUsageTimeInMs(foregroundUsageTimeInMs)
.setBackgroundUsageTimeInMs(backgroundUsageTimeInMs)
.build();
final ContentValues values = new ContentValues();
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_CONSUMER_TYPE,
Integer.valueOf(ConvertUtils.CONSUMER_TYPE_UID_BATTERY));
values.put(BatteryHistEntry.KEY_CONSUME_POWER, consumePower);
values.put(BatteryHistEntry.KEY_FOREGROUND_USAGE_TIME,
Long.valueOf(foregroundUsageTimeInMs));
values.put(BatteryHistEntry.KEY_BACKGROUND_USAGE_TIME,
Long.valueOf(backgroundUsageTimeInMs));
values.put(BatteryHistEntry.KEY_BATTERY_INFORMATION,
ConvertUtils.convertBatteryInformationToString(batteryInformation));
return new BatteryHistEntry(values);
}

View File

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

View File

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

View File

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

View File

@@ -18,9 +18,12 @@ package com.android.settings.fuelgauge.batteryusage.db;
import static com.google.common.truth.Truth.assertThat;
import android.content.Intent;
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.Test;
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_HEALTH = BatteryManager.BATTERY_HEALTH_COLD;
private Intent mBatteryIntent;
private BatteryInformation mBatteryInformation;
@Before
public void setUp() {
mBatteryIntent = new Intent(Intent.ACTION_BATTERY_CHANGED);
// Inserts the battery states into intent.
mBatteryIntent.putExtra(BatteryManager.EXTRA_LEVEL, BATTERY_LEVEL);
mBatteryIntent.putExtra(BatteryManager.EXTRA_STATUS, BATTERY_STATUS);
mBatteryIntent.putExtra(BatteryManager.EXTRA_HEALTH, BATTERY_HEALTH);
final DeviceBatteryState deviceBatteryState =
DeviceBatteryState
.newBuilder()
.setBatteryLevel(BATTERY_LEVEL)
.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
public void testBuilder_returnsExpectedResult() {
mBatteryIntent.putExtra(BatteryManager.EXTRA_SCALE, 100);
BatteryState state = create(mBatteryIntent);
BatteryState state = create(mBatteryInformation);
// Verifies the app relative information.
assertThat(state.uid).isEqualTo(1001L);
assertThat(state.userId).isEqualTo(100L);
assertThat(state.appLabel).isEqualTo("Settings");
assertThat(state.packageName).isEqualTo("com.android.settings");
assertThat(state.isHidden).isTrue();
assertThat(state.bootTimestamp).isEqualTo(101L);
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.batteryLevel).isEqualTo(BATTERY_LEVEL);
assertThat(state.batteryStatus).isEqualTo(BATTERY_STATUS);
assertThat(state.batteryHealth).isEqualTo(BATTERY_HEALTH);
assertThat(state.isFullChargeCycleStart).isTrue();
assertThat(state.batteryInformation).isEqualTo(
ConvertUtils.convertBatteryInformationToString(mBatteryInformation));
}
@Test
public void create_withoutBatteryScale_returnsStateWithInvalidLevel() {
BatteryState state = create(mBatteryIntent);
assertThat(state.batteryLevel).isEqualTo(-1);
}
private static BatteryState create(Intent intent) {
private static BatteryState create(BatteryInformation batteryInformation) {
return BatteryState.newBuilder()
.setUid(1001L)
.setUserId(100L)
.setAppLabel("Settings")
.setPackageName("com.android.settings")
.setIsHidden(true)
.setBootTimestamp(101L)
.setTimestamp(100001L)
.setTotalPower(100f)
.setConsumePower(3f)
.setPercentOfTotal(10f)
.setForegroundUsageTimeInMs(60000)
.setBackgroundUsageTimeInMs(10000)
.setDrainType(1)
.setConsumerType(2)
.setBatteryIntent(intent)
.setIsFullChargeCycleStart(true)
.setBatteryInformation(
ConvertUtils.convertBatteryInformationToString(batteryInformation))
.build();
}
}

View File

@@ -23,6 +23,9 @@ import android.os.UserManager;
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.BatteryStateDao;
import com.android.settings.fuelgauge.batteryusage.db.BatteryStateDatabase;
@@ -75,26 +78,44 @@ public class BatteryTestUtils {
/** Inserts a fake data into the database for testing. */
public static void insertDataToBatteryStateDatabase(
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 =
new BatteryState(
/*uid=*/ 1001L,
/*userId=*/ 100L,
/*appLabel=*/ "Settings",
packageName,
/*isHidden=*/ true,
/*bootTimestamp=*/ timestamp - 1,
timestamp,
/*zoneId=*/ "Europe/Paris",
/*totalPower=*/ 100f,
/*consumePower=*/ 0.3f,
/*percentOfTotal=*/ 10f,
/*foregroundUsageTimeInMs=*/ 60000,
/*backgroundUsageTimeInMs=*/ 10000,
/*drainType=*/ 1,
/*consumerType=*/ 2,
/*batteryLevel=*/ 31,
/*batteryStatus=*/ 0,
/*batteryHealth=*/ 0);
/*isFullChargeCycleStart=*/ false,
ConvertUtils.convertBatteryInformationToString(batteryInformation),
"");
BatteryStateDao dao =
BatteryStateDatabase.getInstance(context).batteryStateDao();
if (multiple) {