From 63b90f28858b9d259a1d4a145f51bdd36ada8730 Mon Sep 17 00:00:00 2001 From: Dianne Hackborn Date: Tue, 29 Sep 2009 16:14:59 -0700 Subject: [PATCH] Fix issue #2153749: Window manager deadlock around the Eclair lock screen Don't synchronously call into the account manager from the lock screen. Change-Id: I2741c81bb31537ddfcce96b1b199ac50fd48e727 --- .../policy/impl/LockPatternKeyguardView.java | 50 +++++++++++++------ .../internal/policy/impl/UnlockScreen.java | 10 ++-- 2 files changed, 40 insertions(+), 20 deletions(-) diff --git a/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java index 7a81c056b7328..b5add64834448 100644 --- a/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java +++ b/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java @@ -20,7 +20,12 @@ import com.android.internal.R; import com.android.internal.telephony.IccCard; import com.android.internal.widget.LockPatternUtils; +import android.accounts.Account; import android.accounts.AccountManager; +import android.accounts.AccountManagerCallback; +import android.accounts.AccountManagerFuture; +import android.accounts.AuthenticatorException; +import android.accounts.OperationCanceledException; import android.app.AlertDialog; import android.content.Context; import android.content.Intent; @@ -37,6 +42,8 @@ import android.view.KeyEvent; import android.view.View; import android.view.WindowManager; +import java.io.IOException; + /** * The host view for all of the screens of the pattern unlock screen. There are * two {@link Mode}s of operation, lock and unlock. This will show the appropriate @@ -48,7 +55,8 @@ import android.view.WindowManager; * {@link com.android.internal.policy.impl.KeyguardViewManager} * via its {@link com.android.internal.policy.impl.KeyguardViewCallback}, as appropriate. */ -public class LockPatternKeyguardView extends KeyguardViewBase { +public class LockPatternKeyguardView extends KeyguardViewBase + implements AccountManagerCallback { // intent action for launching emergency dialer activity. static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL"; @@ -141,6 +149,22 @@ public class LockPatternKeyguardView extends KeyguardViewBase { && (mUpdateMonitor.getSimState() == IccCard.State.ABSENT); } + public void run(AccountManagerFuture future) { + // We err on the side of caution. + // In case of error we assume we have a SAML account. + boolean hasSAMLAccount = true; + try { + hasSAMLAccount = future.getResult().length > 0; + } catch (OperationCanceledException e) { + } catch (IOException e) { + } catch (AuthenticatorException e) { + } + mEnableFallback = !hasSAMLAccount; + if (mUnlockScreen instanceof UnlockScreen) { + ((UnlockScreen)mUnlockScreen).setEnableFallback(true); + } + } + /** * @param context Used to inflate, and create views. * @param updateMonitor Knows the state of the world, and passed along to each @@ -156,25 +180,18 @@ public class LockPatternKeyguardView extends KeyguardViewBase { super(context); final boolean hasAccount = AccountManager.get(context).getAccounts().length > 0; - boolean hasSAMLAccount = false; if (hasAccount) { /* If we have a SAML account which requires web login we can not use the fallback screen UI to ask the user for credentials. For now we will disable fallback screen in this case. Ultimately we could consider bringing up a web login from GLS but need to make sure that it will work in the "locked screen" mode. */ - try { - String[] features = new String[] {"saml"}; - hasSAMLAccount = - AccountManager.get(context).getAccountsByTypeAndFeatures( - "com.google.GAIA", features, null, null).getResult().length > 0; - } catch (Exception e) { - // We err on the side of caution. - // In case of error we assume we have a SAML account. - hasSAMLAccount = true; - } + String[] features = new String[] {"saml"}; + AccountManager.get(context).getAccountsByTypeAndFeatures( + "com.google.GAIA", features, this, null); } - mEnableFallback = hasAccount && !hasSAMLAccount; + + mEnableFallback = false; mRequiresSim = TextUtils.isEmpty(SystemProperties.get("keyguard.no_require_sim")); @@ -452,13 +469,14 @@ public class LockPatternKeyguardView extends KeyguardViewBase { View createUnlockScreenFor(UnlockMode unlockMode) { if (unlockMode == UnlockMode.Pattern) { - return new UnlockScreen( + UnlockScreen view = new UnlockScreen( mContext, mLockPatternUtils, mUpdateMonitor, mKeyguardScreenCallback, - mUpdateMonitor.getFailedAttempts(), - mEnableFallback); + mUpdateMonitor.getFailedAttempts()); + view.setEnableFallback(mEnableFallback); + return view; } else if (unlockMode == UnlockMode.SimPin) { return new SimUnlockScreen( mContext, diff --git a/policy/com/android/internal/policy/impl/UnlockScreen.java b/policy/com/android/internal/policy/impl/UnlockScreen.java index 915e6ab40e24f..a5032b3ae0c56 100644 --- a/policy/com/android/internal/policy/impl/UnlockScreen.java +++ b/policy/com/android/internal/policy/impl/UnlockScreen.java @@ -67,7 +67,7 @@ class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient /** * whether there is a fallback option available when the pattern is forgotten. */ - private final boolean mEnableFallback; + private boolean mEnableFallback; private boolean mCreatedInPortrait; @@ -154,14 +154,12 @@ class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient LockPatternUtils lockPatternUtils, KeyguardUpdateMonitor updateMonitor, KeyguardScreenCallback callback, - int totalFailedAttempts, - boolean enableFallback) { + int totalFailedAttempts) { super(context); mLockPatternUtils = lockPatternUtils; mUpdateMonitor = updateMonitor; mCallback = callback; mTotalFailedPatternAttempts = totalFailedAttempts; - mEnableFallback = enableFallback; mFailedPatternAttemptsSinceLastTimeout = totalFailedAttempts % LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT; if (mUpdateMonitor.isInPortrait()) { @@ -242,6 +240,10 @@ class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient mUpdateMonitor.getTelephonySpn())); } + public void setEnableFallback(boolean state) { + mEnableFallback = state; + } + private void resetStatusInfo() { mInstructions = null; mShowingBatteryInfo = mUpdateMonitor.shouldShowBatteryInfo();