summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAmith Yamasani <yamasani@google.com>2012-11-05 16:46:02 -0800
committerAmith Yamasani <yamasani@google.com>2012-11-05 18:17:40 -0800
commit2c7bc26a7447e6ac9eadcf328259aa3bb1be2949 (patch)
tree2340b52ccf515fa1e44931c57b6569e742b9dd27
parent37238e5a4e10c5c5439f6864dd19049a5544e01a (diff)
downloadframeworks_base-2c7bc26a7447e6ac9eadcf328259aa3bb1be2949.zip
frameworks_base-2c7bc26a7447e6ac9eadcf328259aa3bb1be2949.tar.gz
frameworks_base-2c7bc26a7447e6ac9eadcf328259aa3bb1be2949.tar.bz2
Authenticate correct user's account when pattern fails multiple times.
Bug: 7473142 Provide hidden methods in AccountManager for querying accounts and authenticating for a specific user. Lockscreen is running in the system process. Allow only system process to access accounts across users. Also make sure to launch the lock settings screen on the just reset user using startActivityAsUser() Change-Id: Ifefc0039ba2b51396b8bd0268f36d5271a3d8676
-rw-r--r--core/java/android/accounts/AccountManager.java28
-rw-r--r--core/java/android/accounts/AccountManagerService.java32
-rw-r--r--core/java/android/accounts/IAccountManager.aidl5
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java11
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java7
5 files changed, 67 insertions, 16 deletions
diff --git a/core/java/android/accounts/AccountManager.java b/core/java/android/accounts/AccountManager.java
index f3c6566..bcb35d5 100644
--- a/core/java/android/accounts/AccountManager.java
+++ b/core/java/android/accounts/AccountManager.java
@@ -28,6 +28,8 @@ import android.os.Looper;
import android.os.RemoteException;
import android.os.Parcelable;
import android.os.Build;
+import android.os.Process;
+import android.os.UserHandle;
import android.util.Log;
import android.text.TextUtils;
@@ -42,7 +44,6 @@ import java.util.concurrent.TimeUnit;
import java.util.HashMap;
import java.util.Map;
-import com.google.android.collect.Lists;
import com.google.android.collect.Maps;
/**
@@ -396,8 +397,13 @@ public class AccountManager {
* (never null) if no accounts of the specified type have been added.
*/
public Account[] getAccountsByType(String type) {
+ return getAccountsByTypeAsUser(type, Process.myUserHandle());
+ }
+
+ /** @hide Same as {@link #getAccountsByType(String)} but for a specific user. */
+ public Account[] getAccountsByTypeAsUser(String type, UserHandle userHandle) {
try {
- return mService.getAccounts(type);
+ return mService.getAccountsAsUser(type, userHandle.getIdentifier());
} catch (RemoteException e) {
// won't ever happen
throw new RuntimeException(e);
@@ -1175,10 +1181,26 @@ public class AccountManager {
final Activity activity,
final AccountManagerCallback<Bundle> callback,
final Handler handler) {
+ return confirmCredentialsAsUser(account, options, activity, callback, handler,
+ Process.myUserHandle());
+ }
+
+ /**
+ * @hide
+ * Same as {@link #confirmCredentials(Account, Bundle, Activity, AccountManagerCallback, Handler)}
+ * but for the specified user.
+ */
+ public AccountManagerFuture<Bundle> confirmCredentialsAsUser(final Account account,
+ final Bundle options,
+ final Activity activity,
+ final AccountManagerCallback<Bundle> callback,
+ final Handler handler, UserHandle userHandle) {
if (account == null) throw new IllegalArgumentException("account is null");
+ final int userId = userHandle.getIdentifier();
return new AmsTask(activity, handler, callback) {
public void doWork() throws RemoteException {
- mService.confirmCredentials(mResponse, account, options, activity != null);
+ mService.confirmCredentialsAsUser(mResponse, account, options, activity != null,
+ userId);
}
}.start();
}
diff --git a/core/java/android/accounts/AccountManagerService.java b/core/java/android/accounts/AccountManagerService.java
index 03e0c0f..2b1a2b2 100644
--- a/core/java/android/accounts/AccountManagerService.java
+++ b/core/java/android/accounts/AccountManagerService.java
@@ -1297,8 +1297,17 @@ public class AccountManagerService
}
}
- public void confirmCredentials(IAccountManagerResponse response,
- final Account account, final Bundle options, final boolean expectActivityLaunch) {
+ @Override
+ public void confirmCredentialsAsUser(IAccountManagerResponse response,
+ final Account account, final Bundle options, final boolean expectActivityLaunch,
+ int userId) {
+ // Only allow the system process to read accounts of other users
+ if (userId != UserHandle.getCallingUserId()
+ && Binder.getCallingUid() != android.os.Process.myUid()) {
+ throw new SecurityException("User " + UserHandle.getCallingUserId()
+ + " trying to confirm account credentials for " + userId);
+ }
+
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "confirmCredentials: " + account
+ ", response " + response
@@ -1309,7 +1318,7 @@ public class AccountManagerService
if (response == null) throw new IllegalArgumentException("response is null");
if (account == null) throw new IllegalArgumentException("account is null");
checkManageAccountsPermission();
- UserAccounts accounts = getUserAccountsForCaller();
+ UserAccounts accounts = getUserAccounts(userId);
long identityToken = clearCallingIdentity();
try {
new Session(accounts, response, account.type, expectActivityLaunch,
@@ -1548,14 +1557,22 @@ public class AccountManagerService
return runningAccounts.toArray(accountsArray);
}
- public Account[] getAccounts(String type) {
+ @Override
+ public Account[] getAccountsAsUser(String type, int userId) {
+ // Only allow the system process to read accounts of other users
+ if (userId != UserHandle.getCallingUserId()
+ && Binder.getCallingUid() != android.os.Process.myUid()) {
+ throw new SecurityException("User " + UserHandle.getCallingUserId()
+ + " trying to get account for " + userId);
+ }
+
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "getAccounts: accountType " + type
+ ", caller's uid " + Binder.getCallingUid()
+ ", pid " + Binder.getCallingPid());
}
checkReadAccountsPermission();
- UserAccounts accounts = getUserAccountsForCaller();
+ UserAccounts accounts = getUserAccounts(userId);
long identityToken = clearCallingIdentity();
try {
synchronized (accounts.cacheLock) {
@@ -1566,6 +1583,11 @@ public class AccountManagerService
}
}
+ @Override
+ public Account[] getAccounts(String type) {
+ return getAccountsAsUser(type, UserHandle.getCallingUserId());
+ }
+
public void getAccountsByFeatures(IAccountManagerResponse response,
String type, String[] features) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
diff --git a/core/java/android/accounts/IAccountManager.aidl b/core/java/android/accounts/IAccountManager.aidl
index 6007321..dbb4924 100644
--- a/core/java/android/accounts/IAccountManager.aidl
+++ b/core/java/android/accounts/IAccountManager.aidl
@@ -31,6 +31,7 @@ interface IAccountManager {
String getUserData(in Account account, String key);
AuthenticatorDescription[] getAuthenticatorTypes();
Account[] getAccounts(String accountType);
+ 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);
boolean addAccount(in Account account, String password, in Bundle extras);
@@ -53,8 +54,8 @@ interface IAccountManager {
String authTokenType, boolean expectActivityLaunch, in Bundle options);
void editProperties(in IAccountManagerResponse response, String accountType,
boolean expectActivityLaunch);
- void confirmCredentials(in IAccountManagerResponse response, in Account account,
- in Bundle options, boolean expectActivityLaunch);
+ void confirmCredentialsAsUser(in IAccountManagerResponse response, in Account account,
+ in Bundle options, boolean expectActivityLaunch, int userId);
void getAuthTokenLabel(in IAccountManagerResponse response, String accountType,
String authTokenType);
}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java
index 9c87755..c487ddf 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardAccountView.java
@@ -27,6 +27,7 @@ import android.content.Context;
import android.content.Intent;
import android.graphics.Rect;
import android.os.Bundle;
+import android.os.UserHandle;
import android.text.Editable;
import android.text.InputFilter;
import android.text.LoginFilter;
@@ -175,7 +176,8 @@ public class KeyguardAccountView extends LinearLayout implements KeyguardSecurit
Intent intent = new Intent();
intent.setClassName(LOCK_PATTERN_PACKAGE, LOCK_PATTERN_CLASS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
- mContext.startActivity(intent);
+ mContext.startActivityAsUser(intent,
+ new UserHandle(mLockPatternUtils.getCurrentUser()));
mCallback.reportSuccessfulUnlockAttempt();
// dismiss keyguard
@@ -220,7 +222,8 @@ public class KeyguardAccountView extends LinearLayout implements KeyguardSecurit
* find a single best match.
*/
private Account findIntendedAccount(String username) {
- Account[] accounts = AccountManager.get(mContext).getAccountsByType("com.google");
+ Account[] accounts = AccountManager.get(mContext).getAccountsByTypeAsUser("com.google",
+ new UserHandle(mLockPatternUtils.getCurrentUser()));
// Try to figure out which account they meant if they
// typed only the username (and not the domain), or got
@@ -267,7 +270,7 @@ public class KeyguardAccountView extends LinearLayout implements KeyguardSecurit
getProgressDialog().show();
Bundle options = new Bundle();
options.putString(AccountManager.KEY_PASSWORD, password);
- AccountManager.get(mContext).confirmCredentials(account, options, null /* activity */,
+ AccountManager.get(mContext).confirmCredentialsAsUser(account, options, null /* activity */,
new AccountManagerCallback<Bundle>() {
public void run(AccountManagerFuture<Bundle> future) {
try {
@@ -289,7 +292,7 @@ public class KeyguardAccountView extends LinearLayout implements KeyguardSecurit
});
}
}
- }, null /* handler */);
+ }, null /* handler */, new UserHandle(mLockPatternUtils.getCurrentUser()));
}
private Dialog getProgressDialog() {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java
index 82cb44b..52768d2 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardPatternView.java
@@ -26,6 +26,7 @@ import android.graphics.Rect;
import android.os.Bundle;
import android.os.CountDownTimer;
import android.os.SystemClock;
+import android.os.UserHandle;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
@@ -287,7 +288,8 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
private AccountAnalyzer(AccountManager accountManager) {
mAccountManager = accountManager;
- mAccounts = accountManager.getAccountsByType("com.google");
+ mAccounts = accountManager.getAccountsByTypeAsUser("com.google",
+ new UserHandle(mLockPatternUtils.getCurrentUser()));
}
private void next() {
@@ -298,7 +300,8 @@ public class KeyguardPatternView extends LinearLayout implements KeyguardSecurit
}
// lookup the confirmCredentials intent for the current account
- mAccountManager.confirmCredentials(mAccounts[mAccountIndex], null, null, this, null);
+ mAccountManager.confirmCredentialsAsUser(mAccounts[mAccountIndex], null, null, this,
+ null, new UserHandle(mLockPatternUtils.getCurrentUser()));
}
public void start() {