Update how UsageStats timestamps are written to disk.
When writing UsageStats timestamps to disk in proto, we offset the time by the begin time to save storage space. However, there was logic which reset default timestamp values of 0 to begin time for those stats. This CL standardizes how timestamps are written to disk in proto for UsageStats and updates the parsers. Since backup and restore use database version 4, UsageStatsProto is also updated in addition to UsageStatsProtoV2. Bug: 155149300 Test: atest UsageStatsDatabaseTest Test: atest android.app.usage.cts.UsageStatsTest Change-Id: I624e4d56c91762b56eb1c3be67cd8df033fcac95
This commit is contained in:
@@ -126,7 +126,7 @@ public class UsageStatsDatabaseTest {
|
||||
|
||||
mIntervalStats.majorVersion = 7;
|
||||
mIntervalStats.minorVersion = 8;
|
||||
mIntervalStats.beginTime = time;
|
||||
mIntervalStats.beginTime = time - 1;
|
||||
mIntervalStats.interactiveTracker.count = 2;
|
||||
mIntervalStats.interactiveTracker.duration = 111111;
|
||||
mIntervalStats.nonInteractiveTracker.count = 3;
|
||||
|
||||
@@ -253,10 +253,6 @@ public class IntervalStats {
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (event.mTimeStamp == 0) {
|
||||
//mTimestamp not set, assume default value 0 plus beginTime
|
||||
event.mTimeStamp = beginTime;
|
||||
}
|
||||
return event;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -149,10 +149,6 @@ final class UsageStatsProto {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (stats.mLastTimeUsed == 0) {
|
||||
// mLastTimeUsed was not assigned, assume default value of 0 plus beginTime;
|
||||
stats.mLastTimeUsed = statsOut.beginTime;
|
||||
}
|
||||
proto.end(token);
|
||||
}
|
||||
|
||||
@@ -289,10 +285,6 @@ final class UsageStatsProto {
|
||||
configActive = proto.readBoolean(IntervalStatsProto.Configuration.ACTIVE);
|
||||
break;
|
||||
case ProtoInputStream.NO_MORE_FIELDS:
|
||||
if (configStats.mLastTimeActive == 0) {
|
||||
//mLastTimeActive was not assigned, assume default value of 0 plus beginTime
|
||||
configStats.mLastTimeActive = statsOut.beginTime;
|
||||
}
|
||||
if (configActive) {
|
||||
statsOut.activeConfiguration = configStats.mConfiguration;
|
||||
}
|
||||
@@ -336,21 +328,21 @@ final class UsageStatsProto {
|
||||
// Package not in Stringpool for some reason, write full string instead
|
||||
proto.write(IntervalStatsProto.UsageStats.PACKAGE, usageStats.mPackageName);
|
||||
}
|
||||
// Time attributes stored as an offset of the beginTime.
|
||||
proto.write(IntervalStatsProto.UsageStats.LAST_TIME_ACTIVE_MS,
|
||||
usageStats.mLastTimeUsed - stats.beginTime);
|
||||
UsageStatsProtoV2.writeOffsetTimestamp(proto,
|
||||
IntervalStatsProto.UsageStats.LAST_TIME_ACTIVE_MS,
|
||||
usageStats.mLastTimeUsed, stats.beginTime);
|
||||
proto.write(IntervalStatsProto.UsageStats.TOTAL_TIME_ACTIVE_MS,
|
||||
usageStats.mTotalTimeInForeground);
|
||||
proto.write(IntervalStatsProto.UsageStats.LAST_EVENT,
|
||||
usageStats.mLastEvent);
|
||||
// Time attributes stored as an offset of the beginTime.
|
||||
proto.write(IntervalStatsProto.UsageStats.LAST_TIME_SERVICE_USED_MS,
|
||||
usageStats.mLastTimeForegroundServiceUsed - stats.beginTime);
|
||||
UsageStatsProtoV2.writeOffsetTimestamp(proto,
|
||||
IntervalStatsProto.UsageStats.LAST_TIME_SERVICE_USED_MS,
|
||||
usageStats.mLastTimeForegroundServiceUsed, stats.beginTime);
|
||||
proto.write(IntervalStatsProto.UsageStats.TOTAL_TIME_SERVICE_USED_MS,
|
||||
usageStats.mTotalTimeForegroundServiceUsed);
|
||||
// Time attributes stored as an offset of the beginTime.
|
||||
proto.write(IntervalStatsProto.UsageStats.LAST_TIME_VISIBLE_MS,
|
||||
usageStats.mLastTimeVisible - stats.beginTime);
|
||||
UsageStatsProtoV2.writeOffsetTimestamp(proto,
|
||||
IntervalStatsProto.UsageStats.LAST_TIME_VISIBLE_MS,
|
||||
usageStats.mLastTimeVisible, stats.beginTime);
|
||||
proto.write(IntervalStatsProto.UsageStats.TOTAL_TIME_VISIBLE_MS,
|
||||
usageStats.mTotalTimeVisible);
|
||||
proto.write(IntervalStatsProto.UsageStats.APP_LAUNCH_COUNT, usageStats.mAppLaunchCount);
|
||||
@@ -411,8 +403,9 @@ final class UsageStatsProto {
|
||||
throws IllegalArgumentException {
|
||||
final long token = proto.start(fieldId);
|
||||
configStats.mConfiguration.dumpDebug(proto, IntervalStatsProto.Configuration.CONFIG);
|
||||
proto.write(IntervalStatsProto.Configuration.LAST_TIME_ACTIVE_MS,
|
||||
configStats.mLastTimeActive - stats.beginTime);
|
||||
UsageStatsProtoV2.writeOffsetTimestamp(proto,
|
||||
IntervalStatsProto.Configuration.LAST_TIME_ACTIVE_MS,
|
||||
configStats.mLastTimeActive, stats.beginTime);
|
||||
proto.write(IntervalStatsProto.Configuration.TOTAL_TIME_ACTIVE_MS,
|
||||
configStats.mTotalTimeActive);
|
||||
proto.write(IntervalStatsProto.Configuration.COUNT, configStats.mActivationCount);
|
||||
@@ -439,7 +432,8 @@ final class UsageStatsProto {
|
||||
proto.write(IntervalStatsProto.Event.CLASS, event.mClass);
|
||||
}
|
||||
}
|
||||
proto.write(IntervalStatsProto.Event.TIME_MS, event.mTimeStamp - stats.beginTime);
|
||||
UsageStatsProtoV2.writeOffsetTimestamp(proto, IntervalStatsProto.Event.TIME_MS,
|
||||
event.mTimeStamp, stats.beginTime);
|
||||
proto.write(IntervalStatsProto.Event.FLAGS, event.mFlags);
|
||||
proto.write(IntervalStatsProto.Event.TYPE, event.mEventType);
|
||||
proto.write(IntervalStatsProto.Event.INSTANCE_ID, event.mInstanceId);
|
||||
@@ -566,10 +560,6 @@ final class UsageStatsProto {
|
||||
}
|
||||
break;
|
||||
case ProtoInputStream.NO_MORE_FIELDS:
|
||||
if (statsOut.endTime == 0) {
|
||||
// endTime not assigned, assume default value of 0 plus beginTime
|
||||
statsOut.endTime = statsOut.beginTime;
|
||||
}
|
||||
statsOut.upgradeIfNeeded();
|
||||
return;
|
||||
}
|
||||
@@ -585,7 +575,8 @@ final class UsageStatsProto {
|
||||
public static void write(OutputStream out, IntervalStats stats)
|
||||
throws IOException, IllegalArgumentException {
|
||||
final ProtoOutputStream proto = new ProtoOutputStream(out);
|
||||
proto.write(IntervalStatsProto.END_TIME_MS, stats.endTime - stats.beginTime);
|
||||
proto.write(IntervalStatsProto.END_TIME_MS,
|
||||
UsageStatsProtoV2.getOffsetTimestamp(stats.endTime, stats.beginTime));
|
||||
proto.write(IntervalStatsProto.MAJOR_VERSION, stats.majorVersion);
|
||||
proto.write(IntervalStatsProto.MINOR_VERSION, stats.minorVersion);
|
||||
// String pool should be written before the rest of the usage stats
|
||||
|
||||
@@ -30,6 +30,7 @@ import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
* UsageStats reader/writer V2 for Protocol Buffer format.
|
||||
@@ -37,6 +38,8 @@ import java.util.LinkedList;
|
||||
final class UsageStatsProtoV2 {
|
||||
private static final String TAG = "UsageStatsProtoV2";
|
||||
|
||||
private static final long ONE_HOUR_MS = TimeUnit.HOURS.toMillis(1);
|
||||
|
||||
// Static-only utility class.
|
||||
private UsageStatsProtoV2() {}
|
||||
|
||||
@@ -88,10 +91,6 @@ final class UsageStatsProtoV2 {
|
||||
UsageStatsObfuscatedProto.TOTAL_TIME_VISIBLE_MS);
|
||||
break;
|
||||
case ProtoInputStream.NO_MORE_FIELDS:
|
||||
// mLastTimeUsed was not read, assume default value of 0 plus beginTime
|
||||
if (stats.mLastTimeUsed == 0) {
|
||||
stats.mLastTimeUsed = beginTime;
|
||||
}
|
||||
return stats;
|
||||
}
|
||||
}
|
||||
@@ -219,10 +218,6 @@ final class UsageStatsProtoV2 {
|
||||
IntervalStatsObfuscatedProto.Configuration.ACTIVE);
|
||||
break;
|
||||
case ProtoInputStream.NO_MORE_FIELDS:
|
||||
// mLastTimeActive was not assigned, assume default value of 0 plus beginTime
|
||||
if (configStats.mLastTimeActive == 0) {
|
||||
configStats.mLastTimeActive = stats.beginTime;
|
||||
}
|
||||
if (configActive) {
|
||||
stats.activeConfiguration = configStats.mConfiguration;
|
||||
}
|
||||
@@ -282,27 +277,40 @@ final class UsageStatsProtoV2 {
|
||||
EventObfuscatedProto.LOCUS_ID_TOKEN) - 1;
|
||||
break;
|
||||
case ProtoInputStream.NO_MORE_FIELDS:
|
||||
// timeStamp was not read, assume default value 0 plus beginTime
|
||||
if (event.mTimeStamp == 0) {
|
||||
event.mTimeStamp = beginTime;
|
||||
}
|
||||
return event.mPackageToken == PackagesTokenData.UNASSIGNED_TOKEN ? null : event;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void writeOffsetTimestamp(ProtoOutputStream proto, long fieldId,
|
||||
long timestamp, long beginTime) {
|
||||
// timestamps will only be written if they're after the begin time
|
||||
// a grace period of one hour before the begin time is allowed because of rollover logic
|
||||
final long rolloverGracePeriod = beginTime - ONE_HOUR_MS;
|
||||
if (timestamp > rolloverGracePeriod) {
|
||||
// time attributes are stored as an offset of the begin time (given offset)
|
||||
proto.write(fieldId, getOffsetTimestamp(timestamp, beginTime));
|
||||
}
|
||||
}
|
||||
|
||||
static long getOffsetTimestamp(long timestamp, long offset) {
|
||||
final long offsetTimestamp = timestamp - offset;
|
||||
// add one ms to timestamp if 0 to ensure it's written to proto (default values are ignored)
|
||||
return offsetTimestamp == 0 ? offsetTimestamp + 1 : offsetTimestamp;
|
||||
}
|
||||
|
||||
private static void writeUsageStats(ProtoOutputStream proto, final long beginTime,
|
||||
final UsageStats stats) throws IllegalArgumentException {
|
||||
// Time attributes stored as an offset of the beginTime.
|
||||
proto.write(UsageStatsObfuscatedProto.PACKAGE_TOKEN, stats.mPackageToken + 1);
|
||||
proto.write(UsageStatsObfuscatedProto.LAST_TIME_ACTIVE_MS, stats.mLastTimeUsed - beginTime);
|
||||
writeOffsetTimestamp(proto, UsageStatsObfuscatedProto.LAST_TIME_ACTIVE_MS,
|
||||
stats.mLastTimeUsed, beginTime);
|
||||
proto.write(UsageStatsObfuscatedProto.TOTAL_TIME_ACTIVE_MS, stats.mTotalTimeInForeground);
|
||||
proto.write(UsageStatsObfuscatedProto.LAST_TIME_SERVICE_USED_MS,
|
||||
stats.mLastTimeForegroundServiceUsed - beginTime);
|
||||
writeOffsetTimestamp(proto, UsageStatsObfuscatedProto.LAST_TIME_SERVICE_USED_MS,
|
||||
stats.mLastTimeForegroundServiceUsed, beginTime);
|
||||
proto.write(UsageStatsObfuscatedProto.TOTAL_TIME_SERVICE_USED_MS,
|
||||
stats.mTotalTimeForegroundServiceUsed);
|
||||
proto.write(UsageStatsObfuscatedProto.LAST_TIME_VISIBLE_MS,
|
||||
stats.mLastTimeVisible - beginTime);
|
||||
writeOffsetTimestamp(proto, UsageStatsObfuscatedProto.LAST_TIME_VISIBLE_MS,
|
||||
stats.mLastTimeVisible, beginTime);
|
||||
proto.write(UsageStatsObfuscatedProto.TOTAL_TIME_VISIBLE_MS, stats.mTotalTimeVisible);
|
||||
proto.write(UsageStatsObfuscatedProto.APP_LAUNCH_COUNT, stats.mAppLaunchCount);
|
||||
try {
|
||||
@@ -361,8 +369,8 @@ final class UsageStatsProtoV2 {
|
||||
throws IllegalArgumentException {
|
||||
configStats.mConfiguration.dumpDebug(proto,
|
||||
IntervalStatsObfuscatedProto.Configuration.CONFIG);
|
||||
proto.write(IntervalStatsObfuscatedProto.Configuration.LAST_TIME_ACTIVE_MS,
|
||||
configStats.mLastTimeActive - statsBeginTime);
|
||||
writeOffsetTimestamp(proto, IntervalStatsObfuscatedProto.Configuration.LAST_TIME_ACTIVE_MS,
|
||||
configStats.mLastTimeActive, statsBeginTime);
|
||||
proto.write(IntervalStatsObfuscatedProto.Configuration.TOTAL_TIME_ACTIVE_MS,
|
||||
configStats.mTotalTimeActive);
|
||||
proto.write(IntervalStatsObfuscatedProto.Configuration.COUNT, configStats.mActivationCount);
|
||||
@@ -375,7 +383,7 @@ final class UsageStatsProtoV2 {
|
||||
if (event.mClassToken != PackagesTokenData.UNASSIGNED_TOKEN) {
|
||||
proto.write(EventObfuscatedProto.CLASS_TOKEN, event.mClassToken + 1);
|
||||
}
|
||||
proto.write(EventObfuscatedProto.TIME_MS, event.mTimeStamp - statsBeginTime);
|
||||
writeOffsetTimestamp(proto, EventObfuscatedProto.TIME_MS, event.mTimeStamp, statsBeginTime);
|
||||
proto.write(EventObfuscatedProto.FLAGS, event.mFlags);
|
||||
proto.write(EventObfuscatedProto.TYPE, event.mEventType);
|
||||
proto.write(EventObfuscatedProto.INSTANCE_ID, event.mInstanceId);
|
||||
@@ -489,10 +497,6 @@ final class UsageStatsProtoV2 {
|
||||
}
|
||||
break;
|
||||
case ProtoInputStream.NO_MORE_FIELDS:
|
||||
// endTime not assigned, assume default value of 0 plus beginTime
|
||||
if (stats.endTime == 0) {
|
||||
stats.endTime = stats.beginTime;
|
||||
}
|
||||
// update the begin and end time stamps for all usage stats
|
||||
final int usageStatsSize = stats.packageStatsObfuscated.size();
|
||||
for (int i = 0; i < usageStatsSize; i++) {
|
||||
@@ -514,7 +518,8 @@ final class UsageStatsProtoV2 {
|
||||
public static void write(OutputStream out, IntervalStats stats)
|
||||
throws IOException, IllegalArgumentException {
|
||||
final ProtoOutputStream proto = new ProtoOutputStream(out);
|
||||
proto.write(IntervalStatsObfuscatedProto.END_TIME_MS, stats.endTime - stats.beginTime);
|
||||
proto.write(IntervalStatsObfuscatedProto.END_TIME_MS,
|
||||
getOffsetTimestamp(stats.endTime, stats.beginTime));
|
||||
proto.write(IntervalStatsObfuscatedProto.MAJOR_VERSION, stats.majorVersion);
|
||||
proto.write(IntervalStatsObfuscatedProto.MINOR_VERSION, stats.minorVersion);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user