Use the field isFullChargeCycleStart in database to get the last full
charge cycle start and remove the unused SharedPreference. Test: make RunSettingsRoboTests + manual Bug: 253553141 Change-Id: I74ef71775fa5d4871077f6d5573467aa5843bc6b
This commit is contained in:
@@ -80,6 +80,6 @@ public final class BatteryUsageBroadcastReceiver extends BroadcastReceiver {
|
||||
}
|
||||
|
||||
mFetchBatteryUsageData = true;
|
||||
BatteryUsageDataLoader.enqueueWork(context);
|
||||
BatteryUsageDataLoader.enqueueWork(context, /*isFullChargeStart=*/ true);
|
||||
}
|
||||
}
|
||||
|
@@ -40,9 +40,8 @@ import java.time.Duration;
|
||||
public class BatteryUsageContentProvider extends ContentProvider {
|
||||
private static final String TAG = "BatteryUsageContentProvider";
|
||||
|
||||
// TODO: Updates the duration to a more reasonable value for since-last-full-charge.
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
||||
public static final Duration QUERY_DURATION_HOURS = Duration.ofHours(28);
|
||||
public static final Duration QUERY_DURATION_HOURS = Duration.ofDays(6);
|
||||
|
||||
@VisibleForTesting(otherwise = VisibleForTesting.PRIVATE)
|
||||
public static final String QUERY_KEY_TIMESTAMP = "timestamp";
|
||||
@@ -141,7 +140,7 @@ public class BatteryUsageContentProvider extends ContentProvider {
|
||||
final long timestamp = mClock.millis();
|
||||
Cursor cursor = null;
|
||||
try {
|
||||
cursor = mBatteryStateDao.getCursorAfter(firstTimestamp);
|
||||
cursor = mBatteryStateDao.getCursorSinceLastFullCharge(firstTimestamp);
|
||||
} catch (RuntimeException e) {
|
||||
Log.e(TAG, "query() from:" + uri + " error:" + e);
|
||||
}
|
||||
|
@@ -37,15 +37,15 @@ public final class BatteryUsageDataLoader {
|
||||
private BatteryUsageDataLoader() {
|
||||
}
|
||||
|
||||
static void enqueueWork(Context context) {
|
||||
static void enqueueWork(final Context context, final boolean isFullChargeStart) {
|
||||
AsyncTask.execute(() -> {
|
||||
Log.d(TAG, "loadUsageDataSafely() in the AsyncTask");
|
||||
loadUsageDataSafely(context.getApplicationContext());
|
||||
loadUsageDataSafely(context.getApplicationContext(), isFullChargeStart);
|
||||
});
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static void loadUsageData(Context context) {
|
||||
static void loadUsageData(final Context context, final boolean isFullChargeStart) {
|
||||
final long start = System.currentTimeMillis();
|
||||
final BatteryUsageStats batteryUsageStats = DataProcessor.getBatteryUsageStats(context);
|
||||
final List<BatteryEntry> batteryEntryList =
|
||||
@@ -60,13 +60,14 @@ public final class BatteryUsageDataLoader {
|
||||
|
||||
// Uploads the BatteryEntry data into SettingsIntelligence.
|
||||
DatabaseUtils.sendBatteryEntryData(
|
||||
context, batteryEntryList, batteryUsageStats);
|
||||
context, batteryEntryList, batteryUsageStats, isFullChargeStart);
|
||||
DataProcessor.closeBatteryUsageStats(batteryUsageStats);
|
||||
}
|
||||
|
||||
private static void loadUsageDataSafely(Context context) {
|
||||
private static void loadUsageDataSafely(
|
||||
final Context context, final boolean isFullChargeStart) {
|
||||
try {
|
||||
loadUsageData(context);
|
||||
loadUsageData(context, isFullChargeStart);
|
||||
} catch (RuntimeException e) {
|
||||
Log.e(TAG, "loadUsageData:" + e);
|
||||
}
|
||||
|
@@ -92,7 +92,8 @@ public final class ConvertUtils {
|
||||
final int batteryStatus,
|
||||
final int batteryHealth,
|
||||
final long bootTimestamp,
|
||||
final long timestamp) {
|
||||
final long timestamp,
|
||||
final boolean isFullChargeStart) {
|
||||
final ContentValues values = new ContentValues();
|
||||
if (entry != null && batteryUsageStats != null) {
|
||||
values.put(BatteryHistEntry.KEY_UID, Long.valueOf(entry.getUid()));
|
||||
@@ -106,6 +107,8 @@ public final class ConvertUtils {
|
||||
values.put(BatteryHistEntry.KEY_PACKAGE_NAME, FAKE_PACKAGE_NAME);
|
||||
}
|
||||
values.put(BatteryHistEntry.KEY_TIMESTAMP, Long.valueOf(timestamp));
|
||||
values.put(BatteryHistEntry.KEY_IS_FULL_CHARGE_CYCLE_START,
|
||||
Boolean.valueOf(isFullChargeStart));
|
||||
final BatteryInformation batteryInformation =
|
||||
constructBatteryInformation(
|
||||
entry,
|
||||
@@ -163,7 +166,8 @@ public final class ConvertUtils {
|
||||
/*batteryStatus=*/ 0,
|
||||
/*batteryHealth=*/ 0,
|
||||
/*bootTimestamp=*/ 0,
|
||||
/*timestamp=*/ 0));
|
||||
/*timestamp=*/ 0,
|
||||
/*isFullChargeStart=*/ false));
|
||||
}
|
||||
|
||||
/** Converts UTC timestamp to human readable local time string. */
|
||||
|
@@ -19,7 +19,6 @@ import android.content.ContentResolver;
|
||||
import android.content.ContentValues;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
@@ -37,7 +36,6 @@ import androidx.annotation.VisibleForTesting;
|
||||
|
||||
import com.android.settings.fuelgauge.BatteryUtils;
|
||||
import com.android.settings.fuelgauge.batteryusage.db.BatteryStateDatabase;
|
||||
import com.android.settingslib.fuelgauge.BatteryStatus;
|
||||
|
||||
import java.time.Clock;
|
||||
import java.time.Duration;
|
||||
@@ -50,8 +48,6 @@ import java.util.Map;
|
||||
/** A utility class to operate battery usage database. */
|
||||
public final class DatabaseUtils {
|
||||
private static final String TAG = "DatabaseUtils";
|
||||
private static final String PREF_FILE_NAME = "battery_module_preference";
|
||||
private static final String PREF_FULL_CHARGE_TIMESTAMP_KEY = "last_full_charge_timestamp_key";
|
||||
/** Key for query parameter timestamp used in BATTERY_CONTENT_URI **/
|
||||
private static final String QUERY_KEY_TIMESTAMP = "timestamp";
|
||||
/** Clear memory threshold for device booting phase. **/
|
||||
@@ -89,8 +85,8 @@ public final class DatabaseUtils {
|
||||
public static Map<Long, Map<String, BatteryHistEntry>> getHistoryMapSinceLastFullCharge(
|
||||
Context context, Calendar calendar) {
|
||||
final long startTime = System.currentTimeMillis();
|
||||
final long lastFullChargeTimestamp =
|
||||
getStartTimestampForLastFullCharge(context, calendar);
|
||||
final long sixDaysAgoTimestamp = getTimestampSixDaysAgo(calendar);
|
||||
Log.d(TAG, "sixDayAgoTimestamp: " + sixDaysAgoTimestamp);
|
||||
// Builds the content uri everytime to avoid cache.
|
||||
final Uri batteryStateUri =
|
||||
new Uri.Builder()
|
||||
@@ -98,7 +94,7 @@ public final class DatabaseUtils {
|
||||
.authority(AUTHORITY)
|
||||
.appendPath(BATTERY_STATE_TABLE)
|
||||
.appendQueryParameter(
|
||||
QUERY_KEY_TIMESTAMP, Long.toString(lastFullChargeTimestamp))
|
||||
QUERY_KEY_TIMESTAMP, Long.toString(sixDaysAgoTimestamp))
|
||||
.build();
|
||||
|
||||
final Map<Long, Map<String, BatteryHistEntry>> resultMap =
|
||||
@@ -142,9 +138,10 @@ public final class DatabaseUtils {
|
||||
}
|
||||
|
||||
static List<ContentValues> sendBatteryEntryData(
|
||||
Context context,
|
||||
List<BatteryEntry> batteryEntryList,
|
||||
BatteryUsageStats batteryUsageStats) {
|
||||
final Context context,
|
||||
final List<BatteryEntry> batteryEntryList,
|
||||
final BatteryUsageStats batteryUsageStats,
|
||||
final boolean isFullChargeStart) {
|
||||
final long startTime = System.currentTimeMillis();
|
||||
final Intent intent = BatteryUtils.getBatteryIntent(context);
|
||||
if (intent == null) {
|
||||
@@ -186,7 +183,8 @@ public final class DatabaseUtils {
|
||||
batteryStatus,
|
||||
batteryHealth,
|
||||
snapshotBootTimestamp,
|
||||
snapshotTimestamp)));
|
||||
snapshotTimestamp,
|
||||
isFullChargeStart)));
|
||||
}
|
||||
|
||||
int size = 1;
|
||||
@@ -197,6 +195,8 @@ public final class DatabaseUtils {
|
||||
valuesList.toArray(valuesArray);
|
||||
try {
|
||||
size = resolver.bulkInsert(BATTERY_CONTENT_URI, valuesArray);
|
||||
Log.d(TAG, "insert() data into database with isFullChargeStart:"
|
||||
+ isFullChargeStart);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "bulkInsert() data into database error:\n" + e);
|
||||
}
|
||||
@@ -210,15 +210,18 @@ public final class DatabaseUtils {
|
||||
batteryStatus,
|
||||
batteryHealth,
|
||||
snapshotBootTimestamp,
|
||||
snapshotTimestamp);
|
||||
snapshotTimestamp,
|
||||
isFullChargeStart);
|
||||
try {
|
||||
resolver.insert(BATTERY_CONTENT_URI, contentValues);
|
||||
Log.d(TAG, "insert() data into database with isFullChargeStart:"
|
||||
+ isFullChargeStart);
|
||||
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "insert() data into database error:\n" + e);
|
||||
}
|
||||
valuesList.add(contentValues);
|
||||
}
|
||||
saveLastFullChargeTimestampPref(context, batteryStatus, batteryLevel, snapshotTimestamp);
|
||||
resolver.notifyChange(BATTERY_CONTENT_URI, /*observer=*/ null);
|
||||
Log.d(TAG, String.format("sendBatteryEntryData() size=%d in %d/ms",
|
||||
size, (System.currentTimeMillis() - startTime)));
|
||||
@@ -226,42 +229,6 @@ public final class DatabaseUtils {
|
||||
return valuesList;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static void saveLastFullChargeTimestampPref(
|
||||
Context context, int batteryStatus, int batteryLevel, long timestamp) {
|
||||
// Updates the SharedPreference only when timestamp is valid and phone is full charge.
|
||||
if (!BatteryStatus.isCharged(batteryStatus, batteryLevel)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final boolean success =
|
||||
getSharedPreferences(context)
|
||||
.edit()
|
||||
.putLong(PREF_FULL_CHARGE_TIMESTAMP_KEY, timestamp)
|
||||
.commit();
|
||||
if (!success) {
|
||||
Log.w(TAG, "saveLastFullChargeTimestampPref() fail: value=" + timestamp);
|
||||
}
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
static long getLastFullChargeTimestampPref(Context context) {
|
||||
return getSharedPreferences(context).getLong(PREF_FULL_CHARGE_TIMESTAMP_KEY, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the start timestamp for "since last full charge" battery usage chart.
|
||||
* If the last full charge happens within the last 7 days, returns the timestamp of last full
|
||||
* charge. Otherwise, returns the timestamp for 00:00 6 days before the calendar date.
|
||||
*/
|
||||
@VisibleForTesting
|
||||
static long getStartTimestampForLastFullCharge(
|
||||
Context context, Calendar calendar) {
|
||||
final long lastFullChargeTimestamp = getLastFullChargeTimestampPref(context);
|
||||
final long sixDayAgoTimestamp = getTimestampSixDaysAgo(calendar);
|
||||
return Math.max(lastFullChargeTimestamp, sixDayAgoTimestamp);
|
||||
}
|
||||
|
||||
private static Map<Long, Map<String, BatteryHistEntry>> loadHistoryMapFromContentProvider(
|
||||
Context context, Uri batteryStateUri) {
|
||||
final boolean isWorkProfileUser = isWorkProfile(context);
|
||||
@@ -313,13 +280,6 @@ public final class DatabaseUtils {
|
||||
}, CLEAR_MEMORY_DELAYED_MS);
|
||||
}
|
||||
|
||||
private static SharedPreferences getSharedPreferences(Context context) {
|
||||
return context
|
||||
.getApplicationContext() // ensures we bind it with application
|
||||
.createDeviceProtectedStorageContext()
|
||||
.getSharedPreferences(PREF_FILE_NAME, Context.MODE_PRIVATE);
|
||||
}
|
||||
|
||||
/** Returns the timestamp for 00:00 6 days before the calendar date. */
|
||||
private static long getTimestampSixDaysAgo(Calendar calendar) {
|
||||
Calendar startCalendar =
|
||||
|
@@ -39,7 +39,7 @@ public final class PeriodicJobReceiver extends BroadcastReceiver {
|
||||
Log.w(TAG, "do not refresh job for work profile action=" + action);
|
||||
return;
|
||||
}
|
||||
BatteryUsageDataLoader.enqueueWork(context);
|
||||
BatteryUsageDataLoader.enqueueWork(context, /*isFullChargeStart=*/ false);
|
||||
Log.d(TAG, "refresh periodic job from action=" + action);
|
||||
PeriodicJobManager.getInstance(context).refreshJob();
|
||||
DatabaseUtils.clearExpiredDataIfNeeded(context);
|
||||
|
@@ -41,9 +41,11 @@ public interface BatteryStateDao {
|
||||
@Query("SELECT * FROM BatteryState WHERE timestamp > :timestamp ORDER BY timestamp DESC")
|
||||
List<BatteryState> getAllAfter(long timestamp);
|
||||
|
||||
/** Gets the {@link Cursor} of all recorded data from a specific timestamp. */
|
||||
@Query("SELECT * FROM BatteryState WHERE timestamp >= :timestamp ORDER BY timestamp DESC")
|
||||
Cursor getCursorAfter(long timestamp);
|
||||
/** Gets the {@link Cursor} of all recorded data since last full charge within 7 days. */
|
||||
@Query("SELECT * FROM BatteryState WHERE timestamp >= :timestampSixDaysAgo AND timestamp >= "
|
||||
+ "(SELECT MAX(timestamp) FROM BatteryState WHERE isFullChargeCycleStart = 1)"
|
||||
+ " ORDER BY timestamp ASC")
|
||||
Cursor getCursorSinceLastFullCharge(long timestampSixDaysAgo);
|
||||
|
||||
/** Get the count of distinct timestamp after a specific timestamp. */
|
||||
@Query("SELECT COUNT(DISTINCT timestamp) FROM BatteryState WHERE timestamp > :timestamp")
|
||||
|
Reference in New Issue
Block a user