Files
app_Settings/src/com/android/settings/fuelgauge/batteryusage/BatteryHistEntry.java
Kuan Wang 53a761f55b Populate new fields foreground_service_usage_time_in_ms,
foreground_usage_consume_power, foreground_service_usage_consume_power,
background_usage_consume_power and cached_usage_consume_power into
database and pass them to UI.

Test: make RunSettingsRoboTests + manual
Bug: 256123455
Bug: 258124768
Change-Id: Ic46032f67eff5898f9d4182c517bbebe478eca01
2022-11-29 11:42:26 +08:00

377 lines
17 KiB
Java

/*
* Copyright (C) 2022 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.settings.fuelgauge.batteryusage;
import android.content.ContentValues;
import android.database.Cursor;
import android.os.BatteryConsumer;
import android.util.Log;
import java.time.Duration;
/** A container class to carry data from {@link ContentValues}. */
public class BatteryHistEntry {
private static final boolean DEBUG = false;
private static final String TAG = "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_PACKAGE_NAME = "packageName";
public static final String KEY_TIMESTAMP = "timestamp";
public static final String KEY_CONSUMER_TYPE = "consumerType";
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;
public final String mAppLabel;
public final String mPackageName;
// Whether the data is represented as system component or not?
public final boolean mIsHidden;
// Records the timestamp relative information.
public final long mBootTimestamp;
public final long mTimestamp;
public final String mZoneId;
// Records the battery usage relative information.
public final double mTotalPower;
public final double mConsumePower;
public final double mForegroundUsageConsumePower;
public final double mForegroundServiceUsageConsumePower;
public final double mBackgroundUsageConsumePower;
public final double mCachedUsageConsumePower;
public final double mPercentOfTotal;
public final long mForegroundUsageTimeInMs;
public final long mForegroundServiceUsageTimeInMs;
public final long mBackgroundUsageTimeInMs;
@BatteryConsumer.PowerComponent
public final int mDrainType;
@ConvertUtils.ConsumerType
public final int mConsumerType;
// Records the battery intent relative information.
public final int mBatteryLevel;
public final int mBatteryStatus;
public final int mBatteryHealth;
private String mKey = null;
private boolean mIsValidEntry = true;
public BatteryHistEntry(ContentValues values) {
mUid = getLong(values, KEY_UID);
mUserId = getLong(values, KEY_USER_ID);
mPackageName = getString(values, KEY_PACKAGE_NAME);
mTimestamp = getLong(values, KEY_TIMESTAMP);
mConsumerType = getInteger(values, KEY_CONSUMER_TYPE);
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();
mForegroundUsageConsumePower = batteryInformation.getForegroundUsageConsumePower();
mForegroundServiceUsageConsumePower =
batteryInformation.getForegroundServiceUsageConsumePower();
mBackgroundUsageConsumePower = batteryInformation.getBackgroundUsageConsumePower();
mCachedUsageConsumePower = batteryInformation.getCachedUsageConsumePower();
mPercentOfTotal = batteryInformation.getPercentOfTotal();
mForegroundUsageTimeInMs = batteryInformation.getForegroundUsageTimeInMs();
mForegroundServiceUsageTimeInMs = batteryInformation.getForegroundServiceUsageTimeInMs();
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);
mPackageName = getString(cursor, KEY_PACKAGE_NAME);
mTimestamp = getLong(cursor, KEY_TIMESTAMP);
mConsumerType = getInteger(cursor, KEY_CONSUMER_TYPE);
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();
mForegroundUsageConsumePower = batteryInformation.getForegroundUsageConsumePower();
mForegroundServiceUsageConsumePower =
batteryInformation.getForegroundServiceUsageConsumePower();
mBackgroundUsageConsumePower = batteryInformation.getBackgroundUsageConsumePower();
mCachedUsageConsumePower = batteryInformation.getCachedUsageConsumePower();
mPercentOfTotal = batteryInformation.getPercentOfTotal();
mForegroundUsageTimeInMs = batteryInformation.getForegroundUsageTimeInMs();
mForegroundServiceUsageTimeInMs = batteryInformation.getForegroundServiceUsageTimeInMs();
mBackgroundUsageTimeInMs = batteryInformation.getBackgroundUsageTimeInMs();
mDrainType = batteryInformation.getDrainType();
final DeviceBatteryState deviceBatteryState = batteryInformation.getDeviceBatteryState();
mBatteryLevel = deviceBatteryState.getBatteryLevel();
mBatteryStatus = deviceBatteryState.getBatteryStatus();
mBatteryHealth = deviceBatteryState.getBatteryHealth();
}
private BatteryHistEntry(
BatteryHistEntry fromEntry,
long bootTimestamp,
long timestamp,
double totalPower,
double consumePower,
double foregroundUsageConsumePower,
double foregroundServiceUsageConsumePower,
double backgroundUsageConsumePower,
double cachedUsageConsumePower,
long foregroundUsageTimeInMs,
long foregroundServiceUsageTimeInMs,
long backgroundUsageTimeInMs,
int batteryLevel) {
mUid = fromEntry.mUid;
mUserId = fromEntry.mUserId;
mAppLabel = fromEntry.mAppLabel;
mPackageName = fromEntry.mPackageName;
mIsHidden = fromEntry.mIsHidden;
mBootTimestamp = bootTimestamp;
mTimestamp = timestamp;
mZoneId = fromEntry.mZoneId;
mTotalPower = totalPower;
mConsumePower = consumePower;
mForegroundUsageConsumePower = foregroundUsageConsumePower;
mForegroundServiceUsageConsumePower = foregroundServiceUsageConsumePower;
mBackgroundUsageConsumePower = backgroundUsageConsumePower;
mCachedUsageConsumePower = cachedUsageConsumePower;
mPercentOfTotal = fromEntry.mPercentOfTotal;
mForegroundUsageTimeInMs = foregroundUsageTimeInMs;
mForegroundServiceUsageTimeInMs = foregroundServiceUsageTimeInMs;
mBackgroundUsageTimeInMs = backgroundUsageTimeInMs;
mDrainType = fromEntry.mDrainType;
mConsumerType = fromEntry.mConsumerType;
mBatteryLevel = batteryLevel;
mBatteryStatus = fromEntry.mBatteryStatus;
mBatteryHealth = fromEntry.mBatteryHealth;
}
/** Whether this {@link BatteryHistEntry} is valid or not? */
public boolean isValidEntry() {
return mIsValidEntry;
}
/** Whether this {@link BatteryHistEntry} is user consumer or not. */
public boolean isUserEntry() {
return mConsumerType == ConvertUtils.CONSUMER_TYPE_USER_BATTERY;
}
/** Whether this {@link BatteryHistEntry} is app consumer or not. */
public boolean isAppEntry() {
return mConsumerType == ConvertUtils.CONSUMER_TYPE_UID_BATTERY;
}
/** Whether this {@link BatteryHistEntry} is system consumer or not. */
public boolean isSystemEntry() {
return mConsumerType == ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY;
}
/** Gets an identifier to represent this {@link BatteryHistEntry}. */
public String getKey() {
if (mKey == null) {
switch (mConsumerType) {
case ConvertUtils.CONSUMER_TYPE_UID_BATTERY:
mKey = Long.toString(mUid);
break;
case ConvertUtils.CONSUMER_TYPE_SYSTEM_BATTERY:
mKey = "S|" + mDrainType;
break;
case ConvertUtils.CONSUMER_TYPE_USER_BATTERY:
mKey = "U|" + mUserId;
break;
}
}
return mKey;
}
@Override
public String toString() {
final String recordAtDateTime =
ConvertUtils.utcToLocalTime(/*context=*/ null, mTimestamp);
final StringBuilder builder = new StringBuilder()
.append("\nBatteryHistEntry{")
.append(String.format("\n\tpackage=%s|label=%s|uid=%d|userId=%d|isHidden=%b",
mPackageName, mAppLabel, mUid, mUserId, mIsHidden))
.append(String.format("\n\ttimestamp=%s|zoneId=%s|bootTimestamp=%d",
recordAtDateTime, mZoneId, Duration.ofMillis(mBootTimestamp).getSeconds()))
.append(String.format("\n\tusage=%f|total=%f|consume=%f",
mPercentOfTotal, mTotalPower, mConsumePower))
.append(String.format("\n\tforeground=%f|foregroundService=%f",
mForegroundUsageConsumePower, mForegroundServiceUsageConsumePower))
.append(String.format("\n\tbackground=%f|cached=%f",
mBackgroundUsageConsumePower, mCachedUsageConsumePower))
.append(String.format("\n\telapsedTime=%d|%d|%d",
Duration.ofMillis(mForegroundUsageTimeInMs).getSeconds(),
Duration.ofMillis(mForegroundServiceUsageTimeInMs).getSeconds(),
Duration.ofMillis(mBackgroundUsageTimeInMs).getSeconds()))
.append(String.format("\n\tdrainType=%d|consumerType=%d",
mDrainType, mConsumerType))
.append(String.format("\n\tbattery=%d|status=%d|health=%d\n}",
mBatteryLevel, mBatteryStatus, mBatteryHealth));
return builder.toString();
}
private int getInteger(ContentValues values, String key) {
if (values != null && values.containsKey(key)) {
return values.getAsInteger(key);
}
mIsValidEntry = false;
return 0;
}
private int getInteger(Cursor cursor, String key) {
final int columnIndex = cursor.getColumnIndex(key);
if (columnIndex >= 0) {
return cursor.getInt(columnIndex);
}
mIsValidEntry = false;
return 0;
}
private long getLong(ContentValues values, String key) {
if (values != null && values.containsKey(key)) {
return values.getAsLong(key);
}
mIsValidEntry = false;
return 0L;
}
private long getLong(Cursor cursor, String key) {
final int columnIndex = cursor.getColumnIndex(key);
if (columnIndex >= 0) {
return cursor.getLong(columnIndex);
}
mIsValidEntry = false;
return 0L;
}
private String getString(ContentValues values, String key) {
if (values != null && values.containsKey(key)) {
return values.getAsString(key);
}
mIsValidEntry = false;
return null;
}
private String getString(Cursor cursor, String key) {
final int columnIndex = cursor.getColumnIndex(key);
if (columnIndex >= 0) {
return cursor.getString(columnIndex);
}
mIsValidEntry = false;
return null;
}
/** Creates new {@link BatteryHistEntry} from interpolation. */
public static BatteryHistEntry interpolate(
long slotTimestamp,
long upperTimestamp,
double ratio,
BatteryHistEntry lowerHistEntry,
BatteryHistEntry upperHistEntry) {
final double totalPower = interpolate(
lowerHistEntry == null ? 0 : lowerHistEntry.mTotalPower,
upperHistEntry.mTotalPower,
ratio);
final double consumePower = interpolate(
lowerHistEntry == null ? 0 : lowerHistEntry.mConsumePower,
upperHistEntry.mConsumePower,
ratio);
final double foregroundUsageConsumePower = interpolate(
lowerHistEntry == null ? 0 : lowerHistEntry.mForegroundUsageConsumePower,
upperHistEntry.mForegroundUsageConsumePower,
ratio);
final double foregroundServiceUsageConsumePower = interpolate(
lowerHistEntry == null ? 0 : lowerHistEntry.mForegroundServiceUsageConsumePower,
upperHistEntry.mForegroundServiceUsageConsumePower,
ratio);
final double backgroundUsageConsumePower = interpolate(
lowerHistEntry == null ? 0 : lowerHistEntry.mBackgroundUsageConsumePower,
upperHistEntry.mBackgroundUsageConsumePower,
ratio);
final double cachedUsageConsumePower = interpolate(
lowerHistEntry == null ? 0 : lowerHistEntry.mCachedUsageConsumePower,
upperHistEntry.mCachedUsageConsumePower,
ratio);
final double foregroundUsageTimeInMs = interpolate(
(double) (lowerHistEntry == null ? 0 : lowerHistEntry.mForegroundUsageTimeInMs),
(double) upperHistEntry.mForegroundUsageTimeInMs,
ratio);
final double foregroundServiceUsageTimeInMs = interpolate(
(double) (lowerHistEntry == null
? 0
: lowerHistEntry.mForegroundServiceUsageTimeInMs),
(double) upperHistEntry.mForegroundServiceUsageTimeInMs,
ratio);
final double backgroundUsageTimeInMs = interpolate(
(double) (lowerHistEntry == null ? 0 : lowerHistEntry.mBackgroundUsageTimeInMs),
(double) upperHistEntry.mBackgroundUsageTimeInMs,
ratio);
// Checks whether there is any abnormal cases!
if (upperHistEntry.mConsumePower < consumePower
|| upperHistEntry.mForegroundUsageConsumePower < foregroundUsageConsumePower
|| upperHistEntry.mForegroundServiceUsageConsumePower
< foregroundServiceUsageConsumePower
|| upperHistEntry.mBackgroundUsageConsumePower < backgroundUsageConsumePower
|| upperHistEntry.mCachedUsageConsumePower < cachedUsageConsumePower
|| upperHistEntry.mForegroundUsageTimeInMs < foregroundUsageTimeInMs
|| upperHistEntry.mForegroundServiceUsageTimeInMs < foregroundServiceUsageTimeInMs
|| upperHistEntry.mBackgroundUsageTimeInMs < backgroundUsageTimeInMs) {
if (DEBUG) {
Log.w(TAG, String.format(
"abnormal interpolation:\nupper:%s\nlower:%s",
upperHistEntry, lowerHistEntry));
}
}
final double batteryLevel =
lowerHistEntry == null
? upperHistEntry.mBatteryLevel
: interpolate(
lowerHistEntry.mBatteryLevel,
upperHistEntry.mBatteryLevel,
ratio);
return new BatteryHistEntry(
upperHistEntry,
/*bootTimestamp=*/ upperHistEntry.mBootTimestamp
- (upperTimestamp - slotTimestamp),
/*timestamp=*/ slotTimestamp,
totalPower,
consumePower,
foregroundUsageConsumePower,
foregroundServiceUsageConsumePower,
backgroundUsageConsumePower,
cachedUsageConsumePower,
Math.round(foregroundUsageTimeInMs),
Math.round(foregroundServiceUsageTimeInMs),
Math.round(backgroundUsageTimeInMs),
(int) Math.round(batteryLevel));
}
private static double interpolate(double v1, double v2, double ratio) {
return v1 + ratio * (v2 - v1);
}
}