Merge "Add log of BatteryEvent and BatteryUsageSlot while dumpping." into main

This commit is contained in:
Xinyi Mao
2023-11-08 08:06:44 +00:00
committed by Android (Google) Code Review
4 changed files with 92 additions and 8 deletions

View File

@@ -39,11 +39,16 @@ public final class BugReportContentProvider extends ContentProvider {
@Override
public void dump(FileDescriptor fd, PrintWriter writer, String[] args) {
final Context context = getContext();
Context context = getContext();
if (context == null) {
Log.w(TAG, "failed to dump BatteryUsage state: null context");
return;
}
context = context.getApplicationContext();
if (context == null) {
Log.w(TAG, "failed to dump BatteryUsage state: null application context");
return;
}
if (DatabaseUtils.isWorkProfile(context)) {
Log.w(TAG, "ignore battery usage states dump in the work profile");
return;
@@ -51,6 +56,9 @@ public final class BugReportContentProvider extends ContentProvider {
writer.println("dump BatteryUsage and AppUsage states:");
LogUtils.dumpBatteryUsageDatabaseHist(context, writer);
LogUtils.dumpAppUsageDatabaseHist(context, writer);
LogUtils.dumpBatteryUsageSlotDatabaseHist(context, writer);
LogUtils.dumpBatteryEventDatabaseHist(context, writer);
LogUtils.dumpBatteryStateDatabaseHist(context, writer);
}
@Override

View File

@@ -19,18 +19,26 @@ package com.android.settings.fuelgauge.batteryusage.bugreport;
import android.content.Context;
import android.util.Log;
import com.android.settings.fuelgauge.BatteryUtils;
import com.android.settings.fuelgauge.batteryusage.BatteryUsageSlot;
import com.android.settings.fuelgauge.batteryusage.ConvertUtils;
import com.android.settings.fuelgauge.batteryusage.DatabaseUtils;
import com.android.settings.fuelgauge.batteryusage.db.AppUsageEventDao;
import com.android.settings.fuelgauge.batteryusage.db.AppUsageEventEntity;
import com.android.settings.fuelgauge.batteryusage.db.BatteryEventDao;
import com.android.settings.fuelgauge.batteryusage.db.BatteryEventEntity;
import com.android.settings.fuelgauge.batteryusage.db.BatteryState;
import com.android.settings.fuelgauge.batteryusage.db.BatteryStateDao;
import com.android.settings.fuelgauge.batteryusage.db.BatteryStateDatabase;
import com.android.settings.fuelgauge.batteryusage.db.BatteryUsageSlotDao;
import com.android.settings.fuelgauge.batteryusage.db.BatteryUsageSlotEntity;
import java.io.PrintWriter;
import java.time.Clock;
import java.time.Duration;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Function;
/** A utility class to aggregate and provide required log data. */
public final class LogUtils {
@@ -47,8 +55,7 @@ public final class LogUtils {
// Dumps phenotype environments.
DatabaseUtils.dump(context, writer);
writer.flush();
final BatteryStateDao dao =
BatteryStateDatabase.getInstance(context.getApplicationContext()).batteryStateDao();
final BatteryStateDao dao = BatteryStateDatabase.getInstance(context).batteryStateDao();
final long timeOffset = Clock.systemUTC().millis() - DUMP_TIME_OFFSET.toMillis();
// Gets all distinct timestamps.
@@ -69,22 +76,73 @@ public final class LogUtils {
Log.w(TAG, "\t" + formattedTimestamp);
});
writer.flush();
}
static void dumpBatteryStateDatabaseHist(Context context, PrintWriter writer) {
final BatteryStateDao dao = BatteryStateDatabase.getInstance(context).batteryStateDao();
writer.println("\n\tBatteryState DatabaseHistory:");
final List<BatteryState> stateList =
dao.getAllAfter(Clock.systemUTC().millis() - DUMP_TIME_OFFSET_FOR_ENTRY.toMillis());
stateList.stream().forEach(state -> writer.println(state));
dumpListItems(writer, stateList, state -> state);
}
static void dumpAppUsageDatabaseHist(Context context, PrintWriter writer) {
final AppUsageEventDao dao =
BatteryStateDatabase.getInstance(context.getApplicationContext())
.appUsageEventDao();
final AppUsageEventDao dao = BatteryStateDatabase.getInstance(context).appUsageEventDao();
writer.println("\n\tApp DatabaseHistory:");
final List<AppUsageEventEntity> eventList =
dao.getAllAfter(Clock.systemUTC().millis() - DUMP_TIME_OFFSET_FOR_ENTRY.toMillis());
eventList.stream().forEach(event -> writer.println(event));
dumpListItems(writer, eventList, event -> event);
}
static void dumpBatteryUsageSlotDatabaseHist(Context context, PrintWriter writer) {
final BatteryUsageSlotDao dao =
BatteryStateDatabase.getInstance(context).batteryUsageSlotDao();
writer.println("\n\tBattery Usage Slot DatabaseHistory:");
final List<BatteryUsageSlotEntity> entities =
dao.getAllAfterForLog(getLastFullChargeTimestamp(context));
dumpListItems(
writer,
entities,
entity ->
BatteryUtils.parseProtoFromString(
entity.batteryUsageSlot, BatteryUsageSlot.getDefaultInstance()));
}
static void dumpBatteryEventDatabaseHist(Context context, PrintWriter writer) {
final BatteryEventDao dao = BatteryStateDatabase.getInstance(context).batteryEventDao();
writer.println("\n\tBattery Event DatabaseHistory:");
final List<BatteryEventEntity> entities =
dao.getAllAfterForLog(getLastFullChargeTimestamp(context));
dumpListItems(writer, entities, entity -> entity);
}
private static <T, S> void dumpListItems(
PrintWriter writer, List<T> itemList, Function<T, S> itemConverter) {
final AtomicInteger counter = new AtomicInteger(0);
try {
itemList.forEach(
item -> {
writer.println(itemConverter.apply(item));
if (counter.incrementAndGet() % 20 == 0) {
writer.flush();
}
});
} catch (RuntimeException e) {
Log.e(TAG, "dumpListItems() error: ", e);
}
writer.flush();
}
private static long getLastFullChargeTimestamp(Context context) {
final BatteryEventDao dao = BatteryStateDatabase.getInstance(context).batteryEventDao();
try {
final Long lastFullChargeTimestamp = dao.getLastFullChargeTimestampForLog();
return lastFullChargeTimestamp != null ? lastFullChargeTimestamp : 0L;
} catch (RuntimeException e) {
Log.e(TAG, "getLastFullChargeTimestamp() error: ", e);
return 0L;
}
}
private LogUtils() {}
}

View File

@@ -42,6 +42,12 @@ public interface BatteryEventDao {
+ " WHERE batteryEventType = 3") // BatteryEventType.FULL_CHARGED = 3
Cursor getLastFullChargeTimestamp();
/** Gets the {@link Long} of the last full charge time . */
@Query(
"SELECT MAX(timestamp) FROM BatteryEventEntity"
+ " WHERE batteryEventType = 3") // BatteryEventType.FULL_CHARGED = 3
Long getLastFullChargeTimestampForLog();
/** Gets the {@link Cursor} of all recorded data after a specific timestamp. */
@Query(
"SELECT * FROM BatteryEventEntity"
@@ -49,6 +55,12 @@ public interface BatteryEventDao {
+ " ORDER BY timestamp DESC")
Cursor getAllAfter(long timestamp, List<Integer> batteryEventTypes);
/** Gets all recorded data after a specific timestamp for log.*/
@Query(
"SELECT * FROM BatteryEventEntity "
+ "WHERE timestamp >= :timestamp ORDER BY timestamp DESC")
List<BatteryEventEntity> getAllAfterForLog(long timestamp);
/** Deletes all recorded data before a specific timestamp. */
@Query("DELETE FROM BatteryEventEntity WHERE timestamp <= :timestamp")
void clearAllBefore(long timestamp);

View File

@@ -42,6 +42,12 @@ public interface BatteryUsageSlotDao {
+ " ORDER BY timestamp ASC")
Cursor getAllAfter(long timestamp);
/** Gets all recorded data after a specific timestamp for log.*/
@Query(
"SELECT * FROM BatteryUsageSlotEntity WHERE timestamp >= :timestamp"
+ " ORDER BY timestamp DESC")
List<BatteryUsageSlotEntity> getAllAfterForLog(long timestamp);
/** Deletes all recorded data before a specific timestamp. */
@Query("DELETE FROM BatteryUsageSlotEntity WHERE timestamp <= :timestamp")
void clearAllBefore(long timestamp);