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

This commit is contained in:
Ian Pedowitz
2016-03-15 17:09:51 +00:00
committed by Android (Google) Code Review
11 changed files with 136 additions and 163 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 deprecated java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS"; field public static final 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 deprecated java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS"; field public static final 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 deprecated java.lang.String GET_ACCOUNTS = "android.permission.GET_ACCOUNTS"; field public static final 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 {
} }
/** /**
* List every {@link Account} registered on the device that are managed by * Lists all accounts of any type registered on the device.
* applications whose signatures match the caller. * Equivalent to getAccountsByType(null).
* *
* <p>This method can be called safely from the main thread. It is * <p>It is safe to call this method from the main thread.
* equivalent to calling <code>getAccountsByType(null)</code>.
* *
* <p><b>NOTE:</b> Apps declaring a {@code targetSdkVersion<=23} in their * <p>Clients of this method that have not been granted the
* manifests will continue to behave as they did on devices that support * {@link android.Manifest.permission#GET_ACCOUNTS} permission,
* API level 23. In particular the GET_ACCOUNTS permission is required to * will only see those accounts managed by AbstractAccountAuthenticators whose
* see all the Accounts registered with the AccountManager. See docs for * signature matches the client.
* this function in API level 23 for more information.
* *
* @return Array of Accounts. The array may be empty if no accounts are * @return An array of {@link Account}, one for each account. Empty
* available to the caller. * (never null) if no accounts have been added.
*/ */
@NonNull @NonNull
@RequiresPermission(GET_ACCOUNTS)
public Account[] getAccounts() { public Account[] getAccounts() {
return getAccountsByType(null); try {
return mService.getAccounts(null, mContext.getOpPackageName());
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
} }
/** /**
* @hide * @hide
* List every {@link Account} registered on the device for a specific User * Lists all accounts of any type registered on the device for a given
* that are managed by applications whose signatures match the caller. * user id. Equivalent to getAccountsByType(null).
* *
* <p><b>NOTE:</b> Apps declaring a {@code targetSdkVersion<=23} in their * <p>It is safe to call this method from the main thread.
* 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>This method can be called safely from the main thread. * <p>Clients of this method that have not been granted the
* {@link android.Manifest.permission#GET_ACCOUNTS} permission,
* will only see those accounts managed by AbstractAccountAuthenticators whose
* signature matches the client.
* *
* @param int userId associated with the User whose accounts should be * @return An array of {@link Account}, one for each account. Empty
* queried. * (never null) if no accounts have been added.
* @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,11 +494,10 @@ 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 Array of Accounts. The array may be empty if no accounts of th * @return An array of {@link Account}, one per matching account. Empty
* specified type are visible to the caller. * (never null) if no accounts of the specified type have been added.
*/ */
@NonNull @NonNull
public Account[] getAccountsByTypeForPackage(String type, String packageName) { public Account[] getAccountsByTypeForPackage(String type, String packageName) {
@@ -511,22 +510,29 @@ public class AccountManager {
} }
/** /**
* List every {@link Account} of a specified type managed by applications * Lists all accounts of a particular type. The account type is a
* whose signatures match the caller. * string token corresponding to the authenticator and useful domain
* 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><b>NOTE:</b> Apps declaring a {@code targetSdkVersion<=23} in their * <p>It is safe to call this method from the main thread.
* 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>This method can be called safely from the main thread. * <p>Clients of this method that have not been granted the
* {@link android.Manifest.permission#GET_ACCOUNTS} permission,
* will only see those accounts managed by AbstractAccountAuthenticators whose
* signature matches the client.
* *
* @param type String denoting the type of the accounts to return, * <p><b>NOTE:</b> If targeting your app to work on API level 22 and before,
* {@code null} to retrieve all accounts visible to the caller. * GET_ACCOUNTS permission is needed for those platforms, irrespective of uid
* @return An array of Accounts. Empty (never null) if no accounts * or signature match. See docs for this function in API level 22.
* 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());
} }
@@ -570,7 +576,6 @@ 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) {
@@ -603,13 +608,9 @@ 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><b>Note:</b>The specified account must be managed by an application * <p>This method requires the caller to hold the permission
* whose signature matches the caller. * {@link android.Manifest.permission#GET_ACCOUNTS} or be a signature
* * 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
@@ -618,11 +619,9 @@ 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.
*/ */
@NonNull @RequiresPermission(GET_ACCOUNTS)
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) {
@@ -645,10 +644,9 @@ 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}). Said * type identifies the authenticator (see {@link #getAccountsByType}).
* authenticator must be in a package whose signature matches the callers * Account features are authenticator-specific string tokens identifying
* package signature. Account features are authenticator-specific string tokens * boolean account properties (see {@link #hasFeatures}).
* 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,
@@ -657,14 +655,19 @@ 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><b>NOTE:</b> Apps targeting API level 23 or earlier will continue to * <p>Clients of this method that have not been granted the
* behave as they did on devices that support API level 23. In particular * {@link android.Manifest.permission#GET_ACCOUNTS} permission,
* they may still require the GET_ACCOUNTS permission. See docs for this * will only see those accounts managed by AbstractAccountAuthenticators whose
* function in API level 23. * signature matches the client.
* *
* @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,
@@ -673,7 +676,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.
*/ */
@NonNull @RequiresPermission(GET_ACCOUNTS)
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,8 +1240,7 @@
<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: dangerous <p>Protection level: normal
@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,21 +160,20 @@ 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>Accessing accounts <li>Permission changes
<ul> <ul>
<li>Updated the behavior of {@link android.accounts.AccountManager} account <li>Updated the user interface for permissions and enhanced some of the permissions
discovery methods. behaviors.</li>
<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> <li>The {@code android.permission.READ_PROFILE} and {@code android.permission.WRITE_PROFILE}
<li>Apps targeting API level 24 should start the intent returned by permissions have been removed from the {@link android.Manifest.permission_group#CONTACTS}
newChooseAccountIntent(...) and await the result to acquire a reference permission group.
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,7 +15,8 @@ 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="#QueryAccounts">Query the user for an Account</a></li> <li><a href="#GetPermission">Request GET_ACCOUNT permission</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>
@@ -70,46 +71,48 @@ 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 When you query {@link android.accounts.AccountManager} for account names, you can choose to filter
can choose to filter by account type. The account type is a string that by
uniquely identifies the entity that issued the account. For instance, Google account type. The account type is a string that uniquely identifies the entity
accounts have type "com.google," while Twitter uses that issued the account. For instance, Google accounts have type "com.google,"
"com.twitter.android.auth.login."</p> while Twitter uses "com.twitter.android.auth.login."</p>
<h2 id="QueryAccounts">Query the user for an Account</h2>
<p>Once an account type has been determined, you can prompt the user with an <h2 id="GetPermission">Request GET_ACCOUNT permission</h2>
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>
AccountManager am = AccountManager.get(this); // "this" reference the current Context &lt;manifest ... >
Intent chooserIntent = am.newChooseAccountIntent( &lt;uses-permission android:name="android.permission.GET_ACCOUNTS" /&gt;
null, // currently select account ...
null, // list of accounts that are allowed to be shown &lt;/manifest>
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
appropriately typed accounts. From this list they will select one which will be <h2 id="TaskFive">Query AccountManager for a List of Accounts</h2>
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>
protected void onActivityResult(int requestCode, int resultCode, Intent data) { AccountManager am = AccountManager.get(this); // "this" references the current Context
if (requestCode == MY_REQUEST_CODE && resultCode == RESULT_OK) {
String name = data.getStringExtra(AccountManage.KEY_ACCOUNT_NAME); Account[] accounts = am.getAccountsByType("com.google");
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_PRIVILEDGED" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" />
<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_PRIVILEDGED" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" />
<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_PRIVILEDGED" /> <uses-permission android:name="android.permission.GET_ACCOUNTS" />
<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,9 +1327,8 @@ 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())
if (!isSystemUid(callingUid) && !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,
@@ -4357,6 +4356,21 @@ 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 {
@@ -4431,53 +4445,12 @@ public class AccountManagerService
private List<String> getTypesVisibleToCaller(int callingUid, int userId, private List<String> getTypesVisibleToCaller(int callingUid, int userId,
String opPackageName) { String opPackageName) {
List<String> permissionsToCheck = new ArrayList<String>(2); boolean isPermitted =
permissionsToCheck.add(Manifest.permission.GET_ACCOUNTS_PRIVILEGED); isPermitted(opPackageName, callingUid, Manifest.permission.GET_ACCOUNTS,
long id = Binder.clearCallingIdentity(); Manifest.permission.GET_ACCOUNTS_PRIVILEGED);
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);
} }
@@ -4499,10 +4472,6 @@ 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;
} }