Merge "Revert "Add isRound to WindowInsets""
diff --git a/api/current.txt b/api/current.txt
index b163bd3..9edc6d3 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -19102,6 +19102,7 @@
     field public static final int JELLY_BEAN_MR1 = 17; // 0x11
     field public static final int JELLY_BEAN_MR2 = 18; // 0x12
     field public static final int KITKAT = 19; // 0x13
+    field public static final int KITKAT_WATCH = 10000; // 0x2710
     field public static final int L = 10000; // 0x2710
   }
 
diff --git a/core/java/android/net/NetworkScorerApplication.java b/core/java/android/net/NetworkScorerApplication.java
new file mode 100644
index 0000000..b137ad3
--- /dev/null
+++ b/core/java/android/net/NetworkScorerApplication.java
@@ -0,0 +1,156 @@
+/*
+ * Copyright (C) 2014 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 android.net;
+
+import android.Manifest.permission;
+import android.app.AppOpsManager;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.provider.Settings;
+import android.provider.Settings.Global;
+import android.text.TextUtils;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * Internal class for managing the primary network scorer application.
+ *
+ * @hide
+ */
+public final class NetworkScorerApplication {
+
+    private static final Intent SCORE_INTENT =
+            new Intent(NetworkScoreManager.ACTION_SCORE_NETWORKS);
+
+    /** This class cannot be instantiated. */
+    private NetworkScorerApplication() {}
+
+    /**
+     * Returns the list of available scorer app package names.
+     *
+     * <p>A network scorer is any application which:
+     * <ul>
+     * <li>Declares the {@link android.Manifest.permission#SCORE_NETWORKS} permission.
+     * <li>Includes a receiver for {@link NetworkScoreManager#ACTION_SCORE_NETWORKS} guarded by the
+     *     {@link android.Manifest.permission#BROADCAST_SCORE_NETWORKS} permission.
+     * </ul>
+     *
+     * @return the list of scorers, or the empty list if there are no valid scorers.
+     */
+    public static Collection<String> getAllValidScorers(Context context) {
+        List<String> scorers = new ArrayList<>();
+
+        PackageManager pm = context.getPackageManager();
+        List<ResolveInfo> receivers = pm.queryBroadcastReceivers(SCORE_INTENT, 0 /* flags */);
+        for (ResolveInfo receiver : receivers) {
+            // This field is a misnomer, see android.content.pm.ResolveInfo#activityInfo
+            final ActivityInfo receiverInfo = receiver.activityInfo;
+            if (receiverInfo == null) {
+                // Should never happen with queryBroadcastReceivers, but invalid nonetheless.
+                continue;
+            }
+            if (!permission.BROADCAST_SCORE_NETWORKS.equals(receiverInfo.permission)) {
+                // Receiver doesn't require the BROADCAST_SCORE_NETWORKS permission, which means
+                // anyone could trigger network scoring and flood the framework with score requests.
+                continue;
+            }
+            if (pm.checkPermission(permission.SCORE_NETWORKS, receiverInfo.packageName) !=
+                    PackageManager.PERMISSION_GRANTED) {
+                // Application doesn't hold the SCORE_NETWORKS permission, so the user never
+                // approved it as a network scorer.
+                continue;
+            }
+            scorers.add(receiverInfo.packageName);
+        }
+
+        return scorers;
+    }
+
+    /**
+     * Get the application package name to use for scoring networks.
+     *
+     * @return the scorer package or null if scoring is disabled (including if no scorer was ever
+     *     selected) or if the previously-set scorer is no longer a valid scorer app (e.g. because
+     *     it was disabled or uninstalled).
+     */
+    public static String getActiveScorer(Context context) {
+        String scorerPackage = Settings.Global.getString(context.getContentResolver(),
+                Global.NETWORK_SCORER_APP);
+        Collection<String> applications = getAllValidScorers(context);
+        if (isPackageValidScorer(applications, scorerPackage)) {
+            return scorerPackage;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Set the specified package as the default scorer application.
+     *
+     * <p>The caller must have permission to write to {@link Settings.Global}.
+     *
+     * @param context the context of the calling application
+     * @param packageName the packageName of the new scorer to use. If null, scoring will be
+     *     disabled. Otherwise, the scorer will only be set if it is a valid scorer application.
+     */
+    public static void setActiveScorer(Context context, String packageName) {
+        String oldPackageName = Settings.Global.getString(context.getContentResolver(),
+                Settings.Global.NETWORK_SCORER_APP);
+        if (TextUtils.equals(oldPackageName, packageName)) {
+            // No change.
+            return;
+        }
+
+        if (packageName == null) {
+            Settings.Global.putString(context.getContentResolver(), Global.NETWORK_SCORER_APP,
+                    null);
+        } else {
+            // We only make the change if the new package is valid.
+            Collection<String> applications = getAllValidScorers(context);
+            if (isPackageValidScorer(applications, packageName)) {
+                Settings.Global.putString(context.getContentResolver(),
+                        Settings.Global.NETWORK_SCORER_APP, packageName);
+            }
+        }
+    }
+
+    /** Determine whether the application with the given UID is the enabled scorer. */
+    public static boolean isCallerDefaultScorer(Context context, int callingUid) {
+        String defaultApp = getActiveScorer(context);
+        if (defaultApp == null) {
+            return false;
+        }
+        AppOpsManager appOpsMgr = (AppOpsManager) context.getSystemService(Context.APP_OPS_SERVICE);
+        try {
+            appOpsMgr.checkPackage(callingUid, defaultApp);
+            return true;
+        } catch (SecurityException e) {
+            return false;
+        }
+    }
+
+    /** Returns true if the given package is a valid scorer. */
+    private static boolean isPackageValidScorer(Collection<String> scorerPackageNames,
+            String packageName) {
+        return packageName != null && scorerPackageNames.contains(packageName);
+    }
+}
diff --git a/core/java/android/os/Build.java b/core/java/android/os/Build.java
index 7f1a2e4..63e15a9 100644
--- a/core/java/android/os/Build.java
+++ b/core/java/android/os/Build.java
@@ -476,6 +476,11 @@
         public static final int KITKAT = 19;
 
         /**
+         * Android 4.5: KitKat for watches, snacks on the run.
+         */
+        public static final int KITKAT_WATCH = CUR_DEVELOPMENT; // STOPSHIP: update API level
+
+        /**
          * L!
          *
          * <p>Applications targeting this or a later release will get these
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 7062933..1e202ca 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -5097,6 +5097,13 @@
        public static final String NETWORK_PREFERENCE = "network_preference";
 
        /**
+        * Which package name to use for network scoring. If null, or if the package is not a valid
+        * scorer app, external network scores will neither be requested nor accepted.
+        * @hide
+        */
+       public static final String NETWORK_SCORER_APP = "network_scorer_app";
+
+       /**
         * If the NITZ_UPDATE_DIFF time is exceeded then an automatic adjustment
         * to SystemClock will be allowed even if NITZ_UPDATE_SPACING has not been
         * exceeded.
diff --git a/core/tests/coretests/Android.mk b/core/tests/coretests/Android.mk
index 73a53cb..6bdeaf0 100644
--- a/core/tests/coretests/Android.mk
+++ b/core/tests/coretests/Android.mk
@@ -23,7 +23,7 @@
 
 LOCAL_DX_FLAGS := --core-library
 LOCAL_AAPT_FLAGS = -0 dat -0 gld
-LOCAL_STATIC_JAVA_LIBRARIES := core-tests-support android-common frameworks-core-util-lib mockwebserver guava littlemock
+LOCAL_STATIC_JAVA_LIBRARIES := core-tests-support android-common frameworks-core-util-lib mockwebserver guava littlemock mockito-target
 LOCAL_JAVA_LIBRARIES := android.test.runner conscrypt telephony-common
 LOCAL_PACKAGE_NAME := FrameworksCoreTests
 
diff --git a/core/tests/coretests/src/android/net/NetworkScorerApplicationTest.java b/core/tests/coretests/src/android/net/NetworkScorerApplicationTest.java
new file mode 100644
index 0000000..6d5ede8
--- /dev/null
+++ b/core/tests/coretests/src/android/net/NetworkScorerApplicationTest.java
@@ -0,0 +1,101 @@
+/*
+ * Copyright (C) 2014 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 android.net;
+
+import android.Manifest.permission;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.ActivityInfo;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.test.InstrumentationTestCase;
+
+import com.google.android.collect.Lists;
+
+import org.mockito.ArgumentMatcher;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoAnnotations;
+
+import java.util.Iterator;
+
+public class NetworkScorerApplicationTest extends InstrumentationTestCase {
+    @Mock private Context mMockContext;
+    @Mock private PackageManager mMockPm;
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+
+        // Configuration needed to make mockito/dexcache work.
+        System.setProperty("dexmaker.dexcache",
+                getInstrumentation().getTargetContext().getCacheDir().getPath());
+        ClassLoader newClassLoader = getInstrumentation().getClass().getClassLoader();
+        Thread.currentThread().setContextClassLoader(newClassLoader);
+
+        MockitoAnnotations.initMocks(this);
+        Mockito.when(mMockContext.getPackageManager()).thenReturn(mMockPm);
+    }
+
+    public void testGetAllValidScorers() throws Exception {
+        // Package 1 - Valid scorer.
+        ResolveInfo package1 = buildResolveInfo("package1", true, true);
+
+        // Package 2 - Receiver does not have BROADCAST_SCORE_NETWORKS permission.
+        ResolveInfo package2 = buildResolveInfo("package2", false, true);
+
+        // Package 3 - App does not have SCORE_NETWORKS permission.
+        ResolveInfo package3 = buildResolveInfo("package3", true, false);
+
+        setScorers(package1, package2, package3);
+
+        Iterator<String> result =
+                NetworkScorerApplication.getAllValidScorers(mMockContext).iterator();
+
+        assertTrue(result.hasNext());
+        assertEquals("package1", result.next());
+
+        assertFalse(result.hasNext());
+    }
+
+    private void setScorers(ResolveInfo... scorers) {
+        Mockito.when(mMockPm.queryBroadcastReceivers(
+                Mockito.argThat(new ArgumentMatcher<Intent>() {
+                    @Override
+                    public boolean matches(Object object) {
+                        Intent intent = (Intent) object;
+                        return NetworkScoreManager.ACTION_SCORE_NETWORKS.equals(intent.getAction());
+                    }
+                }), Mockito.eq(0)))
+                .thenReturn(Lists.newArrayList(scorers));
+    }
+
+    private ResolveInfo buildResolveInfo(String packageName,
+            boolean hasReceiverPermission, boolean hasScorePermission) throws Exception {
+        Mockito.when(mMockPm.checkPermission(permission.SCORE_NETWORKS, packageName))
+                .thenReturn(hasScorePermission ?
+                        PackageManager.PERMISSION_GRANTED : PackageManager.PERMISSION_DENIED);
+
+        ResolveInfo resolveInfo = new ResolveInfo();
+        resolveInfo.activityInfo = new ActivityInfo();
+        resolveInfo.activityInfo.packageName = packageName;
+        if (hasReceiverPermission) {
+            resolveInfo.activityInfo.permission = permission.BROADCAST_SCORE_NETWORKS;
+        }
+        return resolveInfo;
+    }
+}
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
index 7cfd684..f85e29f 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardHostView.java
@@ -22,10 +22,8 @@
 import com.android.keyguard.KeyguardSecurityModel.SecurityMode;
 import com.android.keyguard.KeyguardUpdateMonitor.DisplayClientState;
 
-import android.app.Activity;
 import android.app.ActivityManager;
 import android.app.ActivityOptions;
-import android.app.SearchManager;
 import android.app.admin.DevicePolicyManager;
 import android.appwidget.AppWidgetHost;
 import android.appwidget.AppWidgetHostView;
@@ -36,7 +34,6 @@
 import android.content.Intent;
 import android.content.IntentSender;
 import android.content.pm.PackageManager.NameNotFoundException;
-import android.content.pm.UserInfo;
 import android.content.res.Resources;
 import android.graphics.Rect;
 import android.media.RemoteControlClient;
@@ -44,7 +41,6 @@
 import android.os.Looper;
 import android.os.Parcel;
 import android.os.Parcelable;
-import android.os.SystemClock;
 import android.os.UserHandle;
 import android.os.UserManager;
 import android.provider.Settings;
@@ -55,9 +51,7 @@
 import android.view.View;
 import android.widget.RemoteViews.OnClickHandler;
 
-import java.io.File;
 import java.lang.ref.WeakReference;
-import java.util.List;
 
 public class KeyguardHostView extends KeyguardViewBase {
     private static final String TAG = "KeyguardHostView";
@@ -595,16 +589,16 @@
     };
 
     @Override
-    public void onScreenTurnedOn() {
-        super.onScreenTurnedOn();
+    public void onResume() {
+        super.onResume();
         if (mViewStateManager != null) {
             mViewStateManager.showUsabilityHints();
         }
     }
 
     @Override
-    public void onScreenTurnedOff() {
-        super.onScreenTurnedOff();
+    public void onPause() {
+        super.onPause();
         // We use mAppWidgetToShow to show a particular widget after you add it-- once the screen
         // turns off we reset that behavior
         clearAppWidgetToShow();
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
index da6482a..2d492db 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardSecurityModel.java
@@ -28,7 +28,7 @@
      * The different types of security available for {@link Mode#UnlockScreen}.
      * @see com.android.internal.policy.impl.LockPatternKeyguardView#getUnlockMode()
      */
-    enum SecurityMode {
+    public enum SecurityMode {
         Invalid, // NULL state
         None, // No security enabled
         Pattern, // Unlock by drawing a pattern.
diff --git a/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java b/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
index bc0f364..d8e5b8a 100644
--- a/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
+++ b/packages/Keyguard/src/com/android/keyguard/KeyguardViewBase.java
@@ -217,9 +217,9 @@
     }
 
     /**
-     * Called when the screen turned off.
+     * Called when the Keyguard is not actively shown anymore on the screen.
      */
-    public void onScreenTurnedOff() {
+    public void onPause() {
         if (DEBUG) Log.d(TAG, String.format("screen off, instance %s at %s",
                 Integer.toHexString(hashCode()), SystemClock.uptimeMillis()));
         // Once the screen turns off, we no longer consider this to be first boot and we want the
@@ -231,9 +231,9 @@
     }
 
     /**
-     * Called when the screen turned on.
+     * Called when the Keyguard is actively shown on the screen.
      */
-    public void onScreenTurnedOn() {
+    public void onResume() {
         if (DEBUG) Log.d(TAG, "screen on, instance " + Integer.toHexString(hashCode()));
         mSecurityContainer.showPrimarySecurityScreen(false);
         mSecurityContainer.onResume(KeyguardSecurityView.SCREEN_ON);
@@ -476,6 +476,10 @@
         mSecurityContainer.setLockPatternUtils(utils);
     }
 
+    public SecurityMode getSecurityMode() {
+        return mSecurityContainer.getSecurityMode();
+    }
+
     protected abstract void onUserSwitching(boolean switching);
 
     protected abstract void onCreateOptions(Bundle options);
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
index bb39d36..cbfc266 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardViewMediator.java
@@ -1285,6 +1285,9 @@
                     flags |= StatusBarManager.DISABLE_SEARCH;
                 }
             }
+            if (isShowingAndNotOccluded()) {
+                flags |= StatusBarManager.DISABLE_HOME;
+            }
 
             if (DEBUG) {
                 Log.d(TAG, "adjustStatusBarLocked: mShowing=" + mShowing + " mOccluded=" + mOccluded
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
index 7cbde36..f2054a2 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/KeyguardBouncer.java
@@ -17,20 +17,18 @@
 package com.android.systemui.statusbar.phone;
 
 import android.content.Context;
-import android.os.RemoteException;
-import android.util.Slog;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.ViewGroup;
 
-import com.android.internal.policy.IKeyguardShowCallback;
 import com.android.internal.widget.LockPatternUtils;
-import com.android.keyguard.KeyguardHostView;
 import com.android.keyguard.KeyguardViewBase;
 import com.android.keyguard.R;
 import com.android.keyguard.ViewMediatorCallback;
 import com.android.systemui.keyguard.KeyguardViewMediator;
 
+import static com.android.keyguard.KeyguardSecurityModel.*;
+
 /**
  * A class which manages the bouncer on the lockscreen.
  */
@@ -66,6 +64,7 @@
         if (!mKeyguardView.dismiss()) {
             mRoot.setVisibility(View.VISIBLE);
             mKeyguardView.requestFocus();
+            mKeyguardView.onResume();
         }
     }
 
@@ -84,14 +83,8 @@
     }
 
     public void onScreenTurnedOff() {
-        if (mKeyguardView != null) {
-            mKeyguardView.onScreenTurnedOff();
-        }
-    }
-
-    public void onScreenTurnedOn() {
-        if (mKeyguardView != null) {
-            mKeyguardView.onScreenTurnedOn();
+        if (mKeyguardView != null && mRoot.getVisibility() == View.VISIBLE) {
+            mKeyguardView.onPause();
         }
     }
 
@@ -136,4 +129,31 @@
     public boolean onBackPressed() {
         return mKeyguardView != null && mKeyguardView.handleBackKey();
     }
+
+    /**
+     * @return True if and only if the current security method should be shown before showing
+     *         the notifications on Keyguard, like SIM PIN/PUK.
+     */
+    public boolean needsFullscreenBouncer() {
+        if (mKeyguardView != null) {
+            SecurityMode mode = mKeyguardView.getSecurityMode();
+            return mode == SecurityMode.SimPin
+                    || mode == SecurityMode.SimPuk;
+        }
+        return false;
+    }
+
+    public boolean onMenuPressed() {
+        ensureView();
+        if (mKeyguardView.handleMenuKey()) {
+
+            // We need to show it in case it is secure. If not, it will get dismissed in any case.
+            mRoot.setVisibility(View.VISIBLE);
+            mKeyguardView.requestFocus();
+            mKeyguardView.onResume();
+            return true;
+        } else {
+            return false;
+        }
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
index ca97049..5f71516 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -2945,7 +2945,6 @@
         if (isFlippedToSettings()) {
             flipToNotifications();
         }
-        mStatusBarWindow.setSystemUiVisibility(View.STATUS_BAR_DISABLE_HOME);
         mKeyguardStatusView.setVisibility(View.VISIBLE);
         mNotificationPanelHeader.setVisibility(View.GONE);
         if (mKeyguardSettingsFlipButton == null) {
@@ -2962,13 +2961,13 @@
 
     public void hideKeyguard() {
         mOnKeyguard = false;
-        mStatusBarWindow.setSystemUiVisibility(0);
         mKeyguardStatusView.setVisibility(View.GONE);
         mNotificationPanelHeader.setVisibility(View.VISIBLE);
         if (mKeyguardSettingsFlipButton != null) {
             mKeyguardSettingsFlipButton.setVisibility(View.GONE);
         }
         updateRowStates();
+        instantCollapseNotificationPanel();
     }
 
     public void userActivity() {
@@ -2977,6 +2976,10 @@
         }
     }
 
+    public boolean onMenuPressed() {
+        return mOnKeyguard && mStatusBarKeyguardViewManager.onMenuPressed();
+    }
+
     public boolean onBackPressed() {
         if (mOnKeyguard) {
             return mStatusBarKeyguardViewManager.onBackPressed();
@@ -2997,6 +3000,10 @@
         mNotificationPanel.setExpandedFraction(1);
     }
 
+    private void instantCollapseNotificationPanel() {
+        mNotificationPanel.setExpandedFraction(0);
+    }
+
     @Override
     public void onActivated(View view) {
         userActivity();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
index b8592c3..41b5b7c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarKeyguardViewManager.java
@@ -80,11 +80,27 @@
     public void show(Bundle options) {
         mShowing = true;
         mStatusBarWindowManager.setKeyguardShowing(true);
-        mPhoneStatusBar.showKeyguard();
-        mBouncer.prepare();
+        showBouncerOrKeyguard();
         updateBackButtonState();
     }
 
+    /**
+     * Shows the notification keyguard or the bouncer depending on
+     * {@link KeyguardBouncer#needsFullscreenBouncer()}.
+     */
+    private void showBouncerOrKeyguard() {
+        if (mBouncer.needsFullscreenBouncer()) {
+
+            // The keyguard might be showing (already). So we need to hide it.
+            mPhoneStatusBar.hideKeyguard();
+            mBouncer.show();
+        } else {
+            mPhoneStatusBar.showKeyguard();
+            mBouncer.hide();
+            mBouncer.prepare();
+        }
+    }
+
     public void showBouncer() {
         mBouncer.show();
         updateBackButtonState();
@@ -94,8 +110,7 @@
      * Reset the state of the view.
      */
     public void reset() {
-        mBouncer.reset();
-        mPhoneStatusBar.showKeyguard();
+        showBouncerOrKeyguard();
         updateBackButtonState();
     }
 
@@ -106,7 +121,6 @@
 
     public void onScreenTurnedOn(final IKeyguardShowCallback callback) {
         mScreenOn = true;
-        mBouncer.onScreenTurnedOn();
         if (callback != null) {
             callbackAfterDraw(callback);
         }
@@ -185,10 +199,15 @@
 
     private void updateBackButtonState() {
         int vis = mContainer.getSystemUiVisibility();
-        if (mBouncer.isShowing()) {
+        boolean bouncerDismissable = mBouncer.isShowing() && !mBouncer.needsFullscreenBouncer();
+        if (bouncerDismissable || !mShowing) {
             mContainer.setSystemUiVisibility(vis & ~View.STATUS_BAR_DISABLE_BACK);
         } else {
             mContainer.setSystemUiVisibility(vis | View.STATUS_BAR_DISABLE_BACK);
         }
     }
+
+    public boolean onMenuPressed() {
+        return mBouncer.onMenuPressed();
+    }
 }
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
index 6153cde..716e326 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowManager.java
@@ -128,6 +128,10 @@
         }
     }
 
+    private void applyFitsSystemWindows(State state) {
+        mStatusBarView.setFitsSystemWindows(!state.isKeyguardShowingAndNotOccluded());
+    }
+
     private void applyUserActivityTimeout(State state) {
         if (state.isKeyguardShowingAndNotOccluded()) {
             mLp.userActivityTimeout = state.keyguardUserActivityTimeout;
@@ -151,6 +155,7 @@
         applyHeight(state);
         applyUserActivityTimeout(state);
         applyInputFeatures(state);
+        applyFitsSystemWindows(state);
         mWindowManager.updateViewLayout(mStatusBarView, mLp);
     }
 
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
index dd89f47..1d675bd 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/StatusBarWindowView.java
@@ -77,11 +77,15 @@
     public boolean dispatchKeyEvent(KeyEvent event) {
         boolean down = event.getAction() == KeyEvent.ACTION_DOWN;
         switch (event.getKeyCode()) {
-        case KeyEvent.KEYCODE_BACK:
-            if (!down) {
-                mService.onBackPressed();
-            }
-            return true;
+            case KeyEvent.KEYCODE_BACK:
+                if (!down) {
+                    mService.onBackPressed();
+                }
+                return true;
+            case KeyEvent.KEYCODE_MENU:
+                if (!down) {
+                    return mService.onMenuPressed();
+                }
         }
         return super.dispatchKeyEvent(event);
     }