Prevent GC requests from piling up in LockSettingsService
Don't allow an unbounded number of GC requests to be enqueued if
lockscreen credential operations are happening very quickly.
Test: 'atest FrameworksServicesTests:com.android.server.locksettings'
and checked log. No longer see any messages that say
"WaitForGcToComplete blocked Explicit on Explicit". Note, even
before this CL only a few such messages appeared with that atest
command, but apparently it could happen more often in some cases.
Bug: 367713409
Flag: EXEMPT bugfix
Change-Id: I598116754210aa75265a9262e7b63937e2b836c2
diff --git a/services/core/java/com/android/server/locksettings/LockSettingsService.java b/services/core/java/com/android/server/locksettings/LockSettingsService.java
index 45885f0..c314ab0 100644
--- a/services/core/java/com/android/server/locksettings/LockSettingsService.java
+++ b/services/core/java/com/android/server/locksettings/LockSettingsService.java
@@ -347,6 +347,8 @@
private final StorageManagerInternal mStorageManagerInternal;
+ private final Object mGcWorkToken = new Object();
+
// This class manages life cycle events for encrypted users on File Based Encryption (FBE)
// devices. The most basic of these is to show/hide notifications about missing features until
// the user unlocks the account and credential-encrypted storage is available.
@@ -3632,11 +3634,19 @@
* release references to the argument.
*/
private void scheduleGc() {
+ // Cancel any existing GC request first, so that GC requests don't pile up if lockscreen
+ // credential operations are happening very quickly, e.g. as sometimes happens during tests.
+ //
+ // This delays the already-requested GC, but that is fine in practice where lockscreen
+ // operations don't happen very quickly. And the precise time that the sanitization happens
+ // isn't very important; doing it within a minute can be fine, for example.
+ mHandler.removeCallbacksAndMessages(mGcWorkToken);
+
mHandler.postDelayed(() -> {
System.gc();
System.runFinalization();
System.gc();
- }, 2000);
+ }, mGcWorkToken, 2000);
}
private class DeviceProvisionedObserver extends ContentObserver {