summaryrefslogtreecommitdiffstats
path: root/policy
diff options
context:
space:
mode:
Diffstat (limited to 'policy')
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindow.java205
-rw-r--r--policy/src/com/android/internal/policy/impl/PhoneWindowManager.java804
-rw-r--r--policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java347
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java61
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java100
-rw-r--r--policy/src/com/android/internal/policy/impl/keyguard/KeyguardStateMonitor.java86
6 files changed, 870 insertions, 733 deletions
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindow.java b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
index 9c81f0a..30a271e 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindow.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindow.java
@@ -101,6 +101,7 @@ import android.view.accessibility.AccessibilityEvent;
import android.view.accessibility.AccessibilityManager;
import android.view.animation.Animation;
import android.view.animation.AnimationUtils;
+import android.view.animation.Interpolator;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.PopupWindow;
@@ -1332,6 +1333,22 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
@Override
+ public final void setElevation(float elevation) {
+ mElevation = elevation;
+ if (mDecor != null) {
+ mDecor.setElevation(elevation);
+ }
+ }
+
+ @Override
+ public final void setClipToOutline(boolean clipToOutline) {
+ mClipToOutline = clipToOutline;
+ if (mDecor != null) {
+ mDecor.setClipToOutline(clipToOutline);
+ }
+ }
+
+ @Override
public final void setBackgroundDrawable(Drawable drawable) {
if (drawable != mBackgroundDrawable || mBackgroundResource != 0) {
mBackgroundResource = 0;
@@ -2137,6 +2154,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
private final class DecorView extends FrameLayout implements RootViewSurfaceTaker {
+
/* package */int mDefaultOpacity = PixelFormat.OPAQUE;
/** The feature ID of the panel, or -1 if this is the application's DecorView */
@@ -2166,18 +2184,45 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
// View added at runtime to draw under the navigation bar area
private View mNavigationGuard;
- private View mStatusColorView;
- private View mNavigationColorView;
+ private final ColorViewState mStatusColorViewState = new ColorViewState(
+ SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS,
+ Gravity.TOP,
+ STATUS_BAR_BACKGROUND_TRANSITION_NAME,
+ com.android.internal.R.id.statusBarBackground,
+ FLAG_FULLSCREEN);
+ private final ColorViewState mNavigationColorViewState = new ColorViewState(
+ SYSTEM_UI_FLAG_HIDE_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION,
+ Gravity.BOTTOM,
+ NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,
+ com.android.internal.R.id.navigationBarBackground,
+ 0 /* hideWindowFlag */);
+
+ private final Interpolator mShowInterpolator;
+ private final Interpolator mHideInterpolator;
+ private final int mBarEnterExitDuration;
+
private final BackgroundFallback mBackgroundFallback = new BackgroundFallback();
private int mLastTopInset = 0;
private int mLastBottomInset = 0;
private int mLastRightInset = 0;
+ private boolean mLastHasTopStableInset = false;
+ private boolean mLastHasBottomStableInset = false;
+ private int mLastWindowFlags = 0;
+ private int mRootScrollY = 0;
public DecorView(Context context, int featureId) {
super(context);
mFeatureId = featureId;
+
+ mShowInterpolator = AnimationUtils.loadInterpolator(context,
+ android.R.interpolator.linear_out_slow_in);
+ mHideInterpolator = AnimationUtils.loadInterpolator(context,
+ android.R.interpolator.fast_out_linear_in);
+
+ mBarEnterExitDuration = context.getResources().getInteger(
+ R.integer.dock_enter_exit_duration);
}
public void setBackgroundFallback(int resId) {
@@ -2770,13 +2815,13 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
@Override
public void onWindowSystemUiVisibilityChanged(int visible) {
- updateColorViews(null /* insets */);
+ updateColorViews(null /* insets */, true /* animate */);
}
@Override
public WindowInsets onApplyWindowInsets(WindowInsets insets) {
mFrameOffsets.set(insets.getSystemWindowInsets());
- insets = updateColorViews(insets);
+ insets = updateColorViews(insets, true /* animate */);
insets = updateStatusGuard(insets);
updateNavigationGuard(insets);
if (getForeground() != null) {
@@ -2790,11 +2835,16 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return false;
}
- private WindowInsets updateColorViews(WindowInsets insets) {
+ private WindowInsets updateColorViews(WindowInsets insets, boolean animate) {
WindowManager.LayoutParams attrs = getAttributes();
int sysUiVisibility = attrs.systemUiVisibility | getWindowSystemUiVisibility();
if (!mIsFloating && ActivityManager.isHighEndGfx()) {
+ boolean disallowAnimate = !isLaidOut();
+ disallowAnimate |= ((mLastWindowFlags ^ attrs.flags)
+ & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
+ mLastWindowFlags = attrs.flags;
+
if (insets != null) {
mLastTopInset = Math.min(insets.getStableInsetTop(),
insets.getSystemWindowInsetTop());
@@ -2802,19 +2852,23 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
insets.getSystemWindowInsetBottom());
mLastRightInset = Math.min(insets.getStableInsetRight(),
insets.getSystemWindowInsetRight());
+
+ // Don't animate if the presence of stable insets has changed, because that
+ // indicates that the window was either just added and received them for the
+ // first time, or the window size or position has changed.
+ boolean hasTopStableInset = insets.getStableInsetTop() != 0;
+ disallowAnimate |= hasTopStableInset && !mLastHasTopStableInset;
+ mLastHasTopStableInset = hasTopStableInset;
+
+ boolean hasBottomStableInset = insets.getStableInsetBottom() != 0;
+ disallowAnimate |= hasBottomStableInset && !mLastHasBottomStableInset;
+ mLastHasBottomStableInset = hasBottomStableInset;
}
- mStatusColorView = updateColorViewInt(mStatusColorView, sysUiVisibility,
- SYSTEM_UI_FLAG_FULLSCREEN, FLAG_TRANSLUCENT_STATUS,
- mStatusBarColor, mLastTopInset, Gravity.TOP,
- STATUS_BAR_BACKGROUND_TRANSITION_NAME,
- com.android.internal.R.id.statusBarBackground,
- (getAttributes().flags & FLAG_FULLSCREEN) != 0);
- mNavigationColorView = updateColorViewInt(mNavigationColorView, sysUiVisibility,
- SYSTEM_UI_FLAG_HIDE_NAVIGATION, FLAG_TRANSLUCENT_NAVIGATION,
- mNavigationBarColor, mLastBottomInset, Gravity.BOTTOM,
- NAVIGATION_BAR_BACKGROUND_TRANSITION_NAME,
- com.android.internal.R.id.navigationBarBackground,
- false /* hiddenByWindowFlag */);
+
+ updateColorViewInt(mStatusColorViewState, sysUiVisibility, mStatusBarColor,
+ mLastTopInset, animate && !disallowAnimate);
+ updateColorViewInt(mNavigationColorViewState, sysUiVisibility, mNavigationBarColor,
+ mLastBottomInset, animate && !disallowAnimate);
}
// When we expand the window with FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS, we still need
@@ -2858,27 +2912,35 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
return insets;
}
- private View updateColorViewInt(View view, int sysUiVis, int systemUiHideFlag,
- int translucentFlag, int color, int height, int verticalGravity,
- String transitionName, int id, boolean hiddenByWindowFlag) {
- boolean show = height > 0 && (sysUiVis & systemUiHideFlag) == 0
- && !hiddenByWindowFlag
- && (getAttributes().flags & translucentFlag) == 0
+ private void updateColorViewInt(final ColorViewState state, int sysUiVis, int color,
+ int height, boolean animate) {
+ boolean show = height > 0 && (sysUiVis & state.systemUiHideFlag) == 0
+ && (getAttributes().flags & state.hideWindowFlag) == 0
+ && (getAttributes().flags & state.translucentFlag) == 0
&& (color & Color.BLACK) != 0
&& (getAttributes().flags & FLAG_DRAWS_SYSTEM_BAR_BACKGROUNDS) != 0;
+ boolean visibilityChanged = false;
+ View view = state.view;
+
if (view == null) {
if (show) {
- view = new View(mContext);
+ state.view = view = new View(mContext);
view.setBackgroundColor(color);
- view.setTransitionName(transitionName);
- view.setId(id);
+ view.setTransitionName(state.transitionName);
+ view.setId(state.id);
+ visibilityChanged = true;
+ view.setVisibility(INVISIBLE);
+ state.targetVisibility = VISIBLE;
+
addView(view, new LayoutParams(LayoutParams.MATCH_PARENT, height,
- Gravity.START | verticalGravity));
+ Gravity.START | state.verticalGravity));
+ updateColorViewTranslations();
}
} else {
int vis = show ? VISIBLE : INVISIBLE;
- view.setVisibility(vis);
+ visibilityChanged = state.targetVisibility != vis;
+ state.targetVisibility = vis;
if (show) {
LayoutParams lp = (LayoutParams) view.getLayoutParams();
if (lp.height != height) {
@@ -2888,7 +2950,44 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
view.setBackgroundColor(color);
}
}
- return view;
+ if (visibilityChanged) {
+ view.animate().cancel();
+ if (animate) {
+ if (show) {
+ if (view.getVisibility() != VISIBLE) {
+ view.setVisibility(VISIBLE);
+ view.setAlpha(0.0f);
+ }
+ view.animate().alpha(1.0f).setInterpolator(mShowInterpolator).
+ setDuration(mBarEnterExitDuration);
+ } else {
+ view.animate().alpha(0.0f).setInterpolator(mHideInterpolator)
+ .setDuration(mBarEnterExitDuration)
+ .withEndAction(new Runnable() {
+ @Override
+ public void run() {
+ state.view.setAlpha(1.0f);
+ state.view.setVisibility(INVISIBLE);
+ }
+ });
+ }
+ } else {
+ view.setAlpha(1.0f);
+ view.setVisibility(show ? VISIBLE : INVISIBLE);
+ }
+ }
+ }
+
+ private void updateColorViewTranslations() {
+ // Put the color views back in place when they get moved off the screen
+ // due to the the ViewRootImpl panning.
+ int rootScrollY = mRootScrollY;
+ if (mStatusColorViewState.view != null) {
+ mStatusColorViewState.view.setTranslationY(rootScrollY > 0 ? rootScrollY : 0);
+ }
+ if (mNavigationColorViewState.view != null) {
+ mNavigationColorViewState.view.setTranslationY(rootScrollY < 0 ? rootScrollY : 0);
+ }
}
private WindowInsets updateStatusGuard(WindowInsets insets) {
@@ -2918,7 +3017,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
mStatusGuard = new View(mContext);
mStatusGuard.setBackgroundColor(mContext.getResources()
.getColor(R.color.input_method_navigation_guard));
- addView(mStatusGuard, indexOfChild(mStatusColorView),
+ addView(mStatusGuard, indexOfChild(mStatusColorViewState.view),
new LayoutParams(LayoutParams.MATCH_PARENT,
mlp.topMargin, Gravity.START | Gravity.TOP));
} else {
@@ -2978,9 +3077,10 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
mNavigationGuard = new View(mContext);
mNavigationGuard.setBackgroundColor(mContext.getResources()
.getColor(R.color.input_method_navigation_guard));
- addView(mNavigationGuard, indexOfChild(mNavigationColorView), new LayoutParams(
- LayoutParams.MATCH_PARENT, insets.getSystemWindowInsetBottom(),
- Gravity.START | Gravity.BOTTOM));
+ addView(mNavigationGuard, indexOfChild(mNavigationColorViewState.view),
+ new LayoutParams(LayoutParams.MATCH_PARENT,
+ insets.getSystemWindowInsetBottom(),
+ Gravity.START | Gravity.BOTTOM));
} else {
LayoutParams lp = (LayoutParams) mNavigationGuard.getLayoutParams();
lp.height = insets.getSystemWindowInsetBottom();
@@ -3149,6 +3249,12 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
else PhoneWindow.this.clearFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
}
+ @Override
+ public void onRootViewScrollYChanged(int rootScrollY) {
+ mRootScrollY = rootScrollY;
+ updateColorViewTranslations();
+ }
+
/**
* Clears out internal reference when the action mode is destroyed.
*/
@@ -3342,9 +3448,9 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
final boolean noActionBar = !hasFeature(FEATURE_ACTION_BAR) || hasFeature(FEATURE_NO_TITLE);
if (targetPreHoneycomb || (targetPreIcs && targetHcNeedsOptions && noActionBar)) {
- addFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY);
+ setNeedsMenuKey(WindowManager.LayoutParams.NEEDS_MENU_SET_TRUE);
} else {
- clearFlags(WindowManager.LayoutParams.FLAG_NEEDS_MENU_KEY);
+ setNeedsMenuKey(WindowManager.LayoutParams.NEEDS_MENU_SET_FALSE);
}
// Non-floating windows on high end devices must put up decor beneath the system bars and
@@ -3876,7 +3982,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
protected void dispatchWindowAttributesChanged(WindowManager.LayoutParams attrs) {
super.dispatchWindowAttributesChanged(attrs);
if (mDecor != null) {
- mDecor.updateColorViews(null /* insets */);
+ mDecor.updateColorViews(null /* insets */, true /* animate */);
}
}
@@ -4603,6 +4709,29 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
}
}
+ private static class ColorViewState {
+ View view = null;
+ int targetVisibility = View.INVISIBLE;
+
+ final int id;
+ final int systemUiHideFlag;
+ final int translucentFlag;
+ final int verticalGravity;
+ final String transitionName;
+ final int hideWindowFlag;
+
+ ColorViewState(int systemUiHideFlag,
+ int translucentFlag, int verticalGravity,
+ String transitionName, int id, int hideWindowFlag) {
+ this.id = id;
+ this.systemUiHideFlag = systemUiHideFlag;
+ this.translucentFlag = translucentFlag;
+ this.verticalGravity = verticalGravity;
+ this.transitionName = transitionName;
+ this.hideWindowFlag = hideWindowFlag;
+ }
+ }
+
void sendCloseSystemWindows() {
PhoneWindowManager.sendCloseSystemWindows(getContext(), null);
}
@@ -4621,7 +4750,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
mStatusBarColor = color;
mForcedStatusBarColor = true;
if (mDecor != null) {
- mDecor.updateColorViews(null);
+ mDecor.updateColorViews(null, false /* animate */);
}
}
@@ -4635,7 +4764,7 @@ public class PhoneWindow extends Window implements MenuBuilder.Callback {
mNavigationBarColor = color;
mForcedNavigationBarColor = true;
if (mDecor != null) {
- mDecor.updateColorViews(null);
+ mDecor.updateColorViews(null, false /* animate */);
}
}
}
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 99d5848..f0c6bb7 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -48,6 +48,7 @@ import android.media.Ringtone;
import android.media.RingtoneManager;
import android.media.session.MediaSessionLegacyHelper;
import android.os.Bundle;
+import android.os.Debug;
import android.os.FactoryTest;
import android.os.Handler;
import android.os.IBinder;
@@ -102,8 +103,6 @@ import android.view.animation.AnimationSet;
import android.view.animation.AnimationUtils;
import com.android.internal.R;
-import com.android.internal.policy.IKeyguardService;
-import com.android.internal.policy.IKeyguardServiceConstants;
import com.android.internal.policy.PolicyManager;
import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate;
import com.android.internal.policy.impl.keyguard.KeyguardServiceDelegate.ShowListener;
@@ -116,6 +115,7 @@ import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashSet;
+import java.util.List;
import static android.view.WindowManager.LayoutParams.*;
import static android.view.WindowManagerPolicy.WindowManagerFuncs.LID_ABSENT;
@@ -136,8 +136,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static final String TAG = "WindowManager";
static final boolean DEBUG = false;
static final boolean localLOGV = false;
- static final boolean DEBUG_LAYOUT = false;
static final boolean DEBUG_INPUT = false;
+ static final boolean DEBUG_KEYGUARD = false;
+ static final boolean DEBUG_LAYOUT = false;
static final boolean DEBUG_STARTING_WINDOW = false;
static final boolean DEBUG_WAKEUP = false;
static final boolean SHOW_STARTING_ANIMATIONS = true;
@@ -158,6 +159,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
static final int LONG_PRESS_POWER_SHUT_OFF = 2;
static final int LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM = 3;
+ static final int MULTI_PRESS_POWER_NOTHING = 0;
+ static final int MULTI_PRESS_POWER_THEATER_MODE = 1;
+ static final int MULTI_PRESS_POWER_BRIGHTNESS_BOOST = 2;
+
// These need to match the documentation/constant in
// core/res/res/values/config.xml
static final int LONG_PRESS_HOME_NOTHING = 0;
@@ -300,12 +305,22 @@ public class PhoneWindowManager implements WindowManagerPolicy {
};
GlobalActions mGlobalActions;
- volatile boolean mPowerKeyHandled; // accessed from input reader and handler thread
- boolean mPendingPowerKeyUpCanceled;
Handler mHandler;
WindowState mLastInputMethodWindow = null;
WindowState mLastInputMethodTargetWindow = null;
+ // FIXME This state is shared between the input reader and handler thread.
+ // Technically it's broken and buggy but it has been like this for many years
+ // and we have not yet seen any problems. Someday we'll rewrite this logic
+ // so that only one thread is involved in handling input policy. Unfortunately
+ // it's on a critical path for power management so we can't just post the work to the
+ // handler thread. We'll need to resolve this someday by teaching the input dispatcher
+ // to hold wakelocks during dispatch and eliminating the critical path.
+ volatile boolean mPowerKeyHandled;
+ volatile boolean mBeganFromNonInteractive;
+ volatile int mPowerKeyPressCounter;
+ volatile boolean mEndCallKeyHandled;
+
boolean mRecentsVisible;
int mRecentAppsHeldModifiers;
boolean mLanguageSwitchKeyPressed;
@@ -326,6 +341,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int mUndockedHdmiRotation;
int mDemoHdmiRotation;
boolean mDemoHdmiRotationLock;
+ int mDemoRotation;
+ boolean mDemoRotationLock;
boolean mWakeGestureEnabledSetting;
MyWakeGestureListener mWakeGestureListener;
@@ -345,8 +362,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
int mLidKeyboardAccessibility;
int mLidNavigationAccessibility;
boolean mLidControlsSleep;
- int mShortPressOnPowerBehavior = -1;
- int mLongPressOnPowerBehavior = -1;
+ int mShortPressOnPowerBehavior;
+ int mLongPressOnPowerBehavior;
+ int mDoublePressOnPowerBehavior;
+ int mTriplePressOnPowerBehavior;
boolean mAwake;
boolean mScreenOnEarly;
boolean mScreenOnFully;
@@ -462,6 +481,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean mShowingLockscreen;
boolean mShowingDream;
boolean mDreamingLockscreen;
+ boolean mKeyguardSecure;
+ boolean mKeyguardSecureIncludingHidden;
+ volatile boolean mKeyguardOccluded;
boolean mHomePressed;
boolean mHomeConsumed;
boolean mHomeDoubleTapPending;
@@ -503,18 +525,30 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// What we do when the user double-taps on home
private int mDoubleTapOnHomeBehavior;
+ // Allowed theater mode wake actions
+ private boolean mAllowTheaterModeWakeFromKey;
+ private boolean mAllowTheaterModeWakeFromPowerKey;
+ private boolean mAllowTheaterModeWakeFromMotion;
+ private boolean mAllowTheaterModeWakeFromMotionWhenNotDreaming;
+ private boolean mAllowTheaterModeWakeFromCameraLens;
+ private boolean mAllowTheaterModeWakeFromLidSwitch;
+ private boolean mAllowTheaterModeWakeFromWakeGesture;
+
+ // Whether to go to sleep entering theater mode from power button
+ private boolean mGoToSleepOnButtonPressTheaterMode;
+
// Screenshot trigger states
// Time to volume and power must be pressed within this interval of each other.
private static final long SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS = 150;
// Increase the chord delay when taking a screenshot from the keyguard
private static final float KEYGUARD_SCREENSHOT_CHORD_DELAY_MULTIPLIER = 2.5f;
private boolean mScreenshotChordEnabled;
- private boolean mVolumeDownKeyTriggered;
- private long mVolumeDownKeyTime;
- private boolean mVolumeDownKeyConsumedByScreenshotChord;
- private boolean mVolumeUpKeyTriggered;
- private boolean mPowerKeyTriggered;
- private long mPowerKeyTime;
+ private boolean mScreenshotChordVolumeDownKeyTriggered;
+ private long mScreenshotChordVolumeDownKeyTime;
+ private boolean mScreenshotChordVolumeDownKeyConsumed;
+ private boolean mScreenshotChordVolumeUpKeyTriggered;
+ private boolean mScreenshotChordPowerKeyTriggered;
+ private long mScreenshotChordPowerKeyTime;
/* The number of steps between min and max brightness */
private static final int BRIGHTNESS_STEPS = 10;
@@ -522,6 +556,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
SettingsObserver mSettingsObserver;
ShortcutManager mShortcutManager;
PowerManager.WakeLock mBroadcastWakeLock;
+ PowerManager.WakeLock mPowerKeyWakeLock;
boolean mHavePendingMediaKeyRepeatWithWakeLock;
private int mCurrentUserId;
@@ -547,6 +582,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private static final int MSG_DISPATCH_SHOW_GLOBAL_ACTIONS = 10;
private static final int MSG_HIDE_BOOT_MESSAGE = 11;
private static final int MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK = 12;
+ private static final int MSG_POWER_DELAYED_PRESS = 13;
+ private static final int MSG_POWER_LONG_PRESS = 14;
private class PolicyHandler extends Handler {
@Override
@@ -588,6 +625,13 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case MSG_LAUNCH_VOICE_ASSIST_WITH_WAKE_LOCK:
launchVoiceAssistWithWakeLock(msg.arg1 != 0);
break;
+ case MSG_POWER_DELAYED_PRESS:
+ powerPress((Long)msg.obj, msg.arg1 != 0, msg.arg2);
+ finishPowerKeyPress();
+ break;
+ case MSG_POWER_LONG_PRESS:
+ powerLongPress();
+ break;
}
}
}
@@ -656,7 +700,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
synchronized (mLock) {
if (shouldEnableWakeGestureLp()) {
performHapticFeedbackLw(null, HapticFeedbackConstants.VIRTUAL_KEY, false);
- mPowerManager.wakeUp(SystemClock.uptimeMillis());
+ wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromWakeGesture);
}
}
}
@@ -781,38 +825,241 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- private void interceptPowerKeyDown(boolean handled) {
- mPowerKeyHandled = handled;
+ private void interceptPowerKeyDown(KeyEvent event, boolean interactive) {
+ // Hold a wake lock until the power key is released.
+ if (!mPowerKeyWakeLock.isHeld()) {
+ mPowerKeyWakeLock.acquire();
+ }
+
+ // Cancel multi-press detection timeout.
+ if (mPowerKeyPressCounter != 0) {
+ mHandler.removeMessages(MSG_POWER_DELAYED_PRESS);
+ }
+
+ // Detect user pressing the power button in panic when an application has
+ // taken over the whole screen.
+ boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
+ event.getDownTime(), isImmersiveMode(mLastSystemUiFlags));
+ if (panic) {
+ mHandler.post(mRequestTransientNav);
+ }
+
+ // Latch power key state to detect screenshot chord.
+ if (interactive && !mScreenshotChordPowerKeyTriggered
+ && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
+ mScreenshotChordPowerKeyTriggered = true;
+ mScreenshotChordPowerKeyTime = event.getDownTime();
+ interceptScreenshotChord();
+ }
+
+ // Stop ringing or end call if configured to do so when power is pressed.
+ TelecomManager telecomManager = getTelecommService();
+ boolean hungUp = false;
+ if (telecomManager != null) {
+ if (telecomManager.isRinging()) {
+ // Pressing Power while there's a ringing incoming
+ // call should silence the ringer.
+ telecomManager.silenceRinger();
+ } else if ((mIncallPowerBehavior
+ & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
+ && telecomManager.isInCall() && interactive) {
+ // Otherwise, if "Power button ends call" is enabled,
+ // the Power button will hang up any current active call.
+ hungUp = telecomManager.endCall();
+ }
+ }
+
+ // If the power key has still not yet been handled, then detect short
+ // press, long press, or multi press and decide what to do.
+ mPowerKeyHandled = hungUp || mScreenshotChordVolumeDownKeyTriggered
+ || mScreenshotChordVolumeUpKeyTriggered;
+ if (!mPowerKeyHandled) {
+ if (interactive) {
+ // When interactive, we're already awake.
+ // Wait for a long press or for the button to be released to decide what to do.
+ if (hasLongPressOnPowerBehavior()) {
+ Message msg = mHandler.obtainMessage(MSG_POWER_LONG_PRESS);
+ msg.setAsynchronous(true);
+ mHandler.sendMessageDelayed(msg,
+ ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
+ }
+ } else {
+ wakeUpFromPowerKey(event.getDownTime());
+ final int maxCount = getMaxMultiPressPowerCount();
+
+ if (maxCount <= 1) {
+ mPowerKeyHandled = true;
+ } else {
+ mBeganFromNonInteractive = true;
+ }
+ }
+ }
+ }
+
+ private void interceptPowerKeyUp(KeyEvent event, boolean interactive, boolean canceled) {
+ final boolean handled = canceled || mPowerKeyHandled;
+ mScreenshotChordPowerKeyTriggered = false;
+ cancelPendingScreenshotChordAction();
+ cancelPendingPowerKeyAction();
+
if (!handled) {
- mHandler.postDelayed(mPowerLongPress,
- ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
+ // Figure out how to handle the key now that it has been released.
+ mPowerKeyPressCounter += 1;
+
+ final int maxCount = getMaxMultiPressPowerCount();
+ final long eventTime = event.getDownTime();
+ if (mPowerKeyPressCounter < maxCount) {
+ // This could be a multi-press. Wait a little bit longer to confirm.
+ // Continue holding the wake lock.
+ Message msg = mHandler.obtainMessage(MSG_POWER_DELAYED_PRESS,
+ interactive ? 1 : 0, mPowerKeyPressCounter, eventTime);
+ msg.setAsynchronous(true);
+ mHandler.sendMessageDelayed(msg, ViewConfiguration.getDoubleTapTimeout());
+ return;
+ }
+
+ // No other actions. Handle it immediately.
+ powerPress(eventTime, interactive, mPowerKeyPressCounter);
}
+
+ // Done. Reset our state.
+ finishPowerKeyPress();
}
- private boolean interceptPowerKeyUp(boolean canceled) {
- if (!mPowerKeyHandled) {
- mHandler.removeCallbacks(mPowerLongPress);
- return !canceled;
+ private void finishPowerKeyPress() {
+ mBeganFromNonInteractive = false;
+ mPowerKeyPressCounter = 0;
+ if (mPowerKeyWakeLock.isHeld()) {
+ mPowerKeyWakeLock.release();
}
- return false;
}
private void cancelPendingPowerKeyAction() {
if (!mPowerKeyHandled) {
- mHandler.removeCallbacks(mPowerLongPress);
+ mPowerKeyHandled = true;
+ mHandler.removeMessages(MSG_POWER_LONG_PRESS);
+ }
+ }
+
+ private void powerPress(long eventTime, boolean interactive, int count) {
+ if (mScreenOnEarly && !mScreenOnFully) {
+ Slog.i(TAG, "Suppressed redundant power key press while "
+ + "already in the process of turning the screen on.");
+ return;
+ }
+
+ if (count == 2) {
+ powerMultiPressAction(eventTime, interactive, mDoublePressOnPowerBehavior);
+ } else if (count == 3) {
+ powerMultiPressAction(eventTime, interactive, mTriplePressOnPowerBehavior);
+ } else if (interactive && !mBeganFromNonInteractive) {
+ switch (mShortPressOnPowerBehavior) {
+ case SHORT_PRESS_POWER_NOTHING:
+ break;
+ case SHORT_PRESS_POWER_GO_TO_SLEEP:
+ mPowerManager.goToSleep(eventTime,
+ PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
+ break;
+ case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
+ mPowerManager.goToSleep(eventTime,
+ PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
+ PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
+ break;
+ case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
+ mPowerManager.goToSleep(eventTime,
+ PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
+ PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
+ launchHomeFromHotKey();
+ break;
+ }
+ }
+ }
+
+ private void powerMultiPressAction(long eventTime, boolean interactive, int behavior) {
+ switch (behavior) {
+ case MULTI_PRESS_POWER_NOTHING:
+ break;
+ case MULTI_PRESS_POWER_THEATER_MODE:
+ if (isTheaterModeEnabled()) {
+ Slog.i(TAG, "Toggling theater mode off.");
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.THEATER_MODE_ON, 0);
+ if (!interactive) {
+ wakeUpFromPowerKey(eventTime);
+ }
+ } else {
+ Slog.i(TAG, "Toggling theater mode on.");
+ Settings.Global.putInt(mContext.getContentResolver(),
+ Settings.Global.THEATER_MODE_ON, 1);
+
+ if (mGoToSleepOnButtonPressTheaterMode && interactive) {
+ mPowerManager.goToSleep(eventTime,
+ PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
+ }
+ }
+ break;
+ case MULTI_PRESS_POWER_BRIGHTNESS_BOOST:
+ Slog.i(TAG, "Starting brightness boost.");
+ if (!interactive) {
+ wakeUpFromPowerKey(eventTime);
+ }
+ mPowerManager.boostScreenBrightness(eventTime);
+ break;
+ }
+ }
+
+ private int getMaxMultiPressPowerCount() {
+ if (mTriplePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
+ return 3;
+ }
+ if (mDoublePressOnPowerBehavior != MULTI_PRESS_POWER_NOTHING) {
+ return 2;
+ }
+ return 1;
+ }
+
+ private void powerLongPress() {
+ final int behavior = getResolvedLongPressOnPowerBehavior();
+ switch (behavior) {
+ case LONG_PRESS_POWER_NOTHING:
+ break;
+ case LONG_PRESS_POWER_GLOBAL_ACTIONS:
+ mPowerKeyHandled = true;
+ if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
+ performAuditoryFeedbackForAccessibilityIfNeed();
+ }
+ showGlobalActionsInternal();
+ break;
+ case LONG_PRESS_POWER_SHUT_OFF:
+ case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
+ mPowerKeyHandled = true;
+ performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
+ sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
+ mWindowManagerFuncs.shutdown(behavior == LONG_PRESS_POWER_SHUT_OFF);
+ break;
}
- if (mPowerKeyTriggered) {
- mPendingPowerKeyUpCanceled = true;
+ }
+
+ private int getResolvedLongPressOnPowerBehavior() {
+ if (FactoryTest.isLongPressOnPowerOffEnabled()) {
+ return LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
}
+ return mLongPressOnPowerBehavior;
+ }
+
+ private boolean hasLongPressOnPowerBehavior() {
+ return getResolvedLongPressOnPowerBehavior() != LONG_PRESS_POWER_NOTHING;
}
private void interceptScreenshotChord() {
if (mScreenshotChordEnabled
- && mVolumeDownKeyTriggered && mPowerKeyTriggered && !mVolumeUpKeyTriggered) {
+ && mScreenshotChordVolumeDownKeyTriggered && mScreenshotChordPowerKeyTriggered
+ && !mScreenshotChordVolumeUpKeyTriggered) {
final long now = SystemClock.uptimeMillis();
- if (now <= mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
- && now <= mPowerKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
- mVolumeDownKeyConsumedByScreenshotChord = true;
+ if (now <= mScreenshotChordVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS
+ && now <= mScreenshotChordPowerKeyTime
+ + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS) {
+ mScreenshotChordVolumeDownKeyConsumed = true;
cancelPendingPowerKeyAction();
mHandler.postDelayed(mScreenshotRunnable, getScreenshotChordLongPressDelay());
@@ -833,64 +1080,14 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mHandler.removeCallbacks(mScreenshotRunnable);
}
- private void powerShortPress(long eventTime) {
- if (mShortPressOnPowerBehavior < 0) {
- mShortPressOnPowerBehavior = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_shortPressOnPowerBehavior);
- }
-
- switch (mShortPressOnPowerBehavior) {
- case SHORT_PRESS_POWER_NOTHING:
- break;
- case SHORT_PRESS_POWER_GO_TO_SLEEP:
- mPowerManager.goToSleep(eventTime,
- PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
- break;
- case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP:
- mPowerManager.goToSleep(eventTime,
- PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
- PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
- break;
- case SHORT_PRESS_POWER_REALLY_GO_TO_SLEEP_AND_GO_HOME:
- mPowerManager.goToSleep(eventTime,
- PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON,
- PowerManager.GO_TO_SLEEP_FLAG_NO_DOZE);
- launchHomeFromHotKey();
- break;
- }
- }
-
- private final Runnable mPowerLongPress = new Runnable() {
+ private final Runnable mEndCallLongPress = new Runnable() {
@Override
public void run() {
- // The context isn't read
- if (mLongPressOnPowerBehavior < 0) {
- mLongPressOnPowerBehavior = mContext.getResources().getInteger(
- com.android.internal.R.integer.config_longPressOnPowerBehavior);
- }
- int resolvedBehavior = mLongPressOnPowerBehavior;
- if (FactoryTest.isLongPressOnPowerOffEnabled()) {
- resolvedBehavior = LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM;
- }
-
- switch (resolvedBehavior) {
- case LONG_PRESS_POWER_NOTHING:
- break;
- case LONG_PRESS_POWER_GLOBAL_ACTIONS:
- mPowerKeyHandled = true;
- if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
- performAuditoryFeedbackForAccessibilityIfNeed();
- }
- showGlobalActionsInternal();
- break;
- case LONG_PRESS_POWER_SHUT_OFF:
- case LONG_PRESS_POWER_SHUT_OFF_NO_CONFIRM:
- mPowerKeyHandled = true;
- performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false);
- sendCloseSystemWindows(SYSTEM_DIALOG_REASON_GLOBAL_ACTIONS);
- mWindowManagerFuncs.shutdown(resolvedBehavior == LONG_PRESS_POWER_SHUT_OFF);
- break;
+ mEndCallKeyHandled = true;
+ if (!performHapticFeedbackLw(null, HapticFeedbackConstants.LONG_PRESS, false)) {
+ performAuditoryFeedbackForAccessibilityIfNeed();
}
+ showGlobalActionsInternal();
}
};
@@ -912,7 +1109,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mGlobalActions == null) {
mGlobalActions = new GlobalActions(mContext, mWindowManagerFuncs);
}
- final boolean keyguardShowing = keyguardIsShowingTq();
+ final boolean keyguardShowing = isKeyguardShowingAndNotOccluded();
mGlobalActions.showDialog(keyguardShowing, isDeviceProvisioned());
if (keyguardShowing) {
// since it took two seconds of long press to bring this up,
@@ -931,6 +1128,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
Settings.Secure.USER_SETUP_COMPLETE, 0, UserHandle.USER_CURRENT) != 0;
}
+ private void handleShortPressOnHome() {
+ // If there's a dream running then use home to escape the dream
+ // but don't actually go home.
+ if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) {
+ mDreamManagerInternal.stopDream(false /*immediate*/);
+ return;
+ }
+
+ // Go home!
+ launchHomeFromHotKey();
+ }
+
private void handleLongPressOnHome() {
if (mLongPressOnHomeBehavior != LONG_PRESS_HOME_NOTHING) {
mHomeConsumed = true;
@@ -956,7 +1165,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
public void run() {
if (mHomeDoubleTapPending) {
mHomeDoubleTapPending = false;
- launchHomeFromHotKey();
+ handleShortPressOnHome();
}
}
};
@@ -999,6 +1208,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mPowerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
mBroadcastWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
"PhoneWindowManager.mBroadcastWakeLock");
+ mPowerKeyWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
+ "PhoneWindowManager.mPowerKeyWakeLock");
mEnableShiftMenuBugReports = "1".equals(SystemProperties.get("ro.debuggable"));
mSupportAutoRotation = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_supportAutoRotation);
@@ -1022,6 +1233,35 @@ public class PhoneWindowManager implements WindowManagerPolicy {
com.android.internal.R.bool.config_lidControlsSleep);
mTranslucentDecorEnabled = mContext.getResources().getBoolean(
com.android.internal.R.bool.config_enableTranslucentDecor);
+
+ mAllowTheaterModeWakeFromKey = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_allowTheaterModeWakeFromKey);
+ mAllowTheaterModeWakeFromPowerKey = mAllowTheaterModeWakeFromKey
+ || mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_allowTheaterModeWakeFromPowerKey);
+ mAllowTheaterModeWakeFromMotion = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_allowTheaterModeWakeFromMotion);
+ mAllowTheaterModeWakeFromMotionWhenNotDreaming = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_allowTheaterModeWakeFromMotionWhenNotDreaming);
+ mAllowTheaterModeWakeFromCameraLens = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_allowTheaterModeWakeFromCameraLens);
+ mAllowTheaterModeWakeFromLidSwitch = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_allowTheaterModeWakeFromLidSwitch);
+ mAllowTheaterModeWakeFromWakeGesture = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_allowTheaterModeWakeFromGesture);
+
+ mGoToSleepOnButtonPressTheaterMode = mContext.getResources().getBoolean(
+ com.android.internal.R.bool.config_goToSleepOnButtonPressTheaterMode);
+
+ mShortPressOnPowerBehavior = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_shortPressOnPowerBehavior);
+ mLongPressOnPowerBehavior = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_longPressOnPowerBehavior);
+ mDoublePressOnPowerBehavior = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_doublePressOnPowerBehavior);
+ mTriplePressOnPowerBehavior = mContext.getResources().getInteger(
+ com.android.internal.R.integer.config_triplePressOnPowerBehavior);
+
readConfigurationDependentBehaviors();
mAccessibilityManager = (AccessibilityManager) context.getSystemService(
@@ -1212,6 +1452,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
mDemoHdmiRotationLock = SystemProperties.getBoolean("persist.demo.hdmirotationlock", false);
+ // For demo purposes, allow the rotation of the remote display to be controlled.
+ // By default, remote display locks rotation to landscape.
+ if ("portrait".equals(SystemProperties.get("persist.demo.remoterotation"))) {
+ mDemoRotation = mPortraitRotation;
+ } else {
+ mDemoRotation = mLandscapeRotation;
+ }
+ mDemoRotationLock = SystemProperties.getBoolean(
+ "persist.demo.rotationlock", false);
+
// Only force the default orientation if the screen is xlarge, at least 960dp x 720dp, per
// http://developer.android.com/guide/practices/screens_support.html#range
mForceDefaultOrientation = longSizeDp >= 960 && shortSizeDp >= 720 &&
@@ -1408,6 +1658,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case TYPE_WALLPAPER:
case TYPE_PRIVATE_PRESENTATION:
case TYPE_VOICE_INTERACTION:
+ case TYPE_ACCESSIBILITY_OVERLAY:
// The window manager will check these.
break;
case TYPE_PHONE:
@@ -1461,7 +1712,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case TYPE_PHONE:
case TYPE_POINTER:
case TYPE_PRIORITY_PHONE:
- case TYPE_RECENTS_OVERLAY:
case TYPE_SEARCH_BAR:
case TYPE_STATUS_BAR:
case TYPE_STATUS_BAR_PANEL:
@@ -1580,7 +1830,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case TYPE_VOICE_INTERACTION:
// voice interaction layer is almost immediately above apps.
return 5;
- case TYPE_RECENTS_OVERLAY:
case TYPE_SYSTEM_DIALOG:
return 6;
case TYPE_TOAST:
@@ -1639,15 +1888,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// the drag layer: input for drag-and-drop is associated with this window,
// which sits above all other focusable windows
return 25;
- case TYPE_SECURE_SYSTEM_OVERLAY:
+ case TYPE_ACCESSIBILITY_OVERLAY:
+ // overlay put by accessibility services to intercept user interaction
return 26;
- case TYPE_BOOT_PROGRESS:
+ case TYPE_SECURE_SYSTEM_OVERLAY:
return 27;
+ case TYPE_BOOT_PROGRESS:
+ return 28;
case TYPE_POINTER:
// the (mouse) pointer layer
- return 28;
- case TYPE_HIDDEN_NAV_CONSUMER:
return 29;
+ case TYPE_HIDDEN_NAV_CONSUMER:
+ return 30;
}
Log.e(TAG, "Unknown window type: " + type);
return 2;
@@ -1722,7 +1974,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public boolean isForceHiding(WindowManager.LayoutParams attrs) {
return (attrs.privateFlags & PRIVATE_FLAG_KEYGUARD) != 0 ||
- (isKeyguardHostWindow(attrs) && isKeyguardSecureIncludingHidden()) ||
+ (isKeyguardHostWindow(attrs) &&
+ (mKeyguardDelegate != null && mKeyguardDelegate.isShowing())) ||
(attrs.type == TYPE_KEYGUARD_SCRIM);
}
@@ -1874,11 +2127,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
@Override
public void removeStartingWindow(IBinder appToken, View window) {
- if (DEBUG_STARTING_WINDOW) {
- RuntimeException e = new RuntimeException("here");
- e.fillInStackTrace();
- Log.v(TAG, "Removing starting window for " + appToken + ": " + window, e);
- }
+ if (DEBUG_STARTING_WINDOW) Slog.v(TAG, "Removing starting window for " + appToken + ": "
+ + window + " Callers=" + Debug.getCallers(4));
if (window != null) {
WindowManager wm = (WindowManager)mContext.getSystemService(Context.WINDOW_SERVICE);
@@ -1915,7 +2165,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
mStatusBar = win;
mStatusBarController.setWindow(win);
- mKeyguardDelegate.hideScrim();
break;
case TYPE_NAVIGATION_BAR:
mContext.enforceCallingOrSelfPermission(
@@ -1951,7 +2200,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
mKeyguardScrim = win;
break;
-
}
return WindowManagerGlobal.ADD_OKAY;
}
@@ -2075,24 +2323,19 @@ public class PhoneWindowManager implements WindowManagerPolicy {
boolean goingToNotificationShade) {
if (goingToNotificationShade) {
return AnimationUtils.loadAnimation(mContext, R.anim.lock_screen_behind_enter_fade_in);
- } else if (onWallpaper) {
- Animation a = AnimationUtils.loadAnimation(mContext,
- R.anim.lock_screen_behind_enter_wallpaper);
- AnimationSet set = (AnimationSet) a;
-
- // TODO: Use XML interpolators when we have log interpolators available in XML.
- set.getAnimations().get(0).setInterpolator(mLogDecelerateInterpolator);
- set.getAnimations().get(1).setInterpolator(mLogDecelerateInterpolator);
- return set;
- } else {
- Animation a = AnimationUtils.loadAnimation(mContext,
+ }
+
+ AnimationSet set = (AnimationSet) AnimationUtils.loadAnimation(mContext, onWallpaper ?
+ R.anim.lock_screen_behind_enter_wallpaper :
R.anim.lock_screen_behind_enter);
- AnimationSet set = (AnimationSet) a;
- // TODO: Use XML interpolators when we have log interpolators available in XML.
- set.getAnimations().get(0).setInterpolator(mLogDecelerateInterpolator);
- return set;
+ // TODO: Use XML interpolators when we have log interpolators available in XML.
+ final List<Animation> animations = set.getAnimations();
+ for (int i = animations.size() - 1; i >= 0; --i) {
+ animations.get(i).setInterpolator(mLogDecelerateInterpolator);
}
+
+ return set;
}
@@ -2135,7 +2378,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
boolean keyguardOn() {
- return keyguardIsShowingTq() || inKeyguardRestrictedKeyInputMode();
+ return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode();
}
private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = {
@@ -2164,17 +2407,18 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// but we're not sure, then tell the dispatcher to wait a little while and
// try again later before dispatching.
if (mScreenshotChordEnabled && (flags & KeyEvent.FLAG_FALLBACK) == 0) {
- if (mVolumeDownKeyTriggered && !mPowerKeyTriggered) {
+ if (mScreenshotChordVolumeDownKeyTriggered && !mScreenshotChordPowerKeyTriggered) {
final long now = SystemClock.uptimeMillis();
- final long timeoutTime = mVolumeDownKeyTime + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
+ final long timeoutTime = mScreenshotChordVolumeDownKeyTime
+ + SCREENSHOT_CHORD_DEBOUNCE_DELAY_MILLIS;
if (now < timeoutTime) {
return timeoutTime - now;
}
}
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN
- && mVolumeDownKeyConsumedByScreenshotChord) {
+ && mScreenshotChordVolumeDownKeyConsumed) {
if (!down) {
- mVolumeDownKeyConsumedByScreenshotChord = false;
+ mScreenshotChordVolumeDownKeyConsumed = false;
}
return -1;
}
@@ -2226,15 +2470,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return -1;
}
- // If there's a dream running then use home to escape the dream
- // but don't actually go home.
- if (mDreamManagerInternal != null && mDreamManagerInternal.isDreaming()) {
- mDreamManagerInternal.stopDream(false /*immediate*/);
- return -1;
- }
-
- // Go home!
- launchHomeFromHotKey();
+ handleShortPressOnHome();
return -1;
}
@@ -2508,7 +2744,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return -1;
}
- if (mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
+ if (isValidGlobalKey(keyCode)
+ && mGlobalKeyManager.handleGlobalKey(mContext, keyCode, event)) {
return -1;
}
@@ -2734,7 +2971,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
* given the situation with the keyguard.
*/
void launchHomeFromHotKey() {
- if (mKeyguardDelegate != null && mKeyguardDelegate.isShowingAndNotOccluded()) {
+ if (isKeyguardShowingAndNotOccluded()) {
// don't launch home if keyguard showing
} else if (!mHideLockScreen && mKeyguardDelegate.isInputRestricted()) {
// when in keyguard restricted mode, must first verify unlock
@@ -2863,7 +3100,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
@Override
- public void getContentInsetHintLw(WindowManager.LayoutParams attrs, Rect contentInset) {
+ public void getInsetHintLw(WindowManager.LayoutParams attrs, Rect outContentInsets,
+ Rect outStableInsets) {
final int fl = PolicyControl.getWindowFlags(null, attrs);
final int sysuiVis = PolicyControl.getSystemUiVisibility(null, attrs);
final int systemUiVisibility = (sysuiVis | attrs.subtreeSystemUiVisibility);
@@ -2881,26 +3119,30 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
if ((systemUiVisibility & View.SYSTEM_UI_FLAG_LAYOUT_STABLE) != 0) {
if ((fl & FLAG_FULLSCREEN) != 0) {
- contentInset.set(mStableFullscreenLeft, mStableFullscreenTop,
+ outContentInsets.set(mStableFullscreenLeft, mStableFullscreenTop,
availRight - mStableFullscreenRight,
availBottom - mStableFullscreenBottom);
} else {
- contentInset.set(mStableLeft, mStableTop,
+ outContentInsets.set(mStableLeft, mStableTop,
availRight - mStableRight, availBottom - mStableBottom);
}
} else if ((fl & FLAG_FULLSCREEN) != 0 || (fl & FLAG_LAYOUT_IN_OVERSCAN) != 0) {
- contentInset.setEmpty();
+ outContentInsets.setEmpty();
} else if ((systemUiVisibility & (View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN)) == 0) {
- contentInset.set(mCurLeft, mCurTop,
+ outContentInsets.set(mCurLeft, mCurTop,
availRight - mCurRight, availBottom - mCurBottom);
} else {
- contentInset.set(mCurLeft, mCurTop,
+ outContentInsets.set(mCurLeft, mCurTop,
availRight - mCurRight, availBottom - mCurBottom);
}
+
+ outStableInsets.set(mStableLeft, mStableTop,
+ availRight - mStableRight, availBottom - mStableBottom);
return;
}
- contentInset.setEmpty();
+ outContentInsets.setEmpty();
+ outStableInsets.setEmpty();
}
/** {@inheritDoc} */
@@ -3192,10 +3434,15 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// whether it is taking care of insetting its content. If not,
// we need to use the parent's content frame so that the entire
// window is positioned within that content. Otherwise we can use
- // the display frame and let the attached window take care of
+ // the overscan frame and let the attached window take care of
// positioning its content appropriately.
if (adjust != SOFT_INPUT_ADJUST_RESIZE) {
- cf.set(attached.getOverscanFrameLw());
+ // Set the content frame of the attached window to the parent's decor frame
+ // (same as content frame when IME isn't present) if specifically requested by
+ // setting {@link WindowManager.LayoutParams#FLAG_LAYOUT_ATTACHED_IN_DECOR} flag.
+ // Otherwise, use the overscan frame.
+ cf.set((fl & FLAG_LAYOUT_ATTACHED_IN_DECOR) != 0
+ ? attached.getContentFrameLw() : attached.getOverscanFrameLw());
} else {
// If the window is resizing, then we want to base the content
// frame on our attached content frame to resize... however,
@@ -3758,11 +4005,16 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mShowingLockscreen = false;
mShowingDream = false;
mWinShowWhenLocked = null;
+ mKeyguardSecure = isKeyguardSecure();
+ mKeyguardSecureIncludingHidden = mKeyguardSecure
+ && (mKeyguardDelegate != null && mKeyguardDelegate.isShowing());
}
/** {@inheritDoc} */
@Override
- public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs) {
+ public void applyPostLayoutPolicyLw(WindowState win, WindowManager.LayoutParams attrs,
+ WindowState attached) {
+
if (DEBUG_LAYOUT) Slog.i(TAG, "Win " + win + ": isVisibleOrBehindKeyguardLw="
+ win.isVisibleOrBehindKeyguardLw());
final int fl = PolicyControl.getWindowFlags(win, attrs);
@@ -3800,20 +4052,27 @@ public class PhoneWindowManager implements WindowManagerPolicy {
final boolean showWhenLocked = (fl & FLAG_SHOW_WHEN_LOCKED) != 0;
final boolean dismissKeyguard = (fl & FLAG_DISMISS_KEYGUARD) != 0;
- final boolean secureKeyguard = isKeyguardSecure();
- if (appWindow) {
- final IApplicationToken appToken = win.getAppToken();
+ final IApplicationToken appToken = win.getAppToken();
+
+ // For app windows that are not attached, we decide if all windows in the app they
+ // represent should be hidden or if we should hide the lockscreen. For attached app
+ // windows we defer the decision to the window it is attached to.
+ if (appWindow && attached == null) {
if (showWhenLocked) {
// Remove any previous windows with the same appToken.
mAppsToBeHidden.remove(appToken);
mAppsThatDismissKeyguard.remove(appToken);
- if (mAppsToBeHidden.isEmpty() && isKeyguardSecureIncludingHidden()) {
- mWinShowWhenLocked = win;
- mHideLockScreen = true;
- mForceStatusBarFromKeyguard = false;
+ if (mAppsToBeHidden.isEmpty()) {
+ if (dismissKeyguard && !mKeyguardSecure) {
+ mAppsThatDismissKeyguard.add(appToken);
+ } else {
+ mWinShowWhenLocked = win;
+ mHideLockScreen = true;
+ mForceStatusBarFromKeyguard = false;
+ }
}
} else if (dismissKeyguard) {
- if (secureKeyguard) {
+ if (mKeyguardSecure) {
mAppsToBeHidden.add(appToken);
} else {
mAppsToBeHidden.remove(appToken);
@@ -3834,7 +4093,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
mDismissKeyguard = mWinDismissingKeyguard == win ?
DISMISS_KEYGUARD_CONTINUE : DISMISS_KEYGUARD_START;
mWinDismissingKeyguard = win;
- mForceStatusBarFromKeyguard = mShowingLockscreen && secureKeyguard;
+ mForceStatusBarFromKeyguard = mShowingLockscreen && mKeyguardSecure;
} else if (mAppsToBeHidden.isEmpty() && showWhenLocked) {
if (DEBUG_LAYOUT) Slog.v(TAG,
"Setting mHideLockScreen to true by win " + win);
@@ -3945,9 +4204,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mKeyguardDelegate != null && mStatusBar != null) {
if (localLOGV) Slog.v(TAG, "finishPostLayoutPolicyLw: mHideKeyguard="
+ mHideLockScreen);
- if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !isKeyguardSecure()) {
+ if (mDismissKeyguard != DISMISS_KEYGUARD_NONE && !mKeyguardSecure) {
mKeyguardHidden = true;
- if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(true))) {
+ if (setKeyguardOccludedLw(true)) {
changes |= FINISH_LAYOUT_REDO_LAYOUT
| FINISH_LAYOUT_REDO_CONFIG
| FINISH_LAYOUT_REDO_WALLPAPER;
@@ -3962,7 +4221,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
} else if (mHideLockScreen) {
mKeyguardHidden = true;
- if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(true))) {
+ if (setKeyguardOccludedLw(true)) {
changes |= FINISH_LAYOUT_REDO_LAYOUT
| FINISH_LAYOUT_REDO_CONFIG
| FINISH_LAYOUT_REDO_WALLPAPER;
@@ -3972,7 +4231,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (mDismissKeyguard == DISMISS_KEYGUARD_START) {
// Only launch the next keyguard unlock window once per window.
mKeyguardHidden = false;
- if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(false))) {
+ if (setKeyguardOccludedLw(false)) {
changes |= FINISH_LAYOUT_REDO_LAYOUT
| FINISH_LAYOUT_REDO_CONFIG
| FINISH_LAYOUT_REDO_WALLPAPER;
@@ -3987,7 +4246,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} else {
mWinDismissingKeyguard = null;
mKeyguardHidden = false;
- if (processKeyguardSetHiddenResultLw(mKeyguardDelegate.setOccluded(false))) {
+ if (setKeyguardOccludedLw(false)) {
changes |= FINISH_LAYOUT_REDO_LAYOUT
| FINISH_LAYOUT_REDO_CONFIG
| FINISH_LAYOUT_REDO_WALLPAPER;
@@ -4007,23 +4266,22 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
/**
- * Processes the result code of {@link IKeyguardService#setOccluded}. This is needed because we
- * immediately need to put the wallpaper directly behind the Keyguard when a window with flag
- * {@link android.view.WindowManager.LayoutParams#FLAG_SHOW_WHEN_LOCKED} gets dismissed. If we
- * would wait for Keyguard to change the flags, that would be running asynchronously and thus be
- * too late so the user might see the window behind.
+ * Updates the occluded state of the Keyguard.
*
- * @param setHiddenResult The result code from {@link IKeyguardService#setOccluded}.
* @return Whether the flags have changed and we have to redo the layout.
*/
- private boolean processKeyguardSetHiddenResultLw(int setHiddenResult) {
- if (setHiddenResult
- == IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_SET_FLAGS) {
+ private boolean setKeyguardOccludedLw(boolean isOccluded) {
+ boolean wasOccluded = mKeyguardOccluded;
+ boolean showing = mKeyguardDelegate.isShowing();
+ if (wasOccluded && !isOccluded && showing) {
+ mKeyguardOccluded = false;
+ mKeyguardDelegate.setOccluded(false);
mStatusBar.getAttrs().privateFlags |= PRIVATE_FLAG_KEYGUARD;
mStatusBar.getAttrs().flags |= FLAG_SHOW_WALLPAPER;
return true;
- } else if (setHiddenResult
- == IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_UNSET_FLAGS) {
+ } else if (!wasOccluded && isOccluded && showing) {
+ mKeyguardOccluded = true;
+ mKeyguardDelegate.setOccluded(true);
mStatusBar.getAttrs().privateFlags &= ~PRIVATE_FLAG_KEYGUARD;
mStatusBar.getAttrs().flags &= ~FLAG_SHOW_WALLPAPER;
return true;
@@ -4071,7 +4329,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
updateRotation(true);
if (lidOpen) {
- mPowerManager.wakeUp(SystemClock.uptimeMillis());
+ wakeUp(SystemClock.uptimeMillis(), mAllowTheaterModeWakeFromLidSwitch);
} else if (!mLidControlsSleep) {
mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
}
@@ -4093,7 +4351,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
} else {
intent = new Intent(MediaStore.INTENT_ACTION_STILL_IMAGE_CAMERA);
}
- mPowerManager.wakeUp(whenNanos / 1000000);
+ wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromCameraLens);
mContext.startActivityAsUser(intent, UserHandle.CURRENT_OR_SELF);
}
mCameraLensCoverState = lensCoverState;
@@ -4234,7 +4492,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// when the keyguard is hidden by another activity.
final boolean keyguardActive = (mKeyguardDelegate == null ? false :
(interactive ?
- mKeyguardDelegate.isShowingAndNotOccluded() :
+ isKeyguardShowingAndNotOccluded() :
mKeyguardDelegate.isShowing()));
if (DEBUG_INPUT) {
@@ -4269,9 +4527,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// If the key would be handled globally, just return the result, don't worry about special
// key processing.
- if (mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
+ if (isValidGlobalKey(keyCode)
+ && mGlobalKeyManager.shouldHandleGlobalKey(keyCode, event)) {
if (isWakeKey) {
- mPowerManager.wakeUp(event.getEventTime());
+ wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey);
}
return result;
}
@@ -4287,28 +4546,28 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_VOLUME_MUTE: {
if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
if (down) {
- if (interactive && !mVolumeDownKeyTriggered
+ if (interactive && !mScreenshotChordVolumeDownKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
- mVolumeDownKeyTriggered = true;
- mVolumeDownKeyTime = event.getDownTime();
- mVolumeDownKeyConsumedByScreenshotChord = false;
+ mScreenshotChordVolumeDownKeyTriggered = true;
+ mScreenshotChordVolumeDownKeyTime = event.getDownTime();
+ mScreenshotChordVolumeDownKeyConsumed = false;
cancelPendingPowerKeyAction();
interceptScreenshotChord();
}
} else {
- mVolumeDownKeyTriggered = false;
+ mScreenshotChordVolumeDownKeyTriggered = false;
cancelPendingScreenshotChordAction();
}
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
if (down) {
- if (interactive && !mVolumeUpKeyTriggered
+ if (interactive && !mScreenshotChordVolumeUpKeyTriggered
&& (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
- mVolumeUpKeyTriggered = true;
+ mScreenshotChordVolumeUpKeyTriggered = true;
cancelPendingPowerKeyAction();
cancelPendingScreenshotChordAction();
}
} else {
- mVolumeUpKeyTriggered = false;
+ mScreenshotChordVolumeUpKeyTriggered = false;
cancelPendingScreenshotChordAction();
}
}
@@ -4365,20 +4624,29 @@ public class PhoneWindowManager implements WindowManagerPolicy {
if (telecomManager != null) {
hungUp = telecomManager.endCall();
}
- interceptPowerKeyDown(!interactive || hungUp);
+ if (interactive && !hungUp) {
+ mEndCallKeyHandled = false;
+ mHandler.postDelayed(mEndCallLongPress,
+ ViewConfiguration.get(mContext).getDeviceGlobalActionKeyTimeout());
+ } else {
+ mEndCallKeyHandled = true;
+ }
} else {
- if (interceptPowerKeyUp(canceled)) {
- if ((mEndcallBehavior
- & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
- if (goHome()) {
- break;
+ if (!mEndCallKeyHandled) {
+ mHandler.removeCallbacks(mEndCallLongPress);
+ if (!canceled) {
+ if ((mEndcallBehavior
+ & Settings.System.END_BUTTON_BEHAVIOR_HOME) != 0) {
+ if (goHome()) {
+ break;
+ }
+ }
+ if ((mEndcallBehavior
+ & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
+ mPowerManager.goToSleep(event.getEventTime(),
+ PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
+ isWakeKey = false;
}
- }
- if ((mEndcallBehavior
- & Settings.System.END_BUTTON_BEHAVIOR_SLEEP) != 0) {
- mPowerManager.goToSleep(event.getEventTime(),
- PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON, 0);
- isWakeKey = false;
}
}
}
@@ -4387,49 +4655,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
case KeyEvent.KEYCODE_POWER: {
result &= ~ACTION_PASS_TO_USER;
+ isWakeKey = false; // wake-up will be handled separately
if (down) {
- boolean panic = mImmersiveModeConfirmation.onPowerKeyDown(interactive,
- event.getDownTime(), isImmersiveMode(mLastSystemUiFlags));
- if (panic) {
- mHandler.post(mRequestTransientNav);
- }
- if (interactive && !mPowerKeyTriggered
- && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
- mPowerKeyTriggered = true;
- mPowerKeyTime = event.getDownTime();
- interceptScreenshotChord();
- }
-
- TelecomManager telecomManager = getTelecommService();
- boolean hungUp = false;
- if (telecomManager != null) {
- if (telecomManager.isRinging()) {
- // Pressing Power while there's a ringing incoming
- // call should silence the ringer.
- telecomManager.silenceRinger();
- } else if ((mIncallPowerBehavior
- & Settings.Secure.INCALL_POWER_BUTTON_BEHAVIOR_HANGUP) != 0
- && telecomManager.isInCall() && interactive) {
- // Otherwise, if "Power button ends call" is enabled,
- // the Power button will hang up any current active call.
- hungUp = telecomManager.endCall();
- }
- }
- interceptPowerKeyDown(!interactive || hungUp
- || mVolumeDownKeyTriggered || mVolumeUpKeyTriggered);
+ interceptPowerKeyDown(event, interactive);
} else {
- mPowerKeyTriggered = false;
- cancelPendingScreenshotChordAction();
- if (interceptPowerKeyUp(canceled || mPendingPowerKeyUpCanceled)) {
- if (mScreenOnEarly && !mScreenOnFully) {
- Slog.i(TAG, "Suppressed redundant power key press while "
- + "already in the process of turning the screen on.");
- } else {
- powerShortPress(event.getEventTime());
- }
- isWakeKey = false;
- }
- mPendingPowerKeyUpCanceled = false;
+ interceptPowerKeyUp(event, interactive, canceled);
}
break;
}
@@ -4520,12 +4750,29 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
if (isWakeKey) {
- mPowerManager.wakeUp(event.getEventTime());
+ wakeUp(event.getEventTime(), mAllowTheaterModeWakeFromKey);
}
+
return result;
}
/**
+ * Returns true if the key can have global actions attached to it.
+ * We reserve all power management keys for the system since they require
+ * very careful handling.
+ */
+ private static boolean isValidGlobalKey(int keyCode) {
+ switch (keyCode) {
+ case KeyEvent.KEYCODE_POWER:
+ case KeyEvent.KEYCODE_WAKEUP:
+ case KeyEvent.KEYCODE_SLEEP:
+ return false;
+ default:
+ return true;
+ }
+ }
+
+ /**
* When the screen is off we ignore some keys that might otherwise typically
* be considered wake keys. We filter them out here.
*
@@ -4564,18 +4811,47 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public int interceptMotionBeforeQueueingNonInteractive(long whenNanos, int policyFlags) {
if ((policyFlags & FLAG_WAKE) != 0) {
- mPowerManager.wakeUp(whenNanos / 1000000);
- return 0;
+ if (wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotion)) {
+ return 0;
+ }
}
+
if (shouldDispatchInputWhenNonInteractive()) {
return ACTION_PASS_TO_USER;
}
+
+ // If we have not passed the action up and we are in theater mode without dreaming,
+ // there will be no dream to intercept the touch and wake into ambient. The device should
+ // wake up in this case.
+ if (isTheaterModeEnabled() && (policyFlags & FLAG_WAKE) != 0) {
+ wakeUp(whenNanos / 1000000, mAllowTheaterModeWakeFromMotionWhenNotDreaming);
+ }
+
return 0;
}
private boolean shouldDispatchInputWhenNonInteractive() {
- return keyguardIsShowingTq() && mDisplay != null &&
- mDisplay.getState() != Display.STATE_OFF;
+ // Send events to keyguard while the screen is on.
+ if (isKeyguardShowingAndNotOccluded() && mDisplay != null
+ && mDisplay.getState() != Display.STATE_OFF) {
+ return true;
+ }
+
+ // Send events to a dozing dream even if the screen is off since the dream
+ // is in control of the state of the screen.
+ IDreamManager dreamManager = getDreamManager();
+
+ try {
+ if (dreamManager != null && dreamManager.isDreaming()) {
+ return true;
+ }
+ } catch (RemoteException e) {
+ Slog.e(TAG, "RemoteException when checking if dreaming", e);
+ }
+
+ // Otherwise, consume events since the user can't see what is being
+ // interacted with.
+ return false;
}
void dispatchMediaKeyWithWakeLock(KeyEvent event) {
@@ -4742,6 +5018,19 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
+ private void wakeUpFromPowerKey(long eventTime) {
+ wakeUp(eventTime, mAllowTheaterModeWakeFromPowerKey);
+ }
+
+ private boolean wakeUp(long wakeTime, boolean wakeInTheaterMode) {
+ if (!wakeInTheaterMode && isTheaterModeEnabled()) {
+ return false;
+ }
+
+ mPowerManager.wakeUp(wakeTime);
+ return true;
+ }
+
// Called on the PowerManager's Notifier thread.
@Override
public void wakingUp() {
@@ -4916,12 +5205,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
}
}
- private boolean keyguardIsShowingTq() {
+ private boolean isKeyguardShowingAndNotOccluded() {
if (mKeyguardDelegate == null) return false;
- return mKeyguardDelegate.isShowingAndNotOccluded();
+ return mKeyguardDelegate.isShowing() && !mKeyguardOccluded;
}
-
/** {@inheritDoc} */
@Override
public boolean isKeyguardLocked() {
@@ -4935,11 +5223,6 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return mKeyguardDelegate.isSecure();
}
- // Returns true if keyguard is currently locked whether or not it is currently hidden.
- private boolean isKeyguardSecureIncludingHidden() {
- return mKeyguardDelegate.isSecure() && mKeyguardDelegate.isShowing();
- }
-
/** {@inheritDoc} */
@Override
public boolean inKeyguardRestrictedKeyInputMode() {
@@ -4950,6 +5233,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void dismissKeyguardLw() {
if (mKeyguardDelegate != null && mKeyguardDelegate.isShowing()) {
+ if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.dismissKeyguardLw");
mHandler.post(new Runnable() {
@Override
public void run() {
@@ -4981,6 +5265,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
if (mKeyguardDelegate != null) {
+ if (DEBUG_KEYGUARD) Slog.d(TAG, "PWM.startKeyguardExitAnimation");
mKeyguardDelegate.startKeyguardExitAnimation(startTime, fadeoutDuration);
}
}
@@ -5054,6 +5339,10 @@ public class PhoneWindowManager implements WindowManagerPolicy {
// full multi-display support).
// Note that the dock orientation overrides the HDMI orientation.
preferredRotation = mUndockedHdmiRotation;
+ } else if (mDemoRotationLock) {
+ // Ignore sensor when demo rotation lock is enabled.
+ // Note that the dock orientation and HDMI rotation lock override this.
+ preferredRotation = mDemoRotation;
} else if (orientation == ActivityInfo.SCREEN_ORIENTATION_LOCKED) {
// Application just wants to remain locked in the last rotation.
preferredRotation = lastRotation;
@@ -5248,7 +5537,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
/** {@inheritDoc} */
@Override
public void systemReady() {
- mKeyguardDelegate = new KeyguardServiceDelegate(mContext, null);
+ mKeyguardDelegate = new KeyguardServiceDelegate(mContext);
mKeyguardDelegate.onSystemReady();
readCameraLensCoverState();
@@ -5321,7 +5610,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
return true;
}
};
- mBootMsgDialog.setTitle(R.string.android_upgrading_title);
+ if (mContext.getPackageManager().isUpgrade()) {
+ mBootMsgDialog.setTitle(R.string.android_upgrading_title);
+ } else {
+ mBootMsgDialog.setTitle(R.string.android_start_title);
+ }
mBootMsgDialog.setProgressStyle(ProgressDialog.STYLE_SPINNER);
mBootMsgDialog.setIndeterminate(true);
mBootMsgDialog.getWindow().setType(
@@ -5620,6 +5913,11 @@ public class PhoneWindowManager implements WindowManagerPolicy {
ringTone.play();
}
+ private boolean isTheaterModeEnabled() {
+ return Settings.Global.getInt(mContext.getContentResolver(),
+ Settings.Global.THEATER_MODE_ON, 0) == 1;
+ }
+
private boolean isGlobalAccessibilityGestureEnabled() {
return Settings.Global.getInt(mContext.getContentResolver(),
Settings.Global.ENABLE_ACCESSIBILITY_GLOBAL_GESTURE_ENABLED, 0) == 1;
@@ -5686,7 +5984,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
@Override
public void keepScreenOnStoppedLw() {
- if (mKeyguardDelegate != null && !mKeyguardDelegate.isShowingAndNotOccluded()) {
+ if (isKeyguardShowingAndNotOccluded()) {
mPowerManager.userActivity(SystemClock.uptimeMillis(), false);
}
}
@@ -5694,7 +5992,8 @@ public class PhoneWindowManager implements WindowManagerPolicy {
private int updateSystemUiVisibilityLw() {
// If there is no window focused, there will be nobody to handle the events
// anyway, so just hang on in whatever state we're in until things settle down.
- WindowState win = mFocusedWindow != null ? mFocusedWindow : mTopFullscreenOpaqueWindowState;
+ final WindowState win = mFocusedWindow != null ? mFocusedWindow
+ : mTopFullscreenOpaqueWindowState;
if (win == null) {
return 0;
}
@@ -5730,7 +6029,7 @@ public class PhoneWindowManager implements WindowManagerPolicy {
try {
IStatusBarService statusbar = getStatusBarService();
if (statusbar != null) {
- statusbar.setSystemUiVisibility(visibility, 0xffffffff);
+ statusbar.setSystemUiVisibility(visibility, 0xffffffff, win.toString());
statusbar.topAppWindowChanged(needsMenu);
}
} catch (RemoteException e) {
@@ -5943,6 +6242,9 @@ public class PhoneWindowManager implements WindowManagerPolicy {
pw.print(prefix);
pw.print("mShortPressOnPowerBehavior="); pw.print(mShortPressOnPowerBehavior);
pw.print(" mLongPressOnPowerBehavior="); pw.println(mLongPressOnPowerBehavior);
+ pw.print(prefix);
+ pw.print("mDoublePressOnPowerBehavior="); pw.print(mDoublePressOnPowerBehavior);
+ pw.print(" mTriplePressOnPowerBehavior="); pw.println(mTriplePressOnPowerBehavior);
pw.print(prefix); pw.print("mHasSoftInput="); pw.println(mHasSoftInput);
pw.print(prefix); pw.print("mAwake="); pw.println(mAwake);
pw.print(prefix); pw.print("mScreenOnEarly="); pw.print(mScreenOnEarly);
diff --git a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java b/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
deleted file mode 100644
index bc55ed1..0000000
--- a/policy/src/com/android/internal/policy/impl/RecentApplicationsDialog.java
+++ /dev/null
@@ -1,347 +0,0 @@
-/*
- * Copyright (C) 2008 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package com.android.internal.policy.impl;
-
-import android.app.ActivityManager;
-import android.app.Dialog;
-import android.app.StatusBarManager;
-import android.content.ActivityNotFoundException;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.content.pm.ActivityInfo;
-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.util.Log;
-import android.view.KeyEvent;
-import android.view.SoundEffectConstants;
-import android.view.View;
-import android.view.Window;
-import android.view.WindowManager;
-import android.view.View.OnClickListener;
-import android.widget.TextView;
-
-import java.util.List;
-
-public class RecentApplicationsDialog extends Dialog implements OnClickListener {
- // Elements for debugging support
-// private static final String LOG_TAG = "RecentApplicationsDialog";
- private static final boolean DBG_FORCE_EMPTY_LIST = false;
-
- static private StatusBarManager sStatusBar;
-
- private static final int NUM_BUTTONS = 8;
- private static final int MAX_RECENT_TASKS = NUM_BUTTONS * 2; // allow for some discards
-
- final TextView[] mIcons = new TextView[NUM_BUTTONS];
- View mNoAppsText;
- IntentFilter mBroadcastIntentFilter = new IntentFilter(Intent.ACTION_CLOSE_SYSTEM_DIALOGS);
-
- class RecentTag {
- ActivityManager.RecentTaskInfo info;
- Intent intent;
- }
-
- Handler mHandler = new Handler();
- Runnable mCleanup = new Runnable() {
- public void run() {
- // dump extra memory we're hanging on to
- for (TextView icon: mIcons) {
- icon.setCompoundDrawables(null, null, null, null);
- icon.setTag(null);
- }
- }
- };
-
- public RecentApplicationsDialog(Context context) {
- super(context, com.android.internal.R.style.Theme_Dialog_RecentApplications);
-
- }
-
- /**
- * We create the recent applications dialog just once, and it stays around (hidden)
- * until activated by the user.
- *
- * @see PhoneWindowManager#showRecentAppsDialog
- */
- @Override
- protected void onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
-
- Context context = getContext();
-
- if (sStatusBar == null) {
- sStatusBar = (StatusBarManager)context.getSystemService(Context.STATUS_BAR_SERVICE);
- }
-
- Window window = getWindow();
- window.requestFeature(Window.FEATURE_NO_TITLE);
- window.setType(WindowManager.LayoutParams.TYPE_RECENTS_OVERLAY);
- window.setFlags(WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM,
- WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM);
- window.setTitle("Recents");
-
- setContentView(com.android.internal.R.layout.recent_apps_dialog);
-
- final WindowManager.LayoutParams params = window.getAttributes();
- params.width = WindowManager.LayoutParams.MATCH_PARENT;
- params.height = WindowManager.LayoutParams.MATCH_PARENT;
- window.setAttributes(params);
- window.setFlags(0, WindowManager.LayoutParams.FLAG_DIM_BEHIND);
-
- mIcons[0] = (TextView)findViewById(com.android.internal.R.id.button0);
- mIcons[1] = (TextView)findViewById(com.android.internal.R.id.button1);
- mIcons[2] = (TextView)findViewById(com.android.internal.R.id.button2);
- mIcons[3] = (TextView)findViewById(com.android.internal.R.id.button3);
- mIcons[4] = (TextView)findViewById(com.android.internal.R.id.button4);
- mIcons[5] = (TextView)findViewById(com.android.internal.R.id.button5);
- mIcons[6] = (TextView)findViewById(com.android.internal.R.id.button6);
- mIcons[7] = (TextView)findViewById(com.android.internal.R.id.button7);
- mNoAppsText = findViewById(com.android.internal.R.id.no_applications_message);
-
- for (TextView b: mIcons) {
- b.setOnClickListener(this);
- }
- }
-
- @Override
- public boolean onKeyDown(int keyCode, KeyEvent event) {
- if (keyCode == KeyEvent.KEYCODE_TAB) {
- // Ignore all meta keys other than SHIFT. The app switch key could be a
- // fallback action chorded with ALT, META or even CTRL depending on the key map.
- // DPad navigation is handled by the ViewRoot elsewhere.
- final boolean backward = event.isShiftPressed();
- final int numIcons = mIcons.length;
- int numButtons = 0;
- while (numButtons < numIcons && mIcons[numButtons].getVisibility() == View.VISIBLE) {
- numButtons += 1;
- }
- if (numButtons != 0) {
- int nextFocus = backward ? numButtons - 1 : 0;
- for (int i = 0; i < numButtons; i++) {
- if (mIcons[i].hasFocus()) {
- if (backward) {
- nextFocus = (i + numButtons - 1) % numButtons;
- } else {
- nextFocus = (i + 1) % numButtons;
- }
- break;
- }
- }
- final int direction = backward ? View.FOCUS_BACKWARD : View.FOCUS_FORWARD;
- if (mIcons[nextFocus].requestFocus(direction)) {
- mIcons[nextFocus].playSoundEffect(
- SoundEffectConstants.getContantForFocusDirection(direction));
- }
- }
-
- // The dialog always handles the key to prevent the ViewRoot from
- // performing the default navigation itself.
- return true;
- }
-
- return super.onKeyDown(keyCode, event);
- }
-
- /**
- * Dismiss the dialog and switch to the selected application.
- */
- public void dismissAndSwitch() {
- final int numIcons = mIcons.length;
- RecentTag tag = null;
- for (int i = 0; i < numIcons; i++) {
- if (mIcons[i].getVisibility() != View.VISIBLE) {
- break;
- }
- if (i == 0 || mIcons[i].hasFocus()) {
- tag = (RecentTag) mIcons[i].getTag();
- if (mIcons[i].hasFocus()) {
- break;
- }
- }
- }
- if (tag != null) {
- switchTo(tag);
- }
- dismiss();
- }
-
- /**
- * Handler for user clicks. If a button was clicked, launch the corresponding activity.
- */
- public void onClick(View v) {
- for (TextView b: mIcons) {
- if (b == v) {
- RecentTag tag = (RecentTag)b.getTag();
- switchTo(tag);
- break;
- }
- }
- dismiss();
- }
-
- private void switchTo(RecentTag tag) {
- if (tag.info.id >= 0) {
- // This is an active task; it should just go to the foreground.
- final ActivityManager am = (ActivityManager)
- getContext().getSystemService(Context.ACTIVITY_SERVICE);
- am.moveTaskToFront(tag.info.id, ActivityManager.MOVE_TASK_WITH_HOME);
- } else if (tag.intent != null) {
- tag.intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
- | Intent.FLAG_ACTIVITY_TASK_ON_HOME);
- try {
- getContext().startActivity(tag.intent);
- } catch (ActivityNotFoundException e) {
- Log.w("Recent", "Unable to launch recent task", e);
- }
- }
- }
-
- /**
- * Set up and show the recent activities dialog.
- */
- @Override
- public void onStart() {
- super.onStart();
- reloadButtons();
- if (sStatusBar != null) {
- sStatusBar.disable(StatusBarManager.DISABLE_EXPAND);
- }
-
- // receive broadcasts
- getContext().registerReceiver(mBroadcastReceiver, mBroadcastIntentFilter);
-
- mHandler.removeCallbacks(mCleanup);
- }
-
- /**
- * Dismiss the recent activities dialog.
- */
- @Override
- public void onStop() {
- super.onStop();
-
- if (sStatusBar != null) {
- sStatusBar.disable(StatusBarManager.DISABLE_NONE);
- }
-
- // stop receiving broadcasts
- getContext().unregisterReceiver(mBroadcastReceiver);
-
- mHandler.postDelayed(mCleanup, 100);
- }
-
- /**
- * Reload the 6 buttons with recent activities
- */
- private void reloadButtons() {
-
- final Context context = getContext();
- final PackageManager pm = context.getPackageManager();
- final ActivityManager am = (ActivityManager)
- context.getSystemService(Context.ACTIVITY_SERVICE);
- final List<ActivityManager.RecentTaskInfo> recentTasks =
- am.getRecentTasks(MAX_RECENT_TASKS, ActivityManager.RECENT_IGNORE_UNAVAILABLE);
-
- ActivityInfo homeInfo =
- new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME)
- .resolveActivityInfo(pm, 0);
-
- IconUtilities iconUtilities = new IconUtilities(getContext());
-
- // Performance note: Our android performance guide says to prefer Iterator when
- // using a List class, but because we know that getRecentTasks() always returns
- // an ArrayList<>, we'll use a simple index instead.
- int index = 0;
- int numTasks = recentTasks.size();
- for (int i = 0; i < numTasks && (index < NUM_BUTTONS); ++i) {
- final ActivityManager.RecentTaskInfo info = recentTasks.get(i);
-
- // for debug purposes only, disallow first result to create empty lists
- if (DBG_FORCE_EMPTY_LIST && (i == 0)) continue;
-
- Intent intent = new Intent(info.baseIntent);
- if (info.origActivity != null) {
- intent.setComponent(info.origActivity);
- }
-
- // Skip the current home activity.
- if (homeInfo != null) {
- if (homeInfo.packageName.equals(
- intent.getComponent().getPackageName())
- && homeInfo.name.equals(
- intent.getComponent().getClassName())) {
- continue;
- }
- }
-
- intent.setFlags((intent.getFlags()&~Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED)
- | Intent.FLAG_ACTIVITY_NEW_TASK);
- final ResolveInfo resolveInfo = pm.resolveActivity(intent, 0);
- if (resolveInfo != null) {
- final ActivityInfo activityInfo = resolveInfo.activityInfo;
- final String title = activityInfo.loadLabel(pm).toString();
- Drawable icon = activityInfo.loadIcon(pm);
-
- if (title != null && title.length() > 0 && icon != null) {
- final TextView tv = mIcons[index];
- tv.setText(title);
- icon = iconUtilities.createIconDrawable(icon);
- tv.setCompoundDrawables(null, icon, null, null);
- RecentTag tag = new RecentTag();
- tag.info = info;
- tag.intent = intent;
- tv.setTag(tag);
- tv.setVisibility(View.VISIBLE);
- tv.setPressed(false);
- tv.clearFocus();
- ++index;
- }
- }
- }
-
- // handle the case of "no icons to show"
- mNoAppsText.setVisibility((index == 0) ? View.VISIBLE : View.GONE);
-
- // hide the rest
- for (; index < NUM_BUTTONS; ++index) {
- mIcons[index].setVisibility(View.GONE);
- }
- }
-
- /**
- * This is the listener for the ACTION_CLOSE_SYSTEM_DIALOGS intent. It's an indication that
- * we should close ourselves immediately, in order to allow a higher-priority UI to take over
- * (e.g. phone call received).
- */
- private BroadcastReceiver mBroadcastReceiver = new BroadcastReceiver() {
- @Override
- public void onReceive(Context context, Intent intent) {
- String action = intent.getAction();
- if (Intent.ACTION_CLOSE_SYSTEM_DIALOGS.equals(action)) {
- String reason = intent.getStringExtra(PhoneWindowManager.SYSTEM_DIALOG_REASON_KEY);
- if (! PhoneWindowManager.SYSTEM_DIALOG_REASON_RECENT_APPS.equals(reason)) {
- dismiss();
- }
- }
- }
- };
-}
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
index 50fe7c7..6e8f550 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceDelegate.java
@@ -18,9 +18,8 @@ import android.view.WindowManager;
import android.view.WindowManagerPolicy.OnKeyguardExitResult;
import com.android.internal.policy.IKeyguardExitCallback;
-import com.android.internal.policy.IKeyguardShowCallback;
import com.android.internal.policy.IKeyguardService;
-import com.android.internal.widget.LockPatternUtils;
+import com.android.internal.policy.IKeyguardShowCallback;
/**
* A local class that keeps a cache of keyguard state that can be restored in the event
@@ -28,15 +27,17 @@ import com.android.internal.widget.LockPatternUtils;
* local or remote instances of keyguard.
*/
public class KeyguardServiceDelegate {
- // TODO: propagate changes to these to {@link KeyguardTouchDelegate}
public static final String KEYGUARD_PACKAGE = "com.android.systemui";
public static final String KEYGUARD_CLASS = "com.android.systemui.keyguard.KeyguardService";
private static final String TAG = "KeyguardServiceDelegate";
private static final boolean DEBUG = true;
+
protected KeyguardServiceWrapper mKeyguardService;
- private View mScrim; // shown if keyguard crashes
- private KeyguardState mKeyguardState = new KeyguardState();
+ private final Context mContext;
+ private final View mScrim; // shown if keyguard crashes
+ private final KeyguardState mKeyguardState = new KeyguardState();
+ private ShowListener mShowListenerWhenConnect;
/* package */ static final class KeyguardState {
KeyguardState() {
@@ -46,6 +47,7 @@ public class KeyguardServiceDelegate {
showing = true;
showingAndNotOccluded = true;
secure = true;
+ deviceHasKeyguard = true;
}
boolean showing;
boolean showingAndNotOccluded;
@@ -54,6 +56,7 @@ public class KeyguardServiceDelegate {
boolean secure;
boolean dreaming;
boolean systemIsReady;
+ boolean deviceHasKeyguard;
public boolean enabled;
public boolean dismissable;
public int offReason;
@@ -101,7 +104,8 @@ public class KeyguardServiceDelegate {
}
};
- public KeyguardServiceDelegate(Context context, LockPatternUtils lockPatternUtils) {
+ public KeyguardServiceDelegate(Context context) {
+ mContext = context;
mScrim = createScrim(context);
}
@@ -110,10 +114,12 @@ public class KeyguardServiceDelegate {
intent.setClassName(KEYGUARD_PACKAGE, KEYGUARD_CLASS);
if (!context.bindServiceAsUser(intent, mKeyguardConnection,
Context.BIND_AUTO_CREATE, UserHandle.OWNER)) {
- if (DEBUG) Log.v(TAG, "*** Keyguard: can't bind to " + KEYGUARD_CLASS);
+ Log.v(TAG, "*** Keyguard: can't bind to " + KEYGUARD_CLASS);
mKeyguardState.showing = false;
mKeyguardState.showingAndNotOccluded = false;
mKeyguardState.secure = false;
+ mKeyguardState.deviceHasKeyguard = false;
+ hideScrim();
} else {
if (DEBUG) Log.v(TAG, "*** Keyguard started");
}
@@ -123,13 +129,15 @@ public class KeyguardServiceDelegate {
@Override
public void onServiceConnected(ComponentName name, IBinder service) {
if (DEBUG) Log.v(TAG, "*** Keyguard connected (yay!)");
- mKeyguardService = new KeyguardServiceWrapper(
+ mKeyguardService = new KeyguardServiceWrapper(mContext,
IKeyguardService.Stub.asInterface(service));
if (mKeyguardState.systemIsReady) {
// If the system is ready, it means keyguard crashed and restarted.
mKeyguardService.onSystemReady();
// This is used to hide the scrim once keyguard displays.
- mKeyguardService.onScreenTurnedOn(new KeyguardShowDelegate(null));
+ mKeyguardService.onScreenTurnedOn(new KeyguardShowDelegate(
+ mShowListenerWhenConnect));
+ mShowListenerWhenConnect = null;
}
if (mKeyguardState.bootCompleted) {
mKeyguardService.onBootCompleted();
@@ -151,13 +159,6 @@ public class KeyguardServiceDelegate {
return mKeyguardState.showing;
}
- public boolean isShowingAndNotOccluded() {
- if (mKeyguardService != null) {
- mKeyguardState.showingAndNotOccluded = mKeyguardService.isShowingAndNotOccluded();
- }
- return mKeyguardState.showingAndNotOccluded;
- }
-
public boolean isInputRestricted() {
if (mKeyguardService != null) {
mKeyguardState.inputRestricted = mKeyguardService.isInputRestricted();
@@ -177,13 +178,11 @@ public class KeyguardServiceDelegate {
}
}
- public int setOccluded(boolean isOccluded) {
- int result = 0;
+ public void setOccluded(boolean isOccluded) {
if (mKeyguardService != null) {
- result = mKeyguardService.setOccluded(isOccluded);
+ mKeyguardService.setOccluded(isOccluded);
}
mKeyguardState.occluded = isOccluded;
- return result;
}
public void dismiss() {
@@ -220,9 +219,10 @@ public class KeyguardServiceDelegate {
} else {
// try again when we establish a connection
Slog.w(TAG, "onScreenTurnedOn(): no keyguard service!");
- // This shouldn't happen, but if it does, invoke the listener immediately
- // to avoid a dark screen...
- showListener.onShown(null);
+ // This shouldn't happen, but if it does, show the scrim immediately and
+ // invoke the listener's callback after the service actually connects.
+ mShowListenerWhenConnect = showListener;
+ showScrim();
}
mKeyguardState.screenIsOn = true;
}
@@ -242,13 +242,6 @@ public class KeyguardServiceDelegate {
mKeyguardState.enabled = enabled;
}
- public boolean isDismissable() {
- if (mKeyguardService != null) {
- mKeyguardState.dismissable = mKeyguardService.isDismissable();
- }
- return mKeyguardState.dismissable;
- }
-
public void onSystemReady() {
if (mKeyguardService != null) {
mKeyguardService.onSystemReady();
@@ -263,12 +256,6 @@ public class KeyguardServiceDelegate {
}
}
- public void showAssistant() {
- if (mKeyguardService != null) {
- mKeyguardService.showAssistant();
- }
- }
-
public void setCurrentUser(int newUserId) {
if (mKeyguardService != null) {
mKeyguardService.setCurrentUser(newUserId);
@@ -301,7 +288,6 @@ public class KeyguardServiceDelegate {
lp.setTitle("KeyguardScrim");
WindowManager wm = (WindowManager) context.getSystemService(Context.WINDOW_SERVICE);
wm.addView(view, lp);
- view.setVisibility(View.GONE);
// Disable pretty much everything in statusbar until keyguard comes back and we know
// the state of the world.
view.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME
@@ -313,6 +299,7 @@ public class KeyguardServiceDelegate {
}
public void showScrim() {
+ if (!mKeyguardState.deviceHasKeyguard) return;
mScrim.post(new Runnable() {
@Override
public void run() {
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
index 2778b15..b3b7684 100644
--- a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardServiceWrapper.java
@@ -16,16 +16,16 @@
package com.android.internal.policy.impl.keyguard;
+import android.content.Context;
import android.os.Bundle;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Slog;
-import android.view.MotionEvent;
-import com.android.internal.policy.IKeyguardServiceConstants;
-import com.android.internal.policy.IKeyguardShowCallback;
import com.android.internal.policy.IKeyguardExitCallback;
import com.android.internal.policy.IKeyguardService;
+import com.android.internal.policy.IKeyguardShowCallback;
+import com.android.internal.policy.IKeyguardStateCallback;
/**
* A wrapper class for KeyguardService. It implements IKeyguardService to ensure the interface
@@ -33,83 +33,52 @@ import com.android.internal.policy.IKeyguardService;
*
*/
public class KeyguardServiceWrapper implements IKeyguardService {
+ private KeyguardStateMonitor mKeyguardStateMonitor;
private IKeyguardService mService;
private String TAG = "KeyguardServiceWrapper";
- public KeyguardServiceWrapper(IKeyguardService service) {
+ public KeyguardServiceWrapper(Context context, IKeyguardService service) {
mService = service;
+ mKeyguardStateMonitor = new KeyguardStateMonitor(context, service);
}
- public boolean isShowing() {
- try {
- return mService.isShowing();
- } catch (RemoteException e) {
- Slog.w(TAG , "Remote Exception", e);
- }
- return false;
- }
-
- public boolean isSecure() {
- try {
- return mService.isSecure();
- } catch (RemoteException e) {
- Slog.w(TAG , "Remote Exception", e);
- }
- return false; // TODO cache state
- }
-
- public boolean isShowingAndNotOccluded() {
- try {
- return mService.isShowingAndNotOccluded();
- } catch (RemoteException e) {
- Slog.w(TAG , "Remote Exception", e);
- }
- return false; // TODO cache state
- }
-
- public boolean isInputRestricted() {
- try {
- return mService.isInputRestricted();
- } catch (RemoteException e) {
- Slog.w(TAG , "Remote Exception", e);
- }
- return false; // TODO cache state
- }
-
- public boolean isDismissable() {
+ @Override // Binder interface
+ public void verifyUnlock(IKeyguardExitCallback callback) {
try {
- return mService.isDismissable();
+ mService.verifyUnlock(callback);
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
- return true; // TODO cache state
}
- public void verifyUnlock(IKeyguardExitCallback callback) {
+ @Override // Binder interface
+ public void keyguardDone(boolean authenticated, boolean wakeup) {
try {
- mService.verifyUnlock(callback);
+ mService.keyguardDone(authenticated, wakeup);
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
}
- public void keyguardDone(boolean authenticated, boolean wakeup) {
+ @Override // Binder interface
+ public void setOccluded(boolean isOccluded) {
try {
- mService.keyguardDone(authenticated, wakeup);
+ mService.setOccluded(isOccluded);
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
}
}
- public int setOccluded(boolean isOccluded) {
+ @Override
+ public void addStateMonitorCallback(IKeyguardStateCallback callback) {
try {
- return mService.setOccluded(isOccluded);
+ mService.addStateMonitorCallback(callback);
} catch (RemoteException e) {
Slog.w(TAG , "Remote Exception", e);
- return IKeyguardServiceConstants.KEYGUARD_SERVICE_SET_OCCLUDED_RESULT_NONE;
}
}
+ @Override // Binder interface
public void dismiss() {
try {
mService.dismiss();
@@ -118,6 +87,7 @@ public class KeyguardServiceWrapper implements IKeyguardService {
}
}
+ @Override // Binder interface
public void onDreamingStarted() {
try {
mService.onDreamingStarted();
@@ -126,6 +96,7 @@ public class KeyguardServiceWrapper implements IKeyguardService {
}
}
+ @Override // Binder interface
public void onDreamingStopped() {
try {
mService.onDreamingStopped();
@@ -134,6 +105,7 @@ public class KeyguardServiceWrapper implements IKeyguardService {
}
}
+ @Override // Binder interface
public void onScreenTurnedOff(int reason) {
try {
mService.onScreenTurnedOff(reason);
@@ -142,6 +114,7 @@ public class KeyguardServiceWrapper implements IKeyguardService {
}
}
+ @Override // Binder interface
public void onScreenTurnedOn(IKeyguardShowCallback result) {
try {
mService.onScreenTurnedOn(result);
@@ -150,6 +123,7 @@ public class KeyguardServiceWrapper implements IKeyguardService {
}
}
+ @Override // Binder interface
public void setKeyguardEnabled(boolean enabled) {
try {
mService.setKeyguardEnabled(enabled);
@@ -158,6 +132,7 @@ public class KeyguardServiceWrapper implements IKeyguardService {
}
}
+ @Override // Binder interface
public void onSystemReady() {
try {
mService.onSystemReady();
@@ -166,6 +141,7 @@ public class KeyguardServiceWrapper implements IKeyguardService {
}
}
+ @Override // Binder interface
public void doKeyguardTimeout(Bundle options) {
try {
mService.doKeyguardTimeout(options);
@@ -174,7 +150,9 @@ public class KeyguardServiceWrapper implements IKeyguardService {
}
}
+ @Override // Binder interface
public void setCurrentUser(int userId) {
+ mKeyguardStateMonitor.setCurrentUser(userId);
try {
mService.setCurrentUser(userId);
} catch (RemoteException e) {
@@ -182,6 +160,7 @@ public class KeyguardServiceWrapper implements IKeyguardService {
}
}
+ @Override // Binder interface
public void onBootCompleted() {
try {
mService.onBootCompleted();
@@ -190,6 +169,7 @@ public class KeyguardServiceWrapper implements IKeyguardService {
}
}
+ @Override // Binder interface
public void startKeyguardExitAnimation(long startTime, long fadeoutDuration) {
try {
mService.startKeyguardExitAnimation(startTime, fadeoutDuration);
@@ -198,6 +178,7 @@ public class KeyguardServiceWrapper implements IKeyguardService {
}
}
+ @Override // Binder interface
public void onActivityDrawn() {
try {
mService.onActivityDrawn();
@@ -206,21 +187,20 @@ public class KeyguardServiceWrapper implements IKeyguardService {
}
}
- public void showAssistant() {
- // Not used by PhoneWindowManager
+ @Override // Binder interface
+ public IBinder asBinder() {
+ return mService.asBinder();
}
- public void dispatch(MotionEvent event) {
- // Not used by PhoneWindowManager. See code in {@link NavigationBarView}
+ public boolean isShowing() {
+ return mKeyguardStateMonitor.isShowing();
}
- public void launchCamera() {
- // Not used by PhoneWindowManager. See code in {@link NavigationBarView}
+ public boolean isSecure() {
+ return mKeyguardStateMonitor.isSecure();
}
- @Override
- public IBinder asBinder() {
- return mService.asBinder();
+ public boolean isInputRestricted() {
+ return mKeyguardStateMonitor.isInputRestricted();
}
-
} \ No newline at end of file
diff --git a/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStateMonitor.java b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStateMonitor.java
new file mode 100644
index 0000000..6f9c617
--- /dev/null
+++ b/policy/src/com/android/internal/policy/impl/keyguard/KeyguardStateMonitor.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2013 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.policy.impl.keyguard;
+
+import android.app.ActivityManager;
+import android.content.Context;
+import android.os.RemoteException;
+import android.util.Slog;
+
+import com.android.internal.policy.IKeyguardService;
+import com.android.internal.policy.IKeyguardStateCallback;
+import com.android.internal.widget.LockPatternUtils;
+
+/**
+ * Maintains a cached copy of Keyguard's state.
+ * @hide
+ */
+public class KeyguardStateMonitor extends IKeyguardStateCallback.Stub {
+ private static final String TAG = "KeyguardStateMonitor";
+
+ // These cache the current state of Keyguard to improve performance and avoid deadlock. After
+ // Keyguard changes its state, it always triggers a layout in window manager. Because
+ // IKeyguardStateCallback is synchronous and because these states are declared volatile, it's
+ // guaranteed that window manager picks up the new state all the time in the layout caused by
+ // the state change of Keyguard.
+ private volatile boolean mIsShowing;
+ private volatile boolean mSimSecure;
+ private volatile boolean mInputRestricted;
+
+ private final LockPatternUtils mLockPatternUtils;
+
+ public KeyguardStateMonitor(Context context, IKeyguardService service) {
+ mLockPatternUtils = new LockPatternUtils(context);
+ mLockPatternUtils.setCurrentUser(ActivityManager.getCurrentUser());
+ try {
+ service.addStateMonitorCallback(this);
+ } catch (RemoteException e) {
+ Slog.w(TAG, "Remote Exception", e);
+ }
+ }
+
+ public boolean isShowing() {
+ return mIsShowing;
+ }
+
+ public boolean isSecure() {
+ return mLockPatternUtils.isSecure() || mSimSecure;
+ }
+
+ public boolean isInputRestricted() {
+ return mInputRestricted;
+ }
+
+ @Override // Binder interface
+ public void onShowingStateChanged(boolean showing) {
+ mIsShowing = showing;
+ }
+
+ @Override // Binder interface
+ public void onSimSecureStateChanged(boolean simSecure) {
+ mSimSecure = simSecure;
+ }
+
+ public void setCurrentUser(int userId) {
+ mLockPatternUtils.setCurrentUser(userId);
+ }
+
+ @Override // Binder interface
+ public void onInputRestrictedStateChanged(boolean inputRestricted) {
+ mInputRestricted = inputRestricted;
+ }
+} \ No newline at end of file