diff options
Diffstat (limited to 'policy')
6 files changed, 441 insertions, 568 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 54fb89d..e855cf1 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; @@ -340,6 +341,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { int mUndockedHdmiRotation; int mDemoHdmiRotation; boolean mDemoHdmiRotationLock; + int mDemoRotation; + boolean mDemoRotationLock; boolean mWakeGestureEnabledSetting; MyWakeGestureListener mWakeGestureListener; @@ -478,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; @@ -1103,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, @@ -1446,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 && @@ -1625,8 +1641,14 @@ public class PhoneWindowManager implements WindowManagerPolicy { outAppOp[0] = AppOpsManager.OP_NONE; - if (type < WindowManager.LayoutParams.FIRST_SYSTEM_WINDOW - || type > WindowManager.LayoutParams.LAST_SYSTEM_WINDOW) { + if (!((type >= FIRST_APPLICATION_WINDOW && type <= LAST_APPLICATION_WINDOW) + || (type >= FIRST_SUB_WINDOW && type <= LAST_SUB_WINDOW) + || (type >= FIRST_SYSTEM_WINDOW && type <= LAST_SYSTEM_WINDOW))) { + return WindowManagerGlobal.ADD_INVALID_TYPE; + } + + if (type < FIRST_SYSTEM_WINDOW || type > LAST_SYSTEM_WINDOW) { + // Window manager will make sure these are okay. return WindowManagerGlobal.ADD_OKAY; } String permission = null; @@ -1642,6 +1664,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: @@ -1695,7 +1718,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: @@ -1814,7 +1836,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: @@ -1873,15 +1894,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; @@ -1956,7 +1980,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); } @@ -2108,11 +2133,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); @@ -2149,7 +2171,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } mStatusBar = win; mStatusBarController.setWindow(win); - mKeyguardDelegate.hideScrim(); break; case TYPE_NAVIGATION_BAR: mContext.enforceCallingOrSelfPermission( @@ -2185,7 +2206,6 @@ public class PhoneWindowManager implements WindowManagerPolicy { } mKeyguardScrim = win; break; - } return WindowManagerGlobal.ADD_OKAY; } @@ -2309,24 +2329,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; } @@ -2369,7 +2384,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { } boolean keyguardOn() { - return keyguardIsShowingTq() || inKeyguardRestrictedKeyInputMode(); + return isKeyguardShowingAndNotOccluded() || inKeyguardRestrictedKeyInputMode(); } private static final int[] WINDOW_TYPES_WHERE_HOME_DOESNT_WORK = { @@ -2962,7 +2977,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 @@ -3091,7 +3106,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); @@ -3109,26 +3125,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} */ @@ -3420,10 +3440,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, @@ -3986,11 +4011,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); @@ -4028,20 +4058,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); @@ -4062,7 +4099,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); @@ -4173,9 +4210,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; @@ -4190,7 +4227,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; @@ -4200,7 +4237,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; @@ -4215,7 +4252,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; @@ -4235,23 +4272,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; @@ -4462,7 +4498,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) { @@ -4802,7 +4838,8 @@ public class PhoneWindowManager implements WindowManagerPolicy { private boolean shouldDispatchInputWhenNonInteractive() { // Send events to keyguard while the screen is on. - if (keyguardIsShowingTq() && mDisplay != null && mDisplay.getState() != Display.STATE_OFF) { + if (isKeyguardShowingAndNotOccluded() && mDisplay != null + && mDisplay.getState() != Display.STATE_OFF) { return true; } @@ -5174,12 +5211,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() { @@ -5193,11 +5229,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() { @@ -5208,6 +5239,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() { @@ -5239,6 +5271,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); } } @@ -5312,6 +5345,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; @@ -5506,7 +5543,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { /** {@inheritDoc} */ @Override public void systemReady() { - mKeyguardDelegate = new KeyguardServiceDelegate(mContext, null); + mKeyguardDelegate = new KeyguardServiceDelegate(mContext); mKeyguardDelegate.onSystemReady(); readCameraLensCoverState(); @@ -5953,7 +5990,7 @@ public class PhoneWindowManager implements WindowManagerPolicy { @Override public void keepScreenOnStoppedLw() { - if (mKeyguardDelegate != null && !mKeyguardDelegate.isShowingAndNotOccluded()) { + if (isKeyguardShowingAndNotOccluded()) { mPowerManager.userActivity(SystemClock.uptimeMillis(), false); } } @@ -5961,7 +5998,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; } @@ -5997,7 +6035,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) { 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 |