Loading services/core/java/com/android/server/accounts/AccountManagerService.java +78 −45 Original line number Diff line number Diff line Loading @@ -202,16 +202,17 @@ public class AccountManagerService new HashMap<Account, Integer>(); final Object cacheLock = new Object(); /** protected by the {@link #cacheLock} */ final HashMap<String, Account[]> accountCache = new LinkedHashMap<>(); final HashMap<String, Account[]> accountCache = new LinkedHashMap<>(); /** protected by the {@link #cacheLock} */ private final Map<Account, Map<String, String>> userDataCache = new HashMap<>(); /** protected by the {@link #cacheLock} */ private final Map<Account, Map<String, String>> authTokenCache = new HashMap<>(); /** protected by the {@link #cacheLock} */ private final TokenCache accountTokenCaches = new TokenCache(); /** protected by the {@link #cacheLock} */ private final Map<Account, Map<String, Integer>> visibilityCache = new HashMap<>(); /** protected by the {@link #mReceiversForType} /** protected by the {@link #mReceiversForType}, * type -> (packageName -> number of active receivers) * type == null is used to get notifications about all account types */ Loading Loading @@ -524,25 +525,29 @@ public class AccountManagerService String.format("uid %s cannot get secrets for account %s", callingUid, account); throw new SecurityException(msg); } return getPackagesAndVisibilityForAccount(account, accounts); synchronized (accounts.cacheLock) { return getPackagesAndVisibilityForAccountLocked(account, accounts); } } /** * Returns all package names and visibility values, which were set for given account. * Returns Map with all package names and visibility values for given account. * The method and returned map must be guarded by accounts.cacheLock * * @param account Account to get visibility values. * @param accounts UserAccount that currently hosts the account and application * * @return Map from package names to visibility. * @return Map with cache for package names to visibility. */ private Map<String, Integer> getPackagesAndVisibilityForAccount(Account account, private @NonNull Map<String, Integer> getPackagesAndVisibilityForAccountLocked(Account account, UserAccounts accounts) { final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); try { return accounts.accountsDb.findAllVisibilityValuesForAccount(account); } finally { StrictMode.setThreadPolicy(oldPolicy); Map<String, Integer> accountVisibility = accounts.visibilityCache.get(account); if (accountVisibility == null) { Log.d(TAG, "Visibility was not initialized"); accountVisibility = new HashMap<>(); accounts.visibilityCache.put(account, accountVisibility); } return accountVisibility; } @Override Loading Loading @@ -572,14 +577,13 @@ public class AccountManagerService * @return Visibility value, AccountManager.VISIBILITY_UNDEFINED if no value was stored. * */ private int getAccountVisibility(Account account, String packageName, UserAccounts accounts) { final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); try { Integer visibility = accounts.accountsDb.findAccountVisibility(account, packageName); private int getAccountVisibilityFromCache(Account account, String packageName, UserAccounts accounts) { synchronized (accounts.cacheLock) { Map<String, Integer> accountVisibility = getPackagesAndVisibilityForAccountLocked(account, accounts); Integer visibility = accountVisibility.get(packageName); return visibility != null ? visibility : AccountManager.VISIBILITY_UNDEFINED; } finally { StrictMode.setThreadPolicy(oldPolicy); } } Loading @@ -595,9 +599,7 @@ public class AccountManagerService */ private Integer resolveAccountVisibility(Account account, @NonNull String packageName, UserAccounts accounts) { Preconditions.checkNotNull(packageName, "packageName cannot be null"); int uid = -1; try { long identityToken = clearCallingIdentity(); Loading Loading @@ -630,7 +632,7 @@ public class AccountManagerService } // Return stored value if it was set. int visibility = getAccountVisibility(account, packageName, accounts); int visibility = getAccountVisibilityFromCache(account, packageName, accounts); if (AccountManager.VISIBILITY_UNDEFINED != visibility) { return visibility; Loading @@ -652,13 +654,13 @@ public class AccountManagerService || canReadContacts || isPrivileged) { // Use legacy for preO apps with GET_ACCOUNTS permission or pre/postO with signature // match. visibility = getAccountVisibility(account, visibility = getAccountVisibilityFromCache(account, AccountManager.PACKAGE_NAME_KEY_LEGACY_VISIBLE, accounts); if (AccountManager.VISIBILITY_UNDEFINED == visibility) { visibility = AccountManager.VISIBILITY_USER_MANAGED_VISIBLE; } } else { visibility = getAccountVisibility(account, visibility = getAccountVisibilityFromCache(account, AccountManager.PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE, accounts); if (AccountManager.VISIBILITY_UNDEFINED == visibility) { visibility = AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE; Loading Loading @@ -751,6 +753,25 @@ public class AccountManagerService packagesToVisibility = new HashMap<>(); } if (!updateAccountVisibilityLocked(account, packageName, newVisibility, accounts)) { return false; } if (notify) { for (Entry<String, Integer> packageToVisibility : packagesToVisibility.entrySet()) { if (packageToVisibility.getValue() != AccountManager.VISIBILITY_NOT_VISIBLE) { notifyPackage(packageToVisibility.getKey(), accounts); } } sendAccountsChangedBroadcast(accounts.userId); } return true; } } // Update account visibility in cache and database. private boolean updateAccountVisibilityLocked(Account account, String packageName, int newVisibility, UserAccounts accounts) { final long accountId = accounts.accountsDb.findDeAccountId(account); if (accountId < 0) { return false; Loading @@ -765,18 +786,11 @@ public class AccountManagerService } finally { StrictMode.setThreadPolicy(oldPolicy); } if (notify) { for (Entry<String, Integer> packageToVisibility : packagesToVisibility.entrySet()) { if (packageToVisibility.getValue() != AccountManager.VISIBILITY_NOT_VISIBLE) { notifyPackage(packageToVisibility.getKey(), accounts); } } sendAccountsChangedBroadcast(accounts.userId); } Map<String, Integer> accountVisibility = getPackagesAndVisibilityForAccountLocked(account, accounts); accountVisibility.put(packageName, newVisibility); return true; } } @Override public void registerAccountListener(String[] accountTypes, String opPackageName) { Loading Loading @@ -1042,9 +1056,12 @@ public class AccountManagerService accounts.userDataCache.remove(account); accounts.authTokenCache.remove(account); accounts.accountTokenCaches.remove(account); accounts.visibilityCache.remove(account); for (Entry<String, Integer> packageToVisibility : packagesToVisibility.entrySet()) { if (packageToVisibility.getValue() != AccountManager.VISIBILITY_NOT_VISIBLE) { for (Entry<String, Integer> packageToVisibility : packagesToVisibility.entrySet()) { if (packageToVisibility.getValue() != AccountManager.VISIBILITY_NOT_VISIBLE) { notifyPackage(packageToVisibility.getKey(), accounts); } } Loading @@ -1067,6 +1084,7 @@ public class AccountManagerService } accounts.accountCache.put(accountType, accountsForType); } accounts.visibilityCache.putAll(accountsDb.findAllVisibilityValues()); } finally { if (accountDeleted) { sendAccountsChangedBroadcast(accounts.userId); Loading Loading @@ -1181,18 +1199,30 @@ public class AccountManagerService } private void removeVisibilityValuesForPackage(String packageName) { if (isSpecialPackageKey(packageName)) { return; } synchronized (mUsers) { for (int i = 0; i < mUsers.size(); i++) { int numberOfUsers = mUsers.size(); for (int i = 0; i < numberOfUsers; i++) { UserAccounts accounts = mUsers.valueAt(i); try { int uid = mPackageManager.getPackageUidAsUser(packageName, accounts.userId); mPackageManager.getPackageUidAsUser(packageName, accounts.userId); } catch (NameNotFoundException e) { // package does not exist - remove visibility values accounts.accountsDb.deleteAccountVisibilityForPackage(packageName); synchronized(accounts.cacheLock) { for (Account account : accounts.visibilityCache.keySet()) { Map<String, Integer> accountVisibility = getPackagesAndVisibilityForAccountLocked(account, accounts); accountVisibility.remove(packageName); } } } } } } private void onCleanupUser(int userId) { Log.i(TAG, "onCleanupUser " + userId); Loading Loading @@ -1849,6 +1879,7 @@ public class AccountManagerService */ Map<String, String> tmpData = accounts.userDataCache.get(accountToRename); Map<String, String> tmpTokens = accounts.authTokenCache.get(accountToRename); Map<String, Integer> tmpVisibility = accounts.visibilityCache.get(accountToRename); removeAccountFromCacheLocked(accounts, accountToRename); /* * Update the cached data associated with the renamed Loading @@ -1856,6 +1887,7 @@ public class AccountManagerService */ accounts.userDataCache.put(renamedAccount, tmpData); accounts.authTokenCache.put(renamedAccount, tmpTokens); accounts.visibilityCache.put(renamedAccount, tmpVisibility); accounts.previousNameCache.put( renamedAccount, new AtomicReference<>(accountToRename.name)); Loading Loading @@ -5369,6 +5401,7 @@ public class AccountManagerService accounts.userDataCache.remove(account); accounts.authTokenCache.remove(account); accounts.previousNameCache.remove(account); accounts.visibilityCache.remove(account); } /** Loading services/core/java/com/android/server/accounts/AccountsDb.java +37 −2 Original line number Diff line number Diff line Loading @@ -909,7 +909,7 @@ class AccountsDb implements AutoCloseable { } Integer findAccountVisibility(Account account, String packageName) { SQLiteDatabase db = mDeDatabase.getWritableDatabase(); SQLiteDatabase db = mDeDatabase.getReadableDatabase(); final Cursor cursor = db.query(TABLE_VISIBILITY, new String[] {VISIBILITY_VALUE}, SELECTION_ACCOUNTS_ID_BY_ACCOUNT + " AND " + VISIBILITY_PACKAGE + "=? ", new String[] {account.name, account.type, packageName}, null, null, null); Loading @@ -924,7 +924,7 @@ class AccountsDb implements AutoCloseable { } Integer findAccountVisibility(long accountId, String packageName) { SQLiteDatabase db = mDeDatabase.getWritableDatabase(); SQLiteDatabase db = mDeDatabase.getReadableDatabase(); final Cursor cursor = db.query(TABLE_VISIBILITY, new String[] {VISIBILITY_VALUE}, VISIBILITY_ACCOUNTS_ID + "=? AND " + VISIBILITY_PACKAGE + "=? ", new String[] {String.valueOf(accountId), packageName}, null, null, null); Loading Loading @@ -972,6 +972,41 @@ class AccountsDb implements AutoCloseable { return result; } /** * Returns a map account -> (package -> visibility) */ Map <Account, Map<String, Integer>> findAllVisibilityValues() { SQLiteDatabase db = mDeDatabase.getReadableDatabase(); Map<Account, Map<String, Integer>> result = new HashMap<>(); Cursor cursor = db.rawQuery( "SELECT " + TABLE_VISIBILITY + "." + VISIBILITY_PACKAGE + ", " + TABLE_VISIBILITY + "." + VISIBILITY_VALUE + ", " + TABLE_ACCOUNTS + "." + ACCOUNTS_NAME + ", " + TABLE_ACCOUNTS + "." + ACCOUNTS_TYPE + " FROM " + TABLE_VISIBILITY + " JOIN " + TABLE_ACCOUNTS + " ON " + TABLE_ACCOUNTS + "." + ACCOUNTS_ID + " = " + TABLE_VISIBILITY + "." + VISIBILITY_ACCOUNTS_ID, null); try { while (cursor.moveToNext()) { String packageName = cursor.getString(0); Integer visibility = cursor.getInt(1); String accountName = cursor.getString(2); String accountType = cursor.getString(3); Account account = new Account(accountName, accountType); Map <String, Integer> accountVisibility = result.get(account); if (accountVisibility == null) { accountVisibility = new HashMap<>(); result.put(account, accountVisibility); } accountVisibility.put(packageName, visibility); } } finally { cursor.close(); } return result; } boolean deleteAccountVisibilityForPackage(String packageName) { SQLiteDatabase db = mDeDatabase.getWritableDatabase(); return db.delete(TABLE_VISIBILITY, VISIBILITY_PACKAGE + "=? ", Loading services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java +1 −1 Original line number Diff line number Diff line Loading @@ -94,7 +94,7 @@ import java.util.concurrent.atomic.AtomicLong; * <p>Run with:<pre> * mmma -j40 frameworks/base/services/tests/servicestests * adb install -r ${OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk * adb shell am instrument -w -e class package com.android.server.accounts \ * adb shell am instrument -w -e package com.android.server.accounts \ * com.android.frameworks.servicestests\ * /android.support.test.runner.AndroidJUnitRunner * </pre> Loading services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java +36 −0 Original line number Diff line number Diff line Loading @@ -384,6 +384,42 @@ public class AccountsDbTest { assertFalse(mAccountsDb.deleteAccountVisibilityForPackage(packageName1)); // 2nd attempt. } @Test public void testFindAllVisibilityValues() { long accId = 10; long accId2 = 11; String packageName1 = "com.example.one"; String packageName2 = "com.example.two"; Account account = new Account("name", "example.com"); Account account2 = new Account("name2", "example2.com"); assertNull(mAccountsDb.findAccountVisibility(account, packageName1)); mAccountsDb.insertDeAccount(account, accId); assertNull(mAccountsDb.findAccountVisibility(account, packageName1)); assertNull(mAccountsDb.findAccountVisibility(accId, packageName1)); mAccountsDb.insertDeAccount(account2, accId2); mAccountsDb.setAccountVisibility(accId, packageName1, 1); mAccountsDb.setAccountVisibility(accId, packageName2, 2); mAccountsDb.setAccountVisibility(accId2, packageName1, 1); Map<Account, Map<String, Integer>> vis = mAccountsDb.findAllVisibilityValues(); assertEquals(vis.size(), 2); Map<String, Integer> accnt1Visibility = vis.get(account); assertEquals(accnt1Visibility.size(), 2); assertEquals(accnt1Visibility.get(packageName1), Integer.valueOf(1)); assertEquals(accnt1Visibility.get(packageName2), Integer.valueOf(2)); Map<String, Integer> accnt2Visibility = vis.get(account2); assertEquals(accnt2Visibility.size(), 1); assertEquals(accnt2Visibility.get(packageName1), Integer.valueOf(1)); mAccountsDb.setAccountVisibility(accId2, packageName2, 3); vis = mAccountsDb.findAllVisibilityValues(); accnt2Visibility = vis.get(account2); assertEquals(accnt2Visibility.size(), 2); assertEquals(accnt2Visibility.get(packageName2), Integer.valueOf(3)); } @Test public void testVisibilityCleanupTrigger() { long accId = 10; Loading Loading
services/core/java/com/android/server/accounts/AccountManagerService.java +78 −45 Original line number Diff line number Diff line Loading @@ -202,16 +202,17 @@ public class AccountManagerService new HashMap<Account, Integer>(); final Object cacheLock = new Object(); /** protected by the {@link #cacheLock} */ final HashMap<String, Account[]> accountCache = new LinkedHashMap<>(); final HashMap<String, Account[]> accountCache = new LinkedHashMap<>(); /** protected by the {@link #cacheLock} */ private final Map<Account, Map<String, String>> userDataCache = new HashMap<>(); /** protected by the {@link #cacheLock} */ private final Map<Account, Map<String, String>> authTokenCache = new HashMap<>(); /** protected by the {@link #cacheLock} */ private final TokenCache accountTokenCaches = new TokenCache(); /** protected by the {@link #cacheLock} */ private final Map<Account, Map<String, Integer>> visibilityCache = new HashMap<>(); /** protected by the {@link #mReceiversForType} /** protected by the {@link #mReceiversForType}, * type -> (packageName -> number of active receivers) * type == null is used to get notifications about all account types */ Loading Loading @@ -524,25 +525,29 @@ public class AccountManagerService String.format("uid %s cannot get secrets for account %s", callingUid, account); throw new SecurityException(msg); } return getPackagesAndVisibilityForAccount(account, accounts); synchronized (accounts.cacheLock) { return getPackagesAndVisibilityForAccountLocked(account, accounts); } } /** * Returns all package names and visibility values, which were set for given account. * Returns Map with all package names and visibility values for given account. * The method and returned map must be guarded by accounts.cacheLock * * @param account Account to get visibility values. * @param accounts UserAccount that currently hosts the account and application * * @return Map from package names to visibility. * @return Map with cache for package names to visibility. */ private Map<String, Integer> getPackagesAndVisibilityForAccount(Account account, private @NonNull Map<String, Integer> getPackagesAndVisibilityForAccountLocked(Account account, UserAccounts accounts) { final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); try { return accounts.accountsDb.findAllVisibilityValuesForAccount(account); } finally { StrictMode.setThreadPolicy(oldPolicy); Map<String, Integer> accountVisibility = accounts.visibilityCache.get(account); if (accountVisibility == null) { Log.d(TAG, "Visibility was not initialized"); accountVisibility = new HashMap<>(); accounts.visibilityCache.put(account, accountVisibility); } return accountVisibility; } @Override Loading Loading @@ -572,14 +577,13 @@ public class AccountManagerService * @return Visibility value, AccountManager.VISIBILITY_UNDEFINED if no value was stored. * */ private int getAccountVisibility(Account account, String packageName, UserAccounts accounts) { final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads(); try { Integer visibility = accounts.accountsDb.findAccountVisibility(account, packageName); private int getAccountVisibilityFromCache(Account account, String packageName, UserAccounts accounts) { synchronized (accounts.cacheLock) { Map<String, Integer> accountVisibility = getPackagesAndVisibilityForAccountLocked(account, accounts); Integer visibility = accountVisibility.get(packageName); return visibility != null ? visibility : AccountManager.VISIBILITY_UNDEFINED; } finally { StrictMode.setThreadPolicy(oldPolicy); } } Loading @@ -595,9 +599,7 @@ public class AccountManagerService */ private Integer resolveAccountVisibility(Account account, @NonNull String packageName, UserAccounts accounts) { Preconditions.checkNotNull(packageName, "packageName cannot be null"); int uid = -1; try { long identityToken = clearCallingIdentity(); Loading Loading @@ -630,7 +632,7 @@ public class AccountManagerService } // Return stored value if it was set. int visibility = getAccountVisibility(account, packageName, accounts); int visibility = getAccountVisibilityFromCache(account, packageName, accounts); if (AccountManager.VISIBILITY_UNDEFINED != visibility) { return visibility; Loading @@ -652,13 +654,13 @@ public class AccountManagerService || canReadContacts || isPrivileged) { // Use legacy for preO apps with GET_ACCOUNTS permission or pre/postO with signature // match. visibility = getAccountVisibility(account, visibility = getAccountVisibilityFromCache(account, AccountManager.PACKAGE_NAME_KEY_LEGACY_VISIBLE, accounts); if (AccountManager.VISIBILITY_UNDEFINED == visibility) { visibility = AccountManager.VISIBILITY_USER_MANAGED_VISIBLE; } } else { visibility = getAccountVisibility(account, visibility = getAccountVisibilityFromCache(account, AccountManager.PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE, accounts); if (AccountManager.VISIBILITY_UNDEFINED == visibility) { visibility = AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE; Loading Loading @@ -751,6 +753,25 @@ public class AccountManagerService packagesToVisibility = new HashMap<>(); } if (!updateAccountVisibilityLocked(account, packageName, newVisibility, accounts)) { return false; } if (notify) { for (Entry<String, Integer> packageToVisibility : packagesToVisibility.entrySet()) { if (packageToVisibility.getValue() != AccountManager.VISIBILITY_NOT_VISIBLE) { notifyPackage(packageToVisibility.getKey(), accounts); } } sendAccountsChangedBroadcast(accounts.userId); } return true; } } // Update account visibility in cache and database. private boolean updateAccountVisibilityLocked(Account account, String packageName, int newVisibility, UserAccounts accounts) { final long accountId = accounts.accountsDb.findDeAccountId(account); if (accountId < 0) { return false; Loading @@ -765,18 +786,11 @@ public class AccountManagerService } finally { StrictMode.setThreadPolicy(oldPolicy); } if (notify) { for (Entry<String, Integer> packageToVisibility : packagesToVisibility.entrySet()) { if (packageToVisibility.getValue() != AccountManager.VISIBILITY_NOT_VISIBLE) { notifyPackage(packageToVisibility.getKey(), accounts); } } sendAccountsChangedBroadcast(accounts.userId); } Map<String, Integer> accountVisibility = getPackagesAndVisibilityForAccountLocked(account, accounts); accountVisibility.put(packageName, newVisibility); return true; } } @Override public void registerAccountListener(String[] accountTypes, String opPackageName) { Loading Loading @@ -1042,9 +1056,12 @@ public class AccountManagerService accounts.userDataCache.remove(account); accounts.authTokenCache.remove(account); accounts.accountTokenCaches.remove(account); accounts.visibilityCache.remove(account); for (Entry<String, Integer> packageToVisibility : packagesToVisibility.entrySet()) { if (packageToVisibility.getValue() != AccountManager.VISIBILITY_NOT_VISIBLE) { for (Entry<String, Integer> packageToVisibility : packagesToVisibility.entrySet()) { if (packageToVisibility.getValue() != AccountManager.VISIBILITY_NOT_VISIBLE) { notifyPackage(packageToVisibility.getKey(), accounts); } } Loading @@ -1067,6 +1084,7 @@ public class AccountManagerService } accounts.accountCache.put(accountType, accountsForType); } accounts.visibilityCache.putAll(accountsDb.findAllVisibilityValues()); } finally { if (accountDeleted) { sendAccountsChangedBroadcast(accounts.userId); Loading Loading @@ -1181,18 +1199,30 @@ public class AccountManagerService } private void removeVisibilityValuesForPackage(String packageName) { if (isSpecialPackageKey(packageName)) { return; } synchronized (mUsers) { for (int i = 0; i < mUsers.size(); i++) { int numberOfUsers = mUsers.size(); for (int i = 0; i < numberOfUsers; i++) { UserAccounts accounts = mUsers.valueAt(i); try { int uid = mPackageManager.getPackageUidAsUser(packageName, accounts.userId); mPackageManager.getPackageUidAsUser(packageName, accounts.userId); } catch (NameNotFoundException e) { // package does not exist - remove visibility values accounts.accountsDb.deleteAccountVisibilityForPackage(packageName); synchronized(accounts.cacheLock) { for (Account account : accounts.visibilityCache.keySet()) { Map<String, Integer> accountVisibility = getPackagesAndVisibilityForAccountLocked(account, accounts); accountVisibility.remove(packageName); } } } } } } private void onCleanupUser(int userId) { Log.i(TAG, "onCleanupUser " + userId); Loading Loading @@ -1849,6 +1879,7 @@ public class AccountManagerService */ Map<String, String> tmpData = accounts.userDataCache.get(accountToRename); Map<String, String> tmpTokens = accounts.authTokenCache.get(accountToRename); Map<String, Integer> tmpVisibility = accounts.visibilityCache.get(accountToRename); removeAccountFromCacheLocked(accounts, accountToRename); /* * Update the cached data associated with the renamed Loading @@ -1856,6 +1887,7 @@ public class AccountManagerService */ accounts.userDataCache.put(renamedAccount, tmpData); accounts.authTokenCache.put(renamedAccount, tmpTokens); accounts.visibilityCache.put(renamedAccount, tmpVisibility); accounts.previousNameCache.put( renamedAccount, new AtomicReference<>(accountToRename.name)); Loading Loading @@ -5369,6 +5401,7 @@ public class AccountManagerService accounts.userDataCache.remove(account); accounts.authTokenCache.remove(account); accounts.previousNameCache.remove(account); accounts.visibilityCache.remove(account); } /** Loading
services/core/java/com/android/server/accounts/AccountsDb.java +37 −2 Original line number Diff line number Diff line Loading @@ -909,7 +909,7 @@ class AccountsDb implements AutoCloseable { } Integer findAccountVisibility(Account account, String packageName) { SQLiteDatabase db = mDeDatabase.getWritableDatabase(); SQLiteDatabase db = mDeDatabase.getReadableDatabase(); final Cursor cursor = db.query(TABLE_VISIBILITY, new String[] {VISIBILITY_VALUE}, SELECTION_ACCOUNTS_ID_BY_ACCOUNT + " AND " + VISIBILITY_PACKAGE + "=? ", new String[] {account.name, account.type, packageName}, null, null, null); Loading @@ -924,7 +924,7 @@ class AccountsDb implements AutoCloseable { } Integer findAccountVisibility(long accountId, String packageName) { SQLiteDatabase db = mDeDatabase.getWritableDatabase(); SQLiteDatabase db = mDeDatabase.getReadableDatabase(); final Cursor cursor = db.query(TABLE_VISIBILITY, new String[] {VISIBILITY_VALUE}, VISIBILITY_ACCOUNTS_ID + "=? AND " + VISIBILITY_PACKAGE + "=? ", new String[] {String.valueOf(accountId), packageName}, null, null, null); Loading Loading @@ -972,6 +972,41 @@ class AccountsDb implements AutoCloseable { return result; } /** * Returns a map account -> (package -> visibility) */ Map <Account, Map<String, Integer>> findAllVisibilityValues() { SQLiteDatabase db = mDeDatabase.getReadableDatabase(); Map<Account, Map<String, Integer>> result = new HashMap<>(); Cursor cursor = db.rawQuery( "SELECT " + TABLE_VISIBILITY + "." + VISIBILITY_PACKAGE + ", " + TABLE_VISIBILITY + "." + VISIBILITY_VALUE + ", " + TABLE_ACCOUNTS + "." + ACCOUNTS_NAME + ", " + TABLE_ACCOUNTS + "." + ACCOUNTS_TYPE + " FROM " + TABLE_VISIBILITY + " JOIN " + TABLE_ACCOUNTS + " ON " + TABLE_ACCOUNTS + "." + ACCOUNTS_ID + " = " + TABLE_VISIBILITY + "." + VISIBILITY_ACCOUNTS_ID, null); try { while (cursor.moveToNext()) { String packageName = cursor.getString(0); Integer visibility = cursor.getInt(1); String accountName = cursor.getString(2); String accountType = cursor.getString(3); Account account = new Account(accountName, accountType); Map <String, Integer> accountVisibility = result.get(account); if (accountVisibility == null) { accountVisibility = new HashMap<>(); result.put(account, accountVisibility); } accountVisibility.put(packageName, visibility); } } finally { cursor.close(); } return result; } boolean deleteAccountVisibilityForPackage(String packageName) { SQLiteDatabase db = mDeDatabase.getWritableDatabase(); return db.delete(TABLE_VISIBILITY, VISIBILITY_PACKAGE + "=? ", Loading
services/tests/servicestests/src/com/android/server/accounts/AccountManagerServiceTest.java +1 −1 Original line number Diff line number Diff line Loading @@ -94,7 +94,7 @@ import java.util.concurrent.atomic.AtomicLong; * <p>Run with:<pre> * mmma -j40 frameworks/base/services/tests/servicestests * adb install -r ${OUT}/data/app/FrameworksServicesTests/FrameworksServicesTests.apk * adb shell am instrument -w -e class package com.android.server.accounts \ * adb shell am instrument -w -e package com.android.server.accounts \ * com.android.frameworks.servicestests\ * /android.support.test.runner.AndroidJUnitRunner * </pre> Loading
services/tests/servicestests/src/com/android/server/accounts/AccountsDbTest.java +36 −0 Original line number Diff line number Diff line Loading @@ -384,6 +384,42 @@ public class AccountsDbTest { assertFalse(mAccountsDb.deleteAccountVisibilityForPackage(packageName1)); // 2nd attempt. } @Test public void testFindAllVisibilityValues() { long accId = 10; long accId2 = 11; String packageName1 = "com.example.one"; String packageName2 = "com.example.two"; Account account = new Account("name", "example.com"); Account account2 = new Account("name2", "example2.com"); assertNull(mAccountsDb.findAccountVisibility(account, packageName1)); mAccountsDb.insertDeAccount(account, accId); assertNull(mAccountsDb.findAccountVisibility(account, packageName1)); assertNull(mAccountsDb.findAccountVisibility(accId, packageName1)); mAccountsDb.insertDeAccount(account2, accId2); mAccountsDb.setAccountVisibility(accId, packageName1, 1); mAccountsDb.setAccountVisibility(accId, packageName2, 2); mAccountsDb.setAccountVisibility(accId2, packageName1, 1); Map<Account, Map<String, Integer>> vis = mAccountsDb.findAllVisibilityValues(); assertEquals(vis.size(), 2); Map<String, Integer> accnt1Visibility = vis.get(account); assertEquals(accnt1Visibility.size(), 2); assertEquals(accnt1Visibility.get(packageName1), Integer.valueOf(1)); assertEquals(accnt1Visibility.get(packageName2), Integer.valueOf(2)); Map<String, Integer> accnt2Visibility = vis.get(account2); assertEquals(accnt2Visibility.size(), 1); assertEquals(accnt2Visibility.get(packageName1), Integer.valueOf(1)); mAccountsDb.setAccountVisibility(accId2, packageName2, 3); vis = mAccountsDb.findAllVisibilityValues(); accnt2Visibility = vis.get(account2); assertEquals(accnt2Visibility.size(), 2); assertEquals(accnt2Visibility.get(packageName2), Integer.valueOf(3)); } @Test public void testVisibilityCleanupTrigger() { long accId = 10; Loading