merge from open-source master
diff --git a/policy/com/android/internal/policy/impl/AccountUnlockScreen.java b/policy/com/android/internal/policy/impl/AccountUnlockScreen.java
index 65102c6..098a651 100644
--- a/policy/com/android/internal/policy/impl/AccountUnlockScreen.java
+++ b/policy/com/android/internal/policy/impl/AccountUnlockScreen.java
@@ -19,21 +19,15 @@
import com.android.internal.R;
import com.android.internal.widget.LockPatternUtils;
-import android.accounts.AccountsServiceConstants;
-import android.accounts.IAccountsService;
-import android.content.ComponentName;
+import android.accounts.Account;
+import android.accounts.AccountManager;
import android.content.Context;
import android.content.Intent;
-import android.content.ServiceConnection;
import android.graphics.Rect;
-import android.os.IBinder;
-import android.os.RemoteException;
import android.text.Editable;
import android.text.InputFilter;
import android.text.LoginFilter;
import android.text.TextWatcher;
-import android.text.TextUtils;
-import android.util.Log;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.View;
@@ -45,12 +39,9 @@
/**
* When the user forgets their password a bunch of times, we fall back on their
* account's login/password to unlock the phone (and reset their lock pattern).
- *
- * <p>This class is useful only on platforms that support the
- * IAccountsService.
*/
public class AccountUnlockScreen extends RelativeLayout implements KeyguardScreen,
- View.OnClickListener, ServiceConnection, TextWatcher {
+ View.OnClickListener, TextWatcher {
private static final String LOCK_PATTERN_PACKAGE = "com.android.settings";
private static final String LOCK_PATTERN_CLASS =
"com.android.settings.ChooseLockPattern";
@@ -62,7 +53,6 @@
private final KeyguardScreenCallback mCallback;
private final LockPatternUtils mLockPatternUtils;
- private IAccountsService mAccountsService;
private TextView mTopHeader;
private TextView mInstructions;
@@ -73,9 +63,6 @@
/**
* AccountUnlockScreen constructor.
- *
- * @throws IllegalStateException if the IAccountsService is not
- * available on the current platform.
*/
public AccountUnlockScreen(Context context,
KeyguardScreenCallback callback,
@@ -103,14 +90,6 @@
mEmergencyCall = (Button) findViewById(R.id.emergencyCall);
mEmergencyCall.setOnClickListener(this);
-
- Log.v("AccountUnlockScreen", "debug: Connecting to accounts service");
- final boolean connected = mContext.bindService(AccountsServiceConstants.SERVICE_INTENT,
- this, Context.BIND_AUTO_CREATE);
- if (!connected) {
- Log.v("AccountUnlockScreen", "debug: Couldn't connect to accounts service");
- throw new IllegalStateException("couldn't bind to accounts service");
- }
}
public void afterTextChanged(Editable s) {
@@ -150,7 +129,6 @@
/** {@inheritDoc} */
public void cleanUp() {
- mContext.unbindService(this);
}
/** {@inheritDoc} */
@@ -207,33 +185,25 @@
* @return an account name from the database, or null if we can't
* find a single best match.
*/
- private String findIntendedAccount(String username) {
- String[] accounts = null;
- try {
- accounts = mAccountsService.getAccounts();
- } catch (RemoteException e) {
- return null;
- }
- if (accounts == null) {
- return null;
- }
+ private Account findIntendedAccount(String username) {
+ Account[] accounts = AccountManager.get(mContext).blockingGetAccounts();
// Try to figure out which account they meant if they
// typed only the username (and not the domain), or got
// the case wrong.
- String bestAccount = null;
+ Account bestAccount = null;
int bestScore = 0;
- for (String a: accounts) {
+ for (Account a: accounts) {
int score = 0;
- if (username.equals(a)) {
+ if (username.equals(a.mName)) {
score = 4;
- } else if (username.equalsIgnoreCase(a)) {
+ } else if (username.equalsIgnoreCase(a.mName)) {
score = 3;
} else if (username.indexOf('@') < 0) {
- int i = a.indexOf('@');
+ int i = a.mName.indexOf('@');
if (i >= 0) {
- String aUsername = a.substring(0, i);
+ String aUsername = a.mName.substring(0, i);
if (username.equals(aUsername)) {
score = 2;
} else if (username.equalsIgnoreCase(aUsername)) {
@@ -254,25 +224,18 @@
private boolean checkPassword() {
final String login = mLogin.getText().toString();
final String password = mPassword.getText().toString();
- try {
- String account = findIntendedAccount(login);
- if (account == null) {
- return false;
- }
- return mAccountsService.shouldUnlock(account, password);
- } catch (RemoteException e) {
+ Account account = findIntendedAccount(login);
+ if (account == null) {
return false;
}
- }
-
- /** {@inheritDoc} */
- public void onServiceConnected(ComponentName name, IBinder service) {
- Log.v("AccountUnlockScreen", "debug: About to grab as interface");
- mAccountsService = IAccountsService.Stub.asInterface(service);
- }
-
- /** {@inheritDoc} */
- public void onServiceDisconnected(ComponentName name) {
- mAccountsService = null;
+ // TODO(fredq) change this to asynchronously issue the request and wait for the response (by
+ // supplying a callback rather than calling get() immediately)
+ try {
+ return AccountManager.get(mContext).confirmPassword(
+ account, password, null /* callback */, null /* handler */).getResult();
+ } catch (android.accounts.OperationCanceledException e) {
+ // the request was canceled
+ return false;
+ }
}
}
diff --git a/policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index cd21427..44e893b 100644
--- a/policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/policy/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -35,7 +35,6 @@
import static android.provider.Telephony.Intents.EXTRA_SPN;
import static android.provider.Telephony.Intents.SPN_STRINGS_UPDATED_ACTION;
-import com.android.internal.app.ShutdownThread;
import com.android.internal.telephony.IccCard;
import com.android.internal.telephony.TelephonyIntents;
import android.util.Log;
@@ -295,13 +294,6 @@
shouldShowBatteryInfo(), pluggedIn, batteryLevel);
}
}
-
- // shut down gracefully if our battery is critically low and we are not powered
- if (batteryLevel == 0 &&
- pluggedInStatus != BATTERY_STATUS_CHARGING &&
- pluggedInStatus != BATTERY_STATUS_UNKNOWN) {
- ShutdownThread.shutdown(mContext, false);
- }
}
/**
diff --git a/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 6a1c279..4294de4 100644
--- a/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -16,38 +16,36 @@
package com.android.internal.policy.impl;
-import android.accounts.AccountsServiceConstants;
-import android.accounts.IAccountsService;
+import com.android.internal.R;
+import com.android.internal.telephony.IccCard;
+import com.android.internal.widget.LockPatternUtils;
+
+import android.accounts.AccountManager;
import android.app.AlertDialog;
-import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
-import android.content.ServiceConnection;
-import android.os.IBinder;
-import android.os.RemoteException;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.ColorFilter;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.BitmapDrawable;
+import android.graphics.drawable.Drawable;
import android.os.SystemProperties;
-import com.android.internal.telephony.IccCard;
import android.text.TextUtils;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.view.WindowManager;
-import android.graphics.drawable.Drawable;
-import android.graphics.drawable.BitmapDrawable;
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-import android.graphics.PixelFormat;
-import android.graphics.ColorFilter;
-import com.android.internal.R;
-import com.android.internal.widget.LockPatternUtils;
/**
* 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
- * screen, and listen for callbacks via {@link com.android.internal.policy.impl.KeyguardScreenCallback
+ * screen, and listen for callbacks via
+ * {@link com.android.internal.policy.impl.KeyguardScreenCallback}
* from the current screen.
*
- * This view, in turn, communicates back to {@link com.android.internal.policy.impl.KeyguardViewManager}
+ * This view, in turn, communicates back to
+ * {@link com.android.internal.policy.impl.KeyguardViewManager}
* via its {@link com.android.internal.policy.impl.KeyguardViewCallback}, as appropriate.
*/
public class LockPatternKeyguardView extends KeyguardViewBase {
@@ -60,12 +58,12 @@
private final KeyguardUpdateMonitor mUpdateMonitor;
private final KeyguardWindowController mWindowController;
-
+
private View mLockScreen;
private View mUnlockScreen;
private boolean mScreenOn = false;
- private boolean mHasAccount = false; // assume they don't have an account until we know better
+ private boolean mEnableFallback = false; // assume no fallback UI until we know better
/**
@@ -131,11 +129,6 @@
private final LockPatternUtils mLockPatternUtils;
/**
- * Used to fetch accounts from GLS.
- */
- private ServiceConnection mServiceConnection;
-
- /**
* @return Whether we are stuck on the lock screen because the sim is
* missing.
*/
@@ -158,9 +151,28 @@
LockPatternUtils lockPatternUtils,
KeyguardWindowController controller) {
super(context);
-
- asyncCheckForAccount();
-
+
+ final boolean hasAccount = AccountManager.get(context).blockingGetAccounts().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 {
+ hasSAMLAccount =
+ AccountManager.get(context).blockingGetAccountsWithTypeAndFeatures(
+ "com.GOOGLE.GAIA", new String[] {"saml"}).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;
+ }
+ }
+ mEnableFallback = hasAccount && !hasSAMLAccount;
+
mRequiresSim =
TextUtils.isEmpty(SystemProperties.get("keyguard.no_require_sim"));
@@ -169,7 +181,7 @@
mWindowController = controller;
mMode = getInitialMode();
-
+
mKeyguardScreenCallback = new KeyguardScreenCallback() {
public void goToLockScreen() {
@@ -235,11 +247,11 @@
public void reportFailedPatternAttempt() {
mUpdateMonitor.reportFailedAttempt();
final int failedAttempts = mUpdateMonitor.getFailedAttempts();
- if (mHasAccount && failedAttempts ==
- (LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
+ if (mEnableFallback && failedAttempts ==
+ (LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET
- LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
showAlmostAtAccountLoginDialog();
- } else if (mHasAccount
+ } else if (mEnableFallback
&& failedAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_RESET) {
mLockPatternUtils.setPermanentlyLocked(true);
updateScreen(mMode);
@@ -248,9 +260,9 @@
showTimeoutDialog();
}
}
-
+
public boolean doesFallbackUnlockScreenExist() {
- return mHasAccount;
+ return mEnableFallback;
}
};
@@ -277,35 +289,6 @@
updateScreen(mMode);
}
- /**
- * Asynchronously checks for at least one account. This will set mHasAccount
- * to true if an account is found.
- */
- private void asyncCheckForAccount() {
-
- mServiceConnection = new ServiceConnection() {
- public void onServiceConnected(ComponentName className, IBinder service) {
- try {
- IAccountsService accountsService = IAccountsService.Stub.asInterface(service);
- String accounts[] = accountsService.getAccounts();
- mHasAccount = (accounts.length > 0);
- } catch (RemoteException e) {
- // Not much we can do here...
- Log.e(TAG, "Gls died while attempting to get accounts: " + e);
- } finally {
- getContext().unbindService(mServiceConnection);
- mServiceConnection = null;
- }
- }
-
- public void onServiceDisconnected(ComponentName className) {
- // nothing to do here
- }
- };
- boolean status = getContext().bindService(AccountsServiceConstants.SERVICE_INTENT,
- mServiceConnection, Context.BIND_AUTO_CREATE);
- if (!status) Log.e(TAG, "Failed to bind to GLS while checking for account");
- }
@Override
public void reset() {
@@ -423,7 +406,7 @@
// do this before changing visibility so focus isn't requested before the input
// flag is set
mWindowController.setNeedsInput(((KeyguardScreen)visibleScreen).needsInput());
-
+
if (mScreenOn) {
if (goneScreen.getVisibility() == View.VISIBLE) {
diff --git a/policy/com/android/internal/policy/impl/PhoneWindow.java b/policy/com/android/internal/policy/impl/PhoneWindow.java
index 6341771..345b620 100644
--- a/policy/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/com/android/internal/policy/impl/PhoneWindow.java
@@ -295,11 +295,9 @@
/* Custom title feature is enabled and the user is trying to enable another feature */
throw new AndroidRuntimeException("You cannot combine custom titles with other title features");
}
- /* FEATURE_OPENGL disabled for 1.0
if (featureId == FEATURE_OPENGL) {
getAttributes().memoryType = WindowManager.LayoutParams.MEMORY_TYPE_GPU;
}
- */
return super.requestFeature(featureId);
}
@@ -678,6 +676,10 @@
mPanelChordingKey = 0;
mKeycodeMenuTimeoutHandler.removeMessages(MSG_MENU_LONG_PRESS);
+ if (event.isCanceled()) {
+ return;
+ }
+
boolean playSoundEffect = false;
PanelFeatureState st = getPanelState(featureId, true);
if (st.isOpen || st.isHandled) {
@@ -1395,7 +1397,9 @@
mKeycodeMenuTimeoutHandler.removeMessages(MSG_CAMERA_LONG_PRESS);
if (!mKeycodeCameraTimeoutActive) break;
mKeycodeCameraTimeoutActive = false;
- // Add short press behavior here if desired
+ if (!event.isCanceled()) {
+ // Add short press behavior here if desired
+ }
return true;
}
@@ -1407,7 +1411,9 @@
mKeycodeMenuTimeoutHandler.removeMessages(MSG_CALL_LONG_PRESS);
if (!mKeycodeCallTimeoutActive) break;
mKeycodeCallTimeoutActive = false;
- startCallActivity();
+ if (!event.isCanceled()) {
+ startCallActivity();
+ }
return true;
}
@@ -1422,7 +1428,9 @@
break;
}
mSearchKeyDownReceived = false;
- launchDefaultSearch();
+ if (!event.isCanceled()) {
+ launchDefaultSearch();
+ }
return true;
}
}
diff --git a/policy/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/com/android/internal/policy/impl/PhoneWindowManager.java
index 8140b3d..8c0e95d 100644
--- a/policy/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -149,6 +149,9 @@
// Vibrator pattern for haptic feedback of a long press.
private static final long[] LONG_PRESS_VIBE_PATTERN = {0, 1, 20, 21};
+ // Vibrator pattern for haptic feedback of virtual key press.
+ private static final long[] VIRTUAL_KEY_VIBE_PATTERN = {0, 1, 20, 21};
+
final Object mLock = new Object();
Context mContext;
@@ -373,7 +376,7 @@
}
}
- Runnable mEndCallLongPress = new Runnable() {
+ Runnable mPowerLongPress = new Runnable() {
public void run() {
mShouldTurnOffOnKeyUp = false;
performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
@@ -775,7 +778,7 @@
/** {@inheritDoc} */
public boolean interceptKeyTi(WindowState win, int code, int metaKeys, boolean down,
- int repeatCount) {
+ int repeatCount, int flags) {
boolean keyguardOn = keyguardOn();
if (false) {
@@ -800,32 +803,36 @@
if (!down) {
mHomePressed = false;
- // If an incoming call is ringing, HOME is totally disabled.
- // (The user is already on the InCallScreen at this point,
- // and his ONLY options are to answer or reject the call.)
- boolean incomingRinging = false;
- try {
- ITelephony phoneServ = getPhoneInterface();
- if (phoneServ != null) {
- incomingRinging = phoneServ.isRinging();
- } else {
- Log.w(TAG, "Unable to find ITelephony interface");
+ if ((flags&KeyEvent.FLAG_CANCELED) == 0) {
+ // If an incoming call is ringing, HOME is totally disabled.
+ // (The user is already on the InCallScreen at this point,
+ // and his ONLY options are to answer or reject the call.)
+ boolean incomingRinging = false;
+ try {
+ ITelephony phoneServ = getPhoneInterface();
+ if (phoneServ != null) {
+ incomingRinging = phoneServ.isRinging();
+ } else {
+ Log.w(TAG, "Unable to find ITelephony interface");
+ }
+ } catch (RemoteException ex) {
+ Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
}
- } catch (RemoteException ex) {
- Log.w(TAG, "RemoteException from getPhoneInterface()", ex);
- }
-
- if (incomingRinging) {
- Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
+
+ if (incomingRinging) {
+ Log.i(TAG, "Ignoring HOME; there's a ringing incoming call.");
+ } else {
+ launchHomeFromHotKey();
+ }
} else {
- launchHomeFromHotKey();
+ Log.i(TAG, "Ignoring HOME; event canceled.");
}
}
}
return true;
}
-
+
// First we always handle the home key here, so applications
// can never break it, although if keyguard is on, we do let
// it handle it, because that gives us the correct 5 second
@@ -1365,17 +1372,12 @@
* @return Whether music is being played right now.
*/
boolean isMusicActive() {
- final IAudioService audio = getAudioInterface();
- if (audio == null) {
- Log.w(TAG, "isMusicActive: couldn't get IAudioService reference");
+ final AudioManager am = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
+ if (am == null) {
+ Log.w(TAG, "isMusicActive: couldn't get AudioManager reference");
return false;
}
- try {
- return audio.isMusicActive();
- } catch (RemoteException e) {
- Log.w(TAG, "IAudioService.isMusicActive() threw RemoteException " + e);
- return false;
- }
+ return am.isMusicActive();
}
/**
@@ -1475,33 +1477,36 @@
boolean down = event.value != 0;
if (type == RawInputEvent.EV_KEY) {
- if (code == KeyEvent.KEYCODE_ENDCALL) {
+ if (code == KeyEvent.KEYCODE_ENDCALL
+ || code == KeyEvent.KEYCODE_POWER) {
if (down) {
boolean hungUp = false;
// key repeats are generated by the window manager, and we don't see them
// here, so unless the driver is doing something it shouldn't be, we know
// this is the real press event.
- try {
- ITelephony phoneServ = getPhoneInterface();
- if (phoneServ != null) {
- hungUp = phoneServ.endCall();
- } else {
- Log.w(TAG, "!!! Unable to find ITelephony interface !!!");
+ if (code == KeyEvent.KEYCODE_ENDCALL) {
+ try {
+ ITelephony phoneServ = getPhoneInterface();
+ if (phoneServ != null) {
+ hungUp = phoneServ.endCall();
+ } else {
+ Log.w(TAG, "!!! Unable to find ITelephony interface !!!");
+ }
+ } catch (RemoteException ex) {
+ Log.w(TAG, "ITelephony.endCall() threw RemoteException" + ex);
}
- } catch (RemoteException ex) {
- Log.w(TAG, "ITelephony.endCall() threw RemoteException" + ex);
}
if (hungUp || !screenIsOn) {
mShouldTurnOffOnKeyUp = false;
} else {
// only try to turn off the screen if we didn't already hang up
mShouldTurnOffOnKeyUp = true;
- mHandler.postDelayed(mEndCallLongPress,
+ mHandler.postDelayed(mPowerLongPress,
ViewConfiguration.getGlobalActionKeyTimeout());
result &= ~ACTION_PASS_TO_USER;
}
} else {
- mHandler.removeCallbacks(mEndCallLongPress);
+ mHandler.removeCallbacks(mPowerLongPress);
if (mShouldTurnOffOnKeyUp) {
mShouldTurnOffOnKeyUp = false;
boolean gohome = (mEndcallBehavior & ENDCALL_HOME) != 0;
@@ -1859,6 +1864,13 @@
return false;
}
+ public void keyFeedbackFromInput(KeyEvent event) {
+ if (event.getAction() == KeyEvent.ACTION_DOWN
+ && (event.getFlags()&KeyEvent.FLAG_VIRTUAL_HARD_KEY) != 0) {
+ mVibrator.vibrate(VIRTUAL_KEY_VIBE_PATTERN, -1);
+ }
+ }
+
public void screenOnStoppedLw() {
if (!mKeyguardMediator.isShowing()) {
long curTime = SystemClock.uptimeMillis();