eclair snapshot
This commit is contained in:
@@ -19,38 +19,39 @@ package com.android.internal.policy.impl;
|
||||
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.accounts.OperationCanceledException;
|
||||
import android.accounts.AccountManagerFuture;
|
||||
import android.accounts.AuthenticatorException;
|
||||
import android.accounts.AccountManagerCallback;
|
||||
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;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.RelativeLayout;
|
||||
import android.widget.TextView;
|
||||
import android.app.Dialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.os.Bundle;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* 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 +63,6 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree
|
||||
|
||||
private final KeyguardScreenCallback mCallback;
|
||||
private final LockPatternUtils mLockPatternUtils;
|
||||
private IAccountsService mAccountsService;
|
||||
|
||||
private TextView mTopHeader;
|
||||
private TextView mInstructions;
|
||||
@@ -71,15 +71,17 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree
|
||||
private Button mOk;
|
||||
private Button mEmergencyCall;
|
||||
|
||||
/**
|
||||
* Shown while making asynchronous check of password.
|
||||
*/
|
||||
private ProgressDialog mCheckingDialog;
|
||||
|
||||
/**
|
||||
* AccountUnlockScreen constructor.
|
||||
*
|
||||
* @throws IllegalStateException if the IAccountsService is not
|
||||
* available on the current platform.
|
||||
*/
|
||||
public AccountUnlockScreen(Context context,
|
||||
KeyguardScreenCallback callback,
|
||||
LockPatternUtils lockPatternUtils) {
|
||||
KeyguardScreenCallback callback,
|
||||
LockPatternUtils lockPatternUtils) {
|
||||
super(context);
|
||||
mCallback = callback;
|
||||
mLockPatternUtils = lockPatternUtils;
|
||||
@@ -88,6 +90,9 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree
|
||||
R.layout.keyguard_screen_glogin_unlock, this, true);
|
||||
|
||||
mTopHeader = (TextView) findViewById(R.id.topHeader);
|
||||
mTopHeader.setText(mLockPatternUtils.isPermanentlyLocked() ?
|
||||
R.string.lockscreen_glogin_too_many_attempts :
|
||||
R.string.lockscreen_glogin_forgot_pattern);
|
||||
|
||||
mInstructions = (TextView) findViewById(R.id.instructions);
|
||||
|
||||
@@ -103,14 +108,6 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree
|
||||
|
||||
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,30 +147,16 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void cleanUp() {
|
||||
mContext.unbindService(this);
|
||||
if (mCheckingDialog != null) {
|
||||
mCheckingDialog.hide();
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void onClick(View v) {
|
||||
mCallback.pokeWakelock();
|
||||
if (v == mOk) {
|
||||
if (checkPassword()) {
|
||||
// clear out forgotten password
|
||||
mLockPatternUtils.setPermanentlyLocked(false);
|
||||
|
||||
// launch the 'choose lock pattern' activity so
|
||||
// the user can pick a new one if they want to
|
||||
Intent intent = new Intent();
|
||||
intent.setClassName(LOCK_PATTERN_PACKAGE, LOCK_PATTERN_CLASS);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
mContext.startActivity(intent);
|
||||
|
||||
// close the keyguard
|
||||
mCallback.keyguardDone(true);
|
||||
} else {
|
||||
mInstructions.setText(R.string.lockscreen_glogin_invalid_input);
|
||||
mPassword.setText("");
|
||||
}
|
||||
asyncCheckPassword();
|
||||
}
|
||||
|
||||
if (v == mEmergencyCall) {
|
||||
@@ -181,11 +164,37 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree
|
||||
}
|
||||
}
|
||||
|
||||
private void onCheckPasswordResult(boolean success) {
|
||||
if (success) {
|
||||
// clear out forgotten password
|
||||
mLockPatternUtils.setPermanentlyLocked(false);
|
||||
mLockPatternUtils.setLockPatternEnabled(false);
|
||||
mLockPatternUtils.saveLockPattern(null);
|
||||
|
||||
// launch the 'choose lock pattern' activity so
|
||||
// the user can pick a new one if they want to
|
||||
Intent intent = new Intent();
|
||||
intent.setClassName(LOCK_PATTERN_PACKAGE, LOCK_PATTERN_CLASS);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
mContext.startActivity(intent);
|
||||
|
||||
// close the keyguard
|
||||
mCallback.keyguardDone(true);
|
||||
} else {
|
||||
mInstructions.setText(R.string.lockscreen_glogin_invalid_input);
|
||||
mPassword.setText("");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean dispatchKeyEvent(KeyEvent event) {
|
||||
if (event.getAction() == KeyEvent.ACTION_DOWN
|
||||
&& event.getKeyCode() == KeyEvent.KEYCODE_BACK) {
|
||||
mCallback.goToLockScreen();
|
||||
if (mLockPatternUtils.isPermanentlyLocked()) {
|
||||
mCallback.goToLockScreen();
|
||||
} else {
|
||||
mCallback.forgotPattern(false);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return super.dispatchKeyEvent(event);
|
||||
@@ -207,33 +216,25 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree
|
||||
* @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).getAccounts();
|
||||
|
||||
// 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.name)) {
|
||||
score = 4;
|
||||
} else if (username.equalsIgnoreCase(a)) {
|
||||
} else if (username.equalsIgnoreCase(a.name)) {
|
||||
score = 3;
|
||||
} else if (username.indexOf('@') < 0) {
|
||||
int i = a.indexOf('@');
|
||||
int i = a.name.indexOf('@');
|
||||
if (i >= 0) {
|
||||
String aUsername = a.substring(0, i);
|
||||
String aUsername = a.name.substring(0, i);
|
||||
if (username.equals(aUsername)) {
|
||||
score = 2;
|
||||
} else if (username.equalsIgnoreCase(aUsername)) {
|
||||
@@ -251,28 +252,64 @@ public class AccountUnlockScreen extends RelativeLayout implements KeyguardScree
|
||||
return bestAccount;
|
||||
}
|
||||
|
||||
private boolean checkPassword() {
|
||||
private void asyncCheckPassword() {
|
||||
mCallback.pokeWakelock(AWAKE_POKE_MILLIS);
|
||||
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) {
|
||||
return false;
|
||||
Account account = findIntendedAccount(login);
|
||||
if (account == null) {
|
||||
onCheckPasswordResult(false);
|
||||
return;
|
||||
}
|
||||
getProgressDialog().show();
|
||||
Bundle options = new Bundle();
|
||||
options.putString(AccountManager.KEY_PASSWORD, password);
|
||||
AccountManager.get(mContext).confirmCredentials(account, options, null /* activity */,
|
||||
new AccountManagerCallback<Bundle>() {
|
||||
public void run(AccountManagerFuture<Bundle> future) {
|
||||
try {
|
||||
mCallback.pokeWakelock(AWAKE_POKE_MILLIS);
|
||||
final Bundle result = future.getResult();
|
||||
final boolean verified = result.getBoolean(AccountManager.KEY_BOOLEAN_RESULT);
|
||||
// ensure on UI thread
|
||||
mLogin.post(new Runnable() {
|
||||
public void run() {
|
||||
onCheckPasswordResult(verified);
|
||||
}
|
||||
});
|
||||
} catch (OperationCanceledException e) {
|
||||
onCheckPasswordResult(false);
|
||||
} catch (IOException e) {
|
||||
onCheckPasswordResult(false);
|
||||
} catch (AuthenticatorException e) {
|
||||
onCheckPasswordResult(false);
|
||||
} finally {
|
||||
mLogin.post(new Runnable() {
|
||||
public void run() {
|
||||
getProgressDialog().hide();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}, null /* handler */);
|
||||
}
|
||||
|
||||
/** {@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;
|
||||
private Dialog getProgressDialog() {
|
||||
if (mCheckingDialog == null) {
|
||||
mCheckingDialog = new ProgressDialog(mContext);
|
||||
mCheckingDialog.setMessage(
|
||||
mContext.getString(R.string.lockscreen_glogin_checking_password));
|
||||
mCheckingDialog.setIndeterminate(true);
|
||||
mCheckingDialog.setCancelable(false);
|
||||
mCheckingDialog.getWindow().setType(
|
||||
WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
|
||||
if (!mContext.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_sf_slowBlur)) {
|
||||
mCheckingDialog.getWindow().setFlags(
|
||||
WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
|
||||
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
|
||||
}
|
||||
}
|
||||
return mCheckingDialog;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package com.android.internal.policy.impl;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.StatusBarManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
@@ -26,6 +27,7 @@ import android.content.IntentFilter;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.os.SystemProperties;
|
||||
import android.provider.Settings;
|
||||
import android.telephony.PhoneStateListener;
|
||||
import android.telephony.ServiceState;
|
||||
@@ -40,6 +42,8 @@ import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.app.ShutdownThread;
|
||||
import com.android.internal.telephony.TelephonyIntents;
|
||||
import com.android.internal.telephony.TelephonyProperties;
|
||||
import com.google.android.collect.Lists;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -69,6 +73,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
|
||||
private boolean mKeyguardShowing = false;
|
||||
private boolean mDeviceProvisioned = false;
|
||||
private ToggleAction.State mAirplaneState = ToggleAction.State.Off;
|
||||
private boolean mIsWaitingForEcmExit = false;
|
||||
|
||||
/**
|
||||
* @param context everything needs a context :(
|
||||
@@ -81,6 +86,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
|
||||
IntentFilter filter = new IntentFilter();
|
||||
filter.addAction(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
|
||||
filter.addAction(Intent.ACTION_SCREEN_OFF);
|
||||
filter.addAction(TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED);
|
||||
context.registerReceiver(mBroadcastReceiver, filter);
|
||||
|
||||
// get notified of phone state changes
|
||||
@@ -141,20 +147,27 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
|
||||
R.string.global_actions_airplane_mode_off_status) {
|
||||
|
||||
void onToggle(boolean on) {
|
||||
// Change the system setting
|
||||
Settings.System.putInt(
|
||||
mContext.getContentResolver(),
|
||||
Settings.System.AIRPLANE_MODE_ON,
|
||||
on ? 1 : 0);
|
||||
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
|
||||
intent.putExtra("state", on);
|
||||
mContext.sendBroadcast(intent);
|
||||
if (Boolean.parseBoolean(
|
||||
SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE))) {
|
||||
mIsWaitingForEcmExit = true;
|
||||
// Launch ECM exit dialog
|
||||
Intent ecmDialogIntent =
|
||||
new Intent(TelephonyIntents.ACTION_SHOW_NOTICE_ECM_BLOCK_OTHERS, null);
|
||||
ecmDialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
mContext.startActivity(ecmDialogIntent);
|
||||
} else {
|
||||
changeAirplaneModeSystemSetting(on);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void changeStateFromPress(boolean buttonOn) {
|
||||
mState = buttonOn ? State.TurningOn : State.TurningOff;
|
||||
mAirplaneState = mState;
|
||||
// In ECM mode airplane state cannot be changed
|
||||
if (!(Boolean.parseBoolean(
|
||||
SystemProperties.get(TelephonyProperties.PROPERTY_INECM_MODE)))) {
|
||||
mState = buttonOn ? State.TurningOn : State.TurningOff;
|
||||
mAirplaneState = mState;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean showDuringKeyguard() {
|
||||
@@ -200,8 +213,11 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
|
||||
|
||||
final AlertDialog dialog = ab.create();
|
||||
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
|
||||
dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
|
||||
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
|
||||
if (!mContext.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_sf_slowBlur)) {
|
||||
dialog.getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
|
||||
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
|
||||
}
|
||||
|
||||
dialog.setOnDismissListener(this);
|
||||
|
||||
@@ -218,7 +234,7 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
|
||||
if (mKeyguardShowing) {
|
||||
mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
|
||||
} else {
|
||||
mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
|
||||
mDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,6 +506,14 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
|
||||
if (!PhoneWindowManager.SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS.equals(reason)) {
|
||||
mHandler.sendEmptyMessage(MESSAGE_DISMISS);
|
||||
}
|
||||
} else if (TelephonyIntents.ACTION_EMERGENCY_CALLBACK_MODE_CHANGED.equals(action)) {
|
||||
// Airplane mode can be changed after ECM exits if airplane toggle button
|
||||
// is pressed during ECM mode
|
||||
if (!(intent.getBooleanExtra("PHONE_IN_ECM_STATE", false)) &&
|
||||
mIsWaitingForEcmExit) {
|
||||
mIsWaitingForEcmExit = false;
|
||||
changeAirplaneModeSystemSetting(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -514,4 +538,17 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Change the airplane mode system setting
|
||||
*/
|
||||
private void changeAirplaneModeSystemSetting(boolean on) {
|
||||
Settings.System.putInt(
|
||||
mContext.getContentResolver(),
|
||||
Settings.System.AIRPLANE_MODE_ON,
|
||||
on ? 1 : 0);
|
||||
Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
|
||||
intent.putExtra("state", on);
|
||||
mContext.sendBroadcast(intent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,10 +28,19 @@ public interface KeyguardScreenCallback extends KeyguardViewCallback {
|
||||
void goToLockScreen();
|
||||
|
||||
/**
|
||||
* Transitino to th unlock screen.
|
||||
* Transition to the unlock screen.
|
||||
*/
|
||||
void goToUnlockScreen();
|
||||
|
||||
/**
|
||||
* The user reported that they forgot their pattern (or not, when they want to back out of the
|
||||
* forgot pattern screen).
|
||||
*
|
||||
* @param isForgotten True if the user hit the forgot pattern, false if they want to back out
|
||||
* of the account screen.
|
||||
*/
|
||||
void forgotPattern(boolean isForgotten);
|
||||
|
||||
/**
|
||||
* @return Whether the keyguard requires some sort of PIN.
|
||||
*/
|
||||
|
||||
@@ -35,7 +35,6 @@ import static android.provider.Telephony.Intents.EXTRA_SHOW_SPN;
|
||||
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;
|
||||
@@ -67,6 +66,8 @@ public class KeyguardUpdateMonitor {
|
||||
private boolean mInPortrait;
|
||||
private boolean mKeyboardOpen;
|
||||
|
||||
private boolean mKeyguardBypassEnabled;
|
||||
|
||||
private boolean mDevicePluggedIn;
|
||||
|
||||
private boolean mDeviceProvisioned;
|
||||
@@ -163,6 +164,9 @@ public class KeyguardUpdateMonitor {
|
||||
}
|
||||
};
|
||||
|
||||
mKeyguardBypassEnabled = context.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_bypass_keyguard_if_slider_open);
|
||||
|
||||
mDeviceProvisioned = Settings.Secure.getInt(
|
||||
mContext.getContentResolver(), Settings.Secure.DEVICE_PROVISIONED, 0) != 0;
|
||||
|
||||
@@ -295,13 +299,6 @@ public class KeyguardUpdateMonitor {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -513,6 +510,10 @@ public class KeyguardUpdateMonitor {
|
||||
return mKeyboardOpen;
|
||||
}
|
||||
|
||||
public boolean isKeyguardBypassEnabled() {
|
||||
return mKeyguardBypassEnabled;
|
||||
}
|
||||
|
||||
public boolean isDevicePluggedIn() {
|
||||
return mDevicePluggedIn;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ public class KeyguardViewManager implements KeyguardWindowController {
|
||||
|
||||
private WindowManager.LayoutParams mWindowLayoutParams;
|
||||
private boolean mNeedsInput = false;
|
||||
|
||||
|
||||
private FrameLayout mKeyguardHost;
|
||||
private KeyguardViewBase mKeyguardView;
|
||||
|
||||
@@ -101,6 +101,8 @@ public class KeyguardViewManager implements KeyguardWindowController {
|
||||
|
||||
final int stretch = ViewGroup.LayoutParams.FILL_PARENT;
|
||||
int flags = WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN
|
||||
| WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER
|
||||
| WindowManager.LayoutParams.FLAG_KEEP_SURFACE_WHILE_ANIMATING
|
||||
/*| WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
|
||||
| WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR*/ ;
|
||||
if (!mNeedsInput) {
|
||||
@@ -108,7 +110,7 @@ public class KeyguardViewManager implements KeyguardWindowController {
|
||||
}
|
||||
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
|
||||
stretch, stretch, WindowManager.LayoutParams.TYPE_KEYGUARD,
|
||||
flags, PixelFormat.OPAQUE);
|
||||
flags, PixelFormat.TRANSLUCENT);
|
||||
lp.softInputMode = WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN;
|
||||
lp.windowAnimations = com.android.internal.R.style.Animation_LockScreen;
|
||||
lp.screenOrientation = ActivityInfo.SCREEN_ORIENTATION_NOSENSOR;
|
||||
@@ -152,7 +154,7 @@ public class KeyguardViewManager implements KeyguardWindowController {
|
||||
mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Reset the state of the view.
|
||||
*/
|
||||
@@ -195,10 +197,14 @@ public class KeyguardViewManager implements KeyguardWindowController {
|
||||
*
|
||||
* @param keyCode The wake key.
|
||||
*/
|
||||
public void wakeWhenReadyTq(int keyCode) {
|
||||
public boolean wakeWhenReadyTq(int keyCode) {
|
||||
if (DEBUG) Log.d(TAG, "wakeWhenReady(" + keyCode + ")");
|
||||
if (mKeyguardView != null) {
|
||||
mKeyguardView.wakeWhenReadyTq(keyCode);
|
||||
return true;
|
||||
} else {
|
||||
Log.w(TAG, "mKeyguardView is null in wakeWhenReadyTq");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -209,10 +215,19 @@ public class KeyguardViewManager implements KeyguardWindowController {
|
||||
if (DEBUG) Log.d(TAG, "hide()");
|
||||
if (mKeyguardHost != null) {
|
||||
mKeyguardHost.setVisibility(View.GONE);
|
||||
// Don't do this right away, so we can let the view continue to animate
|
||||
// as it goes away.
|
||||
if (mKeyguardView != null) {
|
||||
mKeyguardHost.removeView(mKeyguardView);
|
||||
mKeyguardView.cleanUp();
|
||||
final KeyguardViewBase lastView = mKeyguardView;
|
||||
mKeyguardView = null;
|
||||
mKeyguardHost.postDelayed(new Runnable() {
|
||||
public void run() {
|
||||
synchronized (KeyguardViewManager.this) {
|
||||
mKeyguardHost.removeView(lastView);
|
||||
lastView.cleanUp();
|
||||
}
|
||||
}
|
||||
}, 500);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,11 +19,9 @@ package com.android.internal.policy.impl;
|
||||
import com.android.internal.telephony.IccCard;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
|
||||
import android.app.ActivityManagerNative;
|
||||
import android.app.AlarmManager;
|
||||
import android.app.PendingIntent;
|
||||
import android.app.StatusBarManager;
|
||||
import static android.app.StatusBarManager.DISABLE_EXPAND;
|
||||
import static android.app.StatusBarManager.DISABLE_NONE;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -32,7 +30,9 @@ import android.os.Handler;
|
||||
import android.os.LocalPowerManager;
|
||||
import android.os.Message;
|
||||
import android.os.PowerManager;
|
||||
import android.os.RemoteException;
|
||||
import android.os.SystemClock;
|
||||
import android.os.SystemProperties;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.util.Config;
|
||||
import android.util.EventLog;
|
||||
@@ -84,7 +84,7 @@ import android.view.WindowManagerPolicy;
|
||||
* thread of the keyguard.
|
||||
*/
|
||||
public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
KeyguardUpdateMonitor.ConfigurationChangeCallback, KeyguardUpdateMonitor.SimStateCallback {
|
||||
KeyguardUpdateMonitor.SimStateCallback {
|
||||
private final static boolean DEBUG = false && Config.LOGD;
|
||||
private final static boolean DBG_WAKE = DEBUG || true;
|
||||
|
||||
@@ -104,6 +104,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
private static final int WAKE_WHEN_READY = 8;
|
||||
private static final int KEYGUARD_DONE = 9;
|
||||
private static final int KEYGUARD_DONE_DRAWING = 10;
|
||||
private static final int KEYGUARD_DONE_AUTHENTICATING = 11;
|
||||
|
||||
/**
|
||||
* The default amount of time we stay awake (used for all key input)
|
||||
@@ -122,7 +123,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
* turning on the keyguard (i.e, the user has this much time to turn
|
||||
* the screen back on without having to face the keyguard).
|
||||
*/
|
||||
private static final int KEYGUARD_DELAY_MS = 0;
|
||||
private static final int KEYGUARD_DELAY_MS = 5000;
|
||||
|
||||
/**
|
||||
* How long we'll wait for the {@link KeyguardViewCallback#keyguardDoneDrawing()}
|
||||
@@ -149,6 +150,12 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
*/
|
||||
private PowerManager.WakeLock mWakeLock;
|
||||
|
||||
/**
|
||||
* Used to keep the device awake while to ensure the keyguard finishes opening before
|
||||
* we sleep.
|
||||
*/
|
||||
private PowerManager.WakeLock mShowKeyguardWakeLock;
|
||||
|
||||
/**
|
||||
* Does not turn on screen, held while a call to {@link KeyguardViewManager#wakeWhenReadyTq(int)}
|
||||
* is called to make sure the device doesn't sleep before it has a chance to poke
|
||||
@@ -157,11 +164,6 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
*/
|
||||
private PowerManager.WakeLock mWakeAndHandOff;
|
||||
|
||||
/**
|
||||
* Used to disable / reenable status bar expansion.
|
||||
*/
|
||||
private StatusBarManager mStatusBarManager;
|
||||
|
||||
private KeyguardViewManager mKeyguardViewManager;
|
||||
|
||||
// these are protected by synchronized (this)
|
||||
@@ -182,6 +184,9 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
// answer whether the input should be restricted)
|
||||
private boolean mShowing = false;
|
||||
|
||||
// true if the keyguard is hidden by another window
|
||||
private boolean mHidden = false;
|
||||
|
||||
/**
|
||||
* Helps remember whether the screen has turned on since the last time
|
||||
* it turned off due to timeout. see {@link #onScreenTurnedOff(int)}
|
||||
@@ -229,6 +234,8 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP,
|
||||
"keyguard");
|
||||
mWakeLock.setReferenceCounted(false);
|
||||
mShowKeyguardWakeLock = mPM.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "show keyguard");
|
||||
mShowKeyguardWakeLock.setReferenceCounted(false);
|
||||
|
||||
mWakeAndHandOff = mPM.newWakeLock(
|
||||
PowerManager.PARTIAL_WAKE_LOCK,
|
||||
@@ -245,7 +252,6 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
|
||||
mUpdateMonitor = new KeyguardUpdateMonitor(context);
|
||||
|
||||
mUpdateMonitor.registerConfigurationChangeCallback(this);
|
||||
mUpdateMonitor.registerSimStateCallback(this);
|
||||
|
||||
mKeyguardViewProperties =
|
||||
@@ -347,14 +353,12 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
if (DEBUG) Log.d(TAG, "remembering to reshow, hiding keyguard, "
|
||||
+ "disabling status bar expansion");
|
||||
mNeedToReshowWhenReenabled = true;
|
||||
setStatusBarExpandable(false);
|
||||
hideLocked();
|
||||
} else if (enabled && mNeedToReshowWhenReenabled) {
|
||||
// reenabled after previously hidden, reshow
|
||||
if (DEBUG) Log.d(TAG, "previously hidden, reshowing, reenabling "
|
||||
+ "status bar expansion");
|
||||
mNeedToReshowWhenReenabled = false;
|
||||
setStatusBarExpandable(true);
|
||||
|
||||
if (mExitSecureCallback != null) {
|
||||
if (DEBUG) Log.d(TAG, "onKeyguardExitResult(false), resetting");
|
||||
@@ -409,15 +413,6 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void setStatusBarExpandable(boolean isExpandable) {
|
||||
if (mStatusBarManager == null) {
|
||||
mStatusBarManager =
|
||||
(StatusBarManager) mContext.getSystemService(Context.STATUS_BAR_SERVICE);
|
||||
}
|
||||
mStatusBarManager.disable(isExpandable ? DISABLE_NONE : DISABLE_EXPAND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the keyguard currently showing?
|
||||
*/
|
||||
@@ -425,6 +420,17 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
return mShowing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify us when the keyguard is hidden by another window
|
||||
*/
|
||||
public void setHidden(boolean isHidden) {
|
||||
if (DEBUG) Log.d(TAG, "setHidden " + isHidden);
|
||||
synchronized (KeyguardViewMediator.this) {
|
||||
mHidden = isHidden;
|
||||
adjustUserActivityLocked();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Given the state of the keyguard, is the input restricted?
|
||||
* Input is restricted when the keyguard is showing, or when the keyguard
|
||||
@@ -434,6 +440,21 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
return mShowing || mNeedToReshowWhenReenabled || !mUpdateMonitor.isDeviceProvisioned();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the change is resulting in the keyguard beign dismissed,
|
||||
* meaning the screen can turn on immediately. Otherwise returns false.
|
||||
*/
|
||||
public boolean doLidChangeTq(boolean isLidOpen) {
|
||||
mKeyboardOpen = isLidOpen;
|
||||
|
||||
if (mUpdateMonitor.isKeyguardBypassEnabled() && mKeyboardOpen
|
||||
&& !mKeyguardViewProperties.isSecure() && mKeyguardViewManager.isShowing()) {
|
||||
if (DEBUG) Log.d(TAG, "bypassing keyguard on sliding open of keyboard with non-secure keyguard");
|
||||
mHandler.sendEmptyMessage(KEYGUARD_DONE_AUTHENTICATING);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the keyguard if the settings are appropriate.
|
||||
@@ -463,9 +484,13 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
}
|
||||
|
||||
// if the setup wizard hasn't run yet, don't show
|
||||
final boolean requireSim = !SystemProperties.getBoolean("keyguard.no_require_sim",
|
||||
false);
|
||||
final boolean provisioned = mUpdateMonitor.isDeviceProvisioned();
|
||||
final IccCard.State state = mUpdateMonitor.getSimState();
|
||||
final boolean lockedOrMissing = state.isPinLocked() || (state == IccCard.State.ABSENT);
|
||||
final boolean lockedOrMissing = state.isPinLocked()
|
||||
|| ((state == IccCard.State.ABSENT) && requireSim);
|
||||
|
||||
if (!lockedOrMissing && !provisioned) {
|
||||
if (DEBUG) Log.d(TAG, "doKeyguard: not showing because device isn't provisioned"
|
||||
+ " and the sim is not locked or missing");
|
||||
@@ -544,6 +569,8 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
*/
|
||||
private void showLocked() {
|
||||
if (DEBUG) Log.d(TAG, "showLocked");
|
||||
// ensure we stay awake until we are finished displaying the keyguard
|
||||
mShowKeyguardWakeLock.acquire();
|
||||
Message msg = mHandler.obtainMessage(SHOW);
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
@@ -558,26 +585,6 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
mHandler.sendMessage(msg);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@link KeyguardUpdateMonitor} callbacks.
|
||||
*/
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void onOrientationChange(boolean inPortrait) {
|
||||
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void onKeyboardChange(boolean isKeyboardOpen) {
|
||||
mKeyboardOpen = isKeyboardOpen;
|
||||
|
||||
if (mKeyboardOpen && !mKeyguardViewProperties.isSecure()
|
||||
&& mKeyguardViewManager.isShowing()) {
|
||||
if (DEBUG) Log.d(TAG, "bypassing keyguard on sliding open of keyboard with non-secure keyguard");
|
||||
keyguardDone(true);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void onSimStateChanged(IccCard.State simState) {
|
||||
if (DEBUG) Log.d(TAG, "onSimStateChanged: " + simState);
|
||||
@@ -615,6 +622,10 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSecure() {
|
||||
return mKeyguardViewProperties.isSecure();
|
||||
}
|
||||
|
||||
private BroadcastReceiver mBroadCastReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
public void onReceive(Context context, Intent intent) {
|
||||
@@ -719,10 +730,15 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
* @see #handleKeyguardDone
|
||||
*/
|
||||
public void keyguardDone(boolean authenticated) {
|
||||
keyguardDone(authenticated, true);
|
||||
}
|
||||
|
||||
public void keyguardDone(boolean authenticated, boolean wakeup) {
|
||||
synchronized (this) {
|
||||
EventLog.writeEvent(70000, 2);
|
||||
if (DEBUG) Log.d(TAG, "keyguardDone(" + authenticated + ")");
|
||||
Message msg = mHandler.obtainMessage(KEYGUARD_DONE);
|
||||
msg.arg1 = wakeup ? 1 : 0;
|
||||
mHandler.sendMessage(msg);
|
||||
|
||||
if (authenticated) {
|
||||
@@ -738,7 +754,6 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
// the keyguard when they've released the lock
|
||||
mExternallyEnabled = true;
|
||||
mNeedToReshowWhenReenabled = false;
|
||||
setStatusBarExpandable(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -789,10 +804,14 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
handleWakeWhenReady(msg.arg1);
|
||||
return;
|
||||
case KEYGUARD_DONE:
|
||||
handleKeyguardDone();
|
||||
handleKeyguardDone(msg.arg1 != 0);
|
||||
return;
|
||||
case KEYGUARD_DONE_DRAWING:
|
||||
handleKeyguardDoneDrawing();
|
||||
return;
|
||||
case KEYGUARD_DONE_AUTHENTICATING:
|
||||
keyguardDone(true);
|
||||
return;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -801,10 +820,12 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
* @see #keyguardDone
|
||||
* @see #KEYGUARD_DONE
|
||||
*/
|
||||
private void handleKeyguardDone() {
|
||||
private void handleKeyguardDone(boolean wakeup) {
|
||||
if (DEBUG) Log.d(TAG, "handleKeyguardDone");
|
||||
handleHide();
|
||||
mPM.userActivity(SystemClock.uptimeMillis(), true);
|
||||
if (wakeup) {
|
||||
mPM.userActivity(SystemClock.uptimeMillis(), true);
|
||||
}
|
||||
mWakeLock.release();
|
||||
mContext.sendBroadcast(mUserPresentIntent);
|
||||
}
|
||||
@@ -853,12 +874,14 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
if (DEBUG) Log.d(TAG, "handleShow");
|
||||
if (!mSystemReady) return;
|
||||
|
||||
// while we're showing, we control the wake state, so ask the power
|
||||
// manager not to honor request for userActivity.
|
||||
mRealPowerManager.enableUserActivity(false);
|
||||
|
||||
mKeyguardViewManager.show();
|
||||
mShowing = true;
|
||||
adjustUserActivityLocked();
|
||||
try {
|
||||
ActivityManagerNative.getDefault().closeSystemDialogs("lock");
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
mShowKeyguardWakeLock.release();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -869,11 +892,25 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
private void handleHide() {
|
||||
synchronized (KeyguardViewMediator.this) {
|
||||
if (DEBUG) Log.d(TAG, "handleHide");
|
||||
// When we go away, tell the poewr manager to honor requests from userActivity.
|
||||
mRealPowerManager.enableUserActivity(true);
|
||||
if (mWakeAndHandOff.isHeld()) {
|
||||
Log.w(TAG, "attempt to hide the keyguard while waking, ignored");
|
||||
return;
|
||||
}
|
||||
|
||||
mKeyguardViewManager.hide();
|
||||
mShowing = false;
|
||||
adjustUserActivityLocked();
|
||||
}
|
||||
}
|
||||
|
||||
private void adjustUserActivityLocked() {
|
||||
// disable user activity if we are shown and not hidden
|
||||
if (DEBUG) Log.d(TAG, "adjustUserActivityLocked mShowing: " + mShowing + " mHidden: " + mHidden);
|
||||
boolean enabled = !mShowing || mHidden;
|
||||
mRealPowerManager.enableUserActivity(enabled);
|
||||
if (!enabled && mScreenOn) {
|
||||
// reinstate our short screen timeout policy
|
||||
pokeWakelock();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -888,7 +925,11 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
|
||||
// this should result in a call to 'poke wakelock' which will set a timeout
|
||||
// on releasing the wakelock
|
||||
mKeyguardViewManager.wakeWhenReadyTq(keyCode);
|
||||
if (!mKeyguardViewManager.wakeWhenReadyTq(keyCode)) {
|
||||
// poke wakelock ourselves if keyguard is no longer active
|
||||
Log.w(TAG, "mKeyguardViewManager.wakeWhenReadyTq did not poke wake lock, so poke it ourselves");
|
||||
pokeWakelock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Now that the keyguard is ready and has poked the wake lock, we can
|
||||
@@ -897,7 +938,7 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
|
||||
mWakeAndHandOff.release();
|
||||
|
||||
if (!mWakeLock.isHeld()) {
|
||||
Log.w(TAG, "mKeyguardViewManager.wakeWhenReadyTq did not poke wake lock");
|
||||
Log.w(TAG, "mWakeLock not held in mKeyguardViewManager.wakeWhenReadyTq");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,41 +16,47 @@
|
||||
|
||||
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.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.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;
|
||||
|
||||
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
|
||||
* 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 {
|
||||
public class LockPatternKeyguardView extends KeyguardViewBase
|
||||
implements AccountManagerCallback<Account[]> {
|
||||
|
||||
// intent action for launching emergency dialer activity.
|
||||
static final String ACTION_EMERGENCY_DIAL = "com.android.phone.EmergencyDialer.DIAL";
|
||||
@@ -60,12 +66,12 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
|
||||
|
||||
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
|
||||
|
||||
|
||||
/**
|
||||
@@ -114,10 +120,13 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
|
||||
private Mode mMode = Mode.LockScreen;
|
||||
|
||||
/**
|
||||
* Keeps track of what mode the current unlock screen is
|
||||
* Keeps track of what mode the current unlock screen is (cached from most recent computation in
|
||||
* {@link #getUnlockMode}).
|
||||
*/
|
||||
private UnlockMode mUnlockScreenMode;
|
||||
|
||||
private boolean mForgotPattern;
|
||||
|
||||
/**
|
||||
* If true, it means we are in the process of verifying that the user
|
||||
* can get past the lock screen per {@link #verifyUnlock()}
|
||||
@@ -130,11 +139,6 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
|
||||
*/
|
||||
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.
|
||||
@@ -145,6 +149,22 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
|
||||
&& (mUpdateMonitor.getSimState() == IccCard.State.ABSENT);
|
||||
}
|
||||
|
||||
public void run(AccountManagerFuture<Account[]> 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
|
||||
@@ -158,9 +178,21 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
|
||||
LockPatternUtils lockPatternUtils,
|
||||
KeyguardWindowController controller) {
|
||||
super(context);
|
||||
|
||||
final boolean hasAccount = AccountManager.get(context).getAccounts().length > 0;
|
||||
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. */
|
||||
String[] features = new String[] {"saml"};
|
||||
AccountManager.get(context).getAccountsByTypeAndFeatures(
|
||||
"com.google", features, this, null);
|
||||
}
|
||||
|
||||
asyncCheckForAccount();
|
||||
|
||||
mEnableFallback = false;
|
||||
|
||||
mRequiresSim =
|
||||
TextUtils.isEmpty(SystemProperties.get("keyguard.no_require_sim"));
|
||||
|
||||
@@ -169,10 +201,11 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
|
||||
mWindowController = controller;
|
||||
|
||||
mMode = getInitialMode();
|
||||
|
||||
|
||||
mKeyguardScreenCallback = new KeyguardScreenCallback() {
|
||||
|
||||
public void goToLockScreen() {
|
||||
mForgotPattern = false;
|
||||
if (mIsVerifyUnlockOnly) {
|
||||
// navigating away from unlock screen during verify mode means
|
||||
// we are done and the user failed to authenticate.
|
||||
@@ -197,6 +230,13 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
|
||||
}
|
||||
}
|
||||
|
||||
public void forgotPattern(boolean isForgotten) {
|
||||
if (mEnableFallback) {
|
||||
mForgotPattern = isForgotten;
|
||||
updateScreen(Mode.UnlockScreen);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isSecure() {
|
||||
return LockPatternKeyguardView.this.isSecure();
|
||||
}
|
||||
@@ -235,11 +275,11 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
|
||||
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 +288,9 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
|
||||
showTimeoutDialog();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public boolean doesFallbackUnlockScreenExist() {
|
||||
return mHasAccount;
|
||||
return mEnableFallback;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -262,9 +302,11 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
|
||||
setDescendantFocusability(FOCUS_AFTER_DESCENDANTS);
|
||||
|
||||
// wall paper background
|
||||
final BitmapDrawable drawable = (BitmapDrawable) context.getWallpaper();
|
||||
setBackgroundDrawable(
|
||||
new FastBitmapDrawable(drawable.getBitmap()));
|
||||
if (false) {
|
||||
final BitmapDrawable drawable = (BitmapDrawable) context.getWallpaper();
|
||||
setBackgroundDrawable(
|
||||
new FastBitmapDrawable(drawable.getBitmap()));
|
||||
}
|
||||
|
||||
// create both the lock and unlock screen so they are quickly available
|
||||
// when the screen turns on
|
||||
@@ -277,45 +319,18 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
|
||||
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() {
|
||||
mIsVerifyUnlockOnly = false;
|
||||
mForgotPattern = false;
|
||||
updateScreen(getInitialMode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onScreenTurnedOff() {
|
||||
mScreenOn = false;
|
||||
mForgotPattern = false;
|
||||
if (mMode == Mode.LockScreen) {
|
||||
((KeyguardScreen) mLockScreen).onPause();
|
||||
} else {
|
||||
@@ -423,7 +438,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
|
||||
// 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) {
|
||||
@@ -454,12 +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());
|
||||
view.setEnableFallback(mEnableFallback);
|
||||
return view;
|
||||
} else if (unlockMode == UnlockMode.SimPin) {
|
||||
return new SimUnlockScreen(
|
||||
mContext,
|
||||
@@ -525,7 +542,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
|
||||
final IccCard.State simState = mUpdateMonitor.getSimState();
|
||||
if (stuckOnLockScreenBecauseSimMissing() || (simState == IccCard.State.PUK_REQUIRED)) {
|
||||
return Mode.LockScreen;
|
||||
} else if (mUpdateMonitor.isKeyboardOpen() && isSecure()) {
|
||||
} else if (isSecure()) {
|
||||
return Mode.UnlockScreen;
|
||||
} else {
|
||||
return Mode.LockScreen;
|
||||
@@ -540,7 +557,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
|
||||
if (simState == IccCard.State.PIN_REQUIRED || simState == IccCard.State.PUK_REQUIRED) {
|
||||
return UnlockMode.SimPin;
|
||||
} else {
|
||||
return mLockPatternUtils.isPermanentlyLocked() ?
|
||||
return (mForgotPattern || mLockPatternUtils.isPermanentlyLocked()) ?
|
||||
UnlockMode.Account:
|
||||
UnlockMode.Pattern;
|
||||
}
|
||||
@@ -558,9 +575,12 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
|
||||
.setNeutralButton(R.string.ok, null)
|
||||
.create();
|
||||
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
|
||||
dialog.getWindow().setFlags(
|
||||
WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
|
||||
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
|
||||
if (!mContext.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_sf_slowBlur)) {
|
||||
dialog.getWindow().setFlags(
|
||||
WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
|
||||
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
|
||||
}
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
@@ -578,15 +598,20 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
|
||||
.setNeutralButton(R.string.ok, null)
|
||||
.create();
|
||||
dialog.getWindow().setType(WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
|
||||
dialog.getWindow().setFlags(
|
||||
WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
|
||||
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
|
||||
if (!mContext.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_sf_slowBlur)) {
|
||||
dialog.getWindow().setFlags(
|
||||
WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
|
||||
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
|
||||
}
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to put wallpaper on the background of the lock screen. Centers it Horizontally and
|
||||
* vertically.
|
||||
* Used to put wallpaper on the background of the lock screen. Centers it
|
||||
* Horizontally and pins the bottom (assuming that the lock screen is aligned
|
||||
* with the bottom, so the wallpaper should extend above the top into the
|
||||
* status bar).
|
||||
*/
|
||||
static private class FastBitmapDrawable extends Drawable {
|
||||
private Bitmap mBitmap;
|
||||
@@ -602,7 +627,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase {
|
||||
canvas.drawBitmap(
|
||||
mBitmap,
|
||||
(getBounds().width() - mBitmap.getWidth()) / 2,
|
||||
(getBounds().height() - mBitmap.getHeight()) / 2,
|
||||
(getBounds().height() - mBitmap.getHeight()),
|
||||
null);
|
||||
}
|
||||
|
||||
|
||||
@@ -18,21 +18,26 @@ package com.android.internal.policy.impl;
|
||||
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.RotarySelector;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.Resources;
|
||||
import android.text.format.DateFormat;
|
||||
import android.text.TextUtils;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.LinearLayout;
|
||||
import android.widget.TextView;
|
||||
import android.widget.*;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.Log;
|
||||
import android.media.AudioManager;
|
||||
import android.os.SystemProperties;
|
||||
|
||||
import com.android.internal.telephony.IccCard;
|
||||
|
||||
import java.util.Date;
|
||||
import java.io.File;
|
||||
import java.text.SimpleDateFormat;
|
||||
|
||||
/**
|
||||
* The screen within {@link LockPatternKeyguardView} that shows general
|
||||
@@ -40,40 +45,28 @@ import java.util.Date;
|
||||
* past it, as applicable.
|
||||
*/
|
||||
class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateMonitor.InfoCallback,
|
||||
KeyguardUpdateMonitor.SimStateCallback, KeyguardUpdateMonitor.ConfigurationChangeCallback {
|
||||
KeyguardUpdateMonitor.SimStateCallback, KeyguardUpdateMonitor.ConfigurationChangeCallback,
|
||||
RotarySelector.OnDialTriggerListener {
|
||||
|
||||
private static final boolean DBG = false;
|
||||
private static final String TAG = "LockScreen";
|
||||
private static final String ENABLE_MENU_KEY_FILE = "/data/local/enable_menu_key";
|
||||
|
||||
private Status mStatus = Status.Normal;
|
||||
|
||||
private final LockPatternUtils mLockPatternUtils;
|
||||
private final KeyguardUpdateMonitor mUpdateMonitor;
|
||||
private final KeyguardScreenCallback mCallback;
|
||||
|
||||
private TextView mHeaderSimOk1;
|
||||
private TextView mHeaderSimOk2;
|
||||
|
||||
private TextView mHeaderSimBad1;
|
||||
private TextView mHeaderSimBad2;
|
||||
|
||||
private TextView mCarrier;
|
||||
private RotarySelector mRotary;
|
||||
private TextView mTime;
|
||||
private TextView mDate;
|
||||
|
||||
private ViewGroup mBatteryInfoGroup;
|
||||
private ImageView mBatteryInfoIcon;
|
||||
private TextView mBatteryInfoText;
|
||||
private View mBatteryInfoSpacer;
|
||||
|
||||
private ViewGroup mNextAlarmGroup;
|
||||
private TextView mAlarmText;
|
||||
private View mAlarmSpacer;
|
||||
|
||||
private ViewGroup mScreenLockedMessageGroup;
|
||||
|
||||
private TextView mLockInstructions;
|
||||
|
||||
private TextView mStatus1;
|
||||
private TextView mStatus2;
|
||||
private TextView mScreenLocked;
|
||||
private Button mEmergencyCallButton;
|
||||
|
||||
/**
|
||||
* false means sim is missing or PUK'd
|
||||
*/
|
||||
private boolean mSimOk = true;
|
||||
|
||||
// are we showing battery information?
|
||||
private boolean mShowingBatteryInfo = false;
|
||||
|
||||
@@ -83,10 +76,83 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM
|
||||
// last known battery level
|
||||
private int mBatteryLevel = 100;
|
||||
|
||||
private String mNextAlarm = null;
|
||||
private Drawable mAlarmIcon = null;
|
||||
private String mCharging = null;
|
||||
private Drawable mChargingIcon = null;
|
||||
|
||||
private View[] mOnlyVisibleWhenSimOk;
|
||||
private boolean mSilentMode;
|
||||
private AudioManager mAudioManager;
|
||||
private java.text.DateFormat mDateFormat;
|
||||
private java.text.DateFormat mTimeFormat;
|
||||
private boolean mCreatedInPortrait;
|
||||
private boolean mEnableMenuKeyInLockScreen;
|
||||
|
||||
private View[] mOnlyVisibleWhenSimNotOk;
|
||||
/**
|
||||
* The status of this lock screen.
|
||||
*/
|
||||
enum Status {
|
||||
/**
|
||||
* Normal case (sim card present, it's not locked)
|
||||
*/
|
||||
Normal(true),
|
||||
|
||||
/**
|
||||
* The sim card is 'network locked'.
|
||||
*/
|
||||
NetworkLocked(true),
|
||||
|
||||
/**
|
||||
* The sim card is missing.
|
||||
*/
|
||||
SimMissing(false),
|
||||
|
||||
/**
|
||||
* The sim card is missing, and this is the device isn't provisioned, so we don't let
|
||||
* them get past the screen.
|
||||
*/
|
||||
SimMissingLocked(false),
|
||||
|
||||
/**
|
||||
* The sim card is PUK locked, meaning they've entered the wrong sim unlock code too many
|
||||
* times.
|
||||
*/
|
||||
SimPukLocked(false),
|
||||
|
||||
/**
|
||||
* The sim card is locked.
|
||||
*/
|
||||
SimLocked(true);
|
||||
|
||||
private final boolean mShowStatusLines;
|
||||
|
||||
Status(boolean mShowStatusLines) {
|
||||
this.mShowStatusLines = mShowStatusLines;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether the status lines (battery level and / or next alarm) are shown while
|
||||
* in this state. Mostly dictated by whether this is room for them.
|
||||
*/
|
||||
public boolean showStatusLines() {
|
||||
return mShowStatusLines;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In general, we enable unlocking the insecure key guard with the menu key. However, there are
|
||||
* some cases where we wish to disable it, notably when the menu button placement or technology
|
||||
* is prone to false positives.
|
||||
*
|
||||
* @return true if the menu key should be enabled
|
||||
*/
|
||||
private boolean shouldEnableMenuKey() {
|
||||
final Resources res = getResources();
|
||||
final boolean configDisabled = res.getBoolean(R.bool.config_disableMenuKeyInLockScreen);
|
||||
final boolean isMonkey = SystemProperties.getBoolean("ro.monkey", false);
|
||||
final boolean fileOverride = (new File(ENABLE_MENU_KEY_FILE)).exists();
|
||||
return !configDisabled || isMonkey || fileOverride;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param context Used to setup the view.
|
||||
@@ -103,262 +169,391 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM
|
||||
mUpdateMonitor = updateMonitor;
|
||||
mCallback = callback;
|
||||
|
||||
mEnableMenuKeyInLockScreen = shouldEnableMenuKey();
|
||||
|
||||
mCreatedInPortrait = updateMonitor.isInPortrait();
|
||||
|
||||
final LayoutInflater inflater = LayoutInflater.from(context);
|
||||
inflater.inflate(R.layout.keyguard_screen_lock, this, true);
|
||||
|
||||
mSimOk = isSimOk(updateMonitor.getSimState());
|
||||
mShowingBatteryInfo = updateMonitor.shouldShowBatteryInfo();
|
||||
mPluggedIn = updateMonitor.isDevicePluggedIn();
|
||||
mBatteryLevel = updateMonitor.getBatteryLevel();
|
||||
|
||||
mHeaderSimOk1 = (TextView) findViewById(R.id.headerSimOk1);
|
||||
mHeaderSimOk2 = (TextView) findViewById(R.id.headerSimOk2);
|
||||
|
||||
mHeaderSimBad1 = (TextView) findViewById(R.id.headerSimBad1);
|
||||
mHeaderSimBad2 = (TextView) findViewById(R.id.headerSimBad2);
|
||||
if (mCreatedInPortrait) {
|
||||
inflater.inflate(R.layout.keyguard_screen_rotary_unlock, this, true);
|
||||
} else {
|
||||
inflater.inflate(R.layout.keyguard_screen_rotary_unlock_land, this, true);
|
||||
}
|
||||
|
||||
mCarrier = (TextView) findViewById(R.id.carrier);
|
||||
mTime = (TextView) findViewById(R.id.time);
|
||||
mDate = (TextView) findViewById(R.id.date);
|
||||
|
||||
mBatteryInfoGroup = (ViewGroup) findViewById(R.id.batteryInfo);
|
||||
mBatteryInfoIcon = (ImageView) findViewById(R.id.batteryInfoIcon);
|
||||
mBatteryInfoText = (TextView) findViewById(R.id.batteryInfoText);
|
||||
mBatteryInfoSpacer = findViewById(R.id.batteryInfoSpacer);
|
||||
|
||||
mNextAlarmGroup = (ViewGroup) findViewById(R.id.nextAlarmInfo);
|
||||
mAlarmText = (TextView) findViewById(R.id.nextAlarmText);
|
||||
mAlarmSpacer = findViewById(R.id.nextAlarmSpacer);
|
||||
|
||||
mScreenLockedMessageGroup = (ViewGroup) findViewById(R.id.screenLockedInfo);
|
||||
|
||||
mLockInstructions = (TextView) findViewById(R.id.lockInstructions);
|
||||
mStatus1 = (TextView) findViewById(R.id.status1);
|
||||
mStatus2 = (TextView) findViewById(R.id.status2);
|
||||
|
||||
mEmergencyCallButton = (Button) findViewById(R.id.emergencyCallButton);
|
||||
|
||||
mEmergencyCallButton.setText(R.string.lockscreen_emergency_call);
|
||||
mScreenLocked = (TextView) findViewById(R.id.screenLocked);
|
||||
mRotary = (RotarySelector) findViewById(R.id.rotary);
|
||||
mEmergencyCallButton.setOnClickListener(new View.OnClickListener() {
|
||||
public void onClick(View v) {
|
||||
mCallback.takeEmergencyCallAction();
|
||||
}
|
||||
});
|
||||
|
||||
mOnlyVisibleWhenSimOk = new View[] {
|
||||
mHeaderSimOk1,
|
||||
mHeaderSimOk2,
|
||||
mBatteryInfoGroup,
|
||||
mBatteryInfoSpacer,
|
||||
mNextAlarmGroup,
|
||||
mAlarmSpacer,
|
||||
mScreenLockedMessageGroup,
|
||||
mLockInstructions
|
||||
};
|
||||
|
||||
mOnlyVisibleWhenSimNotOk = new View[] {
|
||||
mHeaderSimBad1,
|
||||
mHeaderSimBad2,
|
||||
mEmergencyCallButton
|
||||
};
|
||||
|
||||
setFocusable(true);
|
||||
setFocusableInTouchMode(true);
|
||||
setDescendantFocusability(ViewGroup.FOCUS_BLOCK_DESCENDANTS);
|
||||
|
||||
refreshBatteryDisplay();
|
||||
refreshAlarmDisplay();
|
||||
refreshTimeAndDateDisplay();
|
||||
refreshUnlockIntructions();
|
||||
refreshViewsWRTSimOk();
|
||||
refreshSimOkHeaders(mUpdateMonitor.getTelephonyPlmn(), mUpdateMonitor.getTelephonySpn());
|
||||
|
||||
updateMonitor.registerInfoCallback(this);
|
||||
updateMonitor.registerSimStateCallback(this);
|
||||
updateMonitor.registerConfigurationChangeCallback(this);
|
||||
|
||||
mAudioManager = (AudioManager) getContext().getSystemService(Context.AUDIO_SERVICE);
|
||||
mSilentMode = mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_SILENT;
|
||||
|
||||
mRotary.setOnDialTriggerListener(this);
|
||||
mRotary.setLeftHandleResource(R.drawable.ic_jog_dial_unlock);
|
||||
mRotary.setRightHandleResource(mSilentMode ?
|
||||
R.drawable.ic_jog_dial_sound_off :
|
||||
R.drawable.ic_jog_dial_sound_on);
|
||||
|
||||
resetStatusInfo(updateMonitor);
|
||||
}
|
||||
|
||||
private void resetStatusInfo(KeyguardUpdateMonitor updateMonitor) {
|
||||
mShowingBatteryInfo = updateMonitor.shouldShowBatteryInfo();
|
||||
mPluggedIn = updateMonitor.isDevicePluggedIn();
|
||||
mBatteryLevel = updateMonitor.getBatteryLevel();
|
||||
|
||||
mStatus = getCurrentStatus(updateMonitor.getSimState());
|
||||
updateLayout(mStatus);
|
||||
|
||||
refreshBatteryStringAndIcon();
|
||||
refreshAlarmDisplay();
|
||||
|
||||
mTimeFormat = DateFormat.getTimeFormat(getContext());
|
||||
mDateFormat = getLockScreenDateFormat();
|
||||
refreshTimeAndDateDisplay();
|
||||
updateStatusLines();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_MENU) {
|
||||
if (keyCode == KeyEvent.KEYCODE_MENU && mEnableMenuKeyInLockScreen) {
|
||||
mCallback.goToUnlockScreen();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private void refreshViewsWRTSimOk() {
|
||||
if (mSimOk) {
|
||||
for (int i = 0; i < mOnlyVisibleWhenSimOk.length; i++) {
|
||||
final View view = mOnlyVisibleWhenSimOk[i];
|
||||
if (view == null) throw new RuntimeException("index " + i + " null");
|
||||
view.setVisibility(View.VISIBLE);
|
||||
}
|
||||
for (int i = 0; i < mOnlyVisibleWhenSimNotOk.length; i++) {
|
||||
final View view = mOnlyVisibleWhenSimNotOk[i];
|
||||
view.setVisibility(View.GONE);
|
||||
}
|
||||
refreshSimOkHeaders(mUpdateMonitor.getTelephonyPlmn(),
|
||||
mUpdateMonitor.getTelephonySpn());
|
||||
refreshAlarmDisplay();
|
||||
refreshBatteryDisplay();
|
||||
} else {
|
||||
for (int i = 0; i < mOnlyVisibleWhenSimOk.length; i++) {
|
||||
final View view = mOnlyVisibleWhenSimOk[i];
|
||||
view.setVisibility(View.GONE);
|
||||
}
|
||||
for (int i = 0; i < mOnlyVisibleWhenSimNotOk.length; i++) {
|
||||
final View view = mOnlyVisibleWhenSimNotOk[i];
|
||||
view.setVisibility(View.VISIBLE);
|
||||
}
|
||||
refreshSimBadInfo();
|
||||
/** {@inheritDoc} */
|
||||
public void onDialTrigger(View v, int whichHandle) {
|
||||
if (whichHandle == RotarySelector.OnDialTriggerListener.LEFT_HANDLE) {
|
||||
mCallback.goToUnlockScreen();
|
||||
} else if (whichHandle == RotarySelector.OnDialTriggerListener.RIGHT_HANDLE) {
|
||||
// toggle silent mode
|
||||
mSilentMode = !mSilentMode;
|
||||
mAudioManager.setRingerMode(mSilentMode ? AudioManager.RINGER_MODE_SILENT
|
||||
: AudioManager.RINGER_MODE_NORMAL);
|
||||
final int handleIcon = mSilentMode ?
|
||||
R.drawable.ic_jog_dial_sound_off :
|
||||
R.drawable.ic_jog_dial_sound_on;
|
||||
final int toastIcon = mSilentMode ?
|
||||
R.drawable.ic_lock_ringer_off :
|
||||
R.drawable.ic_lock_ringer_on;
|
||||
mRotary.setRightHandleResource(handleIcon);
|
||||
String message = mSilentMode ?
|
||||
getContext().getString(R.string.global_action_silent_mode_on_status) :
|
||||
getContext().getString(R.string.global_action_silent_mode_off_status);
|
||||
toastMessage(mScreenLocked, message, toastIcon);
|
||||
mCallback.pokeWakelock();
|
||||
}
|
||||
}
|
||||
|
||||
private void refreshSimBadInfo() {
|
||||
final IccCard.State simState = mUpdateMonitor.getSimState();
|
||||
if (simState == IccCard.State.PUK_REQUIRED) {
|
||||
mHeaderSimBad1.setText(R.string.lockscreen_sim_puk_locked_message);
|
||||
mHeaderSimBad2.setText(R.string.lockscreen_sim_puk_locked_instructions);
|
||||
} else if (simState == IccCard.State.ABSENT) {
|
||||
mHeaderSimBad1.setText(R.string.lockscreen_missing_sim_message);
|
||||
mHeaderSimBad2.setVisibility(View.GONE);
|
||||
//mHeaderSimBad2.setText(R.string.lockscreen_missing_sim_instructions);
|
||||
} else {
|
||||
mHeaderSimBad1.setVisibility(View.GONE);
|
||||
mHeaderSimBad2.setVisibility(View.GONE);
|
||||
}
|
||||
/** {@inheritDoc} */
|
||||
public void onGrabbedStateChange(View v, int grabbedState) {
|
||||
// TODO: Update onscreen hint text based on the new state.
|
||||
}
|
||||
|
||||
private void refreshUnlockIntructions() {
|
||||
if (mLockPatternUtils.isLockPatternEnabled()
|
||||
|| mUpdateMonitor.getSimState() == IccCard.State.PIN_REQUIRED
|
||||
|| mUpdateMonitor.getSimState() == IccCard.State.ABSENT) {
|
||||
mLockInstructions.setText(R.string.lockscreen_instructions_when_pattern_enabled);
|
||||
} else {
|
||||
mLockInstructions.setText(R.string.lockscreen_instructions_when_pattern_disabled);
|
||||
/**
|
||||
* Displays a message in a text view and then removes it.
|
||||
* @param textView The text view.
|
||||
* @param text The text.
|
||||
* @param iconResourceId The left hand icon.
|
||||
*/
|
||||
private void toastMessage(final TextView textView, final String text, final int iconResourceId) {
|
||||
if (mPendingR1 != null) {
|
||||
textView.removeCallbacks(mPendingR1);
|
||||
mPendingR1 = null;
|
||||
}
|
||||
if (mPendingR2 != null) {
|
||||
textView.removeCallbacks(mPendingR2);
|
||||
mPendingR2 = null;
|
||||
}
|
||||
|
||||
mPendingR1 = new Runnable() {
|
||||
public void run() {
|
||||
textView.setText(text);
|
||||
textView.setCompoundDrawablesWithIntrinsicBounds(iconResourceId, 0, 0, 0);
|
||||
textView.setCompoundDrawablePadding(4);
|
||||
}
|
||||
};
|
||||
textView.postDelayed(mPendingR1, 0);
|
||||
mPendingR2 = new Runnable() {
|
||||
public void run() {
|
||||
textView.setText("");
|
||||
textView.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
|
||||
}
|
||||
};
|
||||
textView.postDelayed(mPendingR2, 3500);
|
||||
}
|
||||
private Runnable mPendingR1;
|
||||
private Runnable mPendingR2;
|
||||
|
||||
|
||||
private void refreshAlarmDisplay() {
|
||||
final String nextAlarmText = mLockPatternUtils.getNextAlarm();
|
||||
|
||||
// bug 1685880: if we are in landscape and showing plmn, the information can end up not
|
||||
// fitting on screen. in this case, the alarm will get cut.
|
||||
final CharSequence plmn = mUpdateMonitor.getTelephonyPlmn();
|
||||
final boolean showingPlmn = plmn != null && !TextUtils.isEmpty(plmn);
|
||||
final boolean wontFit = !mUpdateMonitor.isInPortrait() && showingPlmn;
|
||||
if (nextAlarmText != null && mSimOk && !wontFit) {
|
||||
setAlarmInfoVisible(true);
|
||||
mAlarmText.setText(nextAlarmText);
|
||||
} else {
|
||||
setAlarmInfoVisible(false);
|
||||
mNextAlarm = mLockPatternUtils.getNextAlarm();
|
||||
if (mNextAlarm != null) {
|
||||
mAlarmIcon = getContext().getResources().getDrawable(R.drawable.ic_lock_idle_alarm);
|
||||
}
|
||||
updateStatusLines();
|
||||
}
|
||||
|
||||
private void setAlarmInfoVisible(boolean visible) {
|
||||
final int visibilityFlag = visible ? View.VISIBLE : View.GONE;
|
||||
mNextAlarmGroup.setVisibility(visibilityFlag);
|
||||
mAlarmSpacer.setVisibility(visibilityFlag);
|
||||
}
|
||||
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn,
|
||||
int batteryLevel) {
|
||||
if (DBG) Log.d(TAG, "onRefreshBatteryInfo(" + showBatteryInfo + ", " + pluggedIn + ")");
|
||||
mShowingBatteryInfo = showBatteryInfo;
|
||||
mPluggedIn = pluggedIn;
|
||||
mBatteryLevel = batteryLevel;
|
||||
|
||||
refreshBatteryDisplay();
|
||||
refreshBatteryStringAndIcon();
|
||||
updateStatusLines();
|
||||
}
|
||||
|
||||
private void refreshBatteryDisplay() {
|
||||
if (!mShowingBatteryInfo || !mSimOk) {
|
||||
mBatteryInfoGroup.setVisibility(View.GONE);
|
||||
mBatteryInfoSpacer.setVisibility(View.GONE);
|
||||
private void refreshBatteryStringAndIcon() {
|
||||
if (!mShowingBatteryInfo) {
|
||||
mCharging = null;
|
||||
return;
|
||||
}
|
||||
mBatteryInfoGroup.setVisibility(View.VISIBLE);
|
||||
mBatteryInfoSpacer.setVisibility(View.VISIBLE);
|
||||
|
||||
if (mChargingIcon == null) {
|
||||
mChargingIcon =
|
||||
getContext().getResources().getDrawable(R.drawable.ic_lock_idle_charging);
|
||||
}
|
||||
|
||||
if (mPluggedIn) {
|
||||
mBatteryInfoIcon.setImageResource(R.drawable.ic_lock_idle_charging);
|
||||
if (mBatteryLevel >= 100) {
|
||||
mBatteryInfoText.setText(R.string.lockscreen_charged);
|
||||
mCharging = getContext().getString(R.string.lockscreen_charged);
|
||||
} else {
|
||||
mBatteryInfoText.setText(
|
||||
getContext().getString(R.string.lockscreen_plugged_in, mBatteryLevel));
|
||||
mCharging = getContext().getString(R.string.lockscreen_plugged_in, mBatteryLevel);
|
||||
}
|
||||
} else {
|
||||
mBatteryInfoIcon.setImageResource(R.drawable.ic_lock_idle_low_battery);
|
||||
mBatteryInfoText.setText(R.string.lockscreen_low_battery);
|
||||
mCharging = getContext().getString(R.string.lockscreen_low_battery);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void onTimeChanged() {
|
||||
refreshTimeAndDateDisplay();
|
||||
}
|
||||
|
||||
private void refreshTimeAndDateDisplay() {
|
||||
Date now = new Date();
|
||||
mTime.setText(DateFormat.getTimeFormat(getContext()).format(now));
|
||||
mDate.setText(DateFormat.getDateFormat(getContext()).format(now));
|
||||
mTime.setText(mTimeFormat.format(now));
|
||||
mDate.setText(mDateFormat.format(now));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return A localized format like "Fri, Sep 18, 2009"
|
||||
*/
|
||||
private java.text.DateFormat getLockScreenDateFormat() {
|
||||
SimpleDateFormat adjusted = null;
|
||||
try {
|
||||
// this call gives us the localized order
|
||||
final SimpleDateFormat dateFormat = (SimpleDateFormat)
|
||||
java.text.DateFormat.getDateInstance(java.text.DateFormat.FULL);
|
||||
adjusted = new SimpleDateFormat(dateFormat.toPattern()
|
||||
.replace("MMMM", "MMM") // we want "Sep", not "September"
|
||||
.replace("EEEE", "EEE")); // we want "Fri", no "Friday"
|
||||
} catch (ClassCastException e) {
|
||||
// in case the library implementation changes and this throws a class cast exception
|
||||
// or anything else that is funky
|
||||
Log.e("LockScreen", "couldn't finnagle our custom date format :(", e);
|
||||
return java.text.DateFormat.getDateInstance(java.text.DateFormat.MEDIUM);
|
||||
}
|
||||
return adjusted;
|
||||
}
|
||||
|
||||
private void updateStatusLines() {
|
||||
if (!mStatus.showStatusLines()
|
||||
|| (mCharging == null && mNextAlarm == null)) {
|
||||
mStatus1.setVisibility(View.INVISIBLE);
|
||||
mStatus2.setVisibility(View.INVISIBLE);
|
||||
} else if (mCharging != null && mNextAlarm == null) {
|
||||
// charging only
|
||||
mStatus1.setVisibility(View.VISIBLE);
|
||||
mStatus2.setVisibility(View.INVISIBLE);
|
||||
|
||||
mStatus1.setText(mCharging);
|
||||
mStatus1.setCompoundDrawablesWithIntrinsicBounds(mChargingIcon, null, null, null);
|
||||
} else if (mNextAlarm != null && mCharging == null) {
|
||||
// next alarm only
|
||||
mStatus1.setVisibility(View.VISIBLE);
|
||||
mStatus2.setVisibility(View.INVISIBLE);
|
||||
|
||||
mStatus1.setText(mNextAlarm);
|
||||
mStatus1.setCompoundDrawablesWithIntrinsicBounds(mAlarmIcon, null, null, null);
|
||||
} else if (mCharging != null && mNextAlarm != null) {
|
||||
// both charging and next alarm
|
||||
mStatus1.setVisibility(View.VISIBLE);
|
||||
mStatus2.setVisibility(View.VISIBLE);
|
||||
|
||||
mStatus1.setText(mCharging);
|
||||
mStatus1.setCompoundDrawablesWithIntrinsicBounds(mChargingIcon, null, null, null);
|
||||
mStatus2.setText(mNextAlarm);
|
||||
mStatus2.setCompoundDrawablesWithIntrinsicBounds(mAlarmIcon, null, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
|
||||
refreshSimOkHeaders(plmn, spn);
|
||||
refreshAlarmDisplay(); // in case alarm won't fit anymore
|
||||
if (DBG) Log.d(TAG, "onRefreshCarrierInfo(" + plmn + ", " + spn + ")");
|
||||
updateLayout(mStatus);
|
||||
}
|
||||
|
||||
private void refreshSimOkHeaders(CharSequence plmn, CharSequence spn) {
|
||||
final IccCard.State simState = mUpdateMonitor.getSimState();
|
||||
if (simState == IccCard.State.READY) {
|
||||
if (plmn != null && !TextUtils.isEmpty(plmn)) {
|
||||
mHeaderSimOk1.setVisibility(View.VISIBLE);
|
||||
mHeaderSimOk1.setText(plmn);
|
||||
} else {
|
||||
mHeaderSimOk1.setVisibility(View.GONE);
|
||||
}
|
||||
private void putEmergencyBelow(int viewId) {
|
||||
final RelativeLayout.LayoutParams layoutParams =
|
||||
(RelativeLayout.LayoutParams) mEmergencyCallButton.getLayoutParams();
|
||||
layoutParams.addRule(RelativeLayout.BELOW, viewId);
|
||||
mEmergencyCallButton.setLayoutParams(layoutParams);
|
||||
}
|
||||
|
||||
if (spn != null && !TextUtils.isEmpty(spn)) {
|
||||
mHeaderSimOk2.setVisibility(View.VISIBLE);
|
||||
mHeaderSimOk2.setText(spn);
|
||||
} else {
|
||||
mHeaderSimOk2.setVisibility(View.GONE);
|
||||
}
|
||||
} else if (simState == IccCard.State.PIN_REQUIRED) {
|
||||
mHeaderSimOk1.setVisibility(View.VISIBLE);
|
||||
mHeaderSimOk1.setText(R.string.lockscreen_sim_locked_message);
|
||||
mHeaderSimOk2.setVisibility(View.GONE);
|
||||
} else if (simState == IccCard.State.ABSENT) {
|
||||
mHeaderSimOk1.setVisibility(View.VISIBLE);
|
||||
mHeaderSimOk1.setText(R.string.lockscreen_missing_sim_message_short);
|
||||
mHeaderSimOk2.setVisibility(View.GONE);
|
||||
} else if (simState == IccCard.State.NETWORK_LOCKED) {
|
||||
mHeaderSimOk1.setVisibility(View.VISIBLE);
|
||||
mHeaderSimOk1.setText(R.string.lockscreen_network_locked_message);
|
||||
mHeaderSimOk2.setVisibility(View.GONE);
|
||||
/**
|
||||
* Determine the current status of the lock screen given the sim state and other stuff.
|
||||
*/
|
||||
private Status getCurrentStatus(IccCard.State simState) {
|
||||
boolean missingAndNotProvisioned = (!mUpdateMonitor.isDeviceProvisioned()
|
||||
&& simState == IccCard.State.ABSENT);
|
||||
if (missingAndNotProvisioned) {
|
||||
return Status.SimMissingLocked;
|
||||
}
|
||||
|
||||
switch (simState) {
|
||||
case ABSENT:
|
||||
return Status.SimMissing;
|
||||
case NETWORK_LOCKED:
|
||||
return Status.SimMissingLocked;
|
||||
case NOT_READY:
|
||||
return Status.SimMissing;
|
||||
case PIN_REQUIRED:
|
||||
return Status.SimLocked;
|
||||
case PUK_REQUIRED:
|
||||
return Status.SimPukLocked;
|
||||
case READY:
|
||||
return Status.Normal;
|
||||
case UNKNOWN:
|
||||
return Status.SimMissing;
|
||||
}
|
||||
return Status.SimMissing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the layout to match the current status.
|
||||
*/
|
||||
private void updateLayout(Status status) {
|
||||
switch (status) {
|
||||
case Normal:
|
||||
// text
|
||||
mCarrier.setText(
|
||||
getCarrierString(
|
||||
mUpdateMonitor.getTelephonyPlmn(),
|
||||
mUpdateMonitor.getTelephonySpn()));
|
||||
// mScreenLocked.setText(R.string.lockscreen_screen_locked);
|
||||
|
||||
// layout
|
||||
mScreenLocked.setVisibility(View.VISIBLE);
|
||||
mRotary.setVisibility(View.VISIBLE);
|
||||
mEmergencyCallButton.setVisibility(View.GONE);
|
||||
break;
|
||||
case NetworkLocked:
|
||||
// text
|
||||
mCarrier.setText(R.string.lockscreen_network_locked_message);
|
||||
mScreenLocked.setText(R.string.lockscreen_instructions_when_pattern_disabled);
|
||||
|
||||
// layout
|
||||
mScreenLocked.setVisibility(View.VISIBLE);
|
||||
mRotary.setVisibility(View.VISIBLE);
|
||||
mEmergencyCallButton.setVisibility(View.GONE);
|
||||
break;
|
||||
case SimMissing:
|
||||
// text
|
||||
mCarrier.setText(R.string.lockscreen_missing_sim_message_short);
|
||||
mScreenLocked.setText(R.string.lockscreen_instructions_when_pattern_disabled);
|
||||
|
||||
// layout
|
||||
mScreenLocked.setVisibility(View.INVISIBLE);
|
||||
mRotary.setVisibility(View.VISIBLE);
|
||||
mEmergencyCallButton.setVisibility(View.VISIBLE);
|
||||
putEmergencyBelow(R.id.divider);
|
||||
break;
|
||||
case SimMissingLocked:
|
||||
// text
|
||||
mCarrier.setText(R.string.lockscreen_missing_sim_message_short);
|
||||
mScreenLocked.setText(R.string.lockscreen_missing_sim_instructions);
|
||||
|
||||
// layout
|
||||
mScreenLocked.setVisibility(View.VISIBLE);
|
||||
mRotary.setVisibility(View.GONE);
|
||||
mEmergencyCallButton.setVisibility(View.VISIBLE);
|
||||
putEmergencyBelow(R.id.screenLocked);
|
||||
break;
|
||||
case SimLocked:
|
||||
// text
|
||||
mCarrier.setText(R.string.lockscreen_sim_locked_message);
|
||||
|
||||
// layout
|
||||
mScreenLocked.setVisibility(View.INVISIBLE);
|
||||
mRotary.setVisibility(View.VISIBLE);
|
||||
mEmergencyCallButton.setVisibility(View.GONE);
|
||||
break;
|
||||
case SimPukLocked:
|
||||
// text
|
||||
mCarrier.setText(R.string.lockscreen_sim_puk_locked_message);
|
||||
mScreenLocked.setText(R.string.lockscreen_sim_puk_locked_instructions);
|
||||
|
||||
// layout
|
||||
mScreenLocked.setVisibility(View.VISIBLE);
|
||||
mRotary.setVisibility(View.GONE);
|
||||
mEmergencyCallButton.setVisibility(View.VISIBLE);
|
||||
putEmergencyBelow(R.id.screenLocked);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static CharSequence getCarrierString(CharSequence telephonyPlmn, CharSequence telephonySpn) {
|
||||
if (telephonyPlmn != null && telephonySpn == null) {
|
||||
return telephonyPlmn;
|
||||
} else if (telephonyPlmn != null && telephonySpn != null) {
|
||||
return telephonyPlmn + "\n" + telephonySpn;
|
||||
} else if (telephonyPlmn == null && telephonySpn != null) {
|
||||
return telephonySpn;
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
public void onSimStateChanged(IccCard.State simState) {
|
||||
mSimOk = isSimOk(simState);
|
||||
refreshViewsWRTSimOk();
|
||||
refreshUnlockIntructions();
|
||||
if (DBG) Log.d(TAG, "onSimStateChanged(" + simState + ")");
|
||||
mStatus = getCurrentStatus(simState);
|
||||
updateLayout(mStatus);
|
||||
updateStatusLines();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether the sim state is ok, meaning we don't need to show
|
||||
* a special screen with the emergency call button and keep them from
|
||||
* doing anything else.
|
||||
*/
|
||||
private boolean isSimOk(IccCard.State simState) {
|
||||
boolean missingAndNotProvisioned = (!mUpdateMonitor.isDeviceProvisioned()
|
||||
&& simState == IccCard.State.ABSENT);
|
||||
return !(missingAndNotProvisioned || simState == IccCard.State.PUK_REQUIRED);
|
||||
}
|
||||
|
||||
public void onOrientationChange(boolean inPortrait) {
|
||||
if (inPortrait != mCreatedInPortrait) {
|
||||
mCallback.recreateMe();
|
||||
}
|
||||
}
|
||||
|
||||
public void onKeyboardChange(boolean isKeyboardOpen) {
|
||||
if (isKeyboardOpen) {
|
||||
if (mUpdateMonitor.isKeyguardBypassEnabled() && isKeyboardOpen) {
|
||||
mCallback.goToUnlockScreen();
|
||||
}
|
||||
}
|
||||
@@ -376,7 +571,7 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void onResume() {
|
||||
|
||||
resetStatusInfo(mUpdateMonitor);
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
@@ -384,4 +579,3 @@ class LockScreen extends LinearLayout implements KeyguardScreen, KeyguardUpdateM
|
||||
mUpdateMonitor.removeCallback(this);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@ import static android.view.ViewGroup.LayoutParams.WRAP_CONTENT;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_FULLSCREEN;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_INSET_DECOR;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN;
|
||||
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
|
||||
|
||||
import com.android.internal.view.menu.ContextMenuBuilder;
|
||||
import com.android.internal.view.menu.MenuBuilder;
|
||||
@@ -34,7 +35,6 @@ import android.content.Intent;
|
||||
import android.content.res.Configuration;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Paint;
|
||||
import android.graphics.PixelFormat;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
@@ -124,6 +124,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
* this is 0, there is no key held down.
|
||||
*/
|
||||
private int mPanelChordingKey;
|
||||
private boolean mPanelMayLongPress;
|
||||
|
||||
private ImageView mLeftIconView;
|
||||
|
||||
@@ -155,120 +156,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
|
||||
private TelephonyManager mTelephonyManager = null;
|
||||
|
||||
private boolean mSearchKeyDownReceived;
|
||||
|
||||
private boolean mKeycodeCallTimeoutActive = false;
|
||||
|
||||
private boolean mKeycodeCameraTimeoutActive = false;
|
||||
|
||||
static final int MSG_MENU_LONG_PRESS = 1;
|
||||
static final int MSG_MENU_LONG_PRESS_COMPLETE = 2;
|
||||
static final int MSG_CALL_LONG_PRESS = 3;
|
||||
static final int MSG_CALL_LONG_PRESS_COMPLETE = 4;
|
||||
static final int MSG_CAMERA_LONG_PRESS = 5;
|
||||
static final int MSG_CAMERA_LONG_PRESS_COMPLETE = 6;
|
||||
static final int MSG_SEARCH_LONG_PRESS = 7;
|
||||
static final int MSG_SEARCH_LONG_PRESS_COMPLETE = 8;
|
||||
|
||||
private final Handler mKeycodeMenuTimeoutHandler = new Handler() {
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
switch (msg.what) {
|
||||
case MSG_MENU_LONG_PRESS: {
|
||||
if (mPanelChordingKey == 0) return;
|
||||
// Before actually doing the long press, enqueue another
|
||||
// message and do the processing there. This helps if
|
||||
// the app isn't being responsive, and finally woke up --
|
||||
// if the window manager wasn't told about it processing
|
||||
// the down key for too long, it would enqueue the key up
|
||||
// at a time after the timeout of this message. So we go
|
||||
// through another message, to make sure we process an up
|
||||
// before continuing.
|
||||
mKeycodeMenuTimeoutHandler.sendEmptyMessage(
|
||||
MSG_MENU_LONG_PRESS_COMPLETE);
|
||||
break;
|
||||
}
|
||||
case MSG_CALL_LONG_PRESS: {
|
||||
if (!mKeycodeCallTimeoutActive) return;
|
||||
// See above.
|
||||
mKeycodeMenuTimeoutHandler.sendEmptyMessage(
|
||||
MSG_CALL_LONG_PRESS_COMPLETE);
|
||||
break;
|
||||
}
|
||||
case MSG_CAMERA_LONG_PRESS: {
|
||||
if (!mKeycodeCameraTimeoutActive) return;
|
||||
// See above.
|
||||
Message newMessage = Message.obtain(msg);
|
||||
newMessage.what = MSG_CAMERA_LONG_PRESS_COMPLETE;
|
||||
mKeycodeMenuTimeoutHandler.sendMessage(newMessage);
|
||||
break;
|
||||
}
|
||||
case MSG_SEARCH_LONG_PRESS: {
|
||||
if (!mSearchKeyDownReceived) return;
|
||||
// See above.
|
||||
Message newMessage = Message.obtain(msg);
|
||||
newMessage.what = MSG_SEARCH_LONG_PRESS_COMPLETE;
|
||||
mKeycodeMenuTimeoutHandler.sendMessage(newMessage);
|
||||
break;
|
||||
}
|
||||
case MSG_MENU_LONG_PRESS_COMPLETE: {
|
||||
if (mPanelChordingKey == 0) return;
|
||||
mPanelChordingKey = 0;
|
||||
mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||
InputMethodManager imm = (InputMethodManager)
|
||||
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
if (imm != null) {
|
||||
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
|
||||
}
|
||||
} break;
|
||||
case MSG_CALL_LONG_PRESS_COMPLETE: {
|
||||
if (!mKeycodeCallTimeoutActive) return;
|
||||
mKeycodeCallTimeoutActive = false;
|
||||
mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||
// launch the VoiceDialer
|
||||
Intent intent = new Intent(Intent.ACTION_VOICE_COMMAND);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
try {
|
||||
sendCloseSystemWindows();
|
||||
getContext().startActivity(intent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
startCallActivity();
|
||||
}
|
||||
} break;
|
||||
case MSG_CAMERA_LONG_PRESS_COMPLETE: {
|
||||
if (!mKeycodeCameraTimeoutActive) return;
|
||||
mKeycodeCameraTimeoutActive = false;
|
||||
mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||
sendCloseSystemWindows();
|
||||
// Broadcast an intent that the Camera button was longpressed
|
||||
Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null);
|
||||
intent.putExtra(Intent.EXTRA_KEY_EVENT, (KeyEvent) msg.obj);
|
||||
getContext().sendOrderedBroadcast(intent, null);
|
||||
} break;
|
||||
case MSG_SEARCH_LONG_PRESS_COMPLETE: {
|
||||
if (getKeyguardManager().inKeyguardRestrictedInputMode() ||
|
||||
!mSearchKeyDownReceived) {
|
||||
mSearchKeyDownReceived = false;
|
||||
return;
|
||||
}
|
||||
mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||
// launch the search activity
|
||||
Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
try {
|
||||
sendCloseSystemWindows();
|
||||
getContext().startActivity(intent);
|
||||
// Only clear this if we successfully start the
|
||||
// activity; otherwise we will allow the normal short
|
||||
// press action to be performed.
|
||||
mSearchKeyDownReceived = false;
|
||||
} catch (ActivityNotFoundException e) {
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
public PhoneWindow(Context context) {
|
||||
super(context);
|
||||
mLayoutInflater = LayoutInflater.from(context);
|
||||
@@ -295,11 +182,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
/* 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);
|
||||
}
|
||||
|
||||
@@ -567,7 +452,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
|
||||
WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
|
||||
WRAP_CONTENT, WRAP_CONTENT,
|
||||
st.x, st.y, WindowManager.LayoutParams.TYPE_APPLICATION_PANEL,
|
||||
st.x, st.y, WindowManager.LayoutParams.TYPE_APPLICATION_ATTACHED_DIALOG,
|
||||
WindowManager.LayoutParams.FLAG_DITHER
|
||||
| WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
|
||||
st.decorView.mDefaultOpacity);
|
||||
@@ -649,19 +534,35 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
* @return Whether the key was handled.
|
||||
*/
|
||||
public final boolean onKeyDownPanel(int featureId, KeyEvent event) {
|
||||
// The panel key was pushed, so set the chording key
|
||||
mPanelChordingKey = event.getKeyCode();
|
||||
|
||||
PanelFeatureState st = getPanelState(featureId, true);
|
||||
if (!st.isOpen) {
|
||||
if (getContext().getResources().getConfiguration().keyboard
|
||||
== Configuration.KEYBOARD_NOKEYS) {
|
||||
mKeycodeMenuTimeoutHandler.removeMessages(MSG_MENU_LONG_PRESS);
|
||||
mKeycodeMenuTimeoutHandler.sendMessageDelayed(
|
||||
mKeycodeMenuTimeoutHandler.obtainMessage(MSG_MENU_LONG_PRESS),
|
||||
ViewConfiguration.getLongPressTimeout());
|
||||
final int keyCode = event.getKeyCode();
|
||||
|
||||
if (event.getRepeatCount() == 0) {
|
||||
// The panel key was pushed, so set the chording key
|
||||
mPanelChordingKey = keyCode;
|
||||
mPanelMayLongPress = false;
|
||||
|
||||
PanelFeatureState st = getPanelState(featureId, true);
|
||||
if (!st.isOpen) {
|
||||
if (getContext().getResources().getConfiguration().keyboard
|
||||
== Configuration.KEYBOARD_NOKEYS) {
|
||||
mPanelMayLongPress = true;
|
||||
}
|
||||
return preparePanel(st, event);
|
||||
}
|
||||
return preparePanel(st, event);
|
||||
|
||||
} else if (mPanelMayLongPress && mPanelChordingKey == keyCode
|
||||
&& (event.getFlags()&KeyEvent.FLAG_LONG_PRESS) != 0) {
|
||||
// We have had a long press while in a state where this
|
||||
// should be executed... do it!
|
||||
mPanelChordingKey = 0;
|
||||
mPanelMayLongPress = false;
|
||||
InputMethodManager imm = (InputMethodManager)
|
||||
getContext().getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
if (imm != null) {
|
||||
mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||
imm.toggleSoftInput(InputMethodManager.SHOW_FORCED, 0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -676,8 +577,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
// The panel key was released, so clear the chording key
|
||||
if (mPanelChordingKey != 0) {
|
||||
mPanelChordingKey = 0;
|
||||
mKeycodeMenuTimeoutHandler.removeMessages(MSG_MENU_LONG_PRESS);
|
||||
mPanelMayLongPress = false;
|
||||
|
||||
if (event.isCanceled()) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean playSoundEffect = false;
|
||||
PanelFeatureState st = getPanelState(featureId, true);
|
||||
if (st.isOpen || st.isHandled) {
|
||||
@@ -1214,6 +1119,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
* @see android.view.KeyEvent
|
||||
*/
|
||||
protected boolean onKeyDown(int featureId, int keyCode, KeyEvent event) {
|
||||
final KeyEvent.DispatcherState dispatcher =
|
||||
mDecor != null ? mDecor.getKeyDispatcherState() : null;
|
||||
//Log.i(TAG, "Key down: repeat=" + event.getRepeatCount()
|
||||
// + " flags=0x" + Integer.toHexString(event.getFlags()));
|
||||
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_VOLUME_UP:
|
||||
case KeyEvent.KEYCODE_VOLUME_DOWN: {
|
||||
@@ -1260,21 +1170,25 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
}
|
||||
|
||||
case KeyEvent.KEYCODE_CAMERA: {
|
||||
if (getKeyguardManager().inKeyguardRestrictedInputMode()) {
|
||||
if (getKeyguardManager().inKeyguardRestrictedInputMode()
|
||||
|| dispatcher == null) {
|
||||
break;
|
||||
}
|
||||
if (event.getRepeatCount() > 0) break;
|
||||
mKeycodeCameraTimeoutActive = true;
|
||||
mKeycodeMenuTimeoutHandler.removeMessages(MSG_CAMERA_LONG_PRESS);
|
||||
Message message = mKeycodeMenuTimeoutHandler.obtainMessage(MSG_CAMERA_LONG_PRESS);
|
||||
message.obj = event;
|
||||
mKeycodeMenuTimeoutHandler.sendMessageDelayed(message,
|
||||
ViewConfiguration.getLongPressTimeout());
|
||||
if (event.getRepeatCount() == 0) {
|
||||
dispatcher.startTracking(event, this);
|
||||
} else if (event.isLongPress() && dispatcher.isTracking(event)) {
|
||||
dispatcher.performedLongPress(event);
|
||||
mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||
sendCloseSystemWindows();
|
||||
// Broadcast an intent that the Camera button was longpressed
|
||||
Intent intent = new Intent(Intent.ACTION_CAMERA_BUTTON, null);
|
||||
intent.putExtra(Intent.EXTRA_KEY_EVENT, event);
|
||||
getContext().sendOrderedBroadcast(intent, null);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case KeyEvent.KEYCODE_MENU: {
|
||||
if (event.getRepeatCount() > 0) break;
|
||||
onKeyDownPanel((featureId < 0) ? FEATURE_OPTIONS_PANEL : featureId, event);
|
||||
return true;
|
||||
}
|
||||
@@ -1282,48 +1196,61 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
case KeyEvent.KEYCODE_BACK: {
|
||||
if (event.getRepeatCount() > 0) break;
|
||||
if (featureId < 0) break;
|
||||
if (featureId == FEATURE_OPTIONS_PANEL) {
|
||||
PanelFeatureState st = getPanelState(featureId, false);
|
||||
if (st != null && st.isInExpandedMode) {
|
||||
// If the user is in an expanded menu and hits back, it
|
||||
// should go back to the icon menu
|
||||
reopenMenu(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
closePanel(featureId);
|
||||
// Currently don't do anything with long press.
|
||||
dispatcher.startTracking(event, this);
|
||||
return true;
|
||||
}
|
||||
|
||||
case KeyEvent.KEYCODE_CALL: {
|
||||
if (getKeyguardManager().inKeyguardRestrictedInputMode()) {
|
||||
if (getKeyguardManager().inKeyguardRestrictedInputMode()
|
||||
|| dispatcher == null) {
|
||||
break;
|
||||
}
|
||||
if (event.getRepeatCount() > 0) break;
|
||||
mKeycodeCallTimeoutActive = true;
|
||||
mKeycodeMenuTimeoutHandler.removeMessages(MSG_CALL_LONG_PRESS);
|
||||
mKeycodeMenuTimeoutHandler.sendMessageDelayed(
|
||||
mKeycodeMenuTimeoutHandler.obtainMessage(MSG_CALL_LONG_PRESS),
|
||||
ViewConfiguration.getLongPressTimeout());
|
||||
if (event.getRepeatCount() == 0) {
|
||||
dispatcher.startTracking(event, this);
|
||||
} else if (event.isLongPress() && dispatcher.isTracking(event)) {
|
||||
dispatcher.performedLongPress(event);
|
||||
mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||
// launch the VoiceDialer
|
||||
Intent intent = new Intent(Intent.ACTION_VOICE_COMMAND);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
try {
|
||||
sendCloseSystemWindows();
|
||||
getContext().startActivity(intent);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
startCallActivity();
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
case KeyEvent.KEYCODE_SEARCH: {
|
||||
if (getKeyguardManager().inKeyguardRestrictedInputMode()
|
||||
|| dispatcher == null) {
|
||||
break;
|
||||
}
|
||||
if (event.getRepeatCount() == 0) {
|
||||
mSearchKeyDownReceived = true;
|
||||
dispatcher.startTracking(event, this);
|
||||
} else if (event.isLongPress() && dispatcher.isTracking(event)) {
|
||||
Configuration config = getContext().getResources().getConfiguration();
|
||||
if (config.keyboard == Configuration.KEYBOARD_NOKEYS
|
||||
|| config.hardKeyboardHidden == Configuration.HARDKEYBOARDHIDDEN_YES) {
|
||||
// If this device does not have a hardware keyboard,
|
||||
// or that keyboard is hidden, then we can't use the
|
||||
// search key for chording to perform shortcuts;
|
||||
// instead, we will let the user long press,
|
||||
mKeycodeMenuTimeoutHandler.removeMessages(MSG_SEARCH_LONG_PRESS);
|
||||
mKeycodeMenuTimeoutHandler.sendMessageDelayed(
|
||||
mKeycodeMenuTimeoutHandler.obtainMessage(MSG_SEARCH_LONG_PRESS),
|
||||
ViewConfiguration.getLongPressTimeout());
|
||||
|| config.hardKeyboardHidden
|
||||
== Configuration.HARDKEYBOARDHIDDEN_YES) {
|
||||
// launch the search activity
|
||||
Intent intent = new Intent(Intent.ACTION_SEARCH_LONG_PRESS);
|
||||
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
|
||||
try {
|
||||
sendCloseSystemWindows();
|
||||
getContext().startActivity(intent);
|
||||
mDecor.performHapticFeedback(HapticFeedbackConstants.LONG_PRESS);
|
||||
// Only clear this if we successfully start the
|
||||
// activity; otherwise we will allow the normal short
|
||||
// press action to be performed.
|
||||
dispatcher.performedLongPress(event);
|
||||
} catch (ActivityNotFoundException e) {
|
||||
// Ignore
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1349,6 +1276,14 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
* @see android.view.KeyEvent
|
||||
*/
|
||||
protected boolean onKeyUp(int featureId, int keyCode, KeyEvent event) {
|
||||
final KeyEvent.DispatcherState dispatcher =
|
||||
mDecor != null ? mDecor.getKeyDispatcherState() : null;
|
||||
if (dispatcher != null) {
|
||||
dispatcher.handleUpEvent(event);
|
||||
}
|
||||
//Log.i(TAG, "Key up: repeat=" + event.getRepeatCount()
|
||||
// + " flags=0x" + Integer.toHexString(event.getFlags()));
|
||||
|
||||
switch (keyCode) {
|
||||
case KeyEvent.KEYCODE_VOLUME_UP:
|
||||
case KeyEvent.KEYCODE_VOLUME_DOWN: {
|
||||
@@ -1374,6 +1309,24 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
return true;
|
||||
}
|
||||
|
||||
case KeyEvent.KEYCODE_BACK: {
|
||||
if (featureId < 0) break;
|
||||
if (event.isTracking() && !event.isCanceled()) {
|
||||
if (featureId == FEATURE_OPTIONS_PANEL) {
|
||||
PanelFeatureState st = getPanelState(featureId, false);
|
||||
if (st != null && st.isInExpandedMode) {
|
||||
// If the user is in an expanded menu and hits back, it
|
||||
// should go back to the icon menu
|
||||
reopenMenu(true);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
closePanel(featureId);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case KeyEvent.KEYCODE_HEADSETHOOK:
|
||||
case KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE:
|
||||
case KeyEvent.KEYCODE_MEDIA_STOP:
|
||||
@@ -1391,11 +1344,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
if (getKeyguardManager().inKeyguardRestrictedInputMode()) {
|
||||
break;
|
||||
}
|
||||
if (event.getRepeatCount() > 0) break; // Can a key up event repeat?
|
||||
mKeycodeMenuTimeoutHandler.removeMessages(MSG_CAMERA_LONG_PRESS);
|
||||
if (!mKeycodeCameraTimeoutActive) break;
|
||||
mKeycodeCameraTimeoutActive = false;
|
||||
// Add short press behavior here if desired
|
||||
if (event.isTracking() && !event.isCanceled()) {
|
||||
// Add short press behavior here if desired
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1403,11 +1354,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
if (getKeyguardManager().inKeyguardRestrictedInputMode()) {
|
||||
break;
|
||||
}
|
||||
if (event.getRepeatCount() > 0) break;
|
||||
mKeycodeMenuTimeoutHandler.removeMessages(MSG_CALL_LONG_PRESS);
|
||||
if (!mKeycodeCallTimeoutActive) break;
|
||||
mKeycodeCallTimeoutActive = false;
|
||||
startCallActivity();
|
||||
if (event.isTracking() && !event.isCanceled()) {
|
||||
startCallActivity();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1416,13 +1365,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
* Do this in onKeyUp since the Search key is also used for
|
||||
* chording quick launch shortcuts.
|
||||
*/
|
||||
if (getKeyguardManager().inKeyguardRestrictedInputMode() ||
|
||||
!mSearchKeyDownReceived) {
|
||||
mSearchKeyDownReceived = false;
|
||||
if (getKeyguardManager().inKeyguardRestrictedInputMode()) {
|
||||
break;
|
||||
}
|
||||
mSearchKeyDownReceived = false;
|
||||
launchDefaultSearch();
|
||||
if (event.isTracking() && !event.isCanceled()) {
|
||||
launchDefaultSearch();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -1584,9 +1532,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
PanelFeatureState st;
|
||||
for (int i = panels.length - 1; i >= 0; i--) {
|
||||
st = panels[i];
|
||||
if ((st != null) && st.isOpen) {
|
||||
// Clear st.isOpen (openPanel will not open if it's already open)
|
||||
st.isOpen = false;
|
||||
// We restore the panel if it was last open; we skip it if it
|
||||
// now is open, to avoid a race condition if the user immediately
|
||||
// opens it when we are resuming.
|
||||
if ((st != null) && !st.isOpen && st.wasLastOpen) {
|
||||
st.isInExpandedMode = st.wasLastExpanded;
|
||||
openPanel(st, null);
|
||||
}
|
||||
}
|
||||
@@ -1606,8 +1556,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
|
||||
private final Rect mFrameOffsets = new Rect();
|
||||
|
||||
private final Paint mBlackPaint = new Paint();
|
||||
|
||||
private boolean mChanging;
|
||||
|
||||
private Drawable mMenuBackground;
|
||||
@@ -1617,7 +1565,6 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
public DecorView(Context context, int featureId) {
|
||||
super(context);
|
||||
mFeatureId = featureId;
|
||||
mBlackPaint.setColor(0xFF000000);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -2009,16 +1956,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
public void onWindowFocusChanged(boolean hasWindowFocus) {
|
||||
super.onWindowFocusChanged(hasWindowFocus);
|
||||
|
||||
// no KEYCODE_CALL events active across focus changes
|
||||
mKeycodeMenuTimeoutHandler.removeMessages(MSG_MENU_LONG_PRESS);
|
||||
mKeycodeMenuTimeoutHandler.removeMessages(MSG_CALL_LONG_PRESS);
|
||||
mKeycodeMenuTimeoutHandler.removeMessages(MSG_CAMERA_LONG_PRESS);
|
||||
mKeycodeCallTimeoutActive = false;
|
||||
mKeycodeCameraTimeoutActive = false;
|
||||
mPanelMayLongPress = false;
|
||||
|
||||
// If the user is chording a menu shortcut, release the chord since
|
||||
// this window lost focus
|
||||
if (!hasWindowFocus && mPanelChordingKey > 0) {
|
||||
if (!hasWindowFocus && mPanelChordingKey != 0) {
|
||||
closePanel(FEATURE_OPTIONS_PANEL);
|
||||
}
|
||||
|
||||
@@ -2031,6 +1973,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
@Override
|
||||
protected void onAttachedToWindow() {
|
||||
super.onAttachedToWindow();
|
||||
|
||||
final Callback cb = getCallback();
|
||||
if (cb != null && mFeatureId < 0) {
|
||||
cb.onAttachedToWindow();
|
||||
}
|
||||
|
||||
if (mFeatureId == -1) {
|
||||
/*
|
||||
@@ -2043,6 +1990,23 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
openPanelsAfterRestore();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onDetachedFromWindow() {
|
||||
super.onDetachedFromWindow();
|
||||
|
||||
final Callback cb = getCallback();
|
||||
if (cb != null && mFeatureId < 0) {
|
||||
cb.onDetachedFromWindow();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCloseSystemDialogs(String reason) {
|
||||
if (mFeatureId >= 0) {
|
||||
closeAllPanels();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected DecorView generateDecor() {
|
||||
@@ -2097,6 +2061,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
setFlags(FLAG_FULLSCREEN, FLAG_FULLSCREEN&(~getForcedWindowFlags()));
|
||||
}
|
||||
|
||||
if (a.getBoolean(com.android.internal.R.styleable.Window_windowShowWallpaper, false)) {
|
||||
setFlags(FLAG_SHOW_WALLPAPER, FLAG_SHOW_WALLPAPER&(~getForcedWindowFlags()));
|
||||
}
|
||||
|
||||
WindowManager.LayoutParams params = getAttributes();
|
||||
|
||||
if (!hasSoftInputMode()) {
|
||||
@@ -2606,6 +2574,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
|
||||
boolean refreshDecorView;
|
||||
|
||||
boolean wasLastOpen;
|
||||
|
||||
boolean wasLastExpanded;
|
||||
|
||||
/**
|
||||
* Contains the state of the menu when told to freeze.
|
||||
*/
|
||||
@@ -2654,8 +2626,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
|
||||
void onRestoreInstanceState(Parcelable state) {
|
||||
SavedState savedState = (SavedState) state;
|
||||
featureId = savedState.featureId;
|
||||
isOpen = savedState.isOpen;
|
||||
isInExpandedMode = savedState.isInExpandedMode;
|
||||
wasLastOpen = savedState.isOpen;
|
||||
wasLastExpanded = savedState.isInExpandedMode;
|
||||
frozenMenuState = savedState.menuState;
|
||||
|
||||
/*
|
||||
|
||||
640
policy/com/android/internal/policy/impl/PhoneWindowManager.java
Normal file → Executable file
640
policy/com/android/internal/policy/impl/PhoneWindowManager.java
Normal file → Executable file
File diff suppressed because it is too large
Load Diff
@@ -70,8 +70,11 @@ public class PowerDialog extends Dialog implements OnClickListener,
|
||||
setContentView(com.android.internal.R.layout.power_dialog);
|
||||
|
||||
getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
|
||||
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
|
||||
if (!getContext().getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_sf_slowBlur)) {
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
|
||||
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
|
||||
}
|
||||
getWindow().setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
|
||||
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
|
||||
|
||||
|
||||
@@ -20,7 +20,6 @@ import android.app.ActivityManager;
|
||||
import android.app.Dialog;
|
||||
import android.app.StatusBarManager;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
@@ -30,13 +29,10 @@ import android.content.pm.PackageManager;
|
||||
import android.content.pm.ResolveInfo;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.view.View;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
import android.view.View.OnClickListener;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
|
||||
import java.util.List;
|
||||
@@ -59,7 +55,7 @@ public class RecentApplicationsDialog extends Dialog implements OnClickListener
|
||||
private int mIconSize;
|
||||
|
||||
public RecentApplicationsDialog(Context context) {
|
||||
super(context);
|
||||
super(context, com.android.internal.R.style.Theme_Dialog_RecentApplications);
|
||||
|
||||
final Resources resources = context.getResources();
|
||||
mIconSize = (int) resources.getDimension(android.R.dimen.app_icon_size);
|
||||
@@ -84,8 +80,8 @@ public class RecentApplicationsDialog extends Dialog implements OnClickListener
|
||||
Window theWindow = getWindow();
|
||||
theWindow.requestFeature(Window.FEATURE_NO_TITLE);
|
||||
theWindow.setType(WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG);
|
||||
theWindow.setFlags(WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
|
||||
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
|
||||
theWindow.setFlags(WindowManager.LayoutParams.FLAG_DIM_BEHIND,
|
||||
WindowManager.LayoutParams.FLAG_DIM_BEHIND);
|
||||
theWindow.setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
|
||||
WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
|
||||
theWindow.setTitle("Recents");
|
||||
|
||||
@@ -182,9 +182,12 @@ public class SimUnlockScreen extends LinearLayout implements KeyguardScreen, Vie
|
||||
mSimUnlockProgressDialog.setCancelable(false);
|
||||
mSimUnlockProgressDialog.getWindow().setType(
|
||||
WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG);
|
||||
mSimUnlockProgressDialog.getWindow().setFlags(
|
||||
WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
|
||||
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
|
||||
if (!mContext.getResources().getBoolean(
|
||||
com.android.internal.R.bool.config_sf_slowBlur)) {
|
||||
mSimUnlockProgressDialog.getWindow().setFlags(
|
||||
WindowManager.LayoutParams.FLAG_BLUR_BEHIND,
|
||||
WindowManager.LayoutParams.FLAG_BLUR_BEHIND);
|
||||
}
|
||||
}
|
||||
return mSimUnlockProgressDialog;
|
||||
}
|
||||
|
||||
@@ -17,30 +17,33 @@
|
||||
package com.android.internal.policy.impl;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.ServiceConnection;
|
||||
import android.os.CountDownTimer;
|
||||
import android.os.SystemClock;
|
||||
import android.view.KeyEvent;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
import android.view.ViewGroup;
|
||||
import android.view.MotionEvent;
|
||||
import android.widget.Button;
|
||||
import android.widget.ImageView;
|
||||
import android.widget.TextView;
|
||||
import android.text.format.DateFormat;
|
||||
import android.text.TextUtils;
|
||||
import com.android.internal.R;
|
||||
import com.android.internal.telephony.IccCard;
|
||||
import com.android.internal.widget.LinearLayoutWithDefaultTouchRecepient;
|
||||
import com.android.internal.widget.LockPatternUtils;
|
||||
import com.android.internal.widget.LockPatternView;
|
||||
import com.android.internal.widget.LockPatternView.Cell;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* This is the screen that shows the 9 circle unlock widget and instructs
|
||||
* the user how to unlock their device, or make an emergency call.
|
||||
*/
|
||||
class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient
|
||||
implements KeyguardScreen, KeyguardUpdateMonitor.ConfigurationChangeCallback {
|
||||
implements KeyguardScreen, KeyguardUpdateMonitor.ConfigurationChangeCallback,
|
||||
KeyguardUpdateMonitor.InfoCallback, KeyguardUpdateMonitor.SimStateCallback {
|
||||
|
||||
private static final String TAG = "UnlockScreen";
|
||||
|
||||
@@ -50,6 +53,9 @@ class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient
|
||||
// how long we stay awake once the user is ready to enter a pattern
|
||||
private static final int UNLOCK_PATTERN_WAKE_INTERVAL_MS = 7000;
|
||||
|
||||
// how many cells the user has to cross before we poke the wakelock
|
||||
private static final int MIN_PATTERN_BEFORE_POKE_WAKELOCK = 2;
|
||||
|
||||
private int mFailedPatternAttemptsSinceLastTimeout = 0;
|
||||
private int mTotalFailedPatternAttempts = 0;
|
||||
private CountDownTimer mCountdownTimer = null;
|
||||
@@ -58,10 +64,35 @@ class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient
|
||||
private final KeyguardUpdateMonitor mUpdateMonitor;
|
||||
private final KeyguardScreenCallback mCallback;
|
||||
|
||||
/**
|
||||
* whether there is a fallback option available when the pattern is forgotten.
|
||||
*/
|
||||
private boolean mEnableFallback;
|
||||
|
||||
private boolean mCreatedInPortrait;
|
||||
|
||||
private ImageView mUnlockIcon;
|
||||
private TextView mUnlockHeader;
|
||||
private TextView mCarrier;
|
||||
private TextView mCenterDot;
|
||||
private TextView mDate;
|
||||
private TextView mTime;
|
||||
|
||||
// are we showing battery information?
|
||||
private boolean mShowingBatteryInfo = false;
|
||||
|
||||
// last known plugged in state
|
||||
private boolean mPluggedIn = false;
|
||||
|
||||
// last known battery level
|
||||
private int mBatteryLevel = 100;
|
||||
|
||||
private String mNextAlarm = null;
|
||||
|
||||
private String mInstructions = null;
|
||||
private TextView mStatus1;
|
||||
private TextView mStatusSep;
|
||||
private TextView mStatus2;
|
||||
|
||||
|
||||
private LockPatternView mLockPatternView;
|
||||
|
||||
private ViewGroup mFooterNormal;
|
||||
@@ -86,9 +117,6 @@ class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient
|
||||
|
||||
private Button mForgotPatternButton;
|
||||
|
||||
private ServiceConnection mServiceConnection;
|
||||
|
||||
|
||||
enum FooterMode {
|
||||
Normal,
|
||||
ForgotLockPattern,
|
||||
@@ -104,6 +132,7 @@ class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient
|
||||
case ForgotLockPattern:
|
||||
mFooterNormal.setVisibility(View.GONE);
|
||||
mFooterForgotPattern.setVisibility(View.VISIBLE);
|
||||
mForgotPatternButton.setVisibility(View.VISIBLE);
|
||||
break;
|
||||
case VerifyUnlocked:
|
||||
mFooterNormal.setVisibility(View.GONE);
|
||||
@@ -117,12 +146,15 @@ class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient
|
||||
* @param updateMonitor Used to lookup state affecting keyguard.
|
||||
* @param callback Used to notify the manager when we're done, etc.
|
||||
* @param totalFailedAttempts The current number of failed attempts.
|
||||
* @param enableFallback True if a backup unlock option is available when the user has forgotten
|
||||
* their pattern (e.g they have a google account so we can show them the account based
|
||||
* backup option).
|
||||
*/
|
||||
UnlockScreen(Context context,
|
||||
LockPatternUtils lockPatternUtils,
|
||||
KeyguardUpdateMonitor updateMonitor,
|
||||
KeyguardScreenCallback callback,
|
||||
int totalFailedAttempts) {
|
||||
LockPatternUtils lockPatternUtils,
|
||||
KeyguardUpdateMonitor updateMonitor,
|
||||
KeyguardScreenCallback callback,
|
||||
int totalFailedAttempts) {
|
||||
super(context);
|
||||
mLockPatternUtils = lockPatternUtils;
|
||||
mUpdateMonitor = updateMonitor;
|
||||
@@ -136,12 +168,22 @@ class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient
|
||||
LayoutInflater.from(context).inflate(R.layout.keyguard_screen_unlock_landscape, this, true);
|
||||
}
|
||||
|
||||
mUnlockIcon = (ImageView) findViewById(R.id.unlockLockIcon);
|
||||
mCarrier = (TextView) findViewById(R.id.carrier);
|
||||
mCenterDot = (TextView) findViewById(R.id.centerDot);
|
||||
mDate = (TextView) findViewById(R.id.date);
|
||||
mTime = (TextView) findViewById(R.id.time);
|
||||
|
||||
mCenterDot.setText("|");
|
||||
refreshTimeAndDateDisplay();
|
||||
|
||||
mStatus1 = (TextView) findViewById(R.id.status1);
|
||||
mStatusSep = (TextView) findViewById(R.id.statusSep);
|
||||
mStatus2 = (TextView) findViewById(R.id.status2);
|
||||
|
||||
resetStatusInfo();
|
||||
|
||||
|
||||
mLockPatternView = (LockPatternView) findViewById(R.id.lockPattern);
|
||||
mUnlockHeader = (TextView) findViewById(R.id.headerText);
|
||||
|
||||
mUnlockHeader.setText(R.string.lockscreen_pattern_instructions);
|
||||
|
||||
mFooterNormal = (ViewGroup) findViewById(R.id.footerNormal);
|
||||
mFooterForgotPattern = (ViewGroup) findViewById(R.id.footerForgotPattern);
|
||||
@@ -164,8 +206,7 @@ class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient
|
||||
mForgotPatternButton.setOnClickListener(new OnClickListener() {
|
||||
|
||||
public void onClick(View v) {
|
||||
mLockPatternUtils.setPermanentlyLocked(true);
|
||||
mCallback.goToUnlockScreen();
|
||||
mCallback.forgotPattern(true);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -187,18 +228,105 @@ class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient
|
||||
updateFooter(FooterMode.Normal);
|
||||
|
||||
mCreatedInPortrait = updateMonitor.isInPortrait();
|
||||
updateMonitor.registerInfoCallback(this);
|
||||
updateMonitor.registerSimStateCallback(this);
|
||||
updateMonitor.registerConfigurationChangeCallback(this);
|
||||
setFocusableInTouchMode(true);
|
||||
|
||||
// until we get an update...
|
||||
mCarrier.setText(
|
||||
LockScreen.getCarrierString(
|
||||
mUpdateMonitor.getTelephonyPlmn(),
|
||||
mUpdateMonitor.getTelephonySpn()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onKeyDown(int keyCode, KeyEvent event) {
|
||||
if (keyCode == KeyEvent.KEYCODE_BACK) {
|
||||
mCallback.goToLockScreen();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
public void setEnableFallback(boolean state) {
|
||||
mEnableFallback = state;
|
||||
}
|
||||
|
||||
private void resetStatusInfo() {
|
||||
mInstructions = null;
|
||||
mShowingBatteryInfo = mUpdateMonitor.shouldShowBatteryInfo();
|
||||
mPluggedIn = mUpdateMonitor.isDevicePluggedIn();
|
||||
mBatteryLevel = mUpdateMonitor.getBatteryLevel();
|
||||
mNextAlarm = mLockPatternUtils.getNextAlarm();
|
||||
updateStatusLines();
|
||||
}
|
||||
|
||||
private void updateStatusLines() {
|
||||
if (mInstructions != null) {
|
||||
// instructions only
|
||||
mStatus1.setText(mInstructions);
|
||||
if (TextUtils.isEmpty(mInstructions)) {
|
||||
mStatus1.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
|
||||
} else {
|
||||
mStatus1.setCompoundDrawablesWithIntrinsicBounds(
|
||||
R.drawable.ic_lock_idle_lock, 0, 0, 0);
|
||||
}
|
||||
|
||||
mStatus1.setVisibility(View.VISIBLE);
|
||||
mStatusSep.setVisibility(View.GONE);
|
||||
mStatus2.setVisibility(View.GONE);
|
||||
} else if (mShowingBatteryInfo && mNextAlarm == null) {
|
||||
// battery only
|
||||
if (mPluggedIn) {
|
||||
if (mBatteryLevel >= 100) {
|
||||
mStatus1.setText(getContext().getString(R.string.lockscreen_charged));
|
||||
} else {
|
||||
mStatus1.setText(getContext().getString(R.string.lockscreen_plugged_in, mBatteryLevel));
|
||||
}
|
||||
} else {
|
||||
mStatus1.setText(getContext().getString(R.string.lockscreen_low_battery));
|
||||
}
|
||||
mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_charging, 0, 0, 0);
|
||||
|
||||
mStatus1.setVisibility(View.VISIBLE);
|
||||
mStatusSep.setVisibility(View.GONE);
|
||||
mStatus2.setVisibility(View.GONE);
|
||||
|
||||
} else if (mNextAlarm != null && !mShowingBatteryInfo) {
|
||||
// alarm only
|
||||
mStatus1.setText(mNextAlarm);
|
||||
mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_alarm, 0, 0, 0);
|
||||
|
||||
mStatus1.setVisibility(View.VISIBLE);
|
||||
mStatusSep.setVisibility(View.GONE);
|
||||
mStatus2.setVisibility(View.GONE);
|
||||
} else if (mNextAlarm != null && mShowingBatteryInfo) {
|
||||
// both battery and next alarm
|
||||
mStatus1.setText(mNextAlarm);
|
||||
mStatusSep.setText("|");
|
||||
mStatus2.setText(getContext().getString(
|
||||
R.string.lockscreen_battery_short,
|
||||
Math.min(100, mBatteryLevel)));
|
||||
mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_alarm, 0, 0, 0);
|
||||
if (mPluggedIn) {
|
||||
mStatus2.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_charging, 0, 0, 0);
|
||||
} else {
|
||||
mStatus2.setCompoundDrawablesWithIntrinsicBounds(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
mStatus1.setVisibility(View.VISIBLE);
|
||||
mStatusSep.setVisibility(View.VISIBLE);
|
||||
mStatus2.setVisibility(View.VISIBLE);
|
||||
} else {
|
||||
// nothing specific to show; show general instructions
|
||||
mStatus1.setText(R.string.lockscreen_pattern_instructions);
|
||||
mStatus1.setCompoundDrawablesWithIntrinsicBounds(R.drawable.ic_lock_idle_lock, 0, 0, 0);
|
||||
|
||||
mStatus1.setVisibility(View.VISIBLE);
|
||||
mStatusSep.setVisibility(View.GONE);
|
||||
mStatus2.setVisibility(View.GONE);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private void refreshTimeAndDateDisplay() {
|
||||
Date now = new Date();
|
||||
mTime.setText(DateFormat.getTimeFormat(getContext()).format(now));
|
||||
mDate.setText(DateFormat.getMediumDateFormat(getContext()).format(now));
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean dispatchTouchEvent(MotionEvent ev) {
|
||||
@@ -210,11 +338,40 @@ class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient
|
||||
((SystemClock.elapsedRealtime() - mLastPokeTime)
|
||||
> (UNLOCK_PATTERN_WAKE_INTERVAL_MS - 100))) {
|
||||
mLastPokeTime = SystemClock.elapsedRealtime();
|
||||
mCallback.pokeWakelock(UNLOCK_PATTERN_WAKE_INTERVAL_MS);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
// ---------- InfoCallback
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void onRefreshBatteryInfo(boolean showBatteryInfo, boolean pluggedIn, int batteryLevel) {
|
||||
mShowingBatteryInfo = showBatteryInfo;
|
||||
mPluggedIn = pluggedIn;
|
||||
mBatteryLevel = batteryLevel;
|
||||
updateStatusLines();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void onTimeChanged() {
|
||||
refreshTimeAndDateDisplay();
|
||||
}
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void onRefreshCarrierInfo(CharSequence plmn, CharSequence spn) {
|
||||
mCarrier.setText(LockScreen.getCarrierString(plmn, spn));
|
||||
}
|
||||
|
||||
// ---------- SimStateCallback
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void onSimStateChanged(IccCard.State simState) {
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/** {@inheritDoc} */
|
||||
public void onOrientationChange(boolean inPortrait) {
|
||||
if (inPortrait != mCreatedInPortrait) {
|
||||
@@ -241,8 +398,7 @@ class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient
|
||||
/** {@inheritDoc} */
|
||||
public void onResume() {
|
||||
// reset header
|
||||
mUnlockHeader.setText(R.string.lockscreen_pattern_instructions);
|
||||
mUnlockIcon.setVisibility(View.VISIBLE);
|
||||
resetStatusInfo();
|
||||
|
||||
// reset lock pattern
|
||||
mLockPatternView.enableInput();
|
||||
@@ -262,10 +418,11 @@ class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient
|
||||
// the footer depends on how many total attempts the user has failed
|
||||
if (mCallback.isVerifyUnlockOnly()) {
|
||||
updateFooter(FooterMode.VerifyUnlocked);
|
||||
} else if (mTotalFailedPatternAttempts < LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT) {
|
||||
updateFooter(FooterMode.Normal);
|
||||
} else {
|
||||
} else if (mEnableFallback &&
|
||||
(mTotalFailedPatternAttempts >= LockPatternUtils.FAILED_ATTEMPTS_BEFORE_TIMEOUT)) {
|
||||
updateFooter(FooterMode.ForgotLockPattern);
|
||||
} else {
|
||||
updateFooter(FooterMode.Normal);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -274,6 +431,15 @@ class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient
|
||||
mUpdateMonitor.removeCallback(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWindowFocusChanged(boolean hasWindowFocus) {
|
||||
super.onWindowFocusChanged(hasWindowFocus);
|
||||
if (hasWindowFocus) {
|
||||
// when timeout dialog closes we want to update our state
|
||||
onResume();
|
||||
}
|
||||
}
|
||||
|
||||
private class UnlockPatternListener
|
||||
implements LockPatternView.OnPatternListener {
|
||||
|
||||
@@ -284,15 +450,25 @@ class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient
|
||||
public void onPatternCleared() {
|
||||
}
|
||||
|
||||
public void onPatternCellAdded(List<Cell> pattern) {
|
||||
// To guard against accidental poking of the wakelock, look for
|
||||
// the user actually trying to draw a pattern of some minimal length.
|
||||
if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
|
||||
mCallback.pokeWakelock(UNLOCK_PATTERN_WAKE_INTERVAL_MS);
|
||||
}
|
||||
}
|
||||
|
||||
public void onPatternDetected(List<LockPatternView.Cell> pattern) {
|
||||
if (mLockPatternUtils.checkPattern(pattern)) {
|
||||
mLockPatternView
|
||||
.setDisplayMode(LockPatternView.DisplayMode.Correct);
|
||||
mUnlockIcon.setVisibility(View.GONE);
|
||||
mUnlockHeader.setText("");
|
||||
mInstructions = "";
|
||||
updateStatusLines();
|
||||
mCallback.keyguardDone(true);
|
||||
} else {
|
||||
mCallback.pokeWakelock(UNLOCK_PATTERN_WAKE_INTERVAL_MS);
|
||||
if (pattern.size() > MIN_PATTERN_BEFORE_POKE_WAKELOCK) {
|
||||
mCallback.pokeWakelock(UNLOCK_PATTERN_WAKE_INTERVAL_MS);
|
||||
}
|
||||
mLockPatternView.setDisplayMode(LockPatternView.DisplayMode.Wrong);
|
||||
if (pattern.size() >= LockPatternUtils.MIN_PATTERN_REGISTER_FAIL) {
|
||||
mTotalFailedPatternAttempts++;
|
||||
@@ -304,8 +480,9 @@ class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient
|
||||
handleAttemptLockout(deadline);
|
||||
return;
|
||||
}
|
||||
mUnlockIcon.setVisibility(View.VISIBLE);
|
||||
mUnlockHeader.setText(R.string.lockscreen_pattern_wrong);
|
||||
// TODO mUnlockIcon.setVisibility(View.VISIBLE);
|
||||
mInstructions = getContext().getString(R.string.lockscreen_pattern_wrong);
|
||||
updateStatusLines();
|
||||
mLockPatternView.postDelayed(
|
||||
mCancelPatternRunnable,
|
||||
PATTERN_CLEAR_TIMEOUT_MS);
|
||||
@@ -322,20 +499,25 @@ class UnlockScreen extends LinearLayoutWithDefaultTouchRecepient
|
||||
@Override
|
||||
public void onTick(long millisUntilFinished) {
|
||||
int secondsRemaining = (int) (millisUntilFinished / 1000);
|
||||
mUnlockHeader.setText(getContext().getString(
|
||||
mInstructions = getContext().getString(
|
||||
R.string.lockscreen_too_many_failed_attempts_countdown,
|
||||
secondsRemaining));
|
||||
secondsRemaining);
|
||||
updateStatusLines();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onFinish() {
|
||||
mLockPatternView.setEnabled(true);
|
||||
mUnlockHeader.setText(R.string.lockscreen_pattern_instructions);
|
||||
mUnlockIcon.setVisibility(View.VISIBLE);
|
||||
mInstructions = getContext().getString(R.string.lockscreen_pattern_instructions);
|
||||
updateStatusLines();
|
||||
// TODO mUnlockIcon.setVisibility(View.VISIBLE);
|
||||
mFailedPatternAttemptsSinceLastTimeout = 0;
|
||||
updateFooter(FooterMode.ForgotLockPattern);
|
||||
if (mEnableFallback) {
|
||||
updateFooter(FooterMode.ForgotLockPattern);
|
||||
} else {
|
||||
updateFooter(FooterMode.Normal);
|
||||
}
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user