From 23f7206dbcc5cc0c18d3bec6a730fa4cc49284de Mon Sep 17 00:00:00 2001 From: Zhen Zhang Date: Tue, 9 Mar 2021 13:51:38 -0800 Subject: [PATCH] Create component used metrics in UsageStats Created a new metrics called mLastTimeComponentUsed in UsageStats. It is persisted and loaded as other metrics. Bug: 175829712 Test: core/tests/coretests/src/android/app/usage/UsageStatsTest Test: cts/UsageStatsTest Test: UsageStatsDatabaseTest Test: UsageStatsServiceTest Test: UsageStatsPersistenceTest Change-Id: I10cf5c40cf5955246a6a04e96ac0352b4ed29acd --- core/api/system-current.txt | 1 + core/java/android/app/usage/UsageStats.java | 25 +++++++++++++++++++ .../android/server/usagestatsservice.proto | 2 ++ .../android/server/usagestatsservice_v2.proto | 1 + .../app/usage/UsageStatsPersistenceTest.java | 3 ++- .../src/android/app/usage/UsageStatsTest.java | 16 ++++++++++++ .../server/usage/UsageStatsDatabaseTest.java | 1 + .../android/server/usage/UsageStatsProto.java | 7 ++++++ .../server/usage/UsageStatsProtoV2.java | 6 +++++ .../server/usage/UserUsageStatsService.java | 2 ++ 10 files changed, 63 insertions(+), 1 deletion(-) diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 39e259d7db9ab..9bbf265cdaa64 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -1795,6 +1795,7 @@ package android.app.usage { public final class UsageStats implements android.os.Parcelable { method public int getAppLaunchCount(); + method public long getLastTimeComponentUsed(); } public final class UsageStatsManager { diff --git a/core/java/android/app/usage/UsageStats.java b/core/java/android/app/usage/UsageStats.java index dcecd9070a742..5d50c5d778878 100644 --- a/core/java/android/app/usage/UsageStats.java +++ b/core/java/android/app/usage/UsageStats.java @@ -20,6 +20,7 @@ import static android.app.usage.UsageEvents.Event.ACTIVITY_DESTROYED; import static android.app.usage.UsageEvents.Event.ACTIVITY_PAUSED; import static android.app.usage.UsageEvents.Event.ACTIVITY_RESUMED; import static android.app.usage.UsageEvents.Event.ACTIVITY_STOPPED; +import static android.app.usage.UsageEvents.Event.APP_COMPONENT_USED; import static android.app.usage.UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE; import static android.app.usage.UsageEvents.Event.DEVICE_SHUTDOWN; import static android.app.usage.UsageEvents.Event.END_OF_DAY; @@ -108,6 +109,13 @@ public final class UsageStats implements Parcelable { */ public long mTotalTimeForegroundServiceUsed; + /** + * Last time this package's component is used, measured in milliseconds since the epoch. + * See {@link UsageEvents.Event#APP_COMPONENT_USED} + * @hide + */ + public long mLastTimeComponentUsed; + /** * {@hide} */ @@ -166,6 +174,7 @@ public final class UsageStats implements Parcelable { mEndTimeStamp = stats.mEndTimeStamp; mLastTimeUsed = stats.mLastTimeUsed; mLastTimeVisible = stats.mLastTimeVisible; + mLastTimeComponentUsed = stats.mLastTimeComponentUsed; mLastTimeForegroundServiceUsed = stats.mLastTimeForegroundServiceUsed; mTotalTimeInForeground = stats.mTotalTimeInForeground; mTotalTimeVisible = stats.mTotalTimeVisible; @@ -264,6 +273,16 @@ public final class UsageStats implements Parcelable { return mTotalTimeForegroundServiceUsed; } + /** + * Get the last time this package's component was used, measured in milliseconds since the + * epoch. + * @hide + */ + @SystemApi + public long getLastTimeComponentUsed() { + return mLastTimeComponentUsed; + } + /** * Returns the number of times the app was launched as an activity from outside of the app. * Excludes intra-app activity transitions. @@ -323,6 +342,7 @@ public final class UsageStats implements Parcelable { mergeEventMap(mForegroundServices, right.mForegroundServices); mLastTimeUsed = Math.max(mLastTimeUsed, right.mLastTimeUsed); mLastTimeVisible = Math.max(mLastTimeVisible, right.mLastTimeVisible); + mLastTimeComponentUsed = Math.max(mLastTimeComponentUsed, right.mLastTimeComponentUsed); mLastTimeForegroundServiceUsed = Math.max(mLastTimeForegroundServiceUsed, right.mLastTimeForegroundServiceUsed); } @@ -598,6 +618,9 @@ public final class UsageStats implements Parcelable { mLastTimeVisible = timeStamp; } break; + case APP_COMPONENT_USED: + mLastTimeComponentUsed = timeStamp; + break; default: break; } @@ -620,6 +643,7 @@ public final class UsageStats implements Parcelable { dest.writeLong(mEndTimeStamp); dest.writeLong(mLastTimeUsed); dest.writeLong(mLastTimeVisible); + dest.writeLong(mLastTimeComponentUsed); dest.writeLong(mLastTimeForegroundServiceUsed); dest.writeLong(mTotalTimeInForeground); dest.writeLong(mTotalTimeVisible); @@ -674,6 +698,7 @@ public final class UsageStats implements Parcelable { stats.mEndTimeStamp = in.readLong(); stats.mLastTimeUsed = in.readLong(); stats.mLastTimeVisible = in.readLong(); + stats.mLastTimeComponentUsed = in.readLong(); stats.mLastTimeForegroundServiceUsed = in.readLong(); stats.mTotalTimeInForeground = in.readLong(); stats.mTotalTimeVisible = in.readLong(); diff --git a/core/proto/android/server/usagestatsservice.proto b/core/proto/android/server/usagestatsservice.proto index e32c07f50ff27..3a959f13fea42 100644 --- a/core/proto/android/server/usagestatsservice.proto +++ b/core/proto/android/server/usagestatsservice.proto @@ -57,6 +57,8 @@ message IntervalStatsProto { // Time attributes stored as an offset of the IntervalStats's beginTime. optional int64 last_time_visible_ms = 10; optional int64 total_time_visible_ms = 11; + // Time attributes stored as an offset of the IntervalStats's beginTime. + optional int64 last_time_component_used_ms = 12; } // Stores the relevant information an IntervalStats will have about a Configuration diff --git a/core/proto/android/server/usagestatsservice_v2.proto b/core/proto/android/server/usagestatsservice_v2.proto index 664c22de86a63..3e5cd92c2533f 100644 --- a/core/proto/android/server/usagestatsservice_v2.proto +++ b/core/proto/android/server/usagestatsservice_v2.proto @@ -81,6 +81,7 @@ message UsageStatsObfuscatedProto { optional int64 total_time_service_used_ms = 9; optional int64 last_time_visible_ms = 10; optional int64 total_time_visible_ms = 11; + optional int64 last_time_component_used_ms = 12; } /** diff --git a/core/tests/coretests/src/android/app/usage/UsageStatsPersistenceTest.java b/core/tests/coretests/src/android/app/usage/UsageStatsPersistenceTest.java index 8de9454ddedac..083e37a3aaa65 100644 --- a/core/tests/coretests/src/android/app/usage/UsageStatsPersistenceTest.java +++ b/core/tests/coretests/src/android/app/usage/UsageStatsPersistenceTest.java @@ -46,7 +46,8 @@ public class UsageStatsPersistenceTest { private static final String[] USAGESTATS_PERSISTED_FIELDS = {"mBeginTimeStamp", "mEndTimeStamp", "mPackageName", "mPackageToken", "mLastEvent", "mAppLaunchCount", "mChooserCounts", "mLastTimeUsed", "mTotalTimeInForeground", "mLastTimeForegroundServiceUsed", - "mTotalTimeForegroundServiceUsed", "mLastTimeVisible", "mTotalTimeVisible"}; + "mTotalTimeForegroundServiceUsed", "mLastTimeVisible", "mTotalTimeVisible", + "mLastTimeComponentUsed"}; // All fields in this list are defined in UsageStats but not persisted private static final String[] USAGESTATS_IGNORED_FIELDS = {"CREATOR", "mActivities", "mForegroundServices", "mLaunchCount", "mChooserCountsObfuscated"}; diff --git a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java index 0ac00b8e9bbc9..858bbd20f13de 100644 --- a/core/tests/coretests/src/android/app/usage/UsageStatsTest.java +++ b/core/tests/coretests/src/android/app/usage/UsageStatsTest.java @@ -20,6 +20,7 @@ import static android.app.usage.UsageEvents.Event.ACTIVITY_DESTROYED; import static android.app.usage.UsageEvents.Event.ACTIVITY_PAUSED; import static android.app.usage.UsageEvents.Event.ACTIVITY_RESUMED; import static android.app.usage.UsageEvents.Event.ACTIVITY_STOPPED; +import static android.app.usage.UsageEvents.Event.APP_COMPONENT_USED; import static android.app.usage.UsageEvents.Event.CONTINUING_FOREGROUND_SERVICE; import static android.app.usage.UsageEvents.Event.DEVICE_SHUTDOWN; import static android.app.usage.UsageEvents.Event.END_OF_DAY; @@ -137,6 +138,7 @@ public class UsageStatsTest { left.mPackageName = "com.test"; left.mBeginTimeStamp = 100000; left.mTotalTimeInForeground = 10; + left.mLastTimeComponentUsed = 200000; left.mActivities.put(1, Event.ACTIVITY_RESUMED); left.mActivities.put(2, Event.ACTIVITY_RESUMED); @@ -541,6 +543,19 @@ public class UsageStatsTest { assertEquals(left.mTotalTimeForegroundServiceUsed, 400000); } + @Test + public void testEvent_APP_COMPONENT_USED() { + left.mPackageName = "com.test"; + left.mBeginTimeStamp = 100000; + final String className = "com.test.component1"; + + left.update(className, 200000, APP_COMPONENT_USED, 0); + assertEquals(left.mLastTimeComponentUsed, 200000); + + left.update(className, 300000, APP_COMPONENT_USED, 0); + assertEquals(left.mLastTimeComponentUsed, 300000); + } + @Test public void testEvent_DEVICE_SHUTDOWN() { testClosingEvent(DEVICE_SHUTDOWN); @@ -586,6 +601,7 @@ public class UsageStatsTest { assertEquals(us1.mBeginTimeStamp, us2.mBeginTimeStamp); assertEquals(us1.mLastTimeUsed, us2.mLastTimeUsed); assertEquals(us1.mLastTimeVisible, us2.mLastTimeVisible); + assertEquals(us1.mLastTimeComponentUsed, us2.mLastTimeComponentUsed); assertEquals(us1.mLastTimeForegroundServiceUsed, us2.mLastTimeForegroundServiceUsed); assertEquals(us1.mTotalTimeInForeground, us2.mTotalTimeInForeground); assertEquals(us1.mTotalTimeForegroundServiceUsed, us2.mTotalTimeForegroundServiceUsed); diff --git a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java index 60390dc3995e7..b2dacab263653 100644 --- a/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java +++ b/services/tests/servicestests/src/com/android/server/usage/UsageStatsDatabaseTest.java @@ -261,6 +261,7 @@ public class UsageStatsDatabaseTest { // mEndTimeStamp is based on the enclosing IntervalStats, don't bother checking assertEquals(us1.mLastTimeUsed, us2.mLastTimeUsed); assertEquals(us1.mLastTimeVisible, us2.mLastTimeVisible); + assertEquals(us1.mLastTimeComponentUsed, us2.mLastTimeComponentUsed); assertEquals(us1.mTotalTimeInForeground, us2.mTotalTimeInForeground); assertEquals(us1.mTotalTimeVisible, us2.mTotalTimeVisible); assertEquals(us1.mLastTimeForegroundServiceUsed, us2.mLastTimeForegroundServiceUsed); diff --git a/services/usage/java/com/android/server/usage/UsageStatsProto.java b/services/usage/java/com/android/server/usage/UsageStatsProto.java index 78b14779d6b39..ec4c5fc4a846a 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsProto.java +++ b/services/usage/java/com/android/server/usage/UsageStatsProto.java @@ -147,6 +147,10 @@ final class UsageStatsProto { stats.mTotalTimeVisible = proto.readLong( IntervalStatsProto.UsageStats.TOTAL_TIME_VISIBLE_MS); break; + case (int) IntervalStatsProto.UsageStats.LAST_TIME_COMPONENT_USED_MS: + stats.mLastTimeComponentUsed = statsOut.beginTime + proto.readLong( + IntervalStatsProto.UsageStats.LAST_TIME_COMPONENT_USED_MS); + break; } } proto.end(token); @@ -345,6 +349,9 @@ final class UsageStatsProto { usageStats.mLastTimeVisible, stats.beginTime); proto.write(IntervalStatsProto.UsageStats.TOTAL_TIME_VISIBLE_MS, usageStats.mTotalTimeVisible); + UsageStatsProtoV2.writeOffsetTimestamp(proto, + IntervalStatsProto.UsageStats.LAST_TIME_COMPONENT_USED_MS, + usageStats.mLastTimeComponentUsed, stats.beginTime); proto.write(IntervalStatsProto.UsageStats.APP_LAUNCH_COUNT, usageStats.mAppLaunchCount); try { writeChooserCounts(proto, usageStats); diff --git a/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java b/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java index e6d28417d3ca6..5c5667cf0389b 100644 --- a/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java +++ b/services/usage/java/com/android/server/usage/UsageStatsProtoV2.java @@ -90,6 +90,10 @@ final class UsageStatsProtoV2 { stats.mTotalTimeVisible = proto.readLong( UsageStatsObfuscatedProto.TOTAL_TIME_VISIBLE_MS); break; + case (int) UsageStatsObfuscatedProto.LAST_TIME_COMPONENT_USED_MS: + stats.mLastTimeComponentUsed = beginTime + proto.readLong( + UsageStatsObfuscatedProto.LAST_TIME_COMPONENT_USED_MS); + break; case ProtoInputStream.NO_MORE_FIELDS: return stats; } @@ -312,6 +316,8 @@ final class UsageStatsProtoV2 { writeOffsetTimestamp(proto, UsageStatsObfuscatedProto.LAST_TIME_VISIBLE_MS, stats.mLastTimeVisible, beginTime); proto.write(UsageStatsObfuscatedProto.TOTAL_TIME_VISIBLE_MS, stats.mTotalTimeVisible); + writeOffsetTimestamp(proto, UsageStatsObfuscatedProto.LAST_TIME_COMPONENT_USED_MS, + stats.mLastTimeComponentUsed, beginTime); proto.write(UsageStatsObfuscatedProto.APP_LAUNCH_COUNT, stats.mAppLaunchCount); try { writeChooserCounts(proto, stats); diff --git a/services/usage/java/com/android/server/usage/UserUsageStatsService.java b/services/usage/java/com/android/server/usage/UserUsageStatsService.java index f35b9e2ce0edd..22b4f4ef57e5b 100644 --- a/services/usage/java/com/android/server/usage/UserUsageStatsService.java +++ b/services/usage/java/com/android/server/usage/UserUsageStatsService.java @@ -1003,6 +1003,8 @@ class UserUsageStatsService { formatElapsedTime(usageStats.mTotalTimeVisible, prettyDates)); pw.printPair("lastTimeVisible", formatDateTime(usageStats.mLastTimeVisible, prettyDates)); + pw.printPair("lastTimeComponentUsed", + formatDateTime(usageStats.mLastTimeComponentUsed, prettyDates)); pw.printPair("totalTimeFS", formatElapsedTime(usageStats.mTotalTimeForegroundServiceUsed, prettyDates)); pw.printPair("lastTimeFS",