Merge "Permissions: Get rid of GET_ACCOUNTS" into nyc-dev

This commit is contained in:
Carlos Valdivia
2016-03-15 01:36:24 +00:00
committed by Android (Google) Code Review
11 changed files with 163 additions and 136 deletions

View File

@@ -68,7 +68,7 @@ package android {
field public static final java.lang.String DUMP = "android.permission.DUMP"; field public static final java.lang.String DUMP = "android.permission.DUMP";
field public static final java.lang.String EXPAND_STATUS_BAR = "android.permission.EXPAND_STATUS_BAR"; field public static final java.lang.String EXPAND_STATUS_BAR = "android.permission.EXPAND_STATUS_BAR";
field public static final java.lang.String FACTORY_TEST = "android.permission.FACTORY_TEST"; field public static final java.lang.String FACTORY_TEST = "android.permission.FACTORY_TEST";
field public static final java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS"; field public static final deprecated java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
field public static final java.lang.String GET_ACCOUNTS_PRIVILEGED = "android.permission.GET_ACCOUNTS_PRIVILEGED"; field public static final java.lang.String GET_ACCOUNTS_PRIVILEGED = "android.permission.GET_ACCOUNTS_PRIVILEGED";
field public static final java.lang.String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE"; field public static final java.lang.String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
field public static final deprecated java.lang.String GET_TASKS = "android.permission.GET_TASKS"; field public static final deprecated java.lang.String GET_TASKS = "android.permission.GET_TASKS";

View File

@@ -97,7 +97,7 @@ package android {
field public static final java.lang.String FACTORY_TEST = "android.permission.FACTORY_TEST"; field public static final java.lang.String FACTORY_TEST = "android.permission.FACTORY_TEST";
field public static final java.lang.String FORCE_BACK = "android.permission.FORCE_BACK"; field public static final java.lang.String FORCE_BACK = "android.permission.FORCE_BACK";
field public static final java.lang.String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES"; field public static final java.lang.String FORCE_STOP_PACKAGES = "android.permission.FORCE_STOP_PACKAGES";
field public static final java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS"; field public static final deprecated java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
field public static final java.lang.String GET_ACCOUNTS_PRIVILEGED = "android.permission.GET_ACCOUNTS_PRIVILEGED"; field public static final java.lang.String GET_ACCOUNTS_PRIVILEGED = "android.permission.GET_ACCOUNTS_PRIVILEGED";
field public static final java.lang.String GET_APP_OPS_STATS = "android.permission.GET_APP_OPS_STATS"; field public static final java.lang.String GET_APP_OPS_STATS = "android.permission.GET_APP_OPS_STATS";
field public static final java.lang.String GET_PACKAGE_IMPORTANCE = "android.permission.GET_PACKAGE_IMPORTANCE"; field public static final java.lang.String GET_PACKAGE_IMPORTANCE = "android.permission.GET_PACKAGE_IMPORTANCE";

View File

@@ -68,7 +68,7 @@ package android {
field public static final java.lang.String DUMP = "android.permission.DUMP"; field public static final java.lang.String DUMP = "android.permission.DUMP";
field public static final java.lang.String EXPAND_STATUS_BAR = "android.permission.EXPAND_STATUS_BAR"; field public static final java.lang.String EXPAND_STATUS_BAR = "android.permission.EXPAND_STATUS_BAR";
field public static final java.lang.String FACTORY_TEST = "android.permission.FACTORY_TEST"; field public static final java.lang.String FACTORY_TEST = "android.permission.FACTORY_TEST";
field public static final java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS"; field public static final deprecated java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS";
field public static final java.lang.String GET_ACCOUNTS_PRIVILEGED = "android.permission.GET_ACCOUNTS_PRIVILEGED"; field public static final java.lang.String GET_ACCOUNTS_PRIVILEGED = "android.permission.GET_ACCOUNTS_PRIVILEGED";
field public static final java.lang.String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE"; field public static final java.lang.String GET_PACKAGE_SIZE = "android.permission.GET_PACKAGE_SIZE";
field public static final deprecated java.lang.String GET_TASKS = "android.permission.GET_TASKS"; field public static final deprecated java.lang.String GET_TASKS = "android.permission.GET_TASKS";

View File

@@ -426,46 +426,46 @@ public class AccountManager {
} }
/** /**
* Lists all accounts of any type registered on the device. * List every {@link Account} registered on the device that are managed by
* Equivalent to getAccountsByType(null). * applications whose signatures match the caller.
* *
* <p>It is safe to call this method from the main thread. * <p>This method can be called safely from the main thread. It is
* equivalent to calling <code>getAccountsByType(null)</code>.
* *
* <p>Clients of this method that have not been granted the * <p><b>NOTE:</b> Apps declaring a {@code targetSdkVersion<=23} in their
* {@link android.Manifest.permission#GET_ACCOUNTS} permission, * manifests will continue to behave as they did on devices that support
* will only see those accounts managed by AbstractAccountAuthenticators whose * API level 23. In particular the GET_ACCOUNTS permission is required to
* signature matches the client. * see all the Accounts registered with the AccountManager. See docs for
* this function in API level 23 for more information.
* *
* @return An array of {@link Account}, one for each account. Empty * @return Array of Accounts. The array may be empty if no accounts are
* (never null) if no accounts have been added. * available to the caller.
*/ */
@NonNull @NonNull
@RequiresPermission(GET_ACCOUNTS)
public Account[] getAccounts() { public Account[] getAccounts() {
try { return getAccountsByType(null);
return mService.getAccounts(null, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} }
/** /**
* @hide * @hide
* Lists all accounts of any type registered on the device for a given * List every {@link Account} registered on the device for a specific User
* user id. Equivalent to getAccountsByType(null). * that are managed by applications whose signatures match the caller.
* *
* <p>It is safe to call this method from the main thread. * <p><b>NOTE:</b> Apps declaring a {@code targetSdkVersion<=23} in their
* manifests will continue to behave as they did on devices that support
* API level 23. In particular the GET_ACCOUNTS permission is required to
* see all the Accounts registered with the AccountManager for the
* specified userId. See docs for this function in API level 23 for more
* information.
* *
* <p>Clients of this method that have not been granted the * <p>This method can be called safely from the main thread.
* {@link android.Manifest.permission#GET_ACCOUNTS} permission,
* will only see those accounts managed by AbstractAccountAuthenticators whose
* signature matches the client.
* *
* @return An array of {@link Account}, one for each account. Empty * @param int userId associated with the User whose accounts should be
* (never null) if no accounts have been added. * queried.
* @return Array of Accounts. The array may be empty if no accounts are
* available to the caller.
*/ */
@NonNull @NonNull
@RequiresPermission(GET_ACCOUNTS)
public Account[] getAccountsAsUser(int userId) { public Account[] getAccountsAsUser(int userId) {
try { try {
return mService.getAccountsAsUser(null, userId, mContext.getOpPackageName()); return mService.getAccountsAsUser(null, userId, mContext.getOpPackageName());
@@ -494,10 +494,11 @@ public class AccountManager {
/** /**
* Returns the accounts visible to the specified package, in an environment where some 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. * are not authorized to view all accounts. This method can only be called by system apps.
*
* @param type The type of accounts to return, null to retrieve all accounts * @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 * @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 * @return Array of Accounts. The array may be empty if no accounts of th
* (never null) if no accounts of the specified type have been added. * specified type are visible to the caller.
*/ */
@NonNull @NonNull
public Account[] getAccountsByTypeForPackage(String type, String packageName) { public Account[] getAccountsByTypeForPackage(String type, String packageName) {
@@ -510,29 +511,22 @@ public class AccountManager {
} }
/** /**
* Lists all accounts of a particular type. The account type is a * List every {@link Account} of a specified type managed by applications
* string token corresponding to the authenticator and useful domain * whose signatures match the caller.
* of the account. For example, there are types corresponding to Google
* and Facebook. The exact string token to use will be published somewhere
* associated with the authenticator in question.
* *
* <p>It is safe to call this method from the main thread. * <p><b>NOTE:</b> Apps declaring a {@code targetSdkVersion<=23} in their
* manifests will continue to behave as they did on devices that support
* API level 23. See docs for this function in API level 23 for more
* information.
* *
* <p>Clients of this method that have not been granted the * <p>This method can be called safely from the main thread.
* {@link android.Manifest.permission#GET_ACCOUNTS} permission,
* will only see those accounts managed by AbstractAccountAuthenticators whose
* signature matches the client.
* *
* <p><b>NOTE:</b> If targeting your app to work on API level 22 and before, * @param type String denoting the type of the accounts to return,
* GET_ACCOUNTS permission is needed for those platforms, irrespective of uid * {@code null} to retrieve all accounts visible to the caller.
* or signature match. See docs for this function in API level 22. * @return An array of Accounts. Empty (never null) if no accounts
* * are available to the caller.
* @param type The type of accounts to return, null to retrieve all accounts
* @return An array of {@link Account}, one per matching account. Empty
* (never null) if no accounts of the specified type have been added.
*/ */
@NonNull @NonNull
@RequiresPermission(GET_ACCOUNTS)
public Account[] getAccountsByType(String type) { public Account[] getAccountsByType(String type) {
return getAccountsByTypeAsUser(type, Process.myUserHandle()); return getAccountsByTypeAsUser(type, Process.myUserHandle());
} }
@@ -576,6 +570,7 @@ public class AccountManager {
* @return a future containing the label string * @return a future containing the label string
* @hide * @hide
*/ */
@NonNull
public AccountManagerFuture<String> getAuthTokenLabel( public AccountManagerFuture<String> getAuthTokenLabel(
final String accountType, final String authTokenType, final String accountType, final String authTokenType,
AccountManagerCallback<String> callback, Handler handler) { AccountManagerCallback<String> callback, Handler handler) {
@@ -608,9 +603,13 @@ 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><b>Note:</b>The specified account must be managed by an application
* {@link android.Manifest.permission#GET_ACCOUNTS} or be a signature * whose signature matches the caller.
* match with the AbstractAccountAuthenticator that manages the account. *
* <p><b>Further note:</b>Apps targeting API level 23 or earlier will continue to
* behave as they did on devices that support API level 23. In particular
* they may still require the GET_ACCOUNTS permission. See docs for this
* function in API level 23.
* *
* @param account The {@link Account} to test * @param account The {@link Account} to test
* @param features An array of the account features to check * @param features An array of the account features to check
@@ -619,9 +618,11 @@ public class AccountManager {
* @param handler {@link Handler} identifying the callback thread, * @param handler {@link Handler} identifying the callback thread,
* null for the main thread * null for the main thread
* @return An {@link AccountManagerFuture} which resolves to a Boolean, * @return An {@link AccountManagerFuture} which resolves to a Boolean,
* true if the account exists and has all of the specified features. * true if the account exists and has all of the specified features.
* @throws SecurityException if the specified account is managed by an
* application whose signature doesn't match the caller's signature.
*/ */
@RequiresPermission(GET_ACCOUNTS) @NonNull
public AccountManagerFuture<Boolean> hasFeatures(final Account account, public AccountManagerFuture<Boolean> hasFeatures(final Account account,
final String[] features, final String[] features,
AccountManagerCallback<Boolean> callback, Handler handler) { AccountManagerCallback<Boolean> callback, Handler handler) {
@@ -644,9 +645,10 @@ public class AccountManager {
/** /**
* Lists all accounts of a type which have certain features. The account * Lists all accounts of a type which have certain features. The account
* type identifies the authenticator (see {@link #getAccountsByType}). * type identifies the authenticator (see {@link #getAccountsByType}). Said
* Account features are authenticator-specific string tokens identifying * authenticator must be in a package whose signature matches the callers
* boolean account properties (see {@link #hasFeatures}). * package signature. Account features are authenticator-specific string tokens
* identifying boolean account properties (see {@link #hasFeatures}).
* *
* <p>Unlike {@link #getAccountsByType}, this method calls the authenticator, * <p>Unlike {@link #getAccountsByType}, this method calls the authenticator,
* which may contact the server or do other work to check account features, * which may contact the server or do other work to check account features,
@@ -655,19 +657,14 @@ 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>Clients of this method that have not been granted the * <p><b>NOTE:</b> Apps targeting API level 23 or earlier will continue to
* {@link android.Manifest.permission#GET_ACCOUNTS} permission, * behave as they did on devices that support API level 23. In particular
* will only see those accounts managed by AbstractAccountAuthenticators whose * they may still require the GET_ACCOUNTS permission. See docs for this
* signature matches the client. * function in API level 23.
* *
* @param type The type of accounts to return, must not be null * @param type The type of accounts to return, must not be null
* @param features An array of the account features to require, * @param features An array of the account features to require,
* may be null or empty * may be null or empty
*
* <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
* GET_ACCOUNTS permission is needed for those platforms, irrespective of uid
* or signature match. See docs for this function in API level 22.
*
* @param callback Callback to invoke when the request completes, * @param callback Callback to invoke when the request completes,
* null for no callback * null for no callback
* @param handler {@link Handler} identifying the callback thread, * @param handler {@link Handler} identifying the callback thread,
@@ -676,7 +673,7 @@ public class AccountManager {
* {@link Account}, one per account of the specified type which * {@link Account}, one per account of the specified type which
* matches the requested features. * matches the requested features.
*/ */
@RequiresPermission(GET_ACCOUNTS) @NonNull
public AccountManagerFuture<Account[]> getAccountsByTypeAndFeatures( public AccountManagerFuture<Account[]> getAccountsByTypeAndFeatures(
final String type, final String[] features, final String type, final String[] features,
AccountManagerCallback<Account[]> callback, Handler handler) { AccountManagerCallback<Account[]> callback, Handler handler) {

View File

@@ -1240,7 +1240,8 @@
<eat-comment /> <eat-comment />
<!-- Allows access to the list of accounts in the Accounts Service. <!-- Allows access to the list of accounts in the Accounts Service.
<p>Protection level: normal <p>Protection level: dangerous
@deprecated Not operative for apps apps with targetSdkVersion >= 24.
--> -->
<permission android:name="android.permission.GET_ACCOUNTS" <permission android:name="android.permission.GET_ACCOUNTS"
android:permissionGroup="android.permission-group.CONTACTS" android:permissionGroup="android.permission-group.CONTACTS"

View File

@@ -160,20 +160,21 @@ page.image=images/cards/card-support_16-9_2x.png
still perform BTLE and WiFi scans, but only when they are in the foreground. While in the background, those apps will get no results from BTLE and WiFi scans.</li> still perform BTLE and WiFi scans, but only when they are in the foreground. While in the background, those apps will get no results from BTLE and WiFi scans.</li>
</ul> </ul>
</li> </li>
<li>Permission changes <li>Accessing accounts
<ul> <ul>
<li>Updated the user interface for permissions and enhanced some of the permissions <li>Updated the behavior of {@link android.accounts.AccountManager} account
behaviors.</li> discovery methods.
<li>The {@link android.Manifest.permission#GET_ACCOUNTS} permission is now a member of the
{@link android.Manifest.permission_group#CONTACTS} permission group and it has a
{@code android:protectionLevel} of {@code dangerous}. This change means that when
targeting Android 6.0 (API level 23), you must check for and request this permission if
your app requires it.
</li> </li>
<li>The GET_ACCOUNTS permission has been deprecated.
<li>The {@code android.permission.READ_PROFILE} and {@code android.permission.WRITE_PROFILE} </li>
permissions have been removed from the {@link android.Manifest.permission_group#CONTACTS} <li>Apps targeting API level 24 should start the intent returned by
permission group. newChooseAccountIntent(...) and await the result to acquire a reference
to the user's selected account. AccountManager methods like getAccounts and
related methods will only return those accounts managed by
authenticators that match the signatures of the calling app.
</li>
<li>Apps targeting API level 23 or earlier will continue to behave as
before.
</li> </li>
</ul> </ul>
</li> </li>

View File

@@ -15,8 +15,7 @@ next.link=authenticate.html
<ol> <ol>
<li><a href="#ForYou">Determine if AccountManager is for You</a></li> <li><a href="#ForYou">Determine if AccountManager is for You</a></li>
<li><a href="#TaskTwo">Decide What Type of Account to Use</a></li> <li><a href="#TaskTwo">Decide What Type of Account to Use</a></li>
<li><a href="#GetPermission">Request GET_ACCOUNT permission</a></li> <li><a href="#QueryAccounts">Query the user for an Account</a></li>
<li><a href="#TaskFive">Query AccountManager for a List of Accounts</a></li>
<li><a href="#IdentifyUser">Use the Account Object to Personalize Your App</a></li> <li><a href="#IdentifyUser">Use the Account Object to Personalize Your App</a></li>
<li><a href="#IdIsEnough">Decide Whether an Account Name is Enough</a></li> <li><a href="#IdIsEnough">Decide Whether an Account Name is Enough</a></li>
</ol> </ol>
@@ -71,48 +70,46 @@ UI.</p>
<h2 id="TaskTwo">Decide What Type of Account to Use</h2> <h2 id="TaskTwo">Decide What Type of Account to Use</h2>
<p>Android devices can store multiple accounts from many different providers. <p>Android devices can store multiple accounts from many different providers.
When you query {@link android.accounts.AccountManager} for account names, you can choose to filter When you query {@link android.accounts.AccountManager} for account names, you
by can choose to filter by account type. The account type is a string that
account type. The account type is a string that uniquely identifies the entity uniquely identifies the entity that issued the account. For instance, Google
that issued the account. For instance, Google accounts have type "com.google," accounts have type "com.google," while Twitter uses
while Twitter uses "com.twitter.android.auth.login."</p> "com.twitter.android.auth.login."</p>
<h2 id="QueryAccounts">Query the user for an Account</h2>
<h2 id="GetPermission">Request GET_ACCOUNT permission</h2> <p>Once an account type has been determined, you can prompt the user with an
account chooser as follows:
<p>In order to get a list of accounts on the device, your app needs the {@link
android.Manifest.permission#GET_ACCOUNTS}
permission. Add a <a href="{@docRoot}guide/topics/manifest/uses-permission-element.html">{@code
<uses-permission>}</a> tag in your manifest file to request
this permission:</p>
<pre> <pre>
&lt;manifest ... > AccountManager am = AccountManager.get(this); // "this" reference the current Context
&lt;uses-permission android:name="android.permission.GET_ACCOUNTS" /&gt; Intent chooserIntent = am.newChooseAccountIntent(
... null, // currently select account
&lt;/manifest> null, // list of accounts that are allowed to be shown
new String[] { "com.google" }, // Only allow the user to select Google accounts
false,
null, // description text
null, // add account auth token type
null, // required features for added accounts
null); // options for adding an account
this.startActivityForResult(chooserIntent, MY_REQUEST_CODE);
</pre> </pre>
<p>Once the chooser intent is started, the user will be presented with a list of
<h2 id="TaskFive">Query AccountManager for a List of Accounts</h2> appropriately typed accounts. From this list they will select one which will be
returned to your app upon onActivityResult as follows:
<p>Once you decide what account type you're interested in, you need to query for accounts of that
type. Get an instance of {@link android.accounts.AccountManager} by calling {@link
android.accounts.AccountManager#get(android.content.Context) AccountManager.get()}. Then use that
instance to call {@link android.accounts.AccountManager#getAccountsByType(java.lang.String)
getAccountsByType()}.</p>
<pre> <pre>
AccountManager am = AccountManager.get(this); // "this" references the current Context protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == MY_REQUEST_CODE && resultCode == RESULT_OK) {
Account[] accounts = am.getAccountsByType("com.google"); String name = data.getStringExtra(AccountManage.KEY_ACCOUNT_NAME);
String type = data.getStringExtra(AccountManage.KEY_ACCOUNT_TYPE);
Account selectedAccount = new Account(name, type);
doSomethingWithSelectedAccount(selectedAccount);
}
}
</pre> </pre>
<p>This returns an array of {@link android.accounts.Account} objects. If there's more than one
{@link android.accounts.Account} in
the array, you should present a dialog asking the user to select one.</p>
<h2 id="IdentifyUser">Use the Account Object to Personalize Your App</h2> <h2 id="IdentifyUser">Use the Account Object to Personalize Your App</h2>
<p>The {@link android.accounts.Account} object contains an account name, which for Google accounts <p>The {@link android.accounts.Account} object contains an account name, which for Google accounts

View File

@@ -23,7 +23,7 @@
<uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17"/> <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="17"/>
<uses-permission android:name="android.permission.VIBRATE" /> <uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" /> <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.GET_ACCOUNTS_PRIVILEDGED" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" /> <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" /> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL" />
<uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.WAKE_LOCK" />

View File

@@ -93,7 +93,7 @@
<uses-permission android:name="android.permission.MANAGE_USERS" /> <uses-permission android:name="android.permission.MANAGE_USERS" />
<uses-permission android:name="android.permission.MANAGE_DEVICE_ADMINS" /> <uses-permission android:name="android.permission.MANAGE_DEVICE_ADMINS" />
<uses-permission android:name="android.permission.BLUETOOTH_STACK" /> <uses-permission android:name="android.permission.BLUETOOTH_STACK" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.GET_ACCOUNTS_PRIVILEDGED" />
<uses-permission android:name="android.permission.RETRIEVE_WINDOW_TOKEN" /> <uses-permission android:name="android.permission.RETRIEVE_WINDOW_TOKEN" />
<uses-permission android:name="android.permission.FRAME_STATS" /> <uses-permission android:name="android.permission.FRAME_STATS" />
<uses-permission android:name="android.permission.BIND_APPWIDGET" /> <uses-permission android:name="android.permission.BIND_APPWIDGET" />

View File

@@ -103,7 +103,7 @@
<!-- Keyguard --> <!-- Keyguard -->
<uses-permission android:name="android.permission.CONTROL_KEYGUARD" /> <uses-permission android:name="android.permission.CONTROL_KEYGUARD" />
<uses-permission android:name="android.permission.MODIFY_PHONE_STATE" /> <uses-permission android:name="android.permission.MODIFY_PHONE_STATE" />
<uses-permission android:name="android.permission.GET_ACCOUNTS" /> <uses-permission android:name="android.permission.GET_ACCOUNTS_PRIVILEDGED" />
<uses-permission android:name="android.permission.MANAGE_ACCOUNTS" /> <uses-permission android:name="android.permission.MANAGE_ACCOUNTS" />
<uses-permission android:name="android.permission.BIND_DEVICE_ADMIN" /> <uses-permission android:name="android.permission.BIND_DEVICE_ADMIN" />
<uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" /> <uses-permission android:name="android.permission.CHANGE_COMPONENT_ENABLED_STATE" />

View File

@@ -1327,8 +1327,9 @@ public class AccountManagerService
* arbitrary applications (like competing authenticators). * arbitrary applications (like competing authenticators).
*/ */
UserHandle user = new UserHandle(userId); UserHandle user = new UserHandle(userId);
if (!isAccountManagedByCaller(account.type, callingUid, user.getIdentifier())
&& !isSystemUid(callingUid)) { if (!isSystemUid(callingUid)
&& !isAccountManagedByCaller(account.type, callingUid, user.getIdentifier())) {
String msg = String.format( String msg = String.format(
"uid %s cannot remove accounts of type: %s", "uid %s cannot remove accounts of type: %s",
callingUid, callingUid,
@@ -4356,21 +4357,6 @@ public class AccountManagerService
} }
} }
private boolean isPermitted(String opPackageName, int callingUid, String... permissions) {
for (String perm : permissions) {
if (mContext.checkCallingOrSelfPermission(perm) == PackageManager.PERMISSION_GRANTED) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, " caller uid " + callingUid + " has " + perm);
}
final int opCode = AppOpsManager.permissionToOpCode(perm);
if (opCode == AppOpsManager.OP_NONE || mAppOpsManager.noteOp(
opCode, callingUid, opPackageName) == AppOpsManager.MODE_ALLOWED) {
return true;
}
}
}
return false;
}
private int handleIncomingUser(int userId) { private int handleIncomingUser(int userId) {
try { try {
@@ -4445,12 +4431,53 @@ public class AccountManagerService
private List<String> getTypesVisibleToCaller(int callingUid, int userId, private List<String> getTypesVisibleToCaller(int callingUid, int userId,
String opPackageName) { String opPackageName) {
boolean isPermitted = List<String> permissionsToCheck = new ArrayList<String>(2);
isPermitted(opPackageName, callingUid, Manifest.permission.GET_ACCOUNTS, permissionsToCheck.add(Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
Manifest.permission.GET_ACCOUNTS_PRIVILEGED); long id = Binder.clearCallingIdentity();
try {
ApplicationInfo appInfo = mPackageManager.getApplicationInfo(
opPackageName, 0 /* flags */);
/*
* At or before SDK 23, clients discover all the accounts in their
* user profile (via AccountManager.getAccounts(...)) by declaring
* the GET_ACCOUNTS permission.
*
* After SDK 23 the GET_ACCOUNTS permission is deprecated. Instead
* apps will be able to retrieve those accounts managed by
* authenticators sharing a package signature without any special
* permissions. The only clients able to discover all the accounts
* on the device will be those with the GET_ACCOUNTS_PRVILEGED
* system permission.
*/
if (23 >= appInfo.targetSdkVersion) {
permissionsToCheck.add(Manifest.permission.GET_ACCOUNTS);
}
} catch (NameNotFoundException e) {
// No application associated with the specified package.
Log.w(TAG, "No application associated with package: " + opPackageName);
} finally {
Binder.restoreCallingIdentity(id);
}
boolean isPermitted = isPermitted(opPackageName, callingUid, permissionsToCheck);
return getTypesForCaller(callingUid, userId, isPermitted); return getTypesForCaller(callingUid, userId, isPermitted);
} }
private boolean isPermitted(String opPackageName, int callingUid, List<String> permissions) {
for (String perm : permissions) {
if (mContext.checkCallingOrSelfPermission(perm) == PackageManager.PERMISSION_GRANTED) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, " caller uid " + callingUid + " has " + perm);
}
final int opCode = AppOpsManager.permissionToOpCode(perm);
if (opCode == AppOpsManager.OP_NONE || mAppOpsManager.noteOp(
opCode, callingUid, opPackageName) == AppOpsManager.MODE_ALLOWED) {
return true;
}
}
}
return false;
}
private List<String> getTypesManagedByCaller(int callingUid, int userId) { private List<String> getTypesManagedByCaller(int callingUid, int userId) {
return getTypesForCaller(callingUid, userId, false); return getTypesForCaller(callingUid, userId, false);
} }
@@ -4472,6 +4499,10 @@ public class AccountManagerService
managedAccountTypes.add(serviceInfo.type.type); managedAccountTypes.add(serviceInfo.type.type);
} }
} }
if (managedAccountTypes.isEmpty()) {
throw new SecurityException("The calling uid " + callingUid +
" is not permitted access any types of accounts!");
}
return managedAccountTypes; return managedAccountTypes;
} }