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
diff --git a/api/current.txt b/api/current.txt
index 6eb8545..15c75e1 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2193,6 +2193,7 @@
     method public android.accounts.Account[] getAccounts();
     method public android.accounts.Account[] getAccountsByType(java.lang.String);
     method public android.accounts.AccountManagerFuture<android.accounts.Account[]> getAccountsByTypeAndFeatures(java.lang.String, java.lang.String[], android.accounts.AccountManagerCallback<android.accounts.Account[]>, android.os.Handler);
+    method public android.accounts.Account[] getAccountsByTypeForPackage(java.lang.String, java.lang.String);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, java.lang.String, android.os.Bundle, android.app.Activity, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public deprecated android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, java.lang.String, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
     method public android.accounts.AccountManagerFuture<android.os.Bundle> getAuthToken(android.accounts.Account, java.lang.String, android.os.Bundle, boolean, android.accounts.AccountManagerCallback<android.os.Bundle>, android.os.Handler);
@@ -4353,7 +4354,7 @@
     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 241a64a..b4a12c4 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -405,6 +405,23 @@
     }
 
     /**
+     * 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
      * of the account.  For example, there are types corresponding to Google
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl
index 8141813..86e279f 100644
--- a/core/java/android/accounts/IAccountManager.aidl
+++ b/core/java/android/accounts/IAccountManager.aidl
@@ -32,6 +32,7 @@
     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 8284b2c..17e8dd9 100644
--- a/core/java/android/app/admin/DevicePolicyManager.java
+++ b/core/java/android/app/admin/DevicePolicyManager.java
@@ -1537,14 +1537,21 @@
         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.<p/>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 @@
         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 1ab1eb8..67bd952 100644
--- a/core/java/android/content/Intent.java
+++ b/core/java/android/content/Intent.java
@@ -2425,8 +2425,8 @@
      * which is of type <code>ArrayList&lt;RestrictionEntry&gt;</code>. It can also
      * contain an extra {@link #EXTRA_RESTRICTIONS_INTENT}, which is of type <code>Intent</code>.
      * 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 fd7cd78..241b224 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.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 @@
         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)) {