From 3b458ad9ee5f2d6b7cf28a13bc29123cdf540763 Mon Sep 17 00:00:00 2001 From: Amith Yamasani Date: Thu, 18 Apr 2013 18:40:07 -0700 Subject: [PATCH] Improve API and documentation API for querying accounts visible to a specific package. Improve API and docs for device owner. Bug: 8657158 Change-Id: I01b8701534f64b383391508a49ae93ed21f22ae0 --- api/current.txt | 3 ++- .../java/android/accounts/AccountManager.java | 17 ++++++++++++ .../android/accounts/IAccountManager.aidl | 1 + .../app/admin/DevicePolicyManager.java | 27 ++++++++++++++----- core/java/android/content/Intent.java | 4 +-- .../accounts/AccountManagerService.java | 15 +++++++++++ 6 files changed, 58 insertions(+), 9 deletions(-) diff --git a/api/current.txt b/api/current.txt index 6eb8545ab3172..15c75e1ff1d7a 100644 --- a/api/current.txt +++ b/api/current.txt @@ -2193,6 +2193,7 @@ package android.accounts { method public android.accounts.Account[] getAccounts(); method public android.accounts.Account[] getAccountsByType(java.lang.String); method public android.accounts.AccountManagerFuture getAccountsByTypeAndFeatures(java.lang.String, java.lang.String[], android.accounts.AccountManagerCallback, android.os.Handler); + method public android.accounts.Account[] getAccountsByTypeForPackage(java.lang.String, java.lang.String); method public android.accounts.AccountManagerFuture getAuthToken(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback, android.os.Handler); method public deprecated android.accounts.AccountManagerFuture getAuthToken(android.accounts.Account, java.lang.String, boolean, android.accounts.AccountManagerCallback, android.os.Handler); method public android.accounts.AccountManagerFuture getAuthToken(android.accounts.Account, java.lang.String, android.os.Bundle, boolean, android.accounts.AccountManagerCallback, android.os.Handler); @@ -4353,7 +4354,7 @@ package android.app.admin { method public boolean hasGrantedPolicy(android.content.ComponentName, int); method public boolean isActivePasswordSufficient(); method public boolean isAdminActive(android.content.ComponentName); - method public boolean isDeviceOwner(java.lang.String); + method public boolean isDeviceOwnerApp(java.lang.String); method public void lockNow(); method public void removeActiveAdmin(android.content.ComponentName); method public boolean resetPassword(java.lang.String, int); diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java index 241a64af65ae1..b4a12c4bdbffe 100644 --- a/core/java/android/accounts/AccountManager.java +++ b/core/java/android/accounts/AccountManager.java @@ -404,6 +404,23 @@ public class AccountManager { } } + /** + * Returns the accounts visible to the specified package, in an environment where some apps + * are not authorized to view all accounts. This method can only be called by system apps. + * @param type The type of accounts to return, null to retrieve all accounts + * @param packageName The package name of the app for which the accounts are to be returned + * @return An array of {@link Account}, one per matching account. Empty + * (never null) if no accounts of the specified type have been added. + */ + public Account[] getAccountsByTypeForPackage(String type, String packageName) { + try { + return mService.getAccountsByTypeForPackage(type, packageName); + } catch (RemoteException re) { + // possible security exception + throw new RuntimeException(re); + } + } + /** * Lists all accounts of a particular type. The account type is a * string token corresponding to the authenticator and useful domain diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl index 81418132d5c8b..86e279f3d005d 100644 --- a/core/java/android/accounts/IAccountManager.aidl +++ b/core/java/android/accounts/IAccountManager.aidl @@ -32,6 +32,7 @@ interface IAccountManager { AuthenticatorDescription[] getAuthenticatorTypes(); Account[] getAccounts(String accountType); Account[] getAccountsForPackage(String packageName, int uid); + Account[] getAccountsByTypeForPackage(String type, String packageName); Account[] getAccountsAsUser(String accountType, int userId); void hasFeatures(in IAccountManagerResponse response, in Account account, in String[] features); void getAccountsByFeatures(in IAccountManagerResponse response, String accountType, in String[] features); diff --git a/core/java/android/app/admin/DevicePolicyManager.java b/core/java/android/app/admin/DevicePolicyManager.java index 8284b2c0a5e7b..17e8dd9680068 100644 --- a/core/java/android/app/admin/DevicePolicyManager.java +++ b/core/java/android/app/admin/DevicePolicyManager.java @@ -1537,14 +1537,21 @@ public class DevicePolicyManager { return false; } + /** - * Used to determine if a particular package has been registered as a Device Owner admin. - * Device Owner admins cannot be deactivated by the user unless the Device Owner itself allows - * it. And Device Owner packages cannot be uninstalled, once registered. - * @param packageName the package name to check against the registered device owner. - * @return whether or not the package is registered as the Device Owner. + * Used to determine if a particular package has been registered as a Device Owner app. + * A device owner app is a special device admin that cannot be deactivated by the user, once + * activated as a device admin. It also cannot be uninstalled. To check if a particular + * package is currently registered as the device owner app, pass in the package name from + * {@link Context#getPackageName()} to this method.

This is useful for device + * admin apps that want to check if they are also registered as the device owner app. The + * exact mechanism by which a device admin app is registered as a device owner app is defined by + * the setup process. + * @param packageName the package name of the app, to compare with the registered device owner + * app, if any. + * @return whether or not the package is registered as the device owner app. */ - public boolean isDeviceOwner(String packageName) { + public boolean isDeviceOwnerApp(String packageName) { if (mService != null) { try { return mService.isDeviceOwner(packageName); @@ -1555,6 +1562,14 @@ public class DevicePolicyManager { return false; } + /** + * @hide + * Redirect to isDeviceOwnerApp. + */ + public boolean isDeviceOwner(String packageName) { + return isDeviceOwnerApp(packageName); + } + /** @hide */ public String getDeviceOwner() { if (mService != null) { diff --git a/core/java/android/content/Intent.java b/core/java/android/content/Intent.java index 1ab1eb8e90aad..67bd952c3534d 100644 --- a/core/java/android/content/Intent.java +++ b/core/java/android/content/Intent.java @@ -2425,8 +2425,8 @@ public class Intent implements Parcelable, Cloneable { * which is of type ArrayList<RestrictionEntry>. It can also * contain an extra {@link #EXTRA_RESTRICTIONS_INTENT}, which is of type Intent. * The activity specified by that intent will be launched for a result which must contain - * the extra {@link #EXTRA_RESTRICTIONS_LIST}. The keys and values of the returned restrictions - * will be persisted. + * one of the extras {@link #EXTRA_RESTRICTIONS_LIST} or {@link #EXTRA_RESTRICTIONS_BUNDLE}. + * The keys and values of the returned restrictions will be persisted. * @see RestrictionEntry */ public static final String ACTION_GET_RESTRICTION_ENTRIES = diff --git a/services/java/com/android/server/accounts/AccountManagerService.java b/services/java/com/android/server/accounts/AccountManagerService.java index fd7cd784aa9b5..241b224807fba 100644 --- a/services/java/com/android/server/accounts/AccountManagerService.java +++ b/services/java/com/android/server/accounts/AccountManagerService.java @@ -30,6 +30,7 @@ import android.accounts.IAccountManager; import android.accounts.IAccountManagerResponse; import android.app.ActivityManager; import android.app.ActivityManagerNative; +import android.app.AppGlobals; import android.app.Notification; import android.app.NotificationManager; import android.app.PendingIntent; @@ -1874,6 +1875,20 @@ public class AccountManagerService return getAccountsAsUser(null, UserHandle.getCallingUserId(), packageName, uid); } + @Override + public Account[] getAccountsByTypeForPackage(String type, String packageName) { + checkBinderPermission(android.Manifest.permission.INTERACT_ACROSS_USERS); + int packageUid = -1; + try { + packageUid = AppGlobals.getPackageManager().getPackageUid( + packageName, UserHandle.getCallingUserId()); + } catch (RemoteException re) { + Slog.e(TAG, "Couldn't determine the packageUid for " + packageName + re); + return new Account[0]; + } + return getAccountsAsUser(type, UserHandle.getCallingUserId(), packageName, packageUid); + } + public void getAccountsByFeatures(IAccountManagerResponse response, String type, String[] features) { if (Log.isLoggable(TAG, Log.VERBOSE)) {