From dddb1bd3f153e4bc842da088a8a3322e9c34a1ab Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Edgar=20Arriaga=20Garc=C3=ADa?= Date: Thu, 14 Nov 2019 23:25:34 +0000 Subject: [PATCH] Adding binder cache for AccountManagerService:getAccountsAsUser Test: atest AccountManagerTest b/140788621 Change-Id: I5c244cacaffb175f92c3185138bf1277e51aae0a --- .../java/android/accounts/AccountManager.java | 80 +++++++++++++++++-- .../accounts/AccountManagerService.java | 10 +++ 2 files changed, 84 insertions(+), 6 deletions(-) diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 323c922fbf84f..cee7cd145d5e6 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -61,6 +61,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import java.util.concurrent.Callable; import java.util.concurrent.CancellationException; @@ -338,7 +339,60 @@ public class AccountManager { /** * @hide - */ + */ + public static final String CACHE_KEY_ACCOUNTS_DATA_PROPERTY = "cache_key.system_server.accounts_data"; + + /** + * @hide + */ + public static final int CACHE_ACCOUNTS_DATA_SIZE = 4; + + private static final class UserIdPackage + { + public int userId; + public String packageName; + + public UserIdPackage(int UserId, String PackageName) { + this.userId = UserId; + this.packageName = PackageName; + } + + @Override + public boolean equals(Object o) { + if (o == null) { + return false; + } + if (o == this) { + return true; + } + if (o.getClass() != getClass()) { + return false; + } + UserIdPackage e = (UserIdPackage) o; + return e.userId == userId && e.packageName.equals(packageName); + } + + @Override + public int hashCode() { + return userId ^ packageName.hashCode(); + } + } + + PropertyInvalidatedCache mAccountsForUserCache = + new PropertyInvalidatedCache(CACHE_ACCOUNTS_DATA_SIZE, CACHE_KEY_ACCOUNTS_DATA_PROPERTY) { + @Override + protected Account[] recompute(UserIdPackage userAndPackage) { + try { + return mService.getAccountsAsUser(null, userAndPackage.userId, userAndPackage.packageName); + } catch (RemoteException e) { + throw e.rethrowFromSystemServer(); + } + } + }; + + /** + * @hide + */ public static final String CACHE_KEY_USER_DATA_PROPERTY = "cache_key.system_server.account_user_data"; /** @@ -660,11 +714,8 @@ public class AccountManager { */ @NonNull public Account[] getAccountsAsUser(int userId) { - try { - return mService.getAccountsAsUser(null, userId, mContext.getOpPackageName()); - } catch (RemoteException e) { - throw e.rethrowFromSystemServer(); - } + UserIdPackage userAndPackage = new UserIdPackage(userId, mContext.getOpPackageName()); + return mAccountsForUserCache.query(userAndPackage); } /** @@ -3392,6 +3443,23 @@ public class AccountManager { } } + /** + * @hide + * Calling this will invalidate Local Accounts Data Cache which + * forces the next query in any process to recompute the cache + */ + public static void invalidateLocalAccountsDataCaches() { + PropertyInvalidatedCache.invalidateCache(CACHE_KEY_ACCOUNTS_DATA_PROPERTY); + } + + /** + * @hide + * Calling this will disable account data caching. + */ + public void disableLocalAccountCaches() { + mAccountsForUserCache.disableLocal(); + } + /** * @hide * Calling this will invalidate Local Account User Data Cache which diff --git a/services/core/java/com/android/server/accounts/AccountManagerService.java b/services/core/java/com/android/server/accounts/AccountManagerService.java index 096a5b64ba418..8166c83094867 100644 --- a/services/core/java/com/android/server/accounts/AccountManagerService.java +++ b/services/core/java/com/android/server/accounts/AccountManagerService.java @@ -584,6 +584,7 @@ public class AccountManagerService Log.d(TAG, "Visibility was not initialized"); accountVisibility = new HashMap<>(); accounts.visibilityCache.put(account, accountVisibility); + AccountManager.invalidateLocalAccountsDataCaches(); } return accountVisibility; } @@ -871,6 +872,7 @@ public class AccountManagerService Map accountVisibility = getPackagesAndVisibilityForAccountLocked(account, accounts); accountVisibility.put(packageName, newVisibility); + AccountManager.invalidateLocalAccountsDataCaches(); return true; } @@ -1241,6 +1243,7 @@ public class AccountManagerService accounts.accountCache.put(accountType, accountsForType); } accounts.visibilityCache.putAll(accountsDb.findAllVisibilityValues()); + AccountManager.invalidateLocalAccountsDataCaches(); } finally { if (accountDeleted) { sendAccountsChangedBroadcast(accounts.userId); @@ -1325,6 +1328,7 @@ public class AccountManagerService accounts = new UserAccounts(mContext, userId, preNDbFile, deDbFile); mUsers.append(userId, accounts); purgeOldGrants(accounts); + AccountManager.invalidateLocalAccountsDataCaches(); validateAccounts = true; } // open CE database if necessary @@ -1406,6 +1410,7 @@ public class AccountManagerService getPackagesAndVisibilityForAccountLocked(account, accounts); accountVisibility.remove(packageName); } + AccountManager.invalidateLocalAccountsDataCaches(); } } } @@ -1419,6 +1424,7 @@ public class AccountManagerService accounts = mUsers.get(userId); mUsers.remove(userId); mLocalUnlockedUsers.delete(userId); + AccountManager.invalidateLocalAccountsDataCaches(); } if (accounts != null) { synchronized (accounts.dbLock) { @@ -2121,6 +2127,7 @@ public class AccountManagerService sendAccountRemovedBroadcast(accountToRename, packageName, accounts.userId); } + AccountManager.invalidateLocalAccountsDataCaches(); AccountManager.invalidateLocalAccountUserDataCaches(); } } @@ -5838,6 +5845,8 @@ public class AccountManagerService accounts.authTokenCache.remove(account); accounts.previousNameCache.remove(account); accounts.visibilityCache.remove(account); + + AccountManager.invalidateLocalAccountsDataCaches(); } /** @@ -5857,6 +5866,7 @@ public class AccountManagerService : UUID.randomUUID().toString(); newAccountsForType[oldLength] = new Account(account, token); accounts.accountCache.put(account.type, newAccountsForType); + AccountManager.invalidateLocalAccountsDataCaches(); return newAccountsForType[oldLength]; }