am ffb46022: Permissions: Fix account related permissions.
* commit 'ffb46022b30dffdf1cc4cbd08d4bcbe51e1f8814': Permissions: Fix account related permissions.
This commit is contained in:
@@ -17,7 +17,6 @@ package android {
|
|||||||
field public static final java.lang.String ACCESS_WIFI_STATE = "android.permission.ACCESS_WIFI_STATE";
|
field public static final java.lang.String ACCESS_WIFI_STATE = "android.permission.ACCESS_WIFI_STATE";
|
||||||
field public static final java.lang.String ACCOUNT_MANAGER = "android.permission.ACCOUNT_MANAGER";
|
field public static final java.lang.String ACCOUNT_MANAGER = "android.permission.ACCOUNT_MANAGER";
|
||||||
field public static final java.lang.String ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL";
|
field public static final java.lang.String ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL";
|
||||||
field public static final java.lang.String AUTHENTICATE_ACCOUNTS = "android.permission.AUTHENTICATE_ACCOUNTS";
|
|
||||||
field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
|
field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
|
||||||
field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE";
|
field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE";
|
||||||
field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
|
field public static final java.lang.String BIND_APPWIDGET = "android.permission.BIND_APPWIDGET";
|
||||||
@@ -86,7 +85,6 @@ package android {
|
|||||||
field public static final java.lang.String INTERNET = "android.permission.INTERNET";
|
field public static final java.lang.String INTERNET = "android.permission.INTERNET";
|
||||||
field public static final java.lang.String KILL_BACKGROUND_PROCESSES = "android.permission.KILL_BACKGROUND_PROCESSES";
|
field public static final java.lang.String KILL_BACKGROUND_PROCESSES = "android.permission.KILL_BACKGROUND_PROCESSES";
|
||||||
field public static final java.lang.String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE";
|
field public static final java.lang.String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE";
|
||||||
field public static final java.lang.String MANAGE_ACCOUNTS = "android.permission.MANAGE_ACCOUNTS";
|
|
||||||
field public static final java.lang.String MANAGE_APP_TOKENS = "android.permission.MANAGE_APP_TOKENS";
|
field public static final java.lang.String MANAGE_APP_TOKENS = "android.permission.MANAGE_APP_TOKENS";
|
||||||
field public static final java.lang.String MANAGE_DOCUMENTS = "android.permission.MANAGE_DOCUMENTS";
|
field public static final java.lang.String MANAGE_DOCUMENTS = "android.permission.MANAGE_DOCUMENTS";
|
||||||
field public static final java.lang.String MASTER_CLEAR = "android.permission.MASTER_CLEAR";
|
field public static final java.lang.String MASTER_CLEAR = "android.permission.MASTER_CLEAR";
|
||||||
@@ -145,7 +143,6 @@ package android {
|
|||||||
field public static final java.lang.String TRANSMIT_IR = "android.permission.TRANSMIT_IR";
|
field public static final java.lang.String TRANSMIT_IR = "android.permission.TRANSMIT_IR";
|
||||||
field public static final java.lang.String UNINSTALL_SHORTCUT = "com.android.launcher.permission.UNINSTALL_SHORTCUT";
|
field public static final java.lang.String UNINSTALL_SHORTCUT = "com.android.launcher.permission.UNINSTALL_SHORTCUT";
|
||||||
field public static final java.lang.String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS";
|
field public static final java.lang.String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS";
|
||||||
field public static final java.lang.String USE_CREDENTIALS = "android.permission.USE_CREDENTIALS";
|
|
||||||
field public static final java.lang.String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT";
|
field public static final java.lang.String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT";
|
||||||
field public static final java.lang.String USE_SIP = "android.permission.USE_SIP";
|
field public static final java.lang.String USE_SIP = "android.permission.USE_SIP";
|
||||||
field public static final java.lang.String VIBRATE = "android.permission.VIBRATE";
|
field public static final java.lang.String VIBRATE = "android.permission.VIBRATE";
|
||||||
|
|||||||
@@ -24,7 +24,6 @@ package android {
|
|||||||
field public static final java.lang.String ACCOUNT_MANAGER = "android.permission.ACCOUNT_MANAGER";
|
field public static final java.lang.String ACCOUNT_MANAGER = "android.permission.ACCOUNT_MANAGER";
|
||||||
field public static final java.lang.String ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL";
|
field public static final java.lang.String ADD_VOICEMAIL = "com.android.voicemail.permission.ADD_VOICEMAIL";
|
||||||
field public static final java.lang.String ALLOW_ANY_CODEC_FOR_PLAYBACK = "android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK";
|
field public static final java.lang.String ALLOW_ANY_CODEC_FOR_PLAYBACK = "android.permission.ALLOW_ANY_CODEC_FOR_PLAYBACK";
|
||||||
field public static final java.lang.String AUTHENTICATE_ACCOUNTS = "android.permission.AUTHENTICATE_ACCOUNTS";
|
|
||||||
field public static final java.lang.String BACKUP = "android.permission.BACKUP";
|
field public static final java.lang.String BACKUP = "android.permission.BACKUP";
|
||||||
field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
|
field public static final java.lang.String BATTERY_STATS = "android.permission.BATTERY_STATS";
|
||||||
field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE";
|
field public static final java.lang.String BIND_ACCESSIBILITY_SERVICE = "android.permission.BIND_ACCESSIBILITY_SERVICE";
|
||||||
@@ -117,7 +116,6 @@ package android {
|
|||||||
field public static final java.lang.String LOCAL_MAC_ADDRESS = "android.permission.LOCAL_MAC_ADDRESS";
|
field public static final java.lang.String LOCAL_MAC_ADDRESS = "android.permission.LOCAL_MAC_ADDRESS";
|
||||||
field public static final java.lang.String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE";
|
field public static final java.lang.String LOCATION_HARDWARE = "android.permission.LOCATION_HARDWARE";
|
||||||
field public static final java.lang.String LOOP_RADIO = "android.permission.LOOP_RADIO";
|
field public static final java.lang.String LOOP_RADIO = "android.permission.LOOP_RADIO";
|
||||||
field public static final java.lang.String MANAGE_ACCOUNTS = "android.permission.MANAGE_ACCOUNTS";
|
|
||||||
field public static final java.lang.String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS";
|
field public static final java.lang.String MANAGE_ACTIVITY_STACKS = "android.permission.MANAGE_ACTIVITY_STACKS";
|
||||||
field public static final java.lang.String MANAGE_APP_TOKENS = "android.permission.MANAGE_APP_TOKENS";
|
field public static final java.lang.String MANAGE_APP_TOKENS = "android.permission.MANAGE_APP_TOKENS";
|
||||||
field public static final java.lang.String MANAGE_CA_CERTIFICATES = "android.permission.MANAGE_CA_CERTIFICATES";
|
field public static final java.lang.String MANAGE_CA_CERTIFICATES = "android.permission.MANAGE_CA_CERTIFICATES";
|
||||||
@@ -217,7 +215,6 @@ package android {
|
|||||||
field public static final java.lang.String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS";
|
field public static final java.lang.String UPDATE_DEVICE_STATS = "android.permission.UPDATE_DEVICE_STATS";
|
||||||
field public static final java.lang.String UPDATE_LOCK = "android.permission.UPDATE_LOCK";
|
field public static final java.lang.String UPDATE_LOCK = "android.permission.UPDATE_LOCK";
|
||||||
field public static final java.lang.String USER_ACTIVITY = "android.permission.USER_ACTIVITY";
|
field public static final java.lang.String USER_ACTIVITY = "android.permission.USER_ACTIVITY";
|
||||||
field public static final java.lang.String USE_CREDENTIALS = "android.permission.USE_CREDENTIALS";
|
|
||||||
field public static final java.lang.String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT";
|
field public static final java.lang.String USE_FINGERPRINT = "android.permission.USE_FINGERPRINT";
|
||||||
field public static final java.lang.String USE_SIP = "android.permission.USE_SIP";
|
field public static final java.lang.String USE_SIP = "android.permission.USE_SIP";
|
||||||
field public static final java.lang.String VIBRATE = "android.permission.VIBRATE";
|
field public static final java.lang.String VIBRATE = "android.permission.VIBRATE";
|
||||||
|
|||||||
@@ -51,10 +51,7 @@ import java.util.concurrent.FutureTask;
|
|||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import static android.Manifest.permission.AUTHENTICATE_ACCOUNTS;
|
|
||||||
import static android.Manifest.permission.GET_ACCOUNTS;
|
import static android.Manifest.permission.GET_ACCOUNTS;
|
||||||
import static android.Manifest.permission.MANAGE_ACCOUNTS;
|
|
||||||
import static android.Manifest.permission.USE_CREDENTIALS;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This class provides access to a centralized registry of the user's
|
* This class provides access to a centralized registry of the user's
|
||||||
@@ -319,14 +316,12 @@ public class AccountManager {
|
|||||||
*
|
*
|
||||||
* <p>It is safe to call this method from the main thread.
|
* <p>It is safe to call this method from the main thread.
|
||||||
*
|
*
|
||||||
* <p>This method requires the caller to hold the permission
|
* <p>This method requires the caller to have a signature match with the
|
||||||
* {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS}
|
* authenticator that owns the specified account.
|
||||||
* and to have the same UID as the account's authenticator.
|
|
||||||
*
|
*
|
||||||
* @param account The account to query for a password
|
* @param account The account to query for a password. Must not be {@code null}.
|
||||||
* @return The account's password, null if none or if the account doesn't exist
|
* @return The account's password, null if none or if the account doesn't exist
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(AUTHENTICATE_ACCOUNTS)
|
|
||||||
public String getPassword(final Account account) {
|
public String getPassword(final Account account) {
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
try {
|
try {
|
||||||
@@ -345,14 +340,12 @@ public class AccountManager {
|
|||||||
*
|
*
|
||||||
* <p>It is safe to call this method from the main thread.
|
* <p>It is safe to call this method from the main thread.
|
||||||
*
|
*
|
||||||
* <p>This method requires the caller to hold the permission
|
* <p>This method requires the caller to have a signature match with the
|
||||||
* {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS}
|
* authenticator that owns the specified account.
|
||||||
* and to have the same UID as the account's authenticator.
|
|
||||||
*
|
*
|
||||||
* @param account The account to query for user data
|
* @param account The account to query for user data
|
||||||
* @return The user data, null if the account or key doesn't exist
|
* @return The user data, null if the account or key doesn't exist
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(AUTHENTICATE_ACCOUNTS)
|
|
||||||
public String getUserData(final Account account, final String key) {
|
public String getUserData(final Account account, final String key) {
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
if (key == null) throw new IllegalArgumentException("key is null");
|
if (key == null) throw new IllegalArgumentException("key is null");
|
||||||
@@ -662,10 +655,8 @@ public class AccountManager {
|
|||||||
* wizards associated with authenticators, not directly by applications.
|
* wizards associated with authenticators, not directly by applications.
|
||||||
*
|
*
|
||||||
* <p>It is safe to call this method from the main thread.
|
* <p>It is safe to call this method from the main thread.
|
||||||
*
|
* <p>This method requires the caller to have a signature match with the
|
||||||
* <p>This method requires the caller to hold the permission
|
* authenticator that owns the specified account.
|
||||||
* {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS}
|
|
||||||
* and to have the same UID as the added account's authenticator.
|
|
||||||
*
|
*
|
||||||
* @param account The {@link Account} to add
|
* @param account The {@link Account} to add
|
||||||
* @param password The password to associate with the account, null for none
|
* @param password The password to associate with the account, null for none
|
||||||
@@ -673,7 +664,6 @@ public class AccountManager {
|
|||||||
* @return True if the account was successfully added, false if the account
|
* @return True if the account was successfully added, false if the account
|
||||||
* already exists, the account is null, or another error occurs.
|
* already exists, the account is null, or another error occurs.
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(AUTHENTICATE_ACCOUNTS)
|
|
||||||
public boolean addAccountExplicitly(Account account, String password, Bundle userdata) {
|
public boolean addAccountExplicitly(Account account, String password, Bundle userdata) {
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
try {
|
try {
|
||||||
@@ -692,14 +682,13 @@ public class AccountManager {
|
|||||||
* <p>
|
* <p>
|
||||||
* It is not safe to call this method from the main thread. As such, call it
|
* It is not safe to call this method from the main thread. As such, call it
|
||||||
* from another thread.
|
* from another thread.
|
||||||
* <p>
|
* <p>This method requires the caller to have a signature match with the
|
||||||
* This method requires the caller to hold the permission
|
* authenticator that owns the specified account.
|
||||||
* {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and should be
|
|
||||||
* called from the account's authenticator.
|
|
||||||
*
|
*
|
||||||
* @param account The {@link Account} to be updated.
|
* @param account The {@link Account} to be updated.
|
||||||
|
* @return boolean {@code true} if the authentication of the account has been successfully
|
||||||
|
* acknowledged. Otherwise {@code false}.
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(AUTHENTICATE_ACCOUNTS)
|
|
||||||
public boolean notifyAccountAuthenticated(Account account) {
|
public boolean notifyAccountAuthenticated(Account account) {
|
||||||
if (account == null)
|
if (account == null)
|
||||||
throw new IllegalArgumentException("account is null");
|
throw new IllegalArgumentException("account is null");
|
||||||
@@ -717,9 +706,8 @@ public class AccountManager {
|
|||||||
*
|
*
|
||||||
* <p>It is safe to call this method from the main thread.
|
* <p>It is safe to call this method from the main thread.
|
||||||
*
|
*
|
||||||
* <p>This method requires the caller to hold the permission
|
* <p>This method requires the caller to have a signature match with the
|
||||||
* {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS}
|
* authenticator that manages the specified account.
|
||||||
* and have the same UID as the account's authenticator.
|
|
||||||
*
|
*
|
||||||
* @param account The {@link Account} to rename
|
* @param account The {@link Account} to rename
|
||||||
* @param newName String name to be associated with the account.
|
* @param newName String name to be associated with the account.
|
||||||
@@ -731,7 +719,6 @@ public class AccountManager {
|
|||||||
* after the name change. If successful the account's name will be the
|
* after the name change. If successful the account's name will be the
|
||||||
* specified new name.
|
* specified new name.
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(AUTHENTICATE_ACCOUNTS)
|
|
||||||
public AccountManagerFuture<Account> renameAccount(
|
public AccountManagerFuture<Account> renameAccount(
|
||||||
final Account account,
|
final Account account,
|
||||||
@Size(min = 1) final String newName,
|
@Size(min = 1) final String newName,
|
||||||
@@ -783,11 +770,8 @@ public class AccountManager {
|
|||||||
* The authenticator may have its own policies preventing account
|
* The authenticator may have its own policies preventing account
|
||||||
* deletion, in which case the account will not be deleted.
|
* deletion, in which case the account will not be deleted.
|
||||||
*
|
*
|
||||||
* <p>This method may be called from any thread, but the returned
|
* <p>This method requires the caller to have a signature match with the
|
||||||
* {@link AccountManagerFuture} must not be used on the main thread.
|
* authenticator that manages the specified account.
|
||||||
*
|
|
||||||
* <p>This method requires the caller to hold the permission
|
|
||||||
* {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
|
|
||||||
*
|
*
|
||||||
* @param account The {@link Account} to remove
|
* @param account The {@link Account} to remove
|
||||||
* @param callback Callback to invoke when the request completes,
|
* @param callback Callback to invoke when the request completes,
|
||||||
@@ -800,15 +784,16 @@ public class AccountManager {
|
|||||||
* {@link #removeAccount(Account, Activity, AccountManagerCallback, Handler)}
|
* {@link #removeAccount(Account, Activity, AccountManagerCallback, Handler)}
|
||||||
* instead
|
* instead
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(MANAGE_ACCOUNTS)
|
|
||||||
@Deprecated
|
@Deprecated
|
||||||
public AccountManagerFuture<Boolean> removeAccount(final Account account,
|
public AccountManagerFuture<Boolean> removeAccount(final Account account,
|
||||||
AccountManagerCallback<Boolean> callback, Handler handler) {
|
AccountManagerCallback<Boolean> callback, Handler handler) {
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
return new Future2Task<Boolean>(handler, callback) {
|
return new Future2Task<Boolean>(handler, callback) {
|
||||||
|
@Override
|
||||||
public void doWork() throws RemoteException {
|
public void doWork() throws RemoteException {
|
||||||
mService.removeAccount(mResponse, account, false);
|
mService.removeAccount(mResponse, account, false);
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
|
public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
|
||||||
if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
|
if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
|
||||||
throw new AuthenticatorException("no result in response");
|
throw new AuthenticatorException("no result in response");
|
||||||
@@ -827,8 +812,8 @@ public class AccountManager {
|
|||||||
* <p>This method may be called from any thread, but the returned
|
* <p>This method may be called from any thread, but the returned
|
||||||
* {@link AccountManagerFuture} must not be used on the main thread.
|
* {@link AccountManagerFuture} must not be used on the main thread.
|
||||||
*
|
*
|
||||||
* <p>This method requires the caller to hold the permission
|
* <p>This method requires the caller to have a signature match with the
|
||||||
* {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
|
* authenticator that manages the specified account.
|
||||||
*
|
*
|
||||||
* @param account The {@link Account} to remove
|
* @param account The {@link Account} to remove
|
||||||
* @param activity The {@link Activity} context to use for launching a new
|
* @param activity The {@link Activity} context to use for launching a new
|
||||||
@@ -855,11 +840,11 @@ public class AccountManager {
|
|||||||
* adding accounts (of this type) has been disabled by policy
|
* adding accounts (of this type) has been disabled by policy
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(MANAGE_ACCOUNTS)
|
|
||||||
public AccountManagerFuture<Bundle> removeAccount(final Account account,
|
public AccountManagerFuture<Bundle> removeAccount(final Account account,
|
||||||
final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
|
final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
return new AmsTask(activity, handler, callback) {
|
return new AmsTask(activity, handler, callback) {
|
||||||
|
@Override
|
||||||
public void doWork() throws RemoteException {
|
public void doWork() throws RemoteException {
|
||||||
mService.removeAccount(mResponse, account, activity != null);
|
mService.removeAccount(mResponse, account, activity != null);
|
||||||
}
|
}
|
||||||
@@ -880,9 +865,11 @@ public class AccountManager {
|
|||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
if (userHandle == null) throw new IllegalArgumentException("userHandle is null");
|
if (userHandle == null) throw new IllegalArgumentException("userHandle is null");
|
||||||
return new Future2Task<Boolean>(handler, callback) {
|
return new Future2Task<Boolean>(handler, callback) {
|
||||||
|
@Override
|
||||||
public void doWork() throws RemoteException {
|
public void doWork() throws RemoteException {
|
||||||
mService.removeAccountAsUser(mResponse, account, false, userHandle.getIdentifier());
|
mService.removeAccountAsUser(mResponse, account, false, userHandle.getIdentifier());
|
||||||
}
|
}
|
||||||
|
@Override
|
||||||
public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
|
public Boolean bundleToResult(Bundle bundle) throws AuthenticatorException {
|
||||||
if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
|
if (!bundle.containsKey(KEY_BOOLEAN_RESULT)) {
|
||||||
throw new AuthenticatorException("no result in response");
|
throw new AuthenticatorException("no result in response");
|
||||||
@@ -918,17 +905,14 @@ public class AccountManager {
|
|||||||
* in which case the account will not be deleted.
|
* in which case the account will not be deleted.
|
||||||
* <p>
|
* <p>
|
||||||
* It is safe to call this method from the main thread.
|
* It is safe to call this method from the main thread.
|
||||||
* <p>
|
* <p>This method requires the caller to have a signature match with the
|
||||||
* This method requires the caller to hold the permission
|
* authenticator that manages the specified account.
|
||||||
* {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS} and to have the
|
|
||||||
* same UID or signature as the account's authenticator.
|
|
||||||
*
|
*
|
||||||
* @param account The {@link Account} to delete.
|
* @param account The {@link Account} to delete.
|
||||||
* @return True if the account was successfully deleted, false if the
|
* @return True if the account was successfully deleted, false if the
|
||||||
* account did not exist, the account is null, or another error
|
* account did not exist, the account is null, or another error
|
||||||
* occurs.
|
* occurs.
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(AUTHENTICATE_ACCOUNTS)
|
|
||||||
public boolean removeAccountExplicitly(Account account) {
|
public boolean removeAccountExplicitly(Account account) {
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
try {
|
try {
|
||||||
@@ -948,14 +932,9 @@ public class AccountManager {
|
|||||||
*
|
*
|
||||||
* <p>It is safe to call this method from the main thread.
|
* <p>It is safe to call this method from the main thread.
|
||||||
*
|
*
|
||||||
* <p>This method requires the caller to hold the permission
|
|
||||||
* {@link android.Manifest.permission#MANAGE_ACCOUNTS} or
|
|
||||||
* {@link android.Manifest.permission#USE_CREDENTIALS}
|
|
||||||
*
|
|
||||||
* @param accountType The account type of the auth token to invalidate, must not be null
|
* @param accountType The account type of the auth token to invalidate, must not be null
|
||||||
* @param authToken The auth token to invalidate, may be null
|
* @param authToken The auth token to invalidate, may be null
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(anyOf = {MANAGE_ACCOUNTS, USE_CREDENTIALS})
|
|
||||||
public void invalidateAuthToken(final String accountType, final String authToken) {
|
public void invalidateAuthToken(final String accountType, final String authToken) {
|
||||||
if (accountType == null) throw new IllegalArgumentException("accountType is null");
|
if (accountType == null) throw new IllegalArgumentException("accountType is null");
|
||||||
try {
|
try {
|
||||||
@@ -976,16 +955,15 @@ public class AccountManager {
|
|||||||
*
|
*
|
||||||
* <p>It is safe to call this method from the main thread.
|
* <p>It is safe to call this method from the main thread.
|
||||||
*
|
*
|
||||||
* <p>This method requires the caller to hold the permission
|
* <p>This method requires the caller to have a signature match with the
|
||||||
* {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS}
|
* authenticator that manages the specified account.
|
||||||
* and to have the same UID as the account's authenticator.
|
|
||||||
*
|
*
|
||||||
* @param account The account to fetch an auth token for
|
* @param account The account for which an auth token is to be fetched. Cannot be {@code null}.
|
||||||
* @param authTokenType The type of auth token to fetch, see {#getAuthToken}
|
* @param authTokenType The type of auth token to fetch. Cannot be {@code null}.
|
||||||
* @return The cached auth token for this account and type, or null if
|
* @return The cached auth token for this account and type, or null if
|
||||||
* no auth token is cached or the account does not exist.
|
* no auth token is cached or the account does not exist.
|
||||||
|
* @see #getAuthToken
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(AUTHENTICATE_ACCOUNTS)
|
|
||||||
public String peekAuthToken(final Account account, final String authTokenType) {
|
public String peekAuthToken(final Account account, final String authTokenType) {
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
|
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
|
||||||
@@ -1005,14 +983,12 @@ public class AccountManager {
|
|||||||
*
|
*
|
||||||
* <p>It is safe to call this method from the main thread.
|
* <p>It is safe to call this method from the main thread.
|
||||||
*
|
*
|
||||||
* <p>This method requires the caller to hold the permission
|
* <p>This method requires the caller to have a signature match with the
|
||||||
* {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS}
|
* authenticator that manages the specified account.
|
||||||
* and have the same UID as the account's authenticator.
|
|
||||||
*
|
*
|
||||||
* @param account The account to set a password for
|
* @param account The account whose password is to be set. Cannot be {@code null}.
|
||||||
* @param password The password to set, null to clear the password
|
* @param password The password to set, null to clear the password
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(AUTHENTICATE_ACCOUNTS)
|
|
||||||
public void setPassword(final Account account, final String password) {
|
public void setPassword(final Account account, final String password) {
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
try {
|
try {
|
||||||
@@ -1030,14 +1006,14 @@ public class AccountManager {
|
|||||||
* permissions, and may be used by applications or management interfaces
|
* permissions, and may be used by applications or management interfaces
|
||||||
* to "sign out" from an account.
|
* to "sign out" from an account.
|
||||||
*
|
*
|
||||||
* <p>It is safe to call this method from the main thread.
|
* <p>This method only successfully clear the account's password when the
|
||||||
|
* caller has the same signature as the authenticator that owns the
|
||||||
|
* specified account. Otherwise, this method will silently fail.
|
||||||
*
|
*
|
||||||
* <p>This method requires the caller to hold the permission
|
* <p>It is safe to call this method from the main thread.
|
||||||
* {@link android.Manifest.permission#MANAGE_ACCOUNTS}
|
|
||||||
*
|
*
|
||||||
* @param account The account whose password to clear
|
* @param account The account whose password to clear
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(MANAGE_ACCOUNTS)
|
|
||||||
public void clearPassword(final Account account) {
|
public void clearPassword(final Account account) {
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
try {
|
try {
|
||||||
@@ -1055,15 +1031,13 @@ public class AccountManager {
|
|||||||
*
|
*
|
||||||
* <p>It is safe to call this method from the main thread.
|
* <p>It is safe to call this method from the main thread.
|
||||||
*
|
*
|
||||||
* <p>This method requires the caller to hold the permission
|
* <p>This method requires the caller to have a signature match with the
|
||||||
* {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS}
|
* authenticator that manages the specified account.
|
||||||
* and to have the same UID as the account's authenticator.
|
|
||||||
*
|
*
|
||||||
* @param account The account to set the userdata for
|
* @param account Account whose user data is to be set. Must not be {@code null}.
|
||||||
* @param key The userdata key to set. Must not be null
|
* @param key String user data key to set. Must not be null
|
||||||
* @param value The value to set, null to clear this userdata key
|
* @param value String value to set, {@code null} to clear this user data key
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(AUTHENTICATE_ACCOUNTS)
|
|
||||||
public void setUserData(final Account account, final String key, final String value) {
|
public void setUserData(final Account account, final String key, final String value) {
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
if (key == null) throw new IllegalArgumentException("key is null");
|
if (key == null) throw new IllegalArgumentException("key is null");
|
||||||
@@ -1083,15 +1057,13 @@ public class AccountManager {
|
|||||||
*
|
*
|
||||||
* <p>It is safe to call this method from the main thread.
|
* <p>It is safe to call this method from the main thread.
|
||||||
*
|
*
|
||||||
* <p>This method requires the caller to hold the permission
|
* <p>This method requires the caller to have a signature match with the
|
||||||
* {@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS}
|
* authenticator that manages the specified account.
|
||||||
* and to have the same UID as the account's authenticator.
|
|
||||||
*
|
*
|
||||||
* @param account The account to set an auth token for
|
* @param account The account to set an auth token for
|
||||||
* @param authTokenType The type of the auth token, see {#getAuthToken}
|
* @param authTokenType The type of the auth token, see {#getAuthToken}
|
||||||
* @param authToken The auth token to add to the cache
|
* @param authToken The auth token to add to the cache
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(AUTHENTICATE_ACCOUNTS)
|
|
||||||
public void setAuthToken(Account account, final String authTokenType, final String authToken) {
|
public void setAuthToken(Account account, final String authTokenType, final String authToken) {
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
|
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
|
||||||
@@ -1110,9 +1082,6 @@ public class AccountManager {
|
|||||||
* <p>This method may block while a network request completes, and must
|
* <p>This method may block while a network request completes, and must
|
||||||
* never be made from the main thread.
|
* never be made from the main thread.
|
||||||
*
|
*
|
||||||
* <p>This method requires the caller to hold the permission
|
|
||||||
* {@link android.Manifest.permission#USE_CREDENTIALS}.
|
|
||||||
*
|
|
||||||
* @param account The account to fetch an auth token for
|
* @param account The account to fetch an auth token for
|
||||||
* @param authTokenType The auth token type, see {@link #getAuthToken getAuthToken()}
|
* @param authTokenType The auth token type, see {@link #getAuthToken getAuthToken()}
|
||||||
* @param notifyAuthFailure If true, display a notification and return null
|
* @param notifyAuthFailure If true, display a notification and return null
|
||||||
@@ -1126,7 +1095,6 @@ public class AccountManager {
|
|||||||
* @throws java.io.IOException if the authenticator experienced an I/O problem
|
* @throws java.io.IOException if the authenticator experienced an I/O problem
|
||||||
* creating a new auth token, usually because of network trouble
|
* creating a new auth token, usually because of network trouble
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(USE_CREDENTIALS)
|
|
||||||
public String blockingGetAuthToken(Account account, String authTokenType,
|
public String blockingGetAuthToken(Account account, String authTokenType,
|
||||||
boolean notifyAuthFailure)
|
boolean notifyAuthFailure)
|
||||||
throws OperationCanceledException, IOException, AuthenticatorException {
|
throws OperationCanceledException, IOException, AuthenticatorException {
|
||||||
@@ -1165,9 +1133,6 @@ public class AccountManager {
|
|||||||
* <p>This method may be called from any thread, but the returned
|
* <p>This method may be called from any thread, but the returned
|
||||||
* {@link AccountManagerFuture} must not be used on the main thread.
|
* {@link AccountManagerFuture} must not be used on the main thread.
|
||||||
*
|
*
|
||||||
* <p>This method requires the caller to hold the permission
|
|
||||||
* {@link android.Manifest.permission#USE_CREDENTIALS}.
|
|
||||||
*
|
|
||||||
* @param account The account to fetch an auth token for
|
* @param account The account to fetch an auth token for
|
||||||
* @param authTokenType The auth token type, an authenticator-dependent
|
* @param authTokenType The auth token type, an authenticator-dependent
|
||||||
* string token, must not be null
|
* string token, must not be null
|
||||||
@@ -1201,7 +1166,6 @@ public class AccountManager {
|
|||||||
* authenticator-dependent. The caller should verify the validity of the
|
* authenticator-dependent. The caller should verify the validity of the
|
||||||
* account before requesting an auth token.
|
* account before requesting an auth token.
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(USE_CREDENTIALS)
|
|
||||||
public AccountManagerFuture<Bundle> getAuthToken(
|
public AccountManagerFuture<Bundle> getAuthToken(
|
||||||
final Account account, final String authTokenType, final Bundle options,
|
final Account account, final String authTokenType, final Bundle options,
|
||||||
final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
|
final Activity activity, AccountManagerCallback<Bundle> callback, Handler handler) {
|
||||||
@@ -1253,9 +1217,6 @@ public class AccountManager {
|
|||||||
* <p>This method may be called from any thread, but the returned
|
* <p>This method may be called from any thread, but the returned
|
||||||
* {@link AccountManagerFuture} must not be used on the main thread.
|
* {@link AccountManagerFuture} must not be used on the main thread.
|
||||||
*
|
*
|
||||||
* <p>This method requires the caller to hold the permission
|
|
||||||
* {@link android.Manifest.permission#USE_CREDENTIALS}.
|
|
||||||
*
|
|
||||||
* @param account The account to fetch an auth token for
|
* @param account The account to fetch an auth token for
|
||||||
* @param authTokenType The auth token type, an authenticator-dependent
|
* @param authTokenType The auth token type, an authenticator-dependent
|
||||||
* string token, must not be null
|
* string token, must not be null
|
||||||
@@ -1292,7 +1253,6 @@ public class AccountManager {
|
|||||||
* boolean, AccountManagerCallback, android.os.Handler)} instead
|
* boolean, AccountManagerCallback, android.os.Handler)} instead
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
@Deprecated
|
||||||
@RequiresPermission(USE_CREDENTIALS)
|
|
||||||
public AccountManagerFuture<Bundle> getAuthToken(
|
public AccountManagerFuture<Bundle> getAuthToken(
|
||||||
final Account account, final String authTokenType,
|
final Account account, final String authTokenType,
|
||||||
final boolean notifyAuthFailure,
|
final boolean notifyAuthFailure,
|
||||||
@@ -1333,9 +1293,6 @@ public class AccountManager {
|
|||||||
* <p>This method may be called from any thread, but the returned
|
* <p>This method may be called from any thread, but the returned
|
||||||
* {@link AccountManagerFuture} must not be used on the main thread.
|
* {@link AccountManagerFuture} must not be used on the main thread.
|
||||||
*
|
*
|
||||||
* <p>This method requires the caller to hold the permission
|
|
||||||
* {@link android.Manifest.permission#USE_CREDENTIALS}.
|
|
||||||
*
|
|
||||||
* @param account The account to fetch an auth token for
|
* @param account The account to fetch an auth token for
|
||||||
* @param authTokenType The auth token type, an authenticator-dependent
|
* @param authTokenType The auth token type, an authenticator-dependent
|
||||||
* string token, must not be null
|
* string token, must not be null
|
||||||
@@ -1371,7 +1328,6 @@ public class AccountManager {
|
|||||||
* authenticator-dependent. The caller should verify the validity of the
|
* authenticator-dependent. The caller should verify the validity of the
|
||||||
* account before requesting an auth token.
|
* account before requesting an auth token.
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(USE_CREDENTIALS)
|
|
||||||
public AccountManagerFuture<Bundle> getAuthToken(
|
public AccountManagerFuture<Bundle> getAuthToken(
|
||||||
final Account account, final String authTokenType, final Bundle options,
|
final Account account, final String authTokenType, final Bundle options,
|
||||||
final boolean notifyAuthFailure,
|
final boolean notifyAuthFailure,
|
||||||
@@ -1401,9 +1357,6 @@ public class AccountManager {
|
|||||||
* <p>This method may be called from any thread, but the returned
|
* <p>This method may be called from any thread, but the returned
|
||||||
* {@link AccountManagerFuture} must not be used on the main thread.
|
* {@link AccountManagerFuture} must not be used on the main thread.
|
||||||
*
|
*
|
||||||
* <p>This method requires the caller to hold the permission
|
|
||||||
* {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
|
|
||||||
*
|
|
||||||
* @param accountType The type of account to add; must not be null
|
* @param accountType The type of account to add; must not be null
|
||||||
* @param authTokenType The type of auth token (see {@link #getAuthToken})
|
* @param authTokenType The type of auth token (see {@link #getAuthToken})
|
||||||
* this account will need to be able to generate, null for none
|
* this account will need to be able to generate, null for none
|
||||||
@@ -1441,7 +1394,6 @@ public class AccountManager {
|
|||||||
* creating a new account, usually because of network trouble
|
* creating a new account, usually because of network trouble
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(MANAGE_ACCOUNTS)
|
|
||||||
public AccountManagerFuture<Bundle> addAccount(final String accountType,
|
public AccountManagerFuture<Bundle> addAccount(final String accountType,
|
||||||
final String authTokenType, final String[] requiredFeatures,
|
final String authTokenType, final String[] requiredFeatures,
|
||||||
final Bundle addAccountOptions,
|
final Bundle addAccountOptions,
|
||||||
@@ -1586,9 +1538,6 @@ public class AccountManager {
|
|||||||
* <p>This method may be called from any thread, but the returned
|
* <p>This method may be called from any thread, but the returned
|
||||||
* {@link AccountManagerFuture} must not be used on the main thread.
|
* {@link AccountManagerFuture} must not be used on the main thread.
|
||||||
*
|
*
|
||||||
* <p>This method requires the caller to hold the permission
|
|
||||||
* {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
|
|
||||||
*
|
|
||||||
* @param account The account to confirm password knowledge for
|
* @param account The account to confirm password knowledge for
|
||||||
* @param options Authenticator-specific options for the request;
|
* @param options Authenticator-specific options for the request;
|
||||||
* if the {@link #KEY_PASSWORD} string field is present, the
|
* if the {@link #KEY_PASSWORD} string field is present, the
|
||||||
@@ -1615,11 +1564,11 @@ public class AccountManager {
|
|||||||
* If no activity or password was specified, the returned Bundle contains
|
* If no activity or password was specified, the returned Bundle contains
|
||||||
* {@link #KEY_INTENT} with the {@link Intent} needed to launch the
|
* {@link #KEY_INTENT} with the {@link Intent} needed to launch the
|
||||||
* password prompt.
|
* password prompt.
|
||||||
*
|
*
|
||||||
* <p>Also the returning Bundle may contain {@link
|
* <p>Also the returning Bundle may contain {@link
|
||||||
* #KEY_LAST_AUTHENTICATED_TIME} indicating the last time the
|
* #KEY_LAST_AUTHENTICATED_TIME} indicating the last time the
|
||||||
* credential was validated/created.
|
* credential was validated/created.
|
||||||
*
|
*
|
||||||
* If an error occurred,{@link AccountManagerFuture#getResult()} throws:
|
* If an error occurred,{@link AccountManagerFuture#getResult()} throws:
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li> {@link AuthenticatorException} if the authenticator failed to respond
|
* <li> {@link AuthenticatorException} if the authenticator failed to respond
|
||||||
@@ -1629,7 +1578,6 @@ public class AccountManager {
|
|||||||
* verifying the password, usually because of network trouble
|
* verifying the password, usually because of network trouble
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(MANAGE_ACCOUNTS)
|
|
||||||
public AccountManagerFuture<Bundle> confirmCredentials(final Account account,
|
public AccountManagerFuture<Bundle> confirmCredentials(final Account account,
|
||||||
final Bundle options,
|
final Bundle options,
|
||||||
final Activity activity,
|
final Activity activity,
|
||||||
@@ -1668,9 +1616,6 @@ public class AccountManager {
|
|||||||
* <p>This method may be called from any thread, but the returned
|
* <p>This method may be called from any thread, but the returned
|
||||||
* {@link AccountManagerFuture} must not be used on the main thread.
|
* {@link AccountManagerFuture} must not be used on the main thread.
|
||||||
*
|
*
|
||||||
* <p>This method requires the caller to hold the permission
|
|
||||||
* {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
|
|
||||||
*
|
|
||||||
* @param account The account to update credentials for
|
* @param account The account to update credentials for
|
||||||
* @param authTokenType The credentials entered must allow an auth token
|
* @param authTokenType The credentials entered must allow an auth token
|
||||||
* of this type to be created (but no actual auth token is returned);
|
* of this type to be created (but no actual auth token is returned);
|
||||||
@@ -1706,7 +1651,6 @@ public class AccountManager {
|
|||||||
* verifying the password, usually because of network trouble
|
* verifying the password, usually because of network trouble
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(MANAGE_ACCOUNTS)
|
|
||||||
public AccountManagerFuture<Bundle> updateCredentials(final Account account,
|
public AccountManagerFuture<Bundle> updateCredentials(final Account account,
|
||||||
final String authTokenType,
|
final String authTokenType,
|
||||||
final Bundle options, final Activity activity,
|
final Bundle options, final Activity activity,
|
||||||
@@ -1729,8 +1673,8 @@ public class AccountManager {
|
|||||||
* <p>This method may be called from any thread, but the returned
|
* <p>This method may be called from any thread, but the returned
|
||||||
* {@link AccountManagerFuture} must not be used on the main thread.
|
* {@link AccountManagerFuture} must not be used on the main thread.
|
||||||
*
|
*
|
||||||
* <p>This method requires the caller to hold the permission
|
* <p>This method requires the caller to have the same signature as the
|
||||||
* {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
|
* authenticator associated with the specified account type.
|
||||||
*
|
*
|
||||||
* @param accountType The account type associated with the authenticator
|
* @param accountType The account type associated with the authenticator
|
||||||
* to adjust
|
* to adjust
|
||||||
@@ -1758,7 +1702,6 @@ public class AccountManager {
|
|||||||
* updating settings, usually because of network trouble
|
* updating settings, usually because of network trouble
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(MANAGE_ACCOUNTS)
|
|
||||||
public AccountManagerFuture<Bundle> editProperties(final String accountType,
|
public AccountManagerFuture<Bundle> editProperties(final String accountType,
|
||||||
final Activity activity, final AccountManagerCallback<Bundle> callback,
|
final Activity activity, final AccountManagerCallback<Bundle> callback,
|
||||||
final Handler handler) {
|
final Handler handler) {
|
||||||
@@ -2253,9 +2196,6 @@ public class AccountManager {
|
|||||||
* <p>This method may be called from any thread, but the returned
|
* <p>This method may be called from any thread, but the returned
|
||||||
* {@link AccountManagerFuture} must not be used on the main thread.
|
* {@link AccountManagerFuture} must not be used on the main thread.
|
||||||
*
|
*
|
||||||
* <p>This method requires the caller to hold the permission
|
|
||||||
* {@link android.Manifest.permission#MANAGE_ACCOUNTS}.
|
|
||||||
*
|
|
||||||
* @param accountType The account type required
|
* @param accountType The account type required
|
||||||
* (see {@link #getAccountsByType}), must not be null
|
* (see {@link #getAccountsByType}), must not be null
|
||||||
* @param authTokenType The desired auth token type
|
* @param authTokenType The desired auth token type
|
||||||
@@ -2292,7 +2232,6 @@ public class AccountManager {
|
|||||||
* updating settings, usually because of network trouble
|
* updating settings, usually because of network trouble
|
||||||
* </ul>
|
* </ul>
|
||||||
*/
|
*/
|
||||||
@RequiresPermission(MANAGE_ACCOUNTS)
|
|
||||||
public AccountManagerFuture<Bundle> getAuthTokenByFeatures(
|
public AccountManagerFuture<Bundle> getAuthTokenByFeatures(
|
||||||
final String accountType, final String authTokenType, final String[] features,
|
final String accountType, final String authTokenType, final String[] features,
|
||||||
final Activity activity, final Bundle addAccountOptions,
|
final Activity activity, final Bundle addAccountOptions,
|
||||||
|
|||||||
@@ -980,33 +980,11 @@
|
|||||||
|
|
||||||
<!-- Allows access to the list of accounts in the Accounts Service -->
|
<!-- Allows access to the list of accounts in the Accounts Service -->
|
||||||
<permission android:name="android.permission.GET_ACCOUNTS"
|
<permission android:name="android.permission.GET_ACCOUNTS"
|
||||||
android:permissionGroup="android.permission-group.ACCOUNTS"
|
android:permissionGroup="android.permission-group.CONTACTS"
|
||||||
android:protectionLevel="normal"
|
android:protectionLevel="normal"
|
||||||
android:description="@string/permdesc_getAccounts"
|
android:description="@string/permdesc_getAccounts"
|
||||||
android:label="@string/permlab_getAccounts" />
|
android:label="@string/permlab_getAccounts" />
|
||||||
|
|
||||||
<!-- Allows an application to act as an AccountAuthenticator for
|
|
||||||
the AccountManager -->
|
|
||||||
<permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"
|
|
||||||
android:permissionGroup="android.permission-group.ACCOUNTS"
|
|
||||||
android:protectionLevel="dangerous"
|
|
||||||
android:label="@string/permlab_authenticateAccounts"
|
|
||||||
android:description="@string/permdesc_authenticateAccounts" />
|
|
||||||
|
|
||||||
<!-- Allows an application to request authtokens from the AccountManager -->
|
|
||||||
<permission android:name="android.permission.USE_CREDENTIALS"
|
|
||||||
android:permissionGroup="android.permission-group.ACCOUNTS"
|
|
||||||
android:protectionLevel="dangerous"
|
|
||||||
android:label="@string/permlab_useCredentials"
|
|
||||||
android:description="@string/permdesc_useCredentials" />
|
|
||||||
|
|
||||||
<!-- Allows an application to manage the list of accounts in the AccountManager -->
|
|
||||||
<permission android:name="android.permission.MANAGE_ACCOUNTS"
|
|
||||||
android:permissionGroup="android.permission-group.ACCOUNTS"
|
|
||||||
android:protectionLevel="dangerous"
|
|
||||||
android:label="@string/permlab_manageAccounts"
|
|
||||||
android:description="@string/permdesc_manageAccounts" />
|
|
||||||
|
|
||||||
<!-- @SystemApi Allows applications to call into AccountAuthenticators.
|
<!-- @SystemApi Allows applications to call into AccountAuthenticators.
|
||||||
<p>Not for use by third-party applications. -->
|
<p>Not for use by third-party applications. -->
|
||||||
<permission android:name="android.permission.ACCOUNT_MANAGER"
|
<permission android:name="android.permission.ACCOUNT_MANAGER"
|
||||||
|
|||||||
@@ -1113,27 +1113,6 @@
|
|||||||
the list of accounts known by the phone. This may include any accounts
|
the list of accounts known by the phone. This may include any accounts
|
||||||
created by applications you have installed.</string>
|
created by applications you have installed.</string>
|
||||||
|
|
||||||
|
|
||||||
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
|
||||||
<string name="permlab_authenticateAccounts">create accounts and set passwords</string>
|
|
||||||
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
|
||||||
<string name="permdesc_authenticateAccounts">Allows the app
|
|
||||||
to use the account authenticator capabilities of the
|
|
||||||
AccountManager, including creating accounts and getting and
|
|
||||||
setting their passwords.</string>
|
|
||||||
|
|
||||||
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
|
||||||
<string name="permlab_manageAccounts">add or remove accounts</string>
|
|
||||||
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
|
||||||
<string name="permdesc_manageAccounts">Allows the app to
|
|
||||||
perform operations like adding and removing accounts, and deleting
|
|
||||||
their password.</string>
|
|
||||||
|
|
||||||
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
|
||||||
<string name="permlab_useCredentials">use accounts on the device</string>
|
|
||||||
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
|
||||||
<string name="permdesc_useCredentials">Allows the app to request authentication tokens.</string>
|
|
||||||
|
|
||||||
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
<!-- Title of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||||
<string name="permlab_accessNetworkState">view network connections</string>
|
<string name="permlab_accessNetworkState">view network connections</string>
|
||||||
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
<!-- Description of an application permission, listed so the user can choose whether they want to allow the application to do this. -->
|
||||||
|
|||||||
@@ -583,13 +583,6 @@ public class MainActivity extends FragmentActivity {
|
|||||||
running the sync adapter, see <a href="running-sync-adapter.html"
|
running the sync adapter, see <a href="running-sync-adapter.html"
|
||||||
>Running A Sync Adapter</a>.
|
>Running A Sync Adapter</a>.
|
||||||
</dd>
|
</dd>
|
||||||
<dt>
|
|
||||||
{@link android.Manifest.permission#AUTHENTICATE_ACCOUNTS android.permission.AUTHENTICATE_ACCOUNTS}
|
|
||||||
</dt>
|
|
||||||
<dd>
|
|
||||||
Allows you to use the authenticator component you created in the lesson
|
|
||||||
<a href="creating-authenticator.html">Creating a Stub Authenticator</a>.
|
|
||||||
</dd>
|
|
||||||
</dl>
|
</dl>
|
||||||
<p>
|
<p>
|
||||||
The following snippet shows how to add the permissions:
|
The following snippet shows how to add the permissions:
|
||||||
|
|||||||
@@ -87,11 +87,8 @@ import java.io.File;
|
|||||||
import java.io.FileDescriptor;
|
import java.io.FileDescriptor;
|
||||||
import java.io.PrintWriter;
|
import java.io.PrintWriter;
|
||||||
import java.lang.ref.WeakReference;
|
import java.lang.ref.WeakReference;
|
||||||
import java.nio.ByteBuffer;
|
|
||||||
import java.nio.charset.Charset;
|
|
||||||
import java.security.MessageDigest;
|
import java.security.MessageDigest;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.sql.Timestamp;
|
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
@@ -100,7 +97,6 @@ import java.util.Date;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.LinkedHashMap;
|
import java.util.LinkedHashMap;
|
||||||
import java.util.LinkedList;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
@@ -526,14 +522,20 @@ public class AccountManagerService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getPassword(Account account) {
|
public String getPassword(Account account) {
|
||||||
|
int callingUid = Binder.getCallingUid();
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||||
Log.v(TAG, "getPassword: " + account
|
Log.v(TAG, "getPassword: " + account
|
||||||
+ ", caller's uid " + Binder.getCallingUid()
|
+ ", caller's uid " + Binder.getCallingUid()
|
||||||
+ ", pid " + Binder.getCallingPid());
|
+ ", pid " + Binder.getCallingPid());
|
||||||
}
|
}
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
checkAuthenticateAccountsPermission(account);
|
if (!isAccountOwnedByCallingUid(account.type, callingUid)) {
|
||||||
|
String msg = String.format(
|
||||||
|
"uid %s cannot get secrets for accounts of type: %s",
|
||||||
|
callingUid,
|
||||||
|
account.type);
|
||||||
|
throw new SecurityException(msg);
|
||||||
|
}
|
||||||
UserAccounts accounts = getUserAccountsForCaller();
|
UserAccounts accounts = getUserAccountsForCaller();
|
||||||
long identityToken = clearCallingIdentity();
|
long identityToken = clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
@@ -617,15 +619,21 @@ public class AccountManagerService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String getUserData(Account account, String key) {
|
public String getUserData(Account account, String key) {
|
||||||
|
final int callingUid = Binder.getCallingUid();
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||||
Log.v(TAG, "getUserData: " + account
|
String msg = String.format("getUserData( account: %s, key: %s, callerUid: %s, pid: %s",
|
||||||
+ ", key " + key
|
account, key, callingUid, Binder.getCallingPid());
|
||||||
+ ", caller's uid " + Binder.getCallingUid()
|
Log.v(TAG, msg);
|
||||||
+ ", pid " + Binder.getCallingPid());
|
|
||||||
}
|
}
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
if (key == null) throw new IllegalArgumentException("key is null");
|
if (key == null) throw new IllegalArgumentException("key is null");
|
||||||
checkAuthenticateAccountsPermission(account);
|
if (!isAccountOwnedByCallingUid(account.type, callingUid)) {
|
||||||
|
String msg = String.format(
|
||||||
|
"uid %s cannot get user data for accounts of type: %s",
|
||||||
|
callingUid,
|
||||||
|
account.type);
|
||||||
|
throw new SecurityException(msg);
|
||||||
|
}
|
||||||
UserAccounts accounts = getUserAccountsForCaller();
|
UserAccounts accounts = getUserAccountsForCaller();
|
||||||
long identityToken = clearCallingIdentity();
|
long identityToken = clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
@@ -676,13 +684,20 @@ public class AccountManagerService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean addAccountExplicitly(Account account, String password, Bundle extras) {
|
public boolean addAccountExplicitly(Account account, String password, Bundle extras) {
|
||||||
|
final int callingUid = Binder.getCallingUid();
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||||
Log.v(TAG, "addAccountExplicitly: " + account
|
Log.v(TAG, "addAccountExplicitly: " + account
|
||||||
+ ", caller's uid " + Binder.getCallingUid()
|
+ ", caller's uid " + callingUid
|
||||||
+ ", pid " + Binder.getCallingPid());
|
+ ", pid " + Binder.getCallingPid());
|
||||||
}
|
}
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
checkAuthenticateAccountsPermission(account);
|
if (!isAccountOwnedByCallingUid(account.type, callingUid)) {
|
||||||
|
String msg = String.format(
|
||||||
|
"uid %s cannot explicitly add accounts of type: %s",
|
||||||
|
callingUid,
|
||||||
|
account.type);
|
||||||
|
throw new SecurityException(msg);
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Child users are not allowed to add accounts. Only the accounts that are
|
* Child users are not allowed to add accounts. Only the accounts that are
|
||||||
* shared by the parent profile can be added to child profile.
|
* shared by the parent profile can be added to child profile.
|
||||||
@@ -758,10 +773,24 @@ public class AccountManagerService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean accountAuthenticated(final Account account) {
|
public boolean accountAuthenticated(final Account account) {
|
||||||
|
final int callingUid = Binder.getCallingUid();
|
||||||
|
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||||
|
String msg = String.format(
|
||||||
|
"accountAuthenticated( account: %s, callerUid: %s)",
|
||||||
|
account,
|
||||||
|
callingUid);
|
||||||
|
Log.v(TAG, msg);
|
||||||
|
}
|
||||||
if (account == null) {
|
if (account == null) {
|
||||||
throw new IllegalArgumentException("account is null");
|
throw new IllegalArgumentException("account is null");
|
||||||
}
|
}
|
||||||
checkAuthenticateAccountsPermission(account);
|
if (!isAccountOwnedByCallingUid(account.type, callingUid)) {
|
||||||
|
String msg = String.format(
|
||||||
|
"uid %s cannot notify authentication for accounts of type: %s",
|
||||||
|
callingUid,
|
||||||
|
account.type);
|
||||||
|
throw new SecurityException(msg);
|
||||||
|
}
|
||||||
int userId = Binder.getCallingUserHandle().getIdentifier();
|
int userId = Binder.getCallingUserHandle().getIdentifier();
|
||||||
if (!canUserModifyAccounts(userId) || !canUserModifyAccountsForType(userId, account.type)) {
|
if (!canUserModifyAccounts(userId) || !canUserModifyAccountsForType(userId, account.type)) {
|
||||||
return false;
|
return false;
|
||||||
@@ -1007,16 +1036,21 @@ public class AccountManagerService
|
|||||||
@Override
|
@Override
|
||||||
public void renameAccount(
|
public void renameAccount(
|
||||||
IAccountManagerResponse response, Account accountToRename, String newName) {
|
IAccountManagerResponse response, Account accountToRename, String newName) {
|
||||||
|
final int callingUid = Binder.getCallingUid();
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||||
Log.v(TAG, "renameAccount: " + accountToRename + " -> " + newName
|
Log.v(TAG, "renameAccount: " + accountToRename + " -> " + newName
|
||||||
+ ", caller's uid " + Binder.getCallingUid()
|
+ ", caller's uid " + callingUid
|
||||||
+ ", pid " + Binder.getCallingPid());
|
+ ", pid " + Binder.getCallingPid());
|
||||||
}
|
}
|
||||||
if (accountToRename == null) throw new IllegalArgumentException("account is null");
|
if (accountToRename == null) throw new IllegalArgumentException("account is null");
|
||||||
checkAuthenticateAccountsPermission(accountToRename);
|
if (!isAccountOwnedByCallingUid(accountToRename.type, callingUid)) {
|
||||||
|
String msg = String.format(
|
||||||
|
"uid %s cannot rename accounts of type: %s",
|
||||||
|
callingUid,
|
||||||
|
accountToRename.type);
|
||||||
|
throw new SecurityException(msg);
|
||||||
|
}
|
||||||
UserAccounts accounts = getUserAccountsForCaller();
|
UserAccounts accounts = getUserAccountsForCaller();
|
||||||
|
|
||||||
int callingUid = getCallingUid();
|
|
||||||
long identityToken = clearCallingIdentity();
|
long identityToken = clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
Account resultingAccount = renameAccountInternal(accounts, accountToRename, newName,
|
Account resultingAccount = renameAccountInternal(accounts, accountToRename, newName,
|
||||||
@@ -1125,65 +1159,21 @@ public class AccountManagerService
|
|||||||
@Override
|
@Override
|
||||||
public void removeAccount(IAccountManagerResponse response, Account account,
|
public void removeAccount(IAccountManagerResponse response, Account account,
|
||||||
boolean expectActivityLaunch) {
|
boolean expectActivityLaunch) {
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
removeAccountAsUser(
|
||||||
Log.v(TAG, "removeAccount: " + account
|
response,
|
||||||
+ ", response " + response
|
account,
|
||||||
+ ", caller's uid " + Binder.getCallingUid()
|
expectActivityLaunch,
|
||||||
+ ", pid " + Binder.getCallingPid());
|
UserHandle.getCallingUserId());
|
||||||
}
|
|
||||||
if (response == null) throw new IllegalArgumentException("response is null");
|
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
|
||||||
checkManageAccountsPermission();
|
|
||||||
UserHandle user = Binder.getCallingUserHandle();
|
|
||||||
UserAccounts accounts = getUserAccountsForCaller();
|
|
||||||
int userId = Binder.getCallingUserHandle().getIdentifier();
|
|
||||||
if (!canUserModifyAccounts(userId)) {
|
|
||||||
try {
|
|
||||||
// TODO: This should be ERROR_CODE_USER_RESTRICTED instead. See http://b/16322768
|
|
||||||
response.onError(AccountManager.ERROR_CODE_UNSUPPORTED_OPERATION,
|
|
||||||
"User cannot modify accounts");
|
|
||||||
} catch (RemoteException re) {
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (!canUserModifyAccountsForType(userId, account.type)) {
|
|
||||||
try {
|
|
||||||
response.onError(AccountManager.ERROR_CODE_MANAGEMENT_DISABLED_FOR_ACCOUNT_TYPE,
|
|
||||||
"User cannot modify accounts of this type (policy).");
|
|
||||||
} catch (RemoteException re) {
|
|
||||||
}
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
long identityToken = clearCallingIdentity();
|
|
||||||
|
|
||||||
cancelNotification(getSigninRequiredNotificationId(accounts, account), user);
|
|
||||||
synchronized (accounts.credentialsPermissionNotificationIds) {
|
|
||||||
for (Pair<Pair<Account, String>, Integer> pair:
|
|
||||||
accounts.credentialsPermissionNotificationIds.keySet()) {
|
|
||||||
if (account.equals(pair.first.first)) {
|
|
||||||
int id = accounts.credentialsPermissionNotificationIds.get(pair);
|
|
||||||
cancelNotification(id, user);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
logRecord(accounts, DebugDbHelper.ACTION_CALLED_ACCOUNT_REMOVE, TABLE_ACCOUNTS);
|
|
||||||
|
|
||||||
try {
|
|
||||||
new RemoveAccountSession(accounts, response, account, expectActivityLaunch).bind();
|
|
||||||
} finally {
|
|
||||||
restoreCallingIdentity(identityToken);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void removeAccountAsUser(IAccountManagerResponse response, Account account,
|
public void removeAccountAsUser(IAccountManagerResponse response, Account account,
|
||||||
boolean expectActivityLaunch, int userId) {
|
boolean expectActivityLaunch, int userId) {
|
||||||
|
final int callingUid = Binder.getCallingUid();
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||||
Log.v(TAG, "removeAccount: " + account
|
Log.v(TAG, "removeAccount: " + account
|
||||||
+ ", response " + response
|
+ ", response " + response
|
||||||
+ ", caller's uid " + Binder.getCallingUid()
|
+ ", caller's uid " + callingUid
|
||||||
+ ", pid " + Binder.getCallingPid()
|
+ ", pid " + Binder.getCallingPid()
|
||||||
+ ", for user id " + userId);
|
+ ", for user id " + userId);
|
||||||
}
|
}
|
||||||
@@ -1193,7 +1183,18 @@ public class AccountManagerService
|
|||||||
// Only allow the system process to modify accounts of other users
|
// Only allow the system process to modify accounts of other users
|
||||||
enforceCrossUserPermission(userId, "User " + UserHandle.getCallingUserId()
|
enforceCrossUserPermission(userId, "User " + UserHandle.getCallingUserId()
|
||||||
+ " trying to remove account for " + userId);
|
+ " trying to remove account for " + userId);
|
||||||
checkManageAccountsPermission();
|
/*
|
||||||
|
* Only the system or authenticator should be allowed to remove accounts for that
|
||||||
|
* authenticator. This will let users remove accounts (via Settings in the system) but not
|
||||||
|
* arbitrary applications (like competing authenticators).
|
||||||
|
*/
|
||||||
|
if (!isAccountOwnedByCallingUid(account.type, callingUid) && !isSystemUid(callingUid)) {
|
||||||
|
String msg = String.format(
|
||||||
|
"uid %s cannot remove accounts of type: %s",
|
||||||
|
callingUid,
|
||||||
|
account.type);
|
||||||
|
throw new SecurityException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
UserAccounts accounts = getUserAccounts(userId);
|
UserAccounts accounts = getUserAccounts(userId);
|
||||||
if (!canUserModifyAccounts(userId)) {
|
if (!canUserModifyAccounts(userId)) {
|
||||||
@@ -1238,13 +1239,26 @@ public class AccountManagerService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean removeAccountExplicitly(Account account) {
|
public boolean removeAccountExplicitly(Account account) {
|
||||||
|
final int callingUid = Binder.getCallingUid();
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||||
Log.v(TAG, "removeAccountExplicitly: " + account
|
Log.v(TAG, "removeAccountExplicitly: " + account
|
||||||
+ ", caller's uid " + Binder.getCallingUid()
|
+ ", caller's uid " + callingUid
|
||||||
+ ", pid " + Binder.getCallingPid());
|
+ ", pid " + Binder.getCallingPid());
|
||||||
}
|
}
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) {
|
||||||
checkAuthenticateAccountsPermission(account);
|
/*
|
||||||
|
* Null accounts should result in returning false, as per
|
||||||
|
* AccountManage.addAccountExplicitly(...) java doc.
|
||||||
|
*/
|
||||||
|
Log.e(TAG, "account is null");
|
||||||
|
return false;
|
||||||
|
} else if (!isAccountOwnedByCallingUid(account.type, callingUid)) {
|
||||||
|
String msg = String.format(
|
||||||
|
"uid %s cannot explicitly add accounts of type: %s",
|
||||||
|
callingUid,
|
||||||
|
account.type);
|
||||||
|
throw new SecurityException(msg);
|
||||||
|
}
|
||||||
|
|
||||||
UserAccounts accounts = getUserAccountsForCaller();
|
UserAccounts accounts = getUserAccountsForCaller();
|
||||||
int userId = Binder.getCallingUserHandle().getIdentifier();
|
int userId = Binder.getCallingUserHandle().getIdentifier();
|
||||||
@@ -1357,7 +1371,6 @@ public class AccountManagerService
|
|||||||
}
|
}
|
||||||
if (accountType == null) throw new IllegalArgumentException("accountType is null");
|
if (accountType == null) throw new IllegalArgumentException("accountType is null");
|
||||||
if (authToken == null) throw new IllegalArgumentException("authToken is null");
|
if (authToken == null) throw new IllegalArgumentException("authToken is null");
|
||||||
checkManageAccountsOrUseCredentialsPermissions();
|
|
||||||
UserAccounts accounts = getUserAccountsForCaller();
|
UserAccounts accounts = getUserAccountsForCaller();
|
||||||
long identityToken = clearCallingIdentity();
|
long identityToken = clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
@@ -1490,15 +1503,22 @@ public class AccountManagerService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String peekAuthToken(Account account, String authTokenType) {
|
public String peekAuthToken(Account account, String authTokenType) {
|
||||||
|
final int callingUid = Binder.getCallingUid();
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||||
Log.v(TAG, "peekAuthToken: " + account
|
Log.v(TAG, "peekAuthToken: " + account
|
||||||
+ ", authTokenType " + authTokenType
|
+ ", authTokenType " + authTokenType
|
||||||
+ ", caller's uid " + Binder.getCallingUid()
|
+ ", caller's uid " + callingUid
|
||||||
+ ", pid " + Binder.getCallingPid());
|
+ ", pid " + Binder.getCallingPid());
|
||||||
}
|
}
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
|
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
|
||||||
checkAuthenticateAccountsPermission(account);
|
if (!isAccountOwnedByCallingUid(account.type, callingUid)) {
|
||||||
|
String msg = String.format(
|
||||||
|
"uid %s cannot peek the authtokens associated with accounts of type: %s",
|
||||||
|
callingUid,
|
||||||
|
account.type);
|
||||||
|
throw new SecurityException(msg);
|
||||||
|
}
|
||||||
UserAccounts accounts = getUserAccountsForCaller();
|
UserAccounts accounts = getUserAccountsForCaller();
|
||||||
long identityToken = clearCallingIdentity();
|
long identityToken = clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
@@ -1510,15 +1530,22 @@ public class AccountManagerService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setAuthToken(Account account, String authTokenType, String authToken) {
|
public void setAuthToken(Account account, String authTokenType, String authToken) {
|
||||||
|
final int callingUid = Binder.getCallingUid();
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||||
Log.v(TAG, "setAuthToken: " + account
|
Log.v(TAG, "setAuthToken: " + account
|
||||||
+ ", authTokenType " + authTokenType
|
+ ", authTokenType " + authTokenType
|
||||||
+ ", caller's uid " + Binder.getCallingUid()
|
+ ", caller's uid " + callingUid
|
||||||
+ ", pid " + Binder.getCallingPid());
|
+ ", pid " + Binder.getCallingPid());
|
||||||
}
|
}
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
|
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
|
||||||
checkAuthenticateAccountsPermission(account);
|
if (!isAccountOwnedByCallingUid(account.type, callingUid)) {
|
||||||
|
String msg = String.format(
|
||||||
|
"uid %s cannot set auth tokens associated with accounts of type: %s",
|
||||||
|
callingUid,
|
||||||
|
account.type);
|
||||||
|
throw new SecurityException(msg);
|
||||||
|
}
|
||||||
UserAccounts accounts = getUserAccountsForCaller();
|
UserAccounts accounts = getUserAccountsForCaller();
|
||||||
long identityToken = clearCallingIdentity();
|
long identityToken = clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
@@ -1530,15 +1557,21 @@ public class AccountManagerService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setPassword(Account account, String password) {
|
public void setPassword(Account account, String password) {
|
||||||
|
final int callingUid = Binder.getCallingUid();
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||||
Log.v(TAG, "setAuthToken: " + account
|
Log.v(TAG, "setAuthToken: " + account
|
||||||
+ ", caller's uid " + Binder.getCallingUid()
|
+ ", caller's uid " + callingUid
|
||||||
+ ", pid " + Binder.getCallingPid());
|
+ ", pid " + Binder.getCallingPid());
|
||||||
}
|
}
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
checkAuthenticateAccountsPermission(account);
|
if (!isAccountOwnedByCallingUid(account.type, callingUid)) {
|
||||||
|
String msg = String.format(
|
||||||
|
"uid %s cannot set secrets for accounts of type: %s",
|
||||||
|
callingUid,
|
||||||
|
account.type);
|
||||||
|
throw new SecurityException(msg);
|
||||||
|
}
|
||||||
UserAccounts accounts = getUserAccountsForCaller();
|
UserAccounts accounts = getUserAccountsForCaller();
|
||||||
int callingUid = getCallingUid();
|
|
||||||
long identityToken = clearCallingIdentity();
|
long identityToken = clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
setPasswordInternal(accounts, account, password, callingUid);
|
setPasswordInternal(accounts, account, password, callingUid);
|
||||||
@@ -1594,16 +1627,21 @@ public class AccountManagerService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void clearPassword(Account account) {
|
public void clearPassword(Account account) {
|
||||||
|
final int callingUid = Binder.getCallingUid();
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||||
Log.v(TAG, "clearPassword: " + account
|
Log.v(TAG, "clearPassword: " + account
|
||||||
+ ", caller's uid " + Binder.getCallingUid()
|
+ ", caller's uid " + callingUid
|
||||||
+ ", pid " + Binder.getCallingPid());
|
+ ", pid " + Binder.getCallingPid());
|
||||||
}
|
}
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
checkManageAccountsPermission();
|
if (!isAccountOwnedByCallingUid(account.type, callingUid)) {
|
||||||
|
String msg = String.format(
|
||||||
|
"uid %s cannot clear passwords for accounts of type: %s",
|
||||||
|
callingUid,
|
||||||
|
account.type);
|
||||||
|
throw new SecurityException(msg);
|
||||||
|
}
|
||||||
UserAccounts accounts = getUserAccountsForCaller();
|
UserAccounts accounts = getUserAccountsForCaller();
|
||||||
|
|
||||||
int callingUid = getCallingUid();
|
|
||||||
long identityToken = clearCallingIdentity();
|
long identityToken = clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
setPasswordInternal(accounts, account, null, callingUid);
|
setPasswordInternal(accounts, account, null, callingUid);
|
||||||
@@ -1614,15 +1652,22 @@ public class AccountManagerService
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void setUserData(Account account, String key, String value) {
|
public void setUserData(Account account, String key, String value) {
|
||||||
|
final int callingUid = Binder.getCallingUid();
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||||
Log.v(TAG, "setUserData: " + account
|
Log.v(TAG, "setUserData: " + account
|
||||||
+ ", key " + key
|
+ ", key " + key
|
||||||
+ ", caller's uid " + Binder.getCallingUid()
|
+ ", caller's uid " + callingUid
|
||||||
+ ", pid " + Binder.getCallingPid());
|
+ ", pid " + Binder.getCallingPid());
|
||||||
}
|
}
|
||||||
if (key == null) throw new IllegalArgumentException("key is null");
|
if (key == null) throw new IllegalArgumentException("key is null");
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
checkAuthenticateAccountsPermission(account);
|
if (!isAccountOwnedByCallingUid(account.type, callingUid)) {
|
||||||
|
String msg = String.format(
|
||||||
|
"uid %s cannot set user data for accounts of type: %s",
|
||||||
|
callingUid,
|
||||||
|
account.type);
|
||||||
|
throw new SecurityException(msg);
|
||||||
|
}
|
||||||
UserAccounts accounts = getUserAccountsForCaller();
|
UserAccounts accounts = getUserAccountsForCaller();
|
||||||
long identityToken = clearCallingIdentity();
|
long identityToken = clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
@@ -1769,7 +1814,6 @@ public class AccountManagerService
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkBinderPermission(Manifest.permission.USE_CREDENTIALS);
|
|
||||||
final UserAccounts accounts = getUserAccountsForCaller();
|
final UserAccounts accounts = getUserAccountsForCaller();
|
||||||
final RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo;
|
final RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> authenticatorInfo;
|
||||||
authenticatorInfo = mAuthenticatorCache.getServiceInfo(
|
authenticatorInfo = mAuthenticatorCache.getServiceInfo(
|
||||||
@@ -2047,7 +2091,6 @@ public class AccountManagerService
|
|||||||
}
|
}
|
||||||
if (response == null) throw new IllegalArgumentException("response is null");
|
if (response == null) throw new IllegalArgumentException("response is null");
|
||||||
if (accountType == null) throw new IllegalArgumentException("accountType is null");
|
if (accountType == null) throw new IllegalArgumentException("accountType is null");
|
||||||
checkManageAccountsPermission();
|
|
||||||
|
|
||||||
// Is user disallowed from modifying accounts?
|
// Is user disallowed from modifying accounts?
|
||||||
int userId = Binder.getCallingUserHandle().getIdentifier();
|
int userId = Binder.getCallingUserHandle().getIdentifier();
|
||||||
@@ -2122,7 +2165,6 @@ public class AccountManagerService
|
|||||||
}
|
}
|
||||||
if (response == null) throw new IllegalArgumentException("response is null");
|
if (response == null) throw new IllegalArgumentException("response is null");
|
||||||
if (accountType == null) throw new IllegalArgumentException("accountType is null");
|
if (accountType == null) throw new IllegalArgumentException("accountType is null");
|
||||||
checkManageAccountsPermission();
|
|
||||||
|
|
||||||
// Only allow the system process to add accounts of other users
|
// Only allow the system process to add accounts of other users
|
||||||
enforceCrossUserPermission(userId, "User " + UserHandle.getCallingUserId()
|
enforceCrossUserPermission(userId, "User " + UserHandle.getCallingUserId()
|
||||||
@@ -2213,7 +2255,6 @@ public class AccountManagerService
|
|||||||
}
|
}
|
||||||
if (response == null) throw new IllegalArgumentException("response is null");
|
if (response == null) throw new IllegalArgumentException("response is null");
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
checkManageAccountsPermission();
|
|
||||||
UserAccounts accounts = getUserAccounts(userId);
|
UserAccounts accounts = getUserAccounts(userId);
|
||||||
long identityToken = clearCallingIdentity();
|
long identityToken = clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
@@ -2250,7 +2291,6 @@ public class AccountManagerService
|
|||||||
if (response == null) throw new IllegalArgumentException("response is null");
|
if (response == null) throw new IllegalArgumentException("response is null");
|
||||||
if (account == null) throw new IllegalArgumentException("account is null");
|
if (account == null) throw new IllegalArgumentException("account is null");
|
||||||
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
|
if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
|
||||||
checkManageAccountsPermission();
|
|
||||||
UserAccounts accounts = getUserAccountsForCaller();
|
UserAccounts accounts = getUserAccountsForCaller();
|
||||||
long identityToken = clearCallingIdentity();
|
long identityToken = clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
@@ -2278,16 +2318,23 @@ public class AccountManagerService
|
|||||||
@Override
|
@Override
|
||||||
public void editProperties(IAccountManagerResponse response, final String accountType,
|
public void editProperties(IAccountManagerResponse response, final String accountType,
|
||||||
final boolean expectActivityLaunch) {
|
final boolean expectActivityLaunch) {
|
||||||
|
final int callingUid = Binder.getCallingUid();
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||||
Log.v(TAG, "editProperties: accountType " + accountType
|
Log.v(TAG, "editProperties: accountType " + accountType
|
||||||
+ ", response " + response
|
+ ", response " + response
|
||||||
+ ", expectActivityLaunch " + expectActivityLaunch
|
+ ", expectActivityLaunch " + expectActivityLaunch
|
||||||
+ ", caller's uid " + Binder.getCallingUid()
|
+ ", caller's uid " + callingUid
|
||||||
+ ", pid " + Binder.getCallingPid());
|
+ ", pid " + Binder.getCallingPid());
|
||||||
}
|
}
|
||||||
if (response == null) throw new IllegalArgumentException("response is null");
|
if (response == null) throw new IllegalArgumentException("response is null");
|
||||||
if (accountType == null) throw new IllegalArgumentException("accountType is null");
|
if (accountType == null) throw new IllegalArgumentException("accountType is null");
|
||||||
checkManageAccountsPermission();
|
if (!isAccountOwnedByCallingUid(accountType, callingUid) && !isSystemUid(callingUid)) {
|
||||||
|
String msg = String.format(
|
||||||
|
"uid %s cannot edit authenticator properites for account type: %s",
|
||||||
|
callingUid,
|
||||||
|
accountType);
|
||||||
|
throw new SecurityException(msg);
|
||||||
|
}
|
||||||
UserAccounts accounts = getUserAccountsForCaller();
|
UserAccounts accounts = getUserAccountsForCaller();
|
||||||
long identityToken = clearCallingIdentity();
|
long identityToken = clearCallingIdentity();
|
||||||
try {
|
try {
|
||||||
@@ -3588,7 +3635,7 @@ public class AccountManagerService
|
|||||||
private boolean permissionIsGranted(Account account, String authTokenType, int callerUid) {
|
private boolean permissionIsGranted(Account account, String authTokenType, int callerUid) {
|
||||||
final boolean isPrivileged = isPrivileged(callerUid);
|
final boolean isPrivileged = isPrivileged(callerUid);
|
||||||
final boolean fromAuthenticator = account != null
|
final boolean fromAuthenticator = account != null
|
||||||
&& hasAuthenticatorUid(account.type, callerUid);
|
&& isAccountManagedByCaller(account.type, callerUid);
|
||||||
final boolean hasExplicitGrants = account != null
|
final boolean hasExplicitGrants = account != null
|
||||||
&& hasExplicitlyGrantedPermission(account, authTokenType, callerUid);
|
&& hasExplicitlyGrantedPermission(account, authTokenType, callerUid);
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||||
@@ -3600,14 +3647,17 @@ public class AccountManagerService
|
|||||||
return fromAuthenticator || hasExplicitGrants || isPrivileged;
|
return fromAuthenticator || hasExplicitGrants || isPrivileged;
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean hasAuthenticatorUid(String accountType, int callingUid) {
|
private boolean isAccountManagedByCaller(String accountType, int callingUid) {
|
||||||
final int callingUserId = UserHandle.getUserId(callingUid);
|
final int callingUserId = UserHandle.getUserId(callingUid);
|
||||||
for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo :
|
for (RegisteredServicesCache.ServiceInfo<AuthenticatorDescription> serviceInfo :
|
||||||
mAuthenticatorCache.getAllServices(callingUserId)) {
|
mAuthenticatorCache.getAllServices(callingUserId)) {
|
||||||
if (serviceInfo.type.type.equals(accountType)) {
|
if (serviceInfo.type.type.equals(accountType)) {
|
||||||
return (serviceInfo.uid == callingUid) ||
|
/*
|
||||||
(mPackageManager.checkSignatures(serviceInfo.uid, callingUid)
|
* We can't simply compare uids because uids can be recycled before the
|
||||||
== PackageManager.SIGNATURE_MATCH);
|
* authenticator cache is updated.
|
||||||
|
*/
|
||||||
|
final int sigChk = mPackageManager.checkSignatures(serviceInfo.uid, callingUid);
|
||||||
|
return sigChk == PackageManager.SIGNATURE_MATCH;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@@ -3648,36 +3698,49 @@ public class AccountManagerService
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkCallingUidAgainstAuthenticator(Account account) {
|
private boolean isSystemUid(int callingUid) {
|
||||||
final int uid = Binder.getCallingUid();
|
String[] packages = null;
|
||||||
if (account == null || !hasAuthenticatorUid(account.type, uid)) {
|
long ident = Binder.clearCallingIdentity();
|
||||||
String msg = "caller uid " + uid + " is different than the authenticator's uid";
|
try {
|
||||||
Log.w(TAG, msg);
|
packages = mPackageManager.getPackagesForUid(callingUid);
|
||||||
throw new SecurityException(msg);
|
} finally {
|
||||||
|
Binder.restoreCallingIdentity(ident);
|
||||||
}
|
}
|
||||||
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
if (packages != null) {
|
||||||
Log.v(TAG, "caller uid " + uid + " is the same as the authenticator's uid");
|
for (String name : packages) {
|
||||||
|
try {
|
||||||
|
PackageInfo packageInfo = mPackageManager.getPackageInfo(name, 0 /* flags */);
|
||||||
|
if (packageInfo != null
|
||||||
|
&& (packageInfo.applicationInfo.flags & ApplicationInfo.FLAG_SYSTEM)
|
||||||
|
!= 0) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
} catch (PackageManager.NameNotFoundException e) {
|
||||||
|
Log.w(TAG, String.format("Could not find package [%s]", name), e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Log.w(TAG, "No known packages with uid " + callingUid);
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkAuthenticateAccountsPermission(Account account) {
|
private boolean isAccountOwnedByCallingUid(String accountType, int callingUid) {
|
||||||
checkBinderPermission(Manifest.permission.AUTHENTICATE_ACCOUNTS);
|
if (!isAccountManagedByCaller(accountType, callingUid)) {
|
||||||
checkCallingUidAgainstAuthenticator(account);
|
String msg = "caller uid " + callingUid + " is different than the authenticator's uid";
|
||||||
|
Log.w(TAG, msg);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if (Log.isLoggable(TAG, Log.VERBOSE)) {
|
||||||
|
Log.v(TAG, "caller uid " + callingUid + " is the same as the authenticator's uid");
|
||||||
|
}
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkReadAccountsPermission() {
|
private void checkReadAccountsPermission() {
|
||||||
checkBinderPermission(Manifest.permission.GET_ACCOUNTS);
|
checkBinderPermission(Manifest.permission.GET_ACCOUNTS);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void checkManageAccountsPermission() {
|
|
||||||
checkBinderPermission(Manifest.permission.MANAGE_ACCOUNTS);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void checkManageAccountsOrUseCredentialsPermissions() {
|
|
||||||
checkBinderPermission(Manifest.permission.MANAGE_ACCOUNTS,
|
|
||||||
Manifest.permission.USE_CREDENTIALS);
|
|
||||||
}
|
|
||||||
|
|
||||||
private boolean canUserModifyAccounts(int userId) {
|
private boolean canUserModifyAccounts(int userId) {
|
||||||
if (getUserManager().getUserRestrictions(new UserHandle(userId))
|
if (getUserManager().getUserRestrictions(new UserHandle(userId))
|
||||||
.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
|
.getBoolean(UserManager.DISALLOW_MODIFY_ACCOUNTS)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user