Add an updateAppPermission() API call to the AccountManagerService AIDL
and have the GrantCredentialsPermissionActivity call that instead of a
static so that it can be made to run in a different process than the
AccountManagerService. Protect this call by checking that the caller
has the same UID as the system process.

Bug: 6545417
Change-Id: I295e65cad68883349a47e7927c171af45c89b229
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 2b643c2..ad4b58f 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -985,21 +985,25 @@
         }
     }
 
-    void getAuthTokenLabel(final IAccountManagerResponse response,
-            final Account account,
-            final String authTokenType, int uid) {
-        if (account == null) throw new IllegalArgumentException("account is null");
+    public void getAuthTokenLabel(IAccountManagerResponse response, final String accountType,
+                                  final String authTokenType)
+            throws RemoteException {
+        if (accountType == null) throw new IllegalArgumentException("accountType is null");
         if (authTokenType == null) throw new IllegalArgumentException("authTokenType is null");
 
-        checkBinderPermission(Manifest.permission.USE_CREDENTIALS);
-        UserAccounts accounts = getUserAccounts(UserId.getUserId(uid));
+        final int callingUid = getCallingUid();
+        clearCallingIdentity();
+        if (callingUid != android.os.Process.SYSTEM_UID) {
+            throw new SecurityException("can only call from system");
+        }
+        UserAccounts accounts = getUserAccounts(UserId.getUserId(callingUid));
         long identityToken = clearCallingIdentity();
         try {
-            new Session(accounts, response, account.type, false,
+            new Session(accounts, response, accountType, false,
                     false /* stripAuthTokenFromResult */) {
                 protected String toDebugString(long now) {
                     return super.toDebugString(now) + ", getAuthTokenLabel"
-                            + ", " + account
+                            + ", " + accountType
                             + ", authTokenType " + authTokenType;
                 }
 
@@ -2230,6 +2234,21 @@
                 Manifest.permission.USE_CREDENTIALS);
     }
 
+    public void updateAppPermission(Account account, String authTokenType, int uid, boolean value)
+            throws RemoteException {
+        final int callingUid = getCallingUid();
+
+        if (callingUid != android.os.Process.SYSTEM_UID) {
+            throw new SecurityException();
+        }
+
+        if (value) {
+            grantAppPermission(account, authTokenType, uid);
+        } else {
+            revokeAppPermission(account, authTokenType, uid);
+        }
+    }
+
     /**
      * Allow callers with the given uid permission to get credentials for account/authTokenType.
      * <p>
@@ -2237,7 +2256,7 @@
      * which is in the system. This means we don't need to protect it with permissions.
      * @hide
      */
-    public void grantAppPermission(Account account, String authTokenType, int uid) {
+    private void grantAppPermission(Account account, String authTokenType, int uid) {
         if (account == null || authTokenType == null) {
             Log.e(TAG, "grantAppPermission: called with invalid arguments", new Exception());
             return;
@@ -2271,7 +2290,7 @@
      * which is in the system. This means we don't need to protect it with permissions.
      * @hide
      */
-    public void revokeAppPermission(Account account, String authTokenType, int uid) {
+    private void revokeAppPermission(Account account, String authTokenType, int uid) {
         if (account == null || authTokenType == null) {
             Log.e(TAG, "revokeAppPermission: called with invalid arguments", new Exception());
             return;