- add javadoc for the account manager
- add some checks to the AccountManagerService to keep it from crashing when a null is passed in
- cleaned up the API a bit
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 3a11cb3..9c60141 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -154,6 +154,7 @@
     private static final boolean isDebuggableMonkeyBuild =
             SystemProperties.getBoolean("ro.monkey", false)
                     && SystemProperties.getBoolean("ro.debuggable", false);
+    private static final Account[] EMPTY_ACCOUNT_ARRAY = new Account[]{};
 
     static {
         ACCOUNTS_CHANGED_INTENT = new Intent(AccountManager.LOGIN_ACCOUNTS_CHANGED_ACTION);
@@ -268,6 +269,10 @@
     }
 
     private String readPasswordFromDatabase(Account account) {
+        if (account == null) {
+            return null;
+        }
+
         SQLiteDatabase db = mOpenHelper.getReadableDatabase();
         Cursor cursor = db.query(TABLE_ACCOUNTS, new String[]{ACCOUNTS_PASSWORD},
                 ACCOUNTS_NAME + "=? AND " + ACCOUNTS_TYPE+ "=?",
@@ -293,6 +298,10 @@
     }
 
     private String readUserDataFromDatabase(Account account, String key) {
+        if (account == null) {
+            return null;
+        }
+
         SQLiteDatabase db = mOpenHelper.getReadableDatabase();
         Cursor cursor = db.query(TABLE_EXTRAS, new String[]{EXTRAS_VALUE},
                 EXTRAS_ACCOUNTS_ID
@@ -364,6 +373,9 @@
         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
         db.beginTransaction();
         try {
+            if (account == null) {
+                return false;
+            }
             boolean noBroadcast = false;
             if (account.type.equals(GOOGLE_ACCOUNT_TYPE)) {
                 // Look for the 'nobroadcast' flag and remove it since we don't want it to persist
@@ -417,6 +429,14 @@
         checkManageAccountsPermission();
         long identityToken = clearCallingIdentity();
         try {
+            if (account == null) {
+                try {
+                    response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS, "null account");
+                } catch (RemoteException e) {
+                    // it doesn't matter if we are unable to deliver this error
+                }
+                return;
+            }
             new RemoveAccountSession(response, account).bind();
         } finally {
             restoreCallingIdentity(identityToken);
@@ -513,6 +533,9 @@
     }
 
     private boolean saveAuthTokenToDatabase(Account account, String type, String authToken) {
+        if (account == null || type == null) {
+            return false;
+        }
         cancelNotification(getSigninRequiredNotificationId(account));
         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
         db.beginTransaction();
@@ -539,6 +562,9 @@
     }
 
     public String readAuthTokenFromDatabase(Account account, String authTokenType) {
+        if (account == null || authTokenType == null) {
+            return null;
+        }
         SQLiteDatabase db = mOpenHelper.getReadableDatabase();
         Cursor cursor = db.query(TABLE_AUTHTOKENS, new String[]{AUTHTOKENS_AUTHTOKEN},
                 AUTHTOKENS_ACCOUNTS_ID + "=(select _id FROM accounts WHERE name=? AND type=?) AND "
@@ -586,6 +612,9 @@
     }
 
     private void setPasswordInDB(Account account, String password) {
+        if (account == null) {
+            return;
+        }
         ContentValues values = new ContentValues();
         values.put(ACCOUNTS_PASSWORD, password);
         mOpenHelper.getWritableDatabase().update(TABLE_ACCOUNTS, values,
@@ -608,23 +637,12 @@
         }
     }
 
-    private void sendResult(IAccountManagerResponse response, Bundle bundle) {
-        if (response != null) {
-            try {
-                response.onResult(bundle);
-            } catch (RemoteException e) {
-                // if the caller is dead then there is no one to care about remote
-                // exceptions
-                if (Log.isLoggable(TAG, Log.VERBOSE)) {
-                    Log.v(TAG, "failure while notifying response", e);
-                }
-            }
-        }
-    }
-
     public void setUserData(Account account, String key, String value) {
         checkAuthenticateAccountsPermission(account);
         long identityToken = clearCallingIdentity();
+        if (account == null) {
+            return;
+        }
         if (account.type.equals(GOOGLE_ACCOUNT_TYPE) && key.equals("broadcast")) {
             sendAccountsChangedBroadcast();
             return;
@@ -637,6 +655,9 @@
     }
 
     private void writeUserdataIntoDatabase(Account account, String key, String value) {
+        if (account == null || key == null) {
+            return;
+        }
         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
         db.beginTransaction();
         try {
@@ -685,6 +706,22 @@
 
         long identityToken = clearCallingIdentity();
         try {
+            try {
+                if (account == null) {
+                    response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS,
+                            "account is null");
+                    return;
+                }
+                if (authTokenType == null) {
+                    response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS,
+                            "authTokenType is null");
+                    return;
+                }
+            } catch (RemoteException e) {
+                // it doesn't matter if we can't deliver this error
+                return;
+            }
+
             // if the caller has permission, do the peek. otherwise go the more expensive
             // route of starting a Session
             if (permissionGranted) {
@@ -850,6 +887,16 @@
         checkManageAccountsPermission();
         long identityToken = clearCallingIdentity();
         try {
+            try {
+                if (authTokenType == null) {
+                    response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS,
+                            "authTokenType is null");
+                    return;
+                }
+            } catch (RemoteException e) {
+                // it doesn't matter if we can't deliver this error
+                return;
+            }
             new Session(response, accountType, expectActivityLaunch) {
                 public void run() throws RemoteException {
                     mAuthenticator.addAccount(this, mAccountType, authTokenType, requiredFeatures,
@@ -875,6 +922,16 @@
         checkManageAccountsPermission();
         long identityToken = clearCallingIdentity();
         try {
+            try {
+                if (account == null) {
+                    response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS,
+                            "account is null");
+                    return;
+                }
+            } catch (RemoteException e) {
+                // it doesn't matter if we can't deliver this error
+                return;
+            }
             new Session(response, account.type, expectActivityLaunch) {
                 public void run() throws RemoteException {
                     mAuthenticator.confirmCredentials(this, account, options);
@@ -895,6 +952,16 @@
         checkManageAccountsPermission();
         long identityToken = clearCallingIdentity();
         try {
+            try {
+                if (account == null) {
+                    response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS,
+                            "account is null");
+                    return;
+                }
+            } catch (RemoteException e) {
+                // it doesn't matter if we can't deliver this error
+                return;
+            }
             new Session(response, account.type, expectActivityLaunch) {
                 public void run() throws RemoteException {
                     mAuthenticator.updateCredentials(this, account, authTokenType, loginOptions);
@@ -917,6 +984,16 @@
         checkManageAccountsPermission();
         long identityToken = clearCallingIdentity();
         try {
+            try {
+                if (accountType == null) {
+                    response.onError(AccountManager.ERROR_CODE_BAD_ARGUMENTS,
+                            "accountType is null");
+                    return;
+                }
+            } catch (RemoteException e) {
+                // it doesn't matter if we can't deliver this error
+                return;
+            }
             new Session(response, accountType, expectActivityLaunch) {
                 public void run() throws RemoteException {
                     mAuthenticator.editProperties(this, mAccountType);
@@ -1565,8 +1642,10 @@
     }
 
     private boolean permissionIsGranted(Account account, String authTokenType, int callerUid) {
-        final boolean fromAuthenticator = hasAuthenticatorUid(account.type, callerUid);
-        final boolean hasExplicitGrants = hasExplicitlyGrantedPermission(account, authTokenType);
+        final boolean fromAuthenticator = account != null
+                && hasAuthenticatorUid(account.type, callerUid);
+        final boolean hasExplicitGrants = account != null
+                && hasExplicitlyGrantedPermission(account, authTokenType);
         if (Log.isLoggable(TAG, Log.VERBOSE)) {
             Log.v(TAG, "checkGrantsOrCallingUidAgainstAuthenticator: caller uid "
                     + callerUid + ", account " + account
@@ -1610,7 +1689,7 @@
 
     private void checkCallingUidAgainstAuthenticator(Account account) {
         final int uid = Binder.getCallingUid();
-        if (!hasAuthenticatorUid(account.type, uid)) {
+        if (account == null || !hasAuthenticatorUid(account.type, uid)) {
             String msg = "caller uid " + uid + " is different than the authenticator's uid";
             Log.w(TAG, msg);
             throw new SecurityException(msg);
@@ -1641,6 +1720,9 @@
      * @hide
      */
     public void grantAppPermission(Account account, String authTokenType, int uid) {
+        if (account == null  || authTokenType == null) {
+            return;
+        }
         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
         db.beginTransaction();
         try {
@@ -1668,6 +1750,9 @@
      * @hide
      */
     public void revokeAppPermission(Account account, String authTokenType, int uid) {
+        if (account == null  || authTokenType == null) {
+            return;
+        }
         SQLiteDatabase db = mOpenHelper.getWritableDatabase();
         db.beginTransaction();
         try {