From 2614bceca6ee68a8c0d8d7d6a6267ef740622148 Mon Sep 17 00:00:00 2001 From: Pinyao Ting Date: Thu, 30 Nov 2023 23:12:39 +0000 Subject: [PATCH] Added throttle when reporting shortcut usage Bug: 304290201 Test: manual (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:76121eb73d4c40829d5513b073871333520fe0a2) Merged-In: I96370cbd4f6a55f894c1a93307e5f82dfd394652 Change-Id: I96370cbd4f6a55f894c1a93307e5f82dfd394652 --- .../android/server/pm/ShortcutPackage.java | 35 +++++++++++++++++++ .../android/server/pm/ShortcutService.java | 12 +++---- .../server/pm/ShortcutManagerTest2.java | 2 ++ 3 files changed, 41 insertions(+), 8 deletions(-) diff --git a/services/core/java/com/android/server/pm/ShortcutPackage.java b/services/core/java/com/android/server/pm/ShortcutPackage.java index c6bc7576147f7..da018ad041799 100644 --- a/services/core/java/com/android/server/pm/ShortcutPackage.java +++ b/services/core/java/com/android/server/pm/ShortcutPackage.java @@ -19,6 +19,7 @@ import android.annotation.Nullable; import android.annotation.UserIdInt; import android.app.Person; +import android.app.usage.UsageStatsManagerInternal; import android.content.ComponentName; import android.content.Intent; import android.content.IntentFilter; @@ -28,12 +29,14 @@ import android.content.pm.ShortcutManager; import android.content.res.Resources; import android.os.PersistableBundle; +import android.os.SystemClock; import android.text.format.Formatter; import android.util.ArrayMap; import android.util.ArraySet; import android.util.Log; import android.util.Slog; +import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.util.ArrayUtils; import com.android.internal.util.Preconditions; @@ -119,6 +122,11 @@ class ShortcutPackage extends ShortcutPackageItem { private static final String KEY_BITMAPS = "bitmaps"; private static final String KEY_BITMAP_BYTES = "bitmapBytes"; + @VisibleForTesting + public static final int REPORT_USAGE_BUFFER_SIZE = 3; + + private final Object mLock = new Object(); + /** * All the shortcuts from the package, keyed on IDs. */ @@ -143,6 +151,9 @@ class ShortcutPackage extends ShortcutPackageItem { private long mLastKnownForegroundElapsedTime; + @GuardedBy("mLock") + private List mLastReportedTime = new ArrayList<>(); + private ShortcutPackage(ShortcutUser shortcutUser, int packageUserId, String packageName, ShortcutPackageInfo spi) { super(shortcutUser, packageUserId, packageName, @@ -1352,6 +1363,30 @@ public boolean hasNonManifestShortcuts() { return false; } + void reportShortcutUsed(@NonNull final UsageStatsManagerInternal usageStatsManagerInternal, + @NonNull final String shortcutId) { + synchronized (mLock) { + final long currentTS = SystemClock.elapsedRealtime(); + final ShortcutService s = mShortcutUser.mService; + if (mLastReportedTime.isEmpty() + || mLastReportedTime.size() < REPORT_USAGE_BUFFER_SIZE) { + mLastReportedTime.add(currentTS); + } else if (currentTS - mLastReportedTime.get(0) > s.mSaveDelayMillis) { + mLastReportedTime.remove(0); + mLastReportedTime.add(currentTS); + } else { + return; + } + final long token = s.injectClearCallingIdentity(); + try { + usageStatsManagerInternal.reportShortcutUsage(getPackageName(), shortcutId, + getUser().getUserId()); + } finally { + s.injectRestoreCallingIdentity(token); + } + } + } + public void dump(@NonNull PrintWriter pw, @NonNull String prefix, DumpFilter filter) { pw.println(); diff --git a/services/core/java/com/android/server/pm/ShortcutService.java b/services/core/java/com/android/server/pm/ShortcutService.java index 2e2883dcb2a52..c18cdcb891409 100644 --- a/services/core/java/com/android/server/pm/ShortcutService.java +++ b/services/core/java/com/android/server/pm/ShortcutService.java @@ -315,7 +315,7 @@ public boolean test(PackageInfo pi) { private CompressFormat mIconPersistFormat; private int mIconPersistQuality; - private int mSaveDelayMillis; + int mSaveDelayMillis; private final IPackageManager mIPackageManager; private final PackageManagerInternal mPackageManagerInternal; @@ -2285,10 +2285,11 @@ public void reportShortcutUsed(String packageName, String shortcutId, int userId shortcutId, packageName, userId)); } + final ShortcutPackage ps; synchronized (mLock) { throwIfUserLockedL(userId); - final ShortcutPackage ps = getPackageShortcutsForPublisherLocked(packageName, userId); + ps = getPackageShortcutsForPublisherLocked(packageName, userId); if (ps.findShortcutById(shortcutId) == null) { Log.w(TAG, String.format("reportShortcutUsed: package %s doesn't have shortcut %s", @@ -2297,12 +2298,7 @@ public void reportShortcutUsed(String packageName, String shortcutId, int userId } } - final long token = injectClearCallingIdentity(); - try { - mUsageStatsManagerInternal.reportShortcutUsage(packageName, shortcutId, userId); - } finally { - injectRestoreCallingIdentity(token); - } + ps.reportShortcutUsed(mUsageStatsManagerInternal, shortcutId); } @Override diff --git a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java index 18970322d854c..27cf3502d489c 100644 --- a/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java +++ b/services/tests/servicestests/src/com/android/server/pm/ShortcutManagerTest2.java @@ -1940,6 +1940,8 @@ public void testThrottling_resetByInternalCall() throws Exception { public void testReportShortcutUsed() { mRunningUsers.put(USER_10, true); + mService.updateConfigurationLocked( + ShortcutService.ConfigConstants.KEY_SAVE_DELAY_MILLIS + "=1"); runWithCaller(CALLING_PACKAGE_1, USER_10, () -> { reset(mMockUsageStatsManagerInternal);