summaryrefslogtreecommitdiffstats
path: root/policy/src
diff options
context:
space:
mode:
Diffstat (limited to 'policy/src')
-rw-r--r--policy/src/com/android/internal/policy/impl/GlobalActions.java7
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java3
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java2
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardViewBase.java2
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardViewManager.java11
-rw-r--r--policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java15
-rw-r--r--policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java122
-rw-r--r--policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java8
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java34
-rwxr-xr-xpolicy/src/com/android/internal/policy/impl/PhoneWindowManager.java335
10 files changed, 333 insertions, 206 deletions
diff --git a/policy/src/com/android/internal/policy/impl/GlobalActions.java b/policy/src/com/android/internal/policy/impl/GlobalActions.java
index 8569143..11b6c15 100644
--- a/policy/src/com/android/internal/policy/impl/GlobalActions.java
+++ b/policy/src/com/android/internal/policy/impl/GlobalActions.java
@@ -18,7 +18,6 @@ package com.android.internal.policy.impl;
import android.app.Activity;
import android.app.AlertDialog;
-import android.app.StatusBarManager;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.DialogInterface;
@@ -57,8 +56,6 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
private static final String TAG = "GlobalActions";
- private StatusBarManager mStatusBar;
-
private final Context mContext;
private final AudioManager mAudioManager;
@@ -103,13 +100,12 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
mKeyguardShowing = keyguardShowing;
mDeviceProvisioned = isDeviceProvisioned;
if (mDialog == null) {
- mStatusBar = (StatusBarManager)mContext.getSystemService(Context.STATUS_BAR_SERVICE);
mDialog = createDialog();
}
prepareDialog();
- mStatusBar.disable(StatusBarManager.DISABLE_EXPAND);
mDialog.show();
+ mDialog.getWindow().getDecorView().setSystemUiVisibility(View.STATUS_BAR_DISABLE_EXPAND);
}
/**
@@ -249,7 +245,6 @@ class GlobalActions implements DialogInterface.OnDismissListener, DialogInterfac
/** {@inheritDoc} */
public void onDismiss(DialogInterface dialog) {
- mStatusBar.disable(StatusBarManager.DISABLE_NONE);
}
/** {@inheritDoc} */
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
index 86807ad..6614d79 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardStatusViewManager.java
@@ -186,6 +186,9 @@ class KeyguardStatusViewManager implements OnClickListener {
mTransientTextManager = new TransientTextManager(mCarrierView);
+ mUpdateMonitor.registerInfoCallback(mInfoCallback);
+ mUpdateMonitor.registerSimStateCallback(mSimStateCallback);
+
resetStatusInfo();
refreshDate();
updateOwnerInfo();
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
index 303a3b5..2d8185b 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardUpdateMonitor.java
@@ -226,7 +226,7 @@ public class KeyguardUpdateMonitor {
// take a guess to start
mSimState = IccCard.State.READY;
- mBatteryStatus = BATTERY_STATUS_FULL;
+ mBatteryStatus = BATTERY_STATUS_UNKNOWN;
mBatteryLevel = 100;
mTelephonyPlmn = getDefaultPlmn();
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
index 59b546d..de156c9 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewBase.java
@@ -50,8 +50,6 @@ public abstract class KeyguardViewBase extends FrameLayout {
public KeyguardViewBase(Context context) {
super(context);
- setSystemUiVisibility(STATUS_BAR_DISABLE_BACK);
-
// This is a faster way to draw the background on devices without hardware acceleration
setBackgroundDrawable(new Drawable() {
@Override
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
index 90972da..2fd165a 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewManager.java
@@ -171,6 +171,17 @@ public class KeyguardViewManager implements KeyguardWindowController {
}
}
+ // Disable aspects of the system/status/navigation bars that are not appropriate or
+ // useful for the lockscreen but can be re-shown by dialogs or SHOW_WHEN_LOCKED activities.
+ // Other disabled bits are handled by the KeyguardViewMediator talking directly to the
+ // status bar service.
+ int visFlags =
+ ( View.STATUS_BAR_DISABLE_BACK
+ | View.STATUS_BAR_DISABLE_HOME
+ | View.STATUS_BAR_DISABLE_CLOCK
+ );
+ mKeyguardHost.setSystemUiVisibility(visFlags);
+
mViewManager.updateViewLayout(mKeyguardHost, mWindowLayoutParams);
mKeyguardHost.setVisibility(View.VISIBLE);
mKeyguardView.requestFocus();
diff --git a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
index f1b6ef9..0471dfe 100644
--- a/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
+++ b/policy/src/com/android/internal/policy/impl/KeyguardViewMediator.java
@@ -1188,19 +1188,12 @@ public class KeyguardViewMediator implements KeyguardViewCallback,
}
}
+ // Disable aspects of the system/status/navigation bars that must not be re-enabled by
+ // windows that appear on top, ever
int flags = StatusBarManager.DISABLE_NONE;
if (mShowing) {
- // disable navigation status bar components if lock screen is up
- flags |= StatusBarManager.DISABLE_NAVIGATION;
- if (!mHidden) {
- // showing lockscreen exclusively (no activities in front of it)
- // disable back button too
- flags |= StatusBarManager.DISABLE_BACK;
- if (mUpdateMonitor.isClockVisible()) {
- // lockscreen showing a clock, so hide statusbar clock
- flags |= StatusBarManager.DISABLE_CLOCK;
- }
- }
+ // disable navigation status bar components (home, recents) if lock screen is up
+ flags |= StatusBarManager.DISABLE_RECENT;
if (isSecure() || !ENABLE_INSECURE_STATUS_BAR_EXPAND) {
// showing secure lockscreen; disable expanding.
flags |= StatusBarManager.DISABLE_EXPAND;
diff --git a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
index 65cdd32..d1bb8d1 100644
--- a/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
+++ b/policy/src/com/android/internal/policy/impl/LockPatternKeyguardView.java
@@ -98,7 +98,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
private View mLockScreen;
private View mUnlockScreen;
- private boolean mScreenOn = false;
+ private volatile boolean mScreenOn = false;
+ private volatile boolean mWindowFocused = false;
private boolean mEnableFallback = false; // assume no fallback UI until we know better
private boolean mShowLockBeforeUnlock = false;
@@ -110,14 +111,20 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
private boolean mFaceLockServiceRunning = false;
private final Object mFaceLockServiceRunningLock = new Object();
+ private final Object mFaceLockStartupLock = new Object();
private Handler mHandler;
private final int MSG_SHOW_FACELOCK_AREA_VIEW = 0;
private final int MSG_HIDE_FACELOCK_AREA_VIEW = 1;
- // Long enough to stay black while dialer comes up
- // Short enough to not be black if the user goes back immediately
- private final int FACELOCK_VIEW_AREA_EMERGENCY_HIDE_TIMEOUT = 1000;
+ // Long enough to stay visible while dialer comes up
+ // Short enough to not be visible if the user goes back immediately
+ private final int FACELOCK_VIEW_AREA_EMERGENCY_DIALER_TIMEOUT = 1000;
+
+ // Long enough to stay visible while the service starts
+ // Short enough to not have to wait long for backup if service fails to start or crashes
+ // The service can take a couple of seconds to start on the first try after boot
+ private final int FACELOCK_VIEW_AREA_SERVICE_TIMEOUT = 3000;
/**
* The current {@link KeyguardScreen} will use this to communicate back to us.
@@ -126,6 +133,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
private boolean mRequiresSim;
+ private volatile boolean mEmergencyCall;
/**
@@ -266,6 +274,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
mUpdateMonitor = updateMonitor;
mLockPatternUtils = lockPatternUtils;
mWindowController = controller;
+ mEmergencyCall = false;
mUpdateMonitor.registerInfoCallback(this);
@@ -320,12 +329,12 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
}
public void takeEmergencyCallAction() {
+ mEmergencyCall = true;
// FaceLock must be stopped if it is running when emergency call is pressed
stopAndUnbindFromFaceLock();
- // Delay hiding FaceLock area so unlock doesn't display while dialer is coming up
- mHandler.sendEmptyMessageDelayed(MSG_HIDE_FACELOCK_AREA_VIEW,
- FACELOCK_VIEW_AREA_EMERGENCY_HIDE_TIMEOUT);
+ // Continue showing FaceLock area until dialer comes up
+ showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_EMERGENCY_DIALER_TIMEOUT);
pokeWakelock(EMERGENCY_CALL_TIMEOUT);
if (TelephonyManager.getDefault().getCallState()
@@ -504,6 +513,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
public void onScreenTurnedOff() {
mScreenOn = false;
mForgotPattern = false;
+ mEmergencyCall = false;
if (mMode == Mode.LockScreen) {
((KeyguardScreen) mLockScreen).onPause();
} else {
@@ -514,32 +524,56 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
stopAndUnbindFromFaceLock();
}
- @Override
- public void onScreenTurnedOn() {
- mScreenOn = true;
- show();
-
- // When screen is turned on, need to bind to FaceLock service if we are using FaceLock
- // But only if not dealing with a call
+ /** When screen is turned on and focused, need to bind to FaceLock service if we are using
+ * FaceLock, but only if we're not dealing with a call
+ */
+ private void activateFaceLockIfAble() {
final boolean transportInvisible = mTransportControlView == null ? true :
mTransportControlView.getVisibility() != View.VISIBLE;
if (mUpdateMonitor.getPhoneState() == TelephonyManager.CALL_STATE_IDLE
&& transportInvisible) {
bindToFaceLock();
- //Eliminate the black background so that the lockpattern will be visible
- //If FaceUnlock is cancelled
- mHandler.sendEmptyMessageDelayed(MSG_HIDE_FACELOCK_AREA_VIEW, 4000);
+ // Show FaceLock area, but only for a little bit so lockpattern will become visible if
+ // FaceLock fails to start or crashes
+ showFaceLockAreaWithTimeout(FACELOCK_VIEW_AREA_SERVICE_TIMEOUT);
} else {
- mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW);
+ hideFaceLockArea();
}
}
- /** Unbind from facelock if something covers this window (such as an alarm) */
+ @Override
+ public void onScreenTurnedOn() {
+ boolean runFaceLock = false;
+ //Make sure to start facelock iff the screen is both on and focused
+ synchronized(mFaceLockStartupLock) {
+ mScreenOn = true;
+ runFaceLock = mWindowFocused;
+ }
+ show();
+ if(runFaceLock) activateFaceLockIfAble();
+ }
+
+ /** Unbind from facelock if something covers this window (such as an alarm)
+ * bind to facelock if the lockscreen window just came into focus, and the screen is on
+ */
@Override
public void onWindowFocusChanged (boolean hasWindowFocus) {
+ if(DEBUG) Log.d(TAG, hasWindowFocus ? "focused" : "unfocused");
+ boolean runFaceLock = false;
+ //Make sure to start facelock iff the screen is both on and focused
+ synchronized(mFaceLockStartupLock) {
+ if(mScreenOn && !mWindowFocused) runFaceLock = hasWindowFocus;
+ mWindowFocused = hasWindowFocus;
+ }
if(!hasWindowFocus) {
stopAndUnbindFromFaceLock();
- mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW);
+ hideFaceLockArea();
+ } else if (runFaceLock) {
+ //Don't activate facelock while the user is calling 911!
+ if(mEmergencyCall) mEmergencyCall = false;
+ else {
+ activateFaceLockIfAble();
+ }
}
}
@@ -553,9 +587,9 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
if (mLockPatternUtils.usingBiometricWeak() &&
mLockPatternUtils.isBiometricWeakInstalled()) {
- mHandler.sendEmptyMessage(MSG_SHOW_FACELOCK_AREA_VIEW);
+ showFaceLockArea();
} else {
- mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW);
+ hideFaceLockArea();
}
}
@@ -621,9 +655,10 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
//We need to stop faceunlock when a phonecall comes in
@Override
public void onPhoneStateChanged(int phoneState) {
+ if (DEBUG) Log.d(TAG, "phone state: " + phoneState);
if(phoneState == TelephonyManager.CALL_STATE_RINGING) {
stopAndUnbindFromFaceLock();
- mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW);
+ hideFaceLockArea();
}
}
@@ -1056,6 +1091,32 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
return true;
}
+ // Removes show and hide messages from the message queue
+ private void removeFaceLockAreaDisplayMessages() {
+ mHandler.removeMessages(MSG_SHOW_FACELOCK_AREA_VIEW);
+ mHandler.removeMessages(MSG_HIDE_FACELOCK_AREA_VIEW);
+ }
+
+ // Shows the FaceLock area immediately
+ private void showFaceLockArea() {
+ // Remove messages to prevent a delayed hide message from undo-ing the show
+ removeFaceLockAreaDisplayMessages();
+ mHandler.sendEmptyMessage(MSG_SHOW_FACELOCK_AREA_VIEW);
+ }
+
+ // Hides the FaceLock area immediately
+ private void hideFaceLockArea() {
+ // Remove messages to prevent a delayed show message from undo-ing the hide
+ removeFaceLockAreaDisplayMessages();
+ mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW);
+ }
+
+ // Shows the FaceLock area for a period of time
+ private void showFaceLockAreaWithTimeout(long timeoutMillis) {
+ showFaceLockArea();
+ mHandler.sendEmptyMessageDelayed(MSG_HIDE_FACELOCK_AREA_VIEW, timeoutMillis);
+ }
+
// Binds to FaceLock service, but does not tell it to start
public void bindToFaceLock() {
if (mLockPatternUtils.usingBiometricWeak() &&
@@ -1101,7 +1162,10 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
try {
mFaceLockService.registerCallback(mFaceLockCallback);
} catch (RemoteException e) {
- throw new RuntimeException("Remote exception");
+ Log.e(TAG, "Caught exception connecting to FaceLock: " + e.toString());
+ mFaceLockService = null;
+ mBoundToFaceLockService = false;
+ return;
}
if (mFaceLockAreaView != null) {
@@ -1118,6 +1182,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
mFaceLockService = null;
mFaceLockServiceRunning = false;
}
+ mBoundToFaceLockService = false;
Log.w(TAG, "Unexpected disconnect from FaceLock service");
}
};
@@ -1133,7 +1198,8 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
try {
mFaceLockService.startUi(windowToken, x, y, h, w);
} catch (RemoteException e) {
- throw new RuntimeException("Remote exception");
+ Log.e(TAG, "Caught exception starting FaceLock: " + e.toString());
+ return;
}
mFaceLockServiceRunning = true;
} else {
@@ -1157,7 +1223,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
if (DEBUG) Log.d(TAG, "Stopping FaceLock");
mFaceLockService.stopUi();
} catch (RemoteException e) {
- throw new RuntimeException("Remote exception");
+ Log.e(TAG, "Caught exception stopping FaceLock: " + e.toString());
}
mFaceLockServiceRunning = false;
}
@@ -1172,7 +1238,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
@Override
public void unlock() {
if (DEBUG) Log.d(TAG, "FaceLock unlock()");
- mHandler.sendEmptyMessage(MSG_SHOW_FACELOCK_AREA_VIEW); // Keep fallback covered
+ showFaceLockArea(); // Keep fallback covered
stopFaceLock();
mKeyguardScreenCallback.keyguardDone(true);
@@ -1184,7 +1250,7 @@ public class LockPatternKeyguardView extends KeyguardViewBase implements Handler
@Override
public void cancel() {
if (DEBUG) Log.d(TAG, "FaceLock cancel()");
- mHandler.sendEmptyMessage(MSG_HIDE_FACELOCK_AREA_VIEW); // Expose fallback
+ hideFaceLockArea(); // Expose fallback
stopFaceLock();
}
diff --git a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
index ec0072c..3ad716b 100644
--- a/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
+++ b/policy/src/com/android/internal/policy/impl/PasswordUnlockScreen.java
@@ -28,6 +28,7 @@ import com.android.internal.widget.PasswordEntryKeyboardView;
import android.os.CountDownTimer;
import android.os.SystemClock;
+import android.provider.Settings;
import android.security.KeyStore;
import android.text.Editable;
import android.text.InputType;
@@ -109,6 +110,10 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen
mPasswordEntry.setOnEditorActionListener(this);
mKeyboardHelper = new PasswordEntryKeyboardHelper(context, mKeyboardView, this, false);
+ mKeyboardHelper.setEnableHaptics(
+ Settings.Secure.getInt(mContext.getContentResolver(),
+ Settings.Secure.LOCK_PATTERN_TACTILE_FEEDBACK_ENABLED, 0)
+ != 0);
if (mIsAlpha) {
// We always use the system IME for alpha keyboard, so hide lockscreen's soft keyboard
mKeyboardHelper.setKeyboardMode(PasswordEntryKeyboardHelper.KEYBOARD_MODE_ALPHA);
@@ -150,9 +155,6 @@ public class PasswordUnlockScreen extends LinearLayout implements KeyguardScreen
//KeyguardStatusViewManager.LOCK_ICON);
}
- mKeyboardHelper.setVibratePattern(mLockPatternUtils.isTactileFeedbackEnabled() ?
- com.android.internal.R.array.config_virtualKeyVibePattern : 0);
-
// Poke the wakelock any time the text is selected or modified
mPasswordEntry.setOnClickListener(new OnClickListener() {
public void onClick(View v) {
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 2cd6eab..af86ae9 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -349,8 +349,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
// Already prepared (isPrepared will be reset to false later)
- if (st.isPrepared)
+ if (st.isPrepared) {
return true;
+ }
if ((mPreparedPanel != null) && (mPreparedPanel != st)) {
// Another Panel is prepared and possibly open, so close it
@@ -800,14 +801,23 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
closePanel(st, true);
} else if (st.isPrepared) {
+ boolean show = true;
+ if (st.refreshMenuContent) {
+ // Something may have invalidated the menu since we prepared it.
+ // Re-prepare it to refresh.
+ st.isPrepared = false;
+ show = preparePanel(st, event);
+ }
- // Write 'menu opened' to event log
- EventLog.writeEvent(50001, 0);
+ if (show) {
+ // Write 'menu opened' to event log
+ EventLog.writeEvent(50001, 0);
- // Show menu
- openPanel(st, event);
+ // Show menu
+ openPanel(st, event);
- playSoundEffect = true;
+ playSoundEffect = true;
+ }
}
}
@@ -1084,8 +1094,8 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
MenuView menuView = st.isInListMode()
- ? st.getListMenuView(mPanelMenuPresenterCallback)
- : st.getIconMenuView(mPanelMenuPresenterCallback);
+ ? st.getListMenuView(getContext(), mPanelMenuPresenterCallback)
+ : st.getIconMenuView(getContext(), mPanelMenuPresenterCallback);
st.shownPanelView = (View) menuView;
@@ -3251,11 +3261,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
}
- MenuView getListMenuView(MenuPresenter.Callback cb) {
+ MenuView getListMenuView(Context context, MenuPresenter.Callback cb) {
if (menu == null) return null;
if (!isCompact) {
- getIconMenuView(cb); // Need this initialized to know where our offset goes
+ getIconMenuView(context, cb); // Need this initialized to know where our offset goes
}
if (listMenuPresenter == null) {
@@ -3275,11 +3285,11 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return result;
}
- MenuView getIconMenuView(MenuPresenter.Callback cb) {
+ MenuView getIconMenuView(Context context, MenuPresenter.Callback cb) {
if (menu == null) return null;
if (iconMenuPresenter == null) {
- iconMenuPresenter = new IconMenuPresenter();
+ iconMenuPresenter = new IconMenuPresenter(context);
iconMenuPresenter.setCallback(cb);
iconMenuPresenter.setId(com.android.internal.R.id.icon_menu_presenter);
menu.addMenuPresenter(iconMenuPresenter);
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 487063d..aac3209 100755
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -128,7 +128,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_BOOT_PROGRESS;
import android.view.WindowManagerImpl;
import android.view.WindowManagerPolicy;
import android.view.KeyCharacterMap.FallbackAction;
-import android.view.WindowManagerPolicy.WindowManagerFuncs;
import android.view.accessibility.AccessibilityEvent;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
@@ -180,26 +179,26 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static final int PRIORITY_PHONE_LAYER = 7;
// like the ANR / app crashed dialogs
static final int SYSTEM_ALERT_LAYER = 8;
- // system-level error dialogs
- static final int SYSTEM_ERROR_LAYER = 9;
// on-screen keyboards and other such input method user interfaces go here.
- static final int INPUT_METHOD_LAYER = 10;
+ static final int INPUT_METHOD_LAYER = 9;
// on-screen keyboards and other such input method user interfaces go here.
- static final int INPUT_METHOD_DIALOG_LAYER = 11;
+ static final int INPUT_METHOD_DIALOG_LAYER = 10;
// the keyguard; nothing on top of these can take focus, since they are
// responsible for power management when displayed.
- static final int KEYGUARD_LAYER = 12;
- static final int KEYGUARD_DIALOG_LAYER = 13;
- static final int STATUS_BAR_SUB_PANEL_LAYER = 14;
- static final int STATUS_BAR_LAYER = 15;
- static final int STATUS_BAR_PANEL_LAYER = 16;
+ static final int KEYGUARD_LAYER = 11;
+ static final int KEYGUARD_DIALOG_LAYER = 12;
+ static final int STATUS_BAR_SUB_PANEL_LAYER = 13;
+ static final int STATUS_BAR_LAYER = 14;
+ static final int STATUS_BAR_PANEL_LAYER = 15;
// the on-screen volume indicator and controller shown when the user
// changes the device volume
- static final int VOLUME_OVERLAY_LAYER = 17;
+ static final int VOLUME_OVERLAY_LAYER = 16;
// things in here CAN NOT take focus, but are shown on top of everything else.
- static final int SYSTEM_OVERLAY_LAYER = 18;
+ static final int SYSTEM_OVERLAY_LAYER = 17;
// the navigation bar, if available, shows atop most things
- static final int NAVIGATION_BAR_LAYER = 19;
+ static final int NAVIGATION_BAR_LAYER = 18;
+ // system-level error dialogs
+ static final int SYSTEM_ERROR_LAYER = 19;
// the drag layer: input for drag-and-drop is associated with this window,
// which sits above all other focusable windows
static final int DRAG_LAYER = 20;
@@ -267,7 +266,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
WindowState mKeyguard = null;
KeyguardViewMediator mKeyguardMediator;
GlobalActions mGlobalActions;
- volatile boolean mPowerKeyHandled;
+ volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread
+ boolean mPendingPowerKeyUpCanceled;
RecentApplicationsDialog mRecentAppsDialog;
Handler mHandler;
@@ -403,8 +403,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private int mLongPressOnHomeBehavior = -1;
// Screenshot trigger states
- private boolean mVolumeDownTriggered;
- private boolean mPowerDownTriggered;
+ // Time to volume and power must be pressed within this interval of each other.
+ private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
+ private boolean mVolumeDownKeyTriggered;
+ private long mVolumeDownKeyTime;
+ private boolean mVolumeDownKeyConsumedByScreenshotChord;
+ private boolean mVolumeUpKeyTriggered;
+ private boolean mPowerKeyTriggered;
+ private long mPowerKeyTime;
ShortcutManager mShortcutManager;
PowerManager.WakeLock mBroadcastWakeLock;
@@ -552,40 +558,67 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (!mPowerKeyHandled) {
mHandler.removeCallbacks(mPowerLongPress);
return !canceled;
- } else {
- mPowerKeyHandled = true;
- return false;
}
+ return false;
+ }
+
+ private void cancelPendingPowerKeyAction() {
+ if (!mPowerKeyHandled) {
+ mHandler.removeCallbacks(mPowerLongPress);
+ }
+ mPendingPowerKeyUpCanceled = true;
+ }
+
+ private void interceptScreenshotChord() {
+ if (mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) {
+ final long now = SystemClock.uptimeMillis();
+ if (now <= mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
+ && now <= mPowerKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
+ mVolumeDownKeyConsumedByScreenshotChord = true;
+ cancelPendingPowerKeyAction();
+
+ mHandler.postDelayed(mScreenshotChordLongPress,
+ ViewConfiguration.getGlobalActionKeyTimeout());
+ }
+ }
+ }
+
+ private void cancelPendingScreenshotChordAction() {
+ mHandler.removeCallbacks(mScreenshotChordLongPress);
}
private final Runnable mPowerLongPress = new Runnable() {
public void run() {
- if (!mPowerKeyHandled) {
- // The context isn't read
- if (mLongPressOnPowerBehavior < 0) {
- mLongPressOnPowerBehavior = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_longPressOnPowerBehavior);
- }
- switch (mLongPressOnPowerBehavior) {
- case LONG_PRESS_POWER_NOTHING:
- break;
- case LONG_PRESS_POWER_GLOBAL_ACTIONS:
- mPowerKeyHandled = true;
- performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
- sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
- showGlobalActionsDialog();
- break;
- case LONG_PRESS_POWER_SHUT_OFF:
- mPowerKeyHandled = true;
- performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
- sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
- ShutdownThread.shutdown(mContext, true);
- break;
- }
+ // The context isn't read
+ if (mLongPressOnPowerBehavior < 0) {
+ mLongPressOnPowerBehavior = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_longPressOnPowerBehavior);
+ }
+ switch (mLongPressOnPowerBehavior) {
+ case LONG_PRESS_POWER_NOTHING:
+ break;
+ case LONG_PRESS_POWER_GLOBAL_ACTIONS:
+ mPowerKeyHandled = true;
+ performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+ sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
+ showGlobalActionsDialog();
+ break;
+ case LONG_PRESS_POWER_SHUT_OFF:
+ mPowerKeyHandled = true;
+ performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+ sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
+ ShutdownThread.shutdown(mContext, true);
+ break;
}
}
};
+ private final Runnable mScreenshotChordLongPress = new Runnable() {
+ public void run() {
+ takeScreenshot();
+ }
+ };
+
void showGlobalActionsDialog() {
if (mGlobalActions == null) {
mGlobalActions = new GlobalActions(mContext);
@@ -1381,11 +1414,12 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
@Override
- public boolean interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
+ public long interceptKeyBeforeDispatching(WindowState win, KeyEvent event, int policyFlags) {
final boolean keyguardOn = keyguardOn();
final int keyCode = event.getKeyCode();
final int repeatCount = event.getRepeatCount();
final int metaState = event.getMetaState();
+ final int flags = event.getFlags();
final boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
final boolean canceled = event.isCanceled();
@@ -1394,6 +1428,26 @@ public class PhoneWindowManager implements WindowManagerPolicy {
+ repeatCount + " keyguardOn=" + keyguardOn + " mHomePressed=" + mHomePressed);
}
+ // If we think we might have a volume down & power key chord on the way
+ // but we're not sure, then tell the dispatcher to wait a little while and
+ // try again later before dispatching.
+ if ((flags & KeyEvent.FLAG_FALLBACK) == 0) {
+ if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) {
+ final long now = SystemClock.uptimeMillis();
+ final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
+ if (now < timeoutTime) {
+ return timeoutTime - now;
+ }
+ }
+ if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
+ && mVolumeDownKeyConsumedByScreenshotChord) {
+ if (!down) {
+ mVolumeDownKeyConsumedByScreenshotChord = false;
+ }
+ return -1;
+ }
+ }
+
// First we always handle the home key here, so applications
// can never break it, although if keyguard is on, we do let
// it handle it, because that gives us the correct 5 second
@@ -1425,7 +1479,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} else {
Log.i(TAG, "Ignoring HOME; event canceled.");
}
- return true;
+ return -1;
}
// If a system window has focus, then it doesn't make sense
@@ -1436,13 +1490,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (type == WindowManager.LayoutParams.TYPE_KEYGUARD
|| type == WindowManager.LayoutParams.TYPE_KEYGUARD_DIALOG) {
// the "app" is keyguard, so give it the key
- return false;
+ return 0;
}
final int typeCount = WINDOW_TYPES_WHERE_HOME_DOESNT_WORK.length;
for (int i=0; i<typeCount; i++) {
if (type == WINDOW_TYPES_WHERE_HOME_DOESNT_WORK[i]) {
// don't do anything, but also don't pass it to the app
- return true;
+ return -1;
}
}
}
@@ -1456,7 +1510,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
}
- return true;
+ return -1;
} else if (keyCode == KeyEvent.KEYCODE_MENU) {
// Hijack modified menu keys for debugging features
final int chordBug = KeyEvent.META_SHIFT_ON;
@@ -1465,7 +1519,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mEnableShiftMenuBugReports && (metaState & chordBug) == chordBug) {
Intent intent = new Intent(Intent.ACTION_BUG_REPORT);
mContext.sendOrderedBroadcast(intent, null);
- return true;
+ return -1;
} else if (SHOW_PROCESSES_ON_ALT_MENU &&
(metaState & KeyEvent.META_ALT_ON) == KeyEvent.META_ALT_ON) {
Intent service = new Intent();
@@ -1480,7 +1534,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
Settings.System.putInt(
res, Settings.System.SHOW_PROCESSES, shown ? 0 : 1);
- return true;
+ return -1;
}
}
} else if (keyCode == KeyEvent.KEYCODE_SEARCH) {
@@ -1493,15 +1547,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mShortcutKeyPressed = -1;
if (mConsumeShortcutKeyUp) {
mConsumeShortcutKeyUp = false;
- return true;
+ return -1;
}
}
- return false;
+ return 0;
} else if (keyCode == KeyEvent.KEYCODE_APP_SWITCH) {
if (down && repeatCount == 0) {
showOrHideRecentAppsDialog(0, true /*dismissIfShown*/);
}
- return true;
+ return -1;
}
// Shortcuts are invoked through Search+key, so intercept those here
@@ -1531,11 +1585,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
+ "+" + KeyEvent.keyCodeToString(keyCode));
}
}
- return true;
+ return -1;
}
}
- return false;
+ return 0;
}
/** {@inheritDoc} */
@@ -1606,7 +1660,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
flags, event.getSource(), null);
int actions = interceptKeyBeforeQueueing(fallbackEvent, policyFlags, true);
if ((actions & ACTION_PASS_TO_USER) != 0) {
- if (!interceptKeyBeforeDispatching(win, fallbackEvent, policyFlags)) {
+ long delayMillis = interceptKeyBeforeDispatching(
+ win, fallbackEvent, policyFlags);
+ if (delayMillis == 0) {
if (DEBUG_FALLBACK) {
Slog.d(TAG, "Performing fallback.");
}
@@ -2472,76 +2528,65 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final Object mScreenshotLock = new Object();
ServiceConnection mScreenshotConnection = null;
- Runnable mScreenshotTimeout = null;
- void finishScreenshotLSS(ServiceConnection conn) {
- if (mScreenshotConnection == conn) {
- mContext.unbindService(conn);
- mScreenshotConnection = null;
- if (mScreenshotTimeout != null) {
- mHandler.removeCallbacks(mScreenshotTimeout);
- mScreenshotTimeout = null;
+ final Runnable mScreenshotTimeout = new Runnable() {
+ @Override public void run() {
+ synchronized (mScreenshotLock) {
+ if (mScreenshotConnection != null) {
+ mContext.unbindService(mScreenshotConnection);
+ mScreenshotConnection = null;
+ }
}
}
- }
+ };
+ // Assume this is called from the Handler thread.
private void takeScreenshot() {
- mHandler.post(new Runnable() {
- @Override
- public void run() {
- synchronized (mScreenshotLock) {
- if (mScreenshotConnection != null) {
- return;
- }
- ComponentName cn = new ComponentName("com.android.systemui",
- "com.android.systemui.screenshot.TakeScreenshotService");
- Intent intent = new Intent();
- intent.setComponent(cn);
- ServiceConnection conn = new ServiceConnection() {
- @Override
- public void onServiceConnected(ComponentName name, IBinder service) {
- synchronized (mScreenshotLock) {
- if (mScreenshotConnection != this) {
- return;
- }
- Messenger messenger = new Messenger(service);
- Message msg = Message.obtain(null, 1);
- final ServiceConnection myConn = this;
- Handler h = new Handler(mHandler.getLooper()) {
- @Override
- public void handleMessage(Message msg) {
- synchronized (mScreenshotLock) {
- finishScreenshotLSS(myConn);
- }
- }
- };
- msg.replyTo = new Messenger(h);
- try {
- messenger.send(msg);
- } catch (RemoteException e) {
- }
- }
+ synchronized (mScreenshotLock) {
+ if (mScreenshotConnection != null) {
+ return;
+ }
+ ComponentName cn = new ComponentName("com.android.systemui",
+ "com.android.systemui.screenshot.TakeScreenshotService");
+ Intent intent = new Intent();
+ intent.setComponent(cn);
+ ServiceConnection conn = new ServiceConnection() {
+ @Override
+ public void onServiceConnected(ComponentName name, IBinder service) {
+ synchronized (mScreenshotLock) {
+ if (mScreenshotConnection != this) {
+ return;
}
- @Override
- public void onServiceDisconnected(ComponentName name) {}
- };
- if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) {
- mScreenshotConnection = conn;
- mScreenshotTimeout = new Runnable() {
- @Override public void run() {
+ Messenger messenger = new Messenger(service);
+ Message msg = Message.obtain(null, 1);
+ final ServiceConnection myConn = this;
+ Handler h = new Handler(mHandler.getLooper()) {
+ @Override
+ public void handleMessage(Message msg) {
synchronized (mScreenshotLock) {
- if (mScreenshotConnection != null) {
- finishScreenshotLSS(mScreenshotConnection);
+ if (mScreenshotConnection == myConn) {
+ mContext.unbindService(mScreenshotConnection);
+ mScreenshotConnection = null;
+ mHandler.removeCallbacks(mScreenshotTimeout);
}
}
}
-
};
- mHandler.postDelayed(mScreenshotTimeout, 10000);
+ msg.replyTo = new Messenger(h);
+ try {
+ messenger.send(msg);
+ } catch (RemoteException e) {
+ }
}
}
+ @Override
+ public void onServiceDisconnected(ComponentName name) {}
+ };
+ if (mContext.bindService(intent, conn, Context.BIND_AUTO_CREATE)) {
+ mScreenshotConnection = conn;
+ mHandler.postDelayed(mScreenshotTimeout, 10000);
}
- });
+ }
}
/** {@inheritDoc} */
@@ -2609,28 +2654,35 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// Handle special keys.
switch (keyCode) {
case KeyEvent.KEYCODE_VOLUME_DOWN:
- if (down) {
- if (isScreenOn) {
- // If the power key down was already triggered, take the screenshot
- if (mPowerDownTriggered) {
- // Dismiss the power-key longpress
- mHandler.removeCallbacks(mPowerLongPress);
- mPowerKeyHandled = true;
-
- // Take the screenshot
- takeScreenshot();
-
- // Prevent the event from being passed through to the current activity
- result &= ~ACTION_PASS_TO_USER;
- break;
+ case KeyEvent.KEYCODE_VOLUME_UP:
+ case KeyEvent.KEYCODE_VOLUME_MUTE: {
+ if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
+ if (down) {
+ if (isScreenOn && !mVolumeDownKeyTriggered
+ && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
+ mVolumeDownKeyTriggered = true;
+ mVolumeDownKeyTime = event.getDownTime();
+ mVolumeDownKeyConsumedByScreenshotChord = false;
+ cancelPendingPowerKeyAction();
+ interceptScreenshotChord();
+ }
+ } else {
+ mVolumeDownKeyTriggered = false;
+ cancelPendingScreenshotChordAction();
+ }
+ } else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
+ if (down) {
+ if (isScreenOn && !mVolumeUpKeyTriggered
+ && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
+ mVolumeUpKeyTriggered = true;
+ cancelPendingPowerKeyAction();
+ cancelPendingScreenshotChordAction();
}
- mVolumeDownTriggered = true;
+ } else {
+ mVolumeUpKeyTriggered = false;
+ cancelPendingScreenshotChordAction();
}
- } else {
- mVolumeDownTriggered = false;
}
- case KeyEvent.KEYCODE_VOLUME_UP:
- case KeyEvent.KEYCODE_VOLUME_MUTE: {
if (down) {
ITelephony telephonyService = getTelephonyService();
if (telephonyService != null) {
@@ -2709,17 +2761,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_POWER: {
result &= ~ACTION_PASS_TO_USER;
if (down) {
- if (isScreenOn) {
- // If the volume down key has been triggered, then just take the screenshot
- if (mVolumeDownTriggered) {
- // Take the screenshot
- takeScreenshot();
- mPowerKeyHandled = true;
-
- // Prevent the event from being passed through to the current activity
- break;
- }
- mPowerDownTriggered = true;
+ if (isScreenOn && !mPowerKeyTriggered
+ && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
+ mPowerKeyTriggered = true;
+ mPowerKeyTime = event.getDownTime();
+ interceptScreenshotChord();
}
ITelephony telephonyService = getTelephonyService();
@@ -2741,12 +2787,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Log.w(TAG, "ITelephony threw RemoteException", ex);
}
}
- interceptPowerKeyDown(!isScreenOn || hungUp);
+ interceptPowerKeyDown(!isScreenOn || hungUp
+ || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
} else {
- mPowerDownTriggered = false;
- if (interceptPowerKeyUp(canceled)) {
+ mPowerKeyTriggered = false;
+ cancelPendingScreenshotChordAction();
+ if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
result = (result & ~ACTION_POKE_USER_ACTIVITY) | ACTION_GO_TO_SLEEP;
}
+ mPendingPowerKeyUpCanceled = false;
}
break;
}