Merge "Update Account Discovery API."

This commit is contained in:
TreeHugger Robot
2017-02-04 01:18:18 +00:00
committed by Android (Google) Code Review
10 changed files with 283 additions and 196 deletions

View File

@@ -2909,7 +2909,7 @@ package android.accounts {
public class AccountManager {
method public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle);
method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, java.util.Map<java.lang.Integer, java.lang.Integer>);
method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, java.util.Map<java.lang.String, java.lang.Integer>);
method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean);
method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, java.lang.String[]);
method public java.lang.String blockingGetAuthToken(android.accounts.Account, java.lang.String, boolean) throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException;
@@ -2918,7 +2918,7 @@ package android.accounts {
method public android.accounts.AccountManagerFuture<android.os.Bundle> editProperties(java.lang.String, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> finishSession(android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public static android.accounts.AccountManager get(android.content.Context);
method public int getAccountVisibility(android.accounts.Account, int);
method public int getAccountVisibility(android.accounts.Account, java.lang.String);
method public android.accounts.Account[] getAccounts();
method public java.util.Map<android.accounts.Account, java.lang.Integer> getAccountsAndVisibilityForPackage(java.lang.String, java.lang.String);
method public android.accounts.Account[] getAccountsByType(java.lang.String);
@@ -2929,9 +2929,9 @@ package android.accounts {
method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, java.lang.String, android.os.Bundle, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthTokenByFeatures(java.lang.String, java.lang.String, java.lang.String[], android.app.Activity, android.os.Bundle, android.os.Bundle, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AuthenticatorDescription[] getAuthenticatorTypes();
method public java.util.Map<java.lang.String, java.lang.Integer> getPackagesAndVisibilityForAccount(android.accounts.Account);
method public java.lang.String getPassword(android.accounts.Account);
method public java.lang.String getPreviousName(android.accounts.Account);
method public java.util.Map<java.lang.Integer, java.lang.Integer> getUidsAndVisibilityForAccount(android.accounts.Account);
method public java.lang.String getUserData(android.accounts.Account, java.lang.String);
method public android.accounts.AccountManagerFuture<java.lang.Boolean> hasFeatures(android.accounts.Account, java.lang.String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
method public void invalidateAuthToken(java.lang.String, java.lang.String);
@@ -2945,7 +2945,7 @@ package android.accounts {
method public boolean removeAccountExplicitly(android.accounts.Account);
method public void removeOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener);
method public android.accounts.AccountManagerFuture<android.accounts.Account> renameAccount(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler);
method public boolean setAccountVisibility(android.accounts.Account, int, int);
method public boolean setAccountVisibility(android.accounts.Account, java.lang.String, int);
method public void setAuthToken(android.accounts.Account, java.lang.String, java.lang.String);
method public void setPassword(android.accounts.Account, java.lang.String);
method public void setUserData(android.accounts.Account, java.lang.String, java.lang.String);
@@ -2985,8 +2985,8 @@ package android.accounts {
field public static final java.lang.String KEY_PASSWORD = "password";
field public static final java.lang.String KEY_USERDATA = "userdata";
field public static final deprecated java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
field public static final int UID_KEY_DEFAULT_LEGACY_VISIBILITY = -3; // 0xfffffffd
field public static final int UID_KEY_DEFAULT_VISIBILITY = -2; // 0xfffffffe
field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE = "android.accounts.key_legacy_not_visible";
field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_VISIBLE = "android.accounts.key_legacy_visible";
field public static final int VISIBILITY_NOT_VISIBLE = 3; // 0x3
field public static final int VISIBILITY_UNDEFINED = 0; // 0x0
field public static final int VISIBILITY_USER_MANAGED_NOT_VISIBLE = 4; // 0x4

View File

@@ -3028,7 +3028,7 @@ package android.accounts {
public class AccountManager {
method public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle);
method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, java.util.Map<java.lang.Integer, java.lang.Integer>);
method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, java.util.Map<java.lang.String, java.lang.Integer>);
method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean);
method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, java.lang.String[]);
method public java.lang.String blockingGetAuthToken(android.accounts.Account, java.lang.String, boolean) throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException;
@@ -3038,7 +3038,7 @@ package android.accounts {
method public android.accounts.AccountManagerFuture<android.os.Bundle> finishSession(android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> finishSessionAsUser(android.os.Bundle, android.app.Activity, android.os.UserHandle, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public static android.accounts.AccountManager get(android.content.Context);
method public int getAccountVisibility(android.accounts.Account, int);
method public int getAccountVisibility(android.accounts.Account, java.lang.String);
method public android.accounts.Account[] getAccounts();
method public java.util.Map<android.accounts.Account, java.lang.Integer> getAccountsAndVisibilityForPackage(java.lang.String, java.lang.String);
method public android.accounts.Account[] getAccountsByType(java.lang.String);
@@ -3049,9 +3049,9 @@ package android.accounts {
method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, java.lang.String, android.os.Bundle, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthTokenByFeatures(java.lang.String, java.lang.String, java.lang.String[], android.app.Activity, android.os.Bundle, android.os.Bundle, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AuthenticatorDescription[] getAuthenticatorTypes();
method public java.util.Map<java.lang.String, java.lang.Integer> getPackagesAndVisibilityForAccount(android.accounts.Account);
method public java.lang.String getPassword(android.accounts.Account);
method public java.lang.String getPreviousName(android.accounts.Account);
method public java.util.Map<java.lang.Integer, java.lang.Integer> getUidsAndVisibilityForAccount(android.accounts.Account);
method public java.lang.String getUserData(android.accounts.Account, java.lang.String);
method public android.accounts.AccountManagerFuture<java.lang.Boolean> hasFeatures(android.accounts.Account, java.lang.String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
method public void invalidateAuthToken(java.lang.String, java.lang.String);
@@ -3065,7 +3065,7 @@ package android.accounts {
method public boolean removeAccountExplicitly(android.accounts.Account);
method public void removeOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener);
method public android.accounts.AccountManagerFuture<android.accounts.Account> renameAccount(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler);
method public boolean setAccountVisibility(android.accounts.Account, int, int);
method public boolean setAccountVisibility(android.accounts.Account, java.lang.String, int);
method public void setAuthToken(android.accounts.Account, java.lang.String, java.lang.String);
method public void setPassword(android.accounts.Account, java.lang.String);
method public void setUserData(android.accounts.Account, java.lang.String, java.lang.String);
@@ -3105,8 +3105,8 @@ package android.accounts {
field public static final java.lang.String KEY_PASSWORD = "password";
field public static final java.lang.String KEY_USERDATA = "userdata";
field public static final deprecated java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
field public static final int UID_KEY_DEFAULT_LEGACY_VISIBILITY = -3; // 0xfffffffd
field public static final int UID_KEY_DEFAULT_VISIBILITY = -2; // 0xfffffffe
field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE = "android.accounts.key_legacy_not_visible";
field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_VISIBLE = "android.accounts.key_legacy_visible";
field public static final int VISIBILITY_NOT_VISIBLE = 3; // 0x3
field public static final int VISIBILITY_UNDEFINED = 0; // 0x0
field public static final int VISIBILITY_USER_MANAGED_NOT_VISIBLE = 4; // 0x4

View File

@@ -2909,7 +2909,7 @@ package android.accounts {
public class AccountManager {
method public android.accounts.AccountManagerFuture<android.os.Bundle> addAccount(java.lang.String, java.lang.String, java.lang.String[], android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle);
method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, java.util.Map<java.lang.Integer, java.lang.Integer>);
method public boolean addAccountExplicitly(android.accounts.Account, java.lang.String, android.os.Bundle, java.util.Map<java.lang.String, java.lang.Integer>);
method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean);
method public void addOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener, android.os.Handler, boolean, java.lang.String[]);
method public java.lang.String blockingGetAuthToken(android.accounts.Account, java.lang.String, boolean) throws android.accounts.AuthenticatorException, java.io.IOException, android.accounts.OperationCanceledException;
@@ -2918,7 +2918,7 @@ package android.accounts {
method public android.accounts.AccountManagerFuture<android.os.Bundle> editProperties(java.lang.String, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> finishSession(android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public static android.accounts.AccountManager get(android.content.Context);
method public int getAccountVisibility(android.accounts.Account, int);
method public int getAccountVisibility(android.accounts.Account, java.lang.String);
method public android.accounts.Account[] getAccounts();
method public java.util.Map<android.accounts.Account, java.lang.Integer> getAccountsAndVisibilityForPackage(java.lang.String, java.lang.String);
method public android.accounts.Account[] getAccountsByType(java.lang.String);
@@ -2929,9 +2929,9 @@ package android.accounts {
method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, java.lang.String, android.os.Bundle, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthTokenByFeatures(java.lang.String, java.lang.String, java.lang.String[], android.app.Activity, android.os.Bundle, android.os.Bundle, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
method public android.accounts.AuthenticatorDescription[] getAuthenticatorTypes();
method public java.util.Map<java.lang.String, java.lang.Integer> getPackagesAndVisibilityForAccount(android.accounts.Account);
method public java.lang.String getPassword(android.accounts.Account);
method public java.lang.String getPreviousName(android.accounts.Account);
method public java.util.Map<java.lang.Integer, java.lang.Integer> getUidsAndVisibilityForAccount(android.accounts.Account);
method public java.lang.String getUserData(android.accounts.Account, java.lang.String);
method public android.accounts.AccountManagerFuture<java.lang.Boolean> hasFeatures(android.accounts.Account, java.lang.String[], android.accounts.AccountManagerCallback<java.lang.Boolean>, android.os.Handler);
method public void invalidateAuthToken(java.lang.String, java.lang.String);
@@ -2945,7 +2945,7 @@ package android.accounts {
method public boolean removeAccountExplicitly(android.accounts.Account);
method public void removeOnAccountsUpdatedListener(android.accounts.OnAccountsUpdateListener);
method public android.accounts.AccountManagerFuture<android.accounts.Account> renameAccount(android.accounts.Account, java.lang.String, android.accounts.AccountManagerCallback<android.accounts.Account>, android.os.Handler);
method public boolean setAccountVisibility(android.accounts.Account, int, int);
method public boolean setAccountVisibility(android.accounts.Account, java.lang.String, int);
method public void setAuthToken(android.accounts.Account, java.lang.String, java.lang.String);
method public void setPassword(android.accounts.Account, java.lang.String);
method public void setUserData(android.accounts.Account, java.lang.String, java.lang.String);
@@ -2985,8 +2985,8 @@ package android.accounts {
field public static final java.lang.String KEY_PASSWORD = "password";
field public static final java.lang.String KEY_USERDATA = "userdata";
field public static final deprecated java.lang.String LOGIN_ACCOUNTS_CHANGED_ACTION = "android.accounts.LOGIN_ACCOUNTS_CHANGED";
field public static final int UID_KEY_DEFAULT_LEGACY_VISIBILITY = -3; // 0xfffffffd
field public static final int UID_KEY_DEFAULT_VISIBILITY = -2; // 0xfffffffe
field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE = "android.accounts.key_legacy_not_visible";
field public static final java.lang.String PACKAGE_NAME_KEY_LEGACY_VISIBLE = "android.accounts.key_legacy_visible";
field public static final int VISIBILITY_NOT_VISIBLE = 3; // 0x3
field public static final int VISIBILITY_UNDEFINED = 0; // 0x0
field public static final int VISIBILITY_USER_MANAGED_NOT_VISIBLE = 4; // 0x4

View File

@@ -338,21 +338,24 @@ public class AccountManager {
"android.accounts.LOGIN_ACCOUNTS_CHANGED";
/**
* Uid key to set default visibility for applications targeting API level
* Key to set default visibility for applications targeting API level
* {@link android.os.Build.VERSION_CODES#O} or above and don't have the same signature as
* authenticator See {@link #getAccountVisibility}. If the value was not set by authenticator
* USER_MANAGED_NOT_VISIBLE is used.
* {@link #VISIBILITY_USER_MANAGED_NOT_VISIBLE} is used.
*/
public static final int UID_KEY_DEFAULT_VISIBILITY = -2;
public static final String PACKAGE_NAME_KEY_LEGACY_VISIBLE =
"android.accounts.key_legacy_visible";
/**
* Uid key to set visibility for applications targeting API level below
* {@link android.os.Build.VERSION_CODES#O} with GET_ACCOUNS permission, or applications with
* any targeting API level with the same signature as authenticator. See
* {@link #getAccountVisibility}. If the value was not set by authenticator USER_MANAGED_VISIBLE
* is used.
* Key to set visibility for applications targeting API level below
* {@link android.os.Build.VERSION_CODES#O} with
* {@link android.Manifest.permission#GET_ACCOUNTS} permission, or applications with any
* targeting API level with the same signature as authenticator. See
* {@link #getAccountVisibility}. If the value was not set by authenticator
* {@link #VISIBILITY_USER_MANAGED_VISIBLE} is used.
*/
public static final int UID_KEY_DEFAULT_LEGACY_VISIBILITY = -3;
public static final String PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE =
"android.accounts.key_legacy_not_visible";
/**
* @hide
@@ -565,12 +568,14 @@ public class AccountManager {
}
/**
* Returns the accounts visible to the specified package, in an environment where some apps
* are not authorized to view all accounts. This method can only be called by system apps.
* Returns the accounts visible to the specified package, in an environment where some apps are
* not authorized to view all accounts. This method can only be called by system apps and
* authenticators managing the type
*
* @param type The type of accounts to return, null to retrieve all accounts
* @param packageName The package name of the app for which the accounts are to be returned
* @return An array of {@link Account}, one per matching account. Empty
* (never null) if no accounts of the specified type have been added.
* @return An array of {@link Account}, one per matching account. Empty (never null) if no
* accounts of the specified type have been added.
*/
@NonNull
public Account[] getAccountsByTypeForPackage(String type, String packageName) {
@@ -609,7 +614,8 @@ public class AccountManager {
*
* <p>
* <b>NOTE:</b> If targeting your app to work on API level
* {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and before, GET_ACCOUNTS permission is
* {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and before,
* {@link android.Manifest.permission#GET_ACCOUNTS} permission is
* needed for those platforms, irrespective of uid or signature match. See docs for this
* function in API level {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}.
*
@@ -750,7 +756,8 @@ public class AccountManager {
* accounts managed by AbstractAccountAuthenticators whose signature matches the client.
* <p>
* <b>NOTE:</b> If targeting your app to work on API level
* {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and before, GET_ACCOUNTS permission is
* {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1} and before,
* {@link android.Manifest.permission#GET_ACCOUNTS} permission is
* needed for those platforms, irrespective of uid or signature match. See docs for this
* function in API level {@link android.os.Build.VERSION_CODES#LOLLIPOP_MR1}.
*
@@ -822,9 +829,8 @@ public class AccountManager {
}
/**
* Adds an account directly to the AccountManager. Additionally this makes the Account visible
* to desired UIDs of applications on the device, and sends directed broadcasts to these
* individual applications.
* Adds an account directly to the AccountManager. Additionally it specifies Account visiblity
* for given list of packages.
* <p>
* Normally used by sign-up wizards associated with authenticators, not directly by
* applications.
@@ -841,14 +847,14 @@ public class AccountManager {
* @param account The {@link Account} to add
* @param password The password to associate with the account, null for none
* @param extras String values to use for the account's userdata, null for none
* @param visibility Map from uid to visibility values which will be set before account is
* added. See getAccountVisibility for possilbe values.
* @param visibility Map from packageName to visibility values which will be set before account
* is added. See {@link #getAccountVisibility} for possible values.
*
* @return True if the account was successfully added, false if the account already exists, the
* account is null, or another error occurs.
*/
public boolean addAccountExplicitly(Account account, String password, Bundle extras,
Map<Integer, Integer> visibility) {
Map<String, Integer> visibility) {
if (account == null)
throw new IllegalArgumentException("account is null");
try {
@@ -860,20 +866,22 @@ public class AccountManager {
}
/**
* Returns UIDs of applications for which visibility of given account was explicitly set.
* Returns package names and visibility which were explicitly set for given account.
* <p>
* This method requires the caller to have a signature match with the authenticator that owns
* the specified account.
*
* @param account The account for which visibility data should be returned.
*
* @return Map from uid to visibility for given account.
* @return Map from package names to visibility for given account.
*/
public Map<Integer, Integer> getUidsAndVisibilityForAccount(Account account) {
public Map<String, Integer> getPackagesAndVisibilityForAccount(Account account) {
try {
if (account == null)
throw new IllegalArgumentException("account is null");
@SuppressWarnings("unchecked")
Map<Integer, Integer> result = (Map<Integer, Integer>) mService
.getUidsAndVisibilityForAccount(account);
Map<String, Integer> result = (Map<String, Integer>) mService
.getPackagesAndVisibilityForAccount(account);
return result;
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
@@ -907,30 +915,34 @@ public class AccountManager {
}
/**
* Set visibility value of given account to certain UID.
* Set visibility value of given account to certain packageName.
* Package name must match installed application, or be equal to
* {@link #PACKAGE_NAME_KEY_LEGACY_VISIBLE} or {@link #PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE}.
* <p>
* See {@link #getAccountVisibility} for possible values.
* <p>
* This method requires the caller to have a signature match with the authenticator that owns
* the specified account.
*
* @param account Account to make visible.
* @param uid The UID of the application to modify account visibility.
* @param account Account to update visibility
* @param packageName Package name of the application to modify account visibility.
* @param visibility - new visibility value.
*
* @return True if visibility value was succesfully updated.
*/
public boolean setAccountVisibility(Account account, int uid,
public boolean setAccountVisibility(Account account, String packageName,
@AccountVisibility int visibility) {
if (account == null)
throw new IllegalArgumentException("account is null");
try {
return mService.setAccountVisibility(account, uid, visibility);
return mService.setAccountVisibility(account, packageName, visibility);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}
}
/**
* Gets visibility of certain account for given UID. Possible returned values are:
* Get visibility of certain account for given application. Possible returned values are:
* <ul>
* <li>{@link #VISIBILITY_UNDEFINED}</li>
* <li>{@link #VISIBILITY_VISIBLE}</li>
@@ -944,13 +956,15 @@ public class AccountManager {
* the specified account.
*
* @param account Account to get visibility.
* @param uid The UID of the application to get account visibility.
* @param packageName Package name of the application to get account visibility
*
* @return int Visibility for given account and uid.
* @return int Visibility for given account and package.
*/
public @AccountVisibility int getAccountVisibility(Account account, int uid) {
public @AccountVisibility int getAccountVisibility(Account account, String packageName) {
if (account == null)
throw new IllegalArgumentException("account is null");
try {
return mService.getAccountVisibility(account, uid);
return mService.getAccountVisibility(account, packageName);
} catch (RemoteException re) {
throw re.rethrowFromSystemServer();
}

View File

@@ -437,7 +437,7 @@ public class ChooseTypeAndAccountActivity extends Activity
}
if (oldVisibility != null
&& oldVisibility == AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE) {
AccountManager.get(this).setAccountVisibility(account, mCallingUid,
AccountManager.get(this).setAccountVisibility(account, mCallingPackage,
AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
}
Bundle bundle = new Bundle();

View File

@@ -108,15 +108,12 @@ interface IAccountManager {
void isCredentialsUpdateSuggested(in IAccountManagerResponse response, in Account account,
String statusToken);
/* Returns Map<Integer, Integer> from UID to visibility with all values stored for given account*/
Map getUidsAndVisibilityForAccount(in Account account);
/* Returns Map<String, Integer> from package name to visibility with all values stored for given account */
Map getPackagesAndVisibilityForAccount(in Account account);
boolean addAccountExplicitlyWithVisibility(in Account account, String password, in Bundle extras,
in Map visibility);
boolean setAccountVisibility(in Account a, int uid, int newVisibility);
int getAccountVisibility(in Account a, int uid);
boolean setAccountVisibility(in Account a, in String packageName, int newVisibility);
int getAccountVisibility(in Account a, in String packageName);
/* Type may be null returns Map <Account, Integer>*/
Map getAccountsAndVisibilityForPackage(in String packageName, in String accountType);

View File

@@ -287,16 +287,17 @@ public class AccountManagerService
* and then rebuild the cache. All under the cache lock. But that change is too
* large at this point.
*/
final String removedPackageName = intent.getData().toString();
Runnable purgingRunnable = new Runnable() {
@Override
public void run() {
purgeOldGrantsAll();
// Notify authenticator about removed app?
removeVisibilityValuesForPackage(removedPackageName);
}
};
mHandler.post(purgingRunnable);
}
}
}, intentFilter);
@@ -429,7 +430,7 @@ public class AccountManagerService
@Override
public boolean addAccountExplicitlyWithVisibility(Account account, String password,
Bundle extras, Map uidToVisibility) {
Bundle extras, Map packageToVisibility) {
Bundle.setDefusable(extras, true);
final int callingUid = Binder.getCallingUid();
@@ -455,7 +456,7 @@ public class AccountManagerService
try {
UserAccounts accounts = getUserAccounts(userId);
return addAccountInternal(accounts, account, password, extras, callingUid,
(Map<Integer, Integer>) uidToVisibility);
(Map<String, Integer>) packageToVisibility);
} finally {
restoreCallingIdentity(identityToken);
}
@@ -505,7 +506,7 @@ public class AccountManagerService
if (accountsOfType != null) {
for (Account account : accountsOfType) {
result.put(account,
resolveAccountVisibility(account, uid, packageName, accounts));
resolveAccountVisibility(account, packageName, accounts));
}
}
}
@@ -514,7 +515,7 @@ public class AccountManagerService
}
@Override
public Map<Integer, Integer> getUidsAndVisibilityForAccount(Account account) {
public Map<String, Integer> getPackagesAndVisibilityForAccount(Account account) {
if (account == null) throw new IllegalArgumentException("account is null");
int callingUid = Binder.getCallingUid();
int userId = UserHandle.getUserId(callingUid);
@@ -525,18 +526,18 @@ public class AccountManagerService
String.format("uid %s cannot get secrets for account %s", callingUid, account);
throw new SecurityException(msg);
}
return getUidsAndVisibilityForAccount(account, accounts);
return getPackagesAndVisibilityForAccount(account, accounts);
}
/**
* Returns all UIDs and visibility values, which were set for given account
* Returns all package names and visibility values, which were set for given account.
*
* @param account account
* @param account Account to get visibility values.
* @param accounts UserAccount that currently hosts the account and application
*
* @return Map from uid to visibility.
* @return Map from package names to visibility.
*/
private Map<Integer, Integer> getUidsAndVisibilityForAccount(Account account,
private Map<String, Integer> getPackagesAndVisibilityForAccount(Account account,
UserAccounts accounts) {
final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
try {
@@ -548,7 +549,7 @@ public class AccountManagerService
}
@Override
public int getAccountVisibility(Account a, int uid) {
public int getAccountVisibility(Account a, String packageName) {
if (a == null) throw new IllegalArgumentException("account is null");
int callingUid = Binder.getCallingUid();
if (!isAccountManagedByCaller(a.type, callingUid, UserHandle.getUserId(callingUid))
@@ -559,23 +560,24 @@ public class AccountManagerService
a.type);
throw new SecurityException(msg);
}
return getAccountVisibility(a, uid, getUserAccounts(UserHandle.getUserId(callingUid)));
return getAccountVisibility(a, packageName,
getUserAccounts(UserHandle.getUserId(callingUid)));
}
/**
* Method gets visibility for given account and UID from the database
* Method returns visibility for given account and package name.
*
* @param account The account to check visibility of
* @param uid UID to check visibility of
* @param account The account to check visibility.
* @param packageName Package name to check visibility.
* @param accounts UserAccount that currently hosts the account and application
*
* @return Visibility value, AccountManager.VISIBILITY_UNDEFINED if no value was stored.
*
*/
private int getAccountVisibility(Account account, int uid, UserAccounts accounts) {
private int getAccountVisibility(Account account, String packageName, UserAccounts accounts) {
final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
try {
Integer visibility = accounts.accountsDb.findAccountVisibility(account, uid);
Integer visibility = accounts.accountsDb.findAccountVisibility(account, packageName);
return visibility != null ? visibility : AccountManager.VISIBILITY_UNDEFINED;
} finally {
StrictMode.setThreadPolicy(oldPolicy);
@@ -586,19 +588,29 @@ public class AccountManagerService
* Method which handles default values for Account visibility.
*
* @param account The account to check visibility.
* @param uid UID to check visibility.
* @param packageName Package name to check visibility - the method assumes that it has the same
* uid as specified in the parameter.
* @param packageName Package name to check visibility
* @param accounts UserAccount that currently hosts the account and application
*
* @return Visibility value, the method never returns AccountManager.VISIBILITY_UNDEFINED
*
*/
private Integer resolveAccountVisibility(Account account, int uid, String packageName,
private Integer resolveAccountVisibility(Account account, @NonNull String packageName,
UserAccounts accounts) {
if (packageName == null) {
packageName = getPackageNameForUid(uid);
Preconditions.checkNotNull(packageName, "packageName cannot be null");
int uid = -1;
try {
long identityToken = clearCallingIdentity();
try {
uid = mPackageManager.getPackageUidAsUser(packageName, accounts.userId);
} finally {
restoreCallingIdentity(identityToken);
}
} catch (NameNotFoundException e) {
Log.d(TAG, "Package not found " + e.getMessage());
return AccountManager.VISIBILITY_NOT_VISIBLE;
}
// System visibility can not be restricted.
if (UserHandle.isSameApp(uid, Process.SYSTEM_UID)) {
return AccountManager.VISIBILITY_VISIBLE;
@@ -612,8 +624,13 @@ public class AccountManagerService
return AccountManager.VISIBILITY_VISIBLE; // Authenticator can always see the account
}
if (isSpecialPackageKey(packageName)) {
Log.d(TAG, "Package name is forbidden: " + packageName);
return AccountManager.VISIBILITY_NOT_VISIBLE;
}
// Return stored value if it was set.
int visibility = getAccountVisibility(account, uid, accounts);
int visibility = getAccountVisibility(account, packageName, accounts);
if (AccountManager.VISIBILITY_UNDEFINED != visibility) {
return visibility;
@@ -622,10 +639,9 @@ public class AccountManagerService
if (isPermittedForPackage(packageName, accounts.userId,
Manifest.permission.GET_ACCOUNTS_PRIVILEGED)) {
return AccountManager.VISIBILITY_VISIBLE;
}
// Profile owner gets visibility by default.
if(isProfileOwner(uid)) {
if (isProfileOwner(uid)) {
return AccountManager.VISIBILITY_VISIBLE;
}
// Apps with READ_CONTACTS permission get visibility by default even post O.
@@ -638,13 +654,13 @@ public class AccountManagerService
// Use legacy for preO apps with GET_ACCOUNTS permission or pre/postO with signature
// match.
visibility = getAccountVisibility(account,
AccountManager.UID_KEY_DEFAULT_LEGACY_VISIBILITY, accounts);
AccountManager.PACKAGE_NAME_KEY_LEGACY_VISIBLE, accounts);
if (AccountManager.VISIBILITY_UNDEFINED == visibility) {
visibility = AccountManager.VISIBILITY_USER_MANAGED_VISIBLE;
}
} else {
visibility = getAccountVisibility(account, AccountManager.UID_KEY_DEFAULT_VISIBILITY,
accounts);
visibility = getAccountVisibility(account,
AccountManager.PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE, accounts);
if (AccountManager.VISIBILITY_UNDEFINED == visibility) {
visibility = AccountManager.VISIBILITY_USER_MANAGED_NOT_VISIBLE;
}
@@ -655,7 +671,7 @@ public class AccountManagerService
/**
* Checks targetSdk for a package;
*
* @param packageName Package Name
* @param packageName Package name
*
* @return True if package's target SDK is below {@link android.os.Build.VERSION_CODES#O}, or
* undefined
@@ -682,7 +698,7 @@ public class AccountManagerService
}
@Override
public boolean setAccountVisibility(Account a, int uid, int newVisibility) {
public boolean setAccountVisibility(Account a, String packageName, int newVisibility) {
if (a == null) throw new IllegalArgumentException("account is null");
int callingUid = Binder.getCallingUid();
if (!isAccountManagedByCaller(a.type, callingUid, UserHandle.getUserId(callingUid))
@@ -693,38 +709,42 @@ public class AccountManagerService
a.type);
throw new SecurityException(msg);
}
return setAccountVisibility(a, uid, newVisibility, true /* notify */,
return setAccountVisibility(a, packageName, newVisibility, true /* notify */,
getUserAccounts(UserHandle.getUserId(callingUid)));
}
/**
* Gives a certain UID, represented a application, access to an account. This method
* is called indirectly by the Authenticator.
* Updates visibility for given account name and package.
*
* @param account Account to update visibility
* @param uid to add visibility of the Account
* @param newVisibility new visibility
* @param account Account to update visibility.
* @param packageName Package name for which visibility is updated.
* @param newVisibility New visibility calue
* @param notify if the flag is set applications will get notification about visibility change
* @param accounts UserAccount that currently hosts the account and application
*
* @return True if account visibility was changed.
*/
private boolean setAccountVisibility(Account account, int uid, int newVisibility,
private boolean setAccountVisibility(Account account, String packageName, int newVisibility,
boolean notify, UserAccounts accounts) {
synchronized (accounts.cacheLock) {
LinkedHashSet<String> interestedPackages;
if (notify) {
if (uid < 0) {
if (isSpecialPackageKey(packageName)) {
interestedPackages = getRequestingPackageNames(account.type, accounts);
} else {
interestedPackages = new LinkedHashSet<>();
String[] subPackages = mPackageManager.getPackagesForUid(uid);
if (subPackages != null) {
Collections.addAll(interestedPackages, subPackages);
if (!packageExistsForUser(packageName, accounts.userId)) {
return false; // package is not installed.
}
interestedPackages = new LinkedHashSet<>();
interestedPackages.add(packageName);
}
} else {
// Notifications will not be send.
if (!isSpecialPackageKey(packageName) &&
!packageExistsForUser(packageName, accounts.userId)) {
// package is not installed and not meta value.
return false;
}
interestedPackages = new LinkedHashSet<>();
}
Integer[] interestedPackagesVisibility = new Integer[interestedPackages.size()];
@@ -734,14 +754,15 @@ public class AccountManagerService
return false;
}
int index = 0;
for (String packageName : interestedPackages) {
for (String interestedPackage : interestedPackages) {
interestedPackagesVisibility[index++] =
resolveAccountVisibility(account, uid, packageName, accounts);
resolveAccountVisibility(account, interestedPackage, accounts);
}
final StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskWrites();
try {
if (!accounts.accountsDb.setAccountVisibility(accountId, uid, newVisibility)) {
if (!accounts.accountsDb.setAccountVisibility(accountId, packageName,
newVisibility)) {
return false;
}
} finally {
@@ -749,10 +770,10 @@ public class AccountManagerService
}
index = 0;
for (String packageName : interestedPackages) {
int visibility = resolveAccountVisibility(account, uid, packageName, accounts);
for (String interestedPackage : interestedPackages) {
int visibility = resolveAccountVisibility(account, interestedPackage, accounts);
if (visibility != interestedPackagesVisibility[index++]) {
sendNotification(packageName, account, accounts.userId);
sendNotification(interestedPackage, account, accounts.userId);
}
}
if (notify) {
@@ -777,23 +798,40 @@ public class AccountManagerService
LinkedHashSet<String> interestedPackages = getRequestingPackageNames(account.type,
accounts);
for (String packageName : interestedPackages) {
try {
final int uid = mPackageManager.getPackageUidAsUser(packageName, accounts.userId);
int visibility = resolveAccountVisibility(account, uid, packageName, accounts);
if (visibility != AccountManager.VISIBILITY_NOT_VISIBLE) {
sendNotification(packageName, account, accounts.userId);
}
} catch (NameNotFoundException e) {
// ignore
int visibility = resolveAccountVisibility(account, packageName, accounts);
if (visibility != AccountManager.VISIBILITY_NOT_VISIBLE) {
sendNotification(packageName, account, accounts.userId);
}
}
}
LinkedHashSet<String> getRequestingPackageNames(String accountType, UserAccounts accouns) {
LinkedHashSet<String> getRequestingPackageNames(String accountType, UserAccounts accounts) {
// TODO return packages registered to get notifications.
return new LinkedHashSet<String>();
}
private boolean packageExistsForUser(String packageName, int userId) {
try {
long identityToken = clearCallingIdentity();
try {
mPackageManager.getPackageUidAsUser(packageName, userId);
return true; // package exist
} finally {
restoreCallingIdentity(identityToken);
}
} catch (NameNotFoundException e) {
return false;
}
}
/**
* Returns true if packageName is one of special values.
*/
private boolean isSpecialPackageKey(String packageName) {
return (AccountManager.PACKAGE_NAME_KEY_LEGACY_VISIBLE.equals(packageName)
|| AccountManager.PACKAGE_NAME_KEY_LEGACY_NOT_VISIBLE.equals(packageName));
}
private void sendAccountsChangedBroadcast(int userId) {
Log.i(TAG, "the accounts changed, sending broadcast of "
+ ACCOUNTS_CHANGED_INTENT.getAction());
@@ -1075,6 +1113,20 @@ public class AccountManagerService
}
}
private void removeVisibilityValuesForPackage(String packageName) {
synchronized (mUsers) {
for (int i = 0; i < mUsers.size(); i++) {
UserAccounts accounts = mUsers.valueAt(i);
try {
int uid = mPackageManager.getPackageUidAsUser(packageName, accounts.userId);
} catch (NameNotFoundException e) {
// package does not exist - remove visibility values
accounts.accountsDb.deleteAccountVisibilityForPackage(packageName);
}
}
}
}
private void onUserRemoved(Intent intent) {
int userId = intent.getIntExtra(Intent.EXTRA_USER_HANDLE, -1);
if (userId < 1) return;
@@ -1472,7 +1524,7 @@ public class AccountManagerService
}
private boolean addAccountInternal(UserAccounts accounts, Account account, String password,
Bundle extras, int callingUid, Map<Integer, Integer> uidToVisibility) {
Bundle extras, int callingUid, Map<String, Integer> packageToVisibility) {
Bundle.setDefusable(extras, true);
if (account == null) {
return false;
@@ -1513,9 +1565,9 @@ public class AccountManagerService
}
}
if (uidToVisibility != null) {
for (Entry<Integer, Integer> entry : uidToVisibility.entrySet()) {
setAccountVisibility(account, entry.getKey() /* uid */,
if (packageToVisibility != null) {
for (Entry<String, Integer> entry : packageToVisibility.entrySet()) {
setAccountVisibility(account, entry.getKey() /* package */,
entry.getValue() /* visibility */, false /* notify */, accounts);
}
}
@@ -1569,6 +1621,7 @@ public class AccountManagerService
public void hasFeatures(IAccountManagerResponse response,
Account account, String[] features, String opPackageName) {
int callingUid = Binder.getCallingUid();
mAppOpsManager.checkPackage(callingUid, opPackageName);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "hasFeatures: " + account
+ ", response " + response
@@ -1982,14 +2035,7 @@ public class AccountManagerService
int[] visibilityForInterestedPackages = new int[interestedPackages.size()];
int index = 0;
for (String packageName : interestedPackages) {
int visibility = AccountManager.VISIBILITY_NOT_VISIBLE;
try {
final int uid = mPackageManager.getPackageUidAsUser(packageName,
UserHandle.getUserId(callingUid));
visibility = resolveAccountVisibility(account, uid, packageName, accounts);
} catch (NameNotFoundException e) {
// ignore
}
int visibility = resolveAccountVisibility(account, packageName, accounts);
visibilityForInterestedPackages[index++] = visibility;
}
accounts.accountsDb.beginTransaction();
@@ -3663,7 +3709,7 @@ public class AccountManagerService
// In addition to the permissions required to get an auth token we also allow
// the account to be accessed by apps for which user or authenticator granted visibility.
int visibility = resolveAccountVisibility(account, uid, packageName,
int visibility = resolveAccountVisibility(account, packageName,
getUserAccounts(UserHandle.getUserId(uid)));
return (visibility == AccountManager.VISIBILITY_VISIBLE
|| visibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE);
@@ -3870,6 +3916,7 @@ public class AccountManagerService
@NonNull
public Account[] getAccounts(int userId, String opPackageName) {
int callingUid = Binder.getCallingUid();
mAppOpsManager.checkPackage(callingUid, opPackageName);
List<String> visibleAccountTypes = getTypesVisibleToCaller(callingUid, userId,
opPackageName);
if (visibleAccountTypes.isEmpty()) {
@@ -3890,7 +3937,7 @@ public class AccountManagerService
}
/**
* Returns accounts for all running users.
* Returns accounts for all running users, ignores visibility values.
*
* @hide
*/
@@ -3906,7 +3953,11 @@ public class AccountManagerService
return getAccounts(runningUserIds);
}
/** {@hide} */
/**
* Returns accounts for all users, ignores visibility values.
*
* @hide
*/
@NonNull
public AccountAndUser[] getAllAccounts() {
final List<UserInfo> users = getUserManager().getUsers(true);
@@ -3924,10 +3975,12 @@ public class AccountManagerService
UserAccounts userAccounts = getUserAccounts(userId);
if (userAccounts == null) continue;
synchronized (userAccounts.cacheLock) {
Account[] accounts = getAccountsFromCacheLocked(userAccounts, null,
Account[] accounts = getAccountsFromCacheLocked(
userAccounts,
null /* type */,
Binder.getCallingUid(),
null,
false /* incl managed not visible*/);
null /* packageName */,
false /* include managed not visible*/);
for (int a = 0; a < accounts.length; a++) {
runningAccounts.add(new AccountAndUser(accounts[a], userId));
}
@@ -3941,9 +3994,10 @@ public class AccountManagerService
@Override
@NonNull
public Account[] getAccountsAsUser(String type, int userId, String opPackageName) {
// Need calling package
return getAccountsAsUser(type, userId, null /* callingPackage */, -1, opPackageName,
false /* includeUserManagedNotVisible */);
int callingUid = Binder.getCallingUid();
mAppOpsManager.checkPackage(callingUid, opPackageName);
return getAccountsAsUser(type, userId, opPackageName /* callingPackage */, -1,
opPackageName, false /* includeUserManagedNotVisible */);
}
@NonNull
@@ -4112,6 +4166,7 @@ public class AccountManagerService
public Account[] getAccountsForPackage(String packageName, int uid, String opPackageName) {
int callingUid = Binder.getCallingUid();
if (!UserHandle.isSameApp(callingUid, Process.SYSTEM_UID)) {
// Don't do opPackageName check - caller is system.
throw new SecurityException("getAccountsForPackage() called from unauthorized uid "
+ callingUid + " with uid=" + uid);
}
@@ -4125,6 +4180,7 @@ public class AccountManagerService
String opPackageName) {
int callingUid = Binder.getCallingUid();
int userId = UserHandle.getCallingUserId();
mAppOpsManager.checkPackage(callingUid, opPackageName);
int packageUid = -1;
try {
packageUid = mPackageManager.getPackageUidAsUser(packageName, userId);
@@ -4148,6 +4204,7 @@ public class AccountManagerService
String[] features,
String opPackageName) {
int callingUid = Binder.getCallingUid();
mAppOpsManager.checkPackage(callingUid, opPackageName);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getAccounts: accountType " + type
+ ", response " + response
@@ -4738,7 +4795,7 @@ public class AccountManagerService
userAccounts.accountsDb.dumpDeAccountsTable(fout);
} else {
Account[] accounts = getAccountsFromCacheLocked(userAccounts, null /* type */,
Process.SYSTEM_UID, null, false);
Process.SYSTEM_UID, null /* packageName */, false);
fout.println("Accounts: " + accounts.length);
for (Account account : accounts) {
fout.println(" " + account);
@@ -4954,7 +5011,7 @@ public class AccountManagerService
// Method checks visibility for applications targeing API level below {@link
// android.os.Build.VERSION_CODES#O},
// returns true if the the app has GET_ACCOUNTS or GET_ACCOUNTS_PRIVELEGED permission.
// returns true if the the app has GET_ACCOUNTS or GET_ACCOUNTS_PRIVILEGED permission.
private boolean checkGetAccountsPermission(String packageName, int userId) {
return isPermittedForPackage(packageName, userId, Manifest.permission.GET_ACCOUNTS,
Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
@@ -5307,8 +5364,7 @@ public class AccountManagerService
// filter based on visibility.
Map<Account, Integer> firstPass = new HashMap<>();
for (Account account : unfiltered) {
int visibility =
resolveAccountVisibility(account, callingUid, callingPackage, accounts);
int visibility = resolveAccountVisibility(account, callingPackage, accounts);
if ((visibility == AccountManager.VISIBILITY_VISIBLE
|| visibility == AccountManager.VISIBILITY_USER_MANAGED_VISIBLE)
|| (includeManagedNotVisible
@@ -5403,6 +5459,9 @@ public class AccountManagerService
*/
protected Account[] getAccountsFromCacheLocked(UserAccounts userAccounts, String accountType,
int callingUid, String callingPackage, boolean includeManagedNotVisible) {
if (callingPackage == null) {
callingPackage = getPackageNameForUid(callingUid);
}
if (accountType != null) {
final Account[] accounts = userAccounts.accountCache.get(accountType);
if (accounts == null) {

View File

@@ -54,7 +54,7 @@ class AccountsDb implements AutoCloseable {
private static final String DATABASE_NAME = "accounts.db";
private static final int PRE_N_DATABASE_VERSION = 9;
private static final int CE_DATABASE_VERSION = 10;
private static final int DE_DATABASE_VERSION = 2; // Added visibility support in O.
private static final int DE_DATABASE_VERSION = 3; // Added visibility support in O
static final String TABLE_ACCOUNTS = "accounts";
@@ -75,7 +75,7 @@ class AccountsDb implements AutoCloseable {
private static final String TABLE_VISIBILITY = "visibility";
private static final String VISIBILITY_ACCOUNTS_ID = "accounts_id";
private static final String VISIBILITY_UID = "_uid";
private static final String VISIBILITY_PACKAGE = "_package";
private static final String VISIBILITY_VALUE = "value";
private static final String TABLE_GRANTS = "grants";
@@ -252,7 +252,7 @@ class AccountsDb implements AutoCloseable {
createAccountsDeletionTrigger(db);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_GRANTS);
db.execSQL("DROP TABLE IF EXISTS " + TABLE_DEBUG);
oldVersion ++;
oldVersion++;
}
if (oldVersion != newVersion) {
@@ -559,9 +559,9 @@ class AccountsDb implements AutoCloseable {
private void createAccountsVisibilityTable(SQLiteDatabase db) {
db.execSQL("CREATE TABLE " + TABLE_VISIBILITY + " ( "
+ VISIBILITY_ACCOUNTS_ID + " INTEGER NOT NULL, "
+ VISIBILITY_UID + " TEXT NOT NULL, "
+ VISIBILITY_PACKAGE + " TEXT NOT NULL, "
+ VISIBILITY_VALUE + " INTEGER, "
+ "PRIMARY KEY(" + VISIBILITY_ACCOUNTS_ID + "," + VISIBILITY_UID + "))");
+ "PRIMARY KEY(" + VISIBILITY_ACCOUNTS_ID + "," + VISIBILITY_PACKAGE + "))");
}
static void createDebugTable(SQLiteDatabase db) {
@@ -591,9 +591,18 @@ class AccountsDb implements AutoCloseable {
Log.i(TAG, "upgrade from version " + oldVersion + " to version " + newVersion);
if (oldVersion == 1) {
createAccountsVisibilityTable(db);
createAccountsDeletionVisibilityCleanupTrigger(db);
++oldVersion;
createAccountsVisibilityTable(db);
createAccountsDeletionVisibilityCleanupTrigger(db);
oldVersion = 3; // skip version 2 which had uid based table
}
if (oldVersion == 2) {
// Remove uid based table and replace it with packageName based
db.execSQL("DROP TRIGGER IF EXISTS " + TABLE_ACCOUNTS + "DeleteVisibility");
db.execSQL("DROP TABLE IF EXISTS " + TABLE_ACCOUNTS);
createAccountsVisibilityTable(db);
createAccountsDeletionVisibilityCleanupTrigger(db);
oldVersion++;
}
if (oldVersion != newVersion) {
@@ -890,20 +899,20 @@ class AccountsDb implements AutoCloseable {
new String[] {Integer.toString(uid)}) > 0;
}
boolean setAccountVisibility(long accountId, int uid, int visibility) {
boolean setAccountVisibility(long accountId, String packageName, int visibility) {
SQLiteDatabase db = mDeDatabase.getWritableDatabase();
ContentValues values = new ContentValues();
values.put(VISIBILITY_ACCOUNTS_ID, String.valueOf(accountId));
values.put(VISIBILITY_UID, String.valueOf(uid));
values.put(VISIBILITY_PACKAGE, packageName);
values.put(VISIBILITY_VALUE, String.valueOf(visibility));
return (db.replace(TABLE_VISIBILITY, VISIBILITY_VALUE, values) != -1);
}
Integer findAccountVisibility(Account account, int uid) {
Integer findAccountVisibility(Account account, String packageName) {
SQLiteDatabase db = mDeDatabase.getWritableDatabase();
final Cursor cursor = db.query(TABLE_VISIBILITY, new String[] {VISIBILITY_VALUE},
SELECTION_ACCOUNTS_ID_BY_ACCOUNT + " AND " + VISIBILITY_UID + "=? ",
new String[] {account.name, account.type, String.valueOf(uid)}, null, null, null);
SELECTION_ACCOUNTS_ID_BY_ACCOUNT + " AND " + VISIBILITY_PACKAGE + "=? ",
new String[] {account.name, account.type, packageName}, null, null, null);
try {
while (cursor.moveToNext()) {
return cursor.getInt(0);
@@ -914,11 +923,11 @@ class AccountsDb implements AutoCloseable {
return null;
}
Integer findAccountVisibility(long accountId, int uid) {
Integer findAccountVisibility(long accountId, String packageName) {
SQLiteDatabase db = mDeDatabase.getWritableDatabase();
final Cursor cursor = db.query(TABLE_VISIBILITY, new String[] {VISIBILITY_VALUE},
VISIBILITY_ACCOUNTS_ID + "=? AND " + VISIBILITY_UID + "=? ",
new String[] {String.valueOf(accountId), String.valueOf(uid)}, null, null, null);
VISIBILITY_ACCOUNTS_ID + "=? AND " + VISIBILITY_PACKAGE + "=? ",
new String[] {String.valueOf(accountId), packageName}, null, null, null);
try {
while (cursor.moveToNext()) {
return cursor.getInt(0);
@@ -944,18 +953,18 @@ class AccountsDb implements AutoCloseable {
}
/**
* Returns a map from uid to visibility value.
* Returns a map from packageNames to visibility.
*/
Map<Integer, Integer> findAllVisibilityValuesForAccount(Account account) {
Map<String, Integer> findAllVisibilityValuesForAccount(Account account) {
SQLiteDatabase db = mDeDatabase.getReadableDatabase();
Map<Integer, Integer> result = new HashMap<>();
Map<String, Integer> result = new HashMap<>();
final Cursor cursor =
db.query(TABLE_VISIBILITY, new String[] {VISIBILITY_UID, VISIBILITY_VALUE},
SELECTION_ACCOUNTS_ID_BY_ACCOUNT,
new String[] {account.name, account.type}, null, null, null);
db.query(TABLE_VISIBILITY, new String[] {VISIBILITY_PACKAGE, VISIBILITY_VALUE},
SELECTION_ACCOUNTS_ID_BY_ACCOUNT, new String[] {account.name, account.type},
null, null, null);
try {
while (cursor.moveToNext()) {
result.put(cursor.getInt(0), cursor.getInt(1));
result.put(cursor.getString(0), cursor.getInt(1));
}
} finally {
cursor.close();
@@ -963,10 +972,10 @@ class AccountsDb implements AutoCloseable {
return result;
}
boolean deleteAccountVisibilityForUid(int uid) {
boolean deleteAccountVisibilityForPackage(String packageName) {
SQLiteDatabase db = mDeDatabase.getWritableDatabase();
return db.delete(TABLE_VISIBILITY, VISIBILITY_UID + "=? ",
new String[] {Integer.toString(uid)}) > 0;
return db.delete(TABLE_VISIBILITY, VISIBILITY_PACKAGE + "=? ",
new String[] {packageName}) > 0;
}
long insertOrReplaceMetaAuthTypeAndUid(String authenticatorType, int uid) {

View File

@@ -190,6 +190,8 @@ public class AccountManagerServiceTest extends AndroidTestCase {
mAms.addAccountExplicitly(a31, "p31", null);
mAms.addAccountExplicitly(a32, "p32", null);
String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE};
when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list);
Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName());
Arrays.sort(accounts, new AccountSorter());
assertEquals(6, accounts.length);
@@ -306,6 +308,8 @@ public class AccountManagerServiceTest extends AndroidTestCase {
@SmallTest
public void testRemovedAccountSync() throws Exception {
String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE};
when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list);
unlockSystemUser();
Account a1 = new Account("account1", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_1);
Account a2 = new Account("account2", AccountManagerServiceTestFixtures.ACCOUNT_TYPE_2);
@@ -347,6 +351,8 @@ public class AccountManagerServiceTest extends AndroidTestCase {
// Start testing
unlockSystemUser();
String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE};
when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list);
Account[] accounts = mAms.getAccounts(null, mContext.getOpPackageName());
assertEquals("1 account should be migrated", 1, accounts.length);
assertEquals(PreNTestDatabaseHelper.ACCOUNT_NAME, accounts[0].name);
@@ -1048,7 +1054,6 @@ public class AccountManagerServiceTest extends AndroidTestCase {
// Assert finishSessionAsUser added calling uid and pid into the sessionBundle
assertTrue(sessionBundle.containsKey(AccountManager.KEY_CALLER_UID));
assertTrue(sessionBundle.containsKey(AccountManager.KEY_CALLER_PID));
// Assert App bundle data overrides sessionBundle data
assertEquals(sessionBundle.getString(
AccountManager.KEY_ANDROID_PACKAGE_NAME), "APCT.package");
@@ -1387,6 +1392,9 @@ public class AccountManagerServiceTest extends AndroidTestCase {
@SmallTest
public void testRemoveAccountAsUserRemovalAllowed() throws Exception {
String[] list = new String[]{AccountManagerServiceTestFixtures.CALLER_PACKAGE};
when(mMockPackageManager.getPackagesForUid(anyInt())).thenReturn(list);
unlockSystemUser();
mAms.addAccountExplicitly(AccountManagerServiceTestFixtures.ACCOUNT_SUCCESS, "p1", null);
Account[] addedAccounts =

View File

@@ -355,49 +355,49 @@ public class AccountsDbTest {
@Test
public void testVisibilityFindSetDelete() {
long accId = 10;
int uid1 = 100500;
int uid2 = 100501;
String packageName1 = "com.example.one";
String packageName2 = "com.example.two";
Account account = new Account("name", "example.com");
assertNull(mAccountsDb.findAccountVisibility(account, uid1));
assertNull(mAccountsDb.findAccountVisibility(account, packageName1));
mAccountsDb.insertDeAccount(account, accId);
assertNull(mAccountsDb.findAccountVisibility(account, uid1));
assertNull(mAccountsDb.findAccountVisibility(accId, uid1));
assertNull(mAccountsDb.findAccountVisibility(account, packageName1));
assertNull(mAccountsDb.findAccountVisibility(accId, packageName1));
mAccountsDb.setAccountVisibility(accId, uid1, 1);
assertEquals(mAccountsDb.findAccountVisibility(account, uid1), Integer.valueOf(1));
assertEquals(mAccountsDb.findAccountVisibility(accId, uid1), Integer.valueOf(1));
mAccountsDb.setAccountVisibility(accId, packageName1, 1);
assertEquals(mAccountsDb.findAccountVisibility(account, packageName1), Integer.valueOf(1));
assertEquals(mAccountsDb.findAccountVisibility(accId, packageName1), Integer.valueOf(1));
mAccountsDb.setAccountVisibility(accId, uid2, 2);
assertEquals(mAccountsDb.findAccountVisibility(accId, uid2), Integer.valueOf(2));
mAccountsDb.setAccountVisibility(accId, packageName2, 2);
assertEquals(mAccountsDb.findAccountVisibility(accId, packageName2), Integer.valueOf(2));
mAccountsDb.setAccountVisibility(accId, uid2, 3);
assertEquals(mAccountsDb.findAccountVisibility(accId, uid2), Integer.valueOf(3));
mAccountsDb.setAccountVisibility(accId, packageName2, 3);
assertEquals(mAccountsDb.findAccountVisibility(accId, packageName2), Integer.valueOf(3));
Map<Integer, Integer> vis = mAccountsDb.findAllVisibilityValuesForAccount(account);
Map<String, Integer> vis = mAccountsDb.findAllVisibilityValuesForAccount(account);
assertEquals(vis.size(), 2);
assertEquals(vis.get(uid1), Integer.valueOf(1));
assertEquals(vis.get(uid2), Integer.valueOf(3));
assertEquals(vis.get(packageName1), Integer.valueOf(1));
assertEquals(vis.get(packageName2), Integer.valueOf(3));
assertTrue(mAccountsDb.deleteAccountVisibilityForUid(uid1));
assertNull(mAccountsDb.findAccountVisibility(accId, uid1));
assertFalse(mAccountsDb.deleteAccountVisibilityForUid(uid1)); // Already deleted.
assertTrue(mAccountsDb.deleteAccountVisibilityForPackage(packageName1));
assertNull(mAccountsDb.findAccountVisibility(accId, packageName1));
assertFalse(mAccountsDb.deleteAccountVisibilityForPackage(packageName1)); // 2nd attempt.
}
@Test
public void testVisibilityCleanupTrigger() {
long accId = 10;
int uid1 = 100500;
String packageName1 = "com.example.one";
Account account = new Account("name", "example.com");
assertNull(mAccountsDb.findAccountVisibility(account, uid1));
assertNull(mAccountsDb.findAccountVisibility(account, packageName1));
mAccountsDb.insertDeAccount(account, accId);
assertNull(mAccountsDb.findAccountVisibility(account, uid1));
assertNull(mAccountsDb.findAccountVisibility(account, packageName1));
mAccountsDb.setAccountVisibility(accId, uid1, 1);
assertEquals(mAccountsDb.findAccountVisibility(accId, uid1), Integer.valueOf(1));
mAccountsDb.setAccountVisibility(accId, packageName1, 1);
assertEquals(mAccountsDb.findAccountVisibility(accId, packageName1), Integer.valueOf(1));
assertTrue(mAccountsDb.deleteDeAccount(accId)); // Trigger should remove visibility.
assertNull(mAccountsDb.findAccountVisibility(account, uid1));
assertNull(mAccountsDb.findAccountVisibility(account, packageName1));
}
}