Implement new SYSTEM_UI_FLAG_IMMERSIVE_STICKY.

Migrate transient bar mode to IMMERSIVE_STICKY, and
introduce new behavior for IMMERSIVE: namely the
opaque bars are revealed by clearing the flags on swipe.

Remove low-profile optimization that confuses api demos
and other apps using low-profile as a signal.

TransientNavigationConfirmation renamed to
ImmersiveModeConfirmation, and its associated resources,
since the confirmation is now shown when the nav bar is
shown in either of the two immersive modes.

Remove unused Toast.makeBar and associated hidden framework
bits now that the confirmation uses a cling instead.

Bug:11062108
Change-Id: Iae49d31973940b9bee9f5b1827756db5eaa76aa3
diff --git a/core/java/android/provider/Settings.java b/core/java/android/provider/Settings.java
index 6f1c6ba..7f24539 100644
--- a/core/java/android/provider/Settings.java
+++ b/core/java/android/provider/Settings.java
@@ -4379,7 +4379,7 @@
         public static final String BAR_SERVICE_COMPONENT = "bar_service_component";
 
         /** @hide */
-        public static final String TRANSIENT_NAV_CONFIRMATIONS = "transient_nav_confirmations";
+        public static final String IMMERSIVE_MODE_CONFIRMATIONS = "immersive_mode_confirmations";
 
         /**
          * This is the query URI for finding a print service to install.
diff --git a/core/java/android/widget/Toast.java b/core/java/android/widget/Toast.java
index 4b71e36..e38dfa7 100644
--- a/core/java/android/widget/Toast.java
+++ b/core/java/android/widget/Toast.java
@@ -75,9 +75,6 @@
      */
     public static final int LENGTH_LONG = 1;
 
-    /** @hide */
-    public static final int LENGTH_INFINITE = 2;
-
     final Context mContext;
     final TN mTN;
     int mDuration;
@@ -294,61 +291,6 @@
         tv.setText(s);
     }
 
-    /** @hide */
-    public static Toast makeBar(Context context, int resId, int duration) {
-        return makeBar(context, context.getResources().getText(resId), duration);
-    }
-
-    /** @hide */
-    public static Toast makeBar(Context context, CharSequence text, int duration) {
-        Toast result = new Toast(context);
-
-        LayoutInflater inflate = (LayoutInflater)
-                context.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
-        View v = inflate.inflate(com.android.internal.R.layout.toast_bar, null);
-        ((TextView)v.findViewById(android.R.id.message)).setText(text);
-        v.findViewById(android.R.id.button1).setVisibility(View.GONE);
-
-        result.mNextView = v;
-        result.mDuration = duration;
-        result.mTN.mParams.alpha = 0.9f;
-        result.mTN.mParams.windowAnimations = com.android.internal.R.style.Animation_ToastBar;
-
-        return result;
-    }
-
-    /** @hide */
-    public Toast setAction(int resId, Runnable action) {
-        return setAction(mContext.getResources().getText(resId), action);
-    }
-
-    /** @hide */
-    public Toast setAction(CharSequence actionText, final Runnable action) {
-        if (mNextView != null) {
-            TextView text1 = (TextView)mNextView.findViewById(android.R.id.text1);
-            View button1 =  mNextView.findViewById(android.R.id.button1);
-            if (text1 != null && button1 != null) {
-                text1.setText(actionText);
-                button1.setVisibility(View.VISIBLE);
-                button1.setOnClickListener(new OnClickListener() {
-                    @Override
-                    public void onClick(View v) {
-                        if (action != null) {
-                            action.run();
-                        }
-                    }});
-                return setInteractive(true);
-            }
-        }
-        throw new RuntimeException("This Toast was not created with Toast.makeBar()");
-    }
-
-    /** @hide */
-    public Toast setInteractive(boolean interactive) {
-        mTN.setInteractive(interactive);
-        return this;
-    }
-
     // =======================================================================================
     // All the gunk below is the interaction with the Notification Service, which handles
     // the proper ordering of these system-wide.
@@ -405,16 +347,9 @@
             params.windowAnimations = com.android.internal.R.style.Animation_Toast;
             params.type = WindowManager.LayoutParams.TYPE_TOAST;
             params.setTitle("Toast");
-            setInteractive(false);
-        }
-
-        private void setInteractive(boolean interactive) {
-            mParams.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
+            params.flags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                     | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
-                    | (interactive
-                            ? (WindowManager.LayoutParams.FLAG_NOT_TOUCH_MODAL
-                                    | WindowManager.LayoutParams.FLAG_WATCH_OUTSIDE_TOUCH)
-                            : WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE);
+                    | WindowManager.LayoutParams.FLAG_NOT_TOUCHABLE;
         }
 
         /**
diff --git a/core/res/res/anim/toast_bar_enter.xml b/core/res/res/anim/toast_bar_enter.xml
deleted file mode 100644
index 5c0dfcf..0000000
--- a/core/res/res/anim/toast_bar_enter.xml
+++ /dev/null
@@ -1,27 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-** Copyright 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.
-*/
--->
-
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-        android:shareInterpolator="false">
-    <translate android:fromYDelta="10%" android:toYDelta="0"
-            android:interpolator="@interpolator/decelerate_quint"
-            android:duration="@android:integer/config_shortAnimTime"/>
-    <alpha android:fromAlpha="0.5" android:toAlpha="1.0"
-            android:interpolator="@interpolator/decelerate_cubic"
-            android:duration="@android:integer/config_shortAnimTime" />
-</set>
diff --git a/core/res/res/anim/toast_bar_exit.xml b/core/res/res/anim/toast_bar_exit.xml
deleted file mode 100644
index 4e3b7da..0000000
--- a/core/res/res/anim/toast_bar_exit.xml
+++ /dev/null
@@ -1,26 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-** Copyright 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.
-*/
--->
-<set xmlns:android="http://schemas.android.com/apk/res/android"
-    android:shareInterpolator="false">
-    <translate android:fromYDelta="0" android:toYDelta="10%"
-            android:interpolator="@interpolator/accelerate_quint"
-            android:duration="@android:integer/config_shortAnimTime"/>
-    <alpha android:fromAlpha="1.0" android:toAlpha="0.0"
-            android:interpolator="@interpolator/accelerate_cubic"
-            android:duration="@android:integer/config_shortAnimTime"/>
-</set>
diff --git a/core/res/res/drawable-hdpi/toast_bar_bg.9.png b/core/res/res/drawable-hdpi/toast_bar_bg.9.png
deleted file mode 100644
index 2396b26..0000000
--- a/core/res/res/drawable-hdpi/toast_bar_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-mdpi/toast_bar_bg.9.png b/core/res/res/drawable-mdpi/toast_bar_bg.9.png
deleted file mode 100644
index 291a936..0000000
--- a/core/res/res/drawable-mdpi/toast_bar_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/toast_bar_bg.9.png b/core/res/res/drawable-xhdpi/toast_bar_bg.9.png
deleted file mode 100644
index 1dc4927..0000000
--- a/core/res/res/drawable-xhdpi/toast_bar_bg.9.png
+++ /dev/null
Binary files differ
diff --git a/core/res/res/layout/transient_navigation_cling.xml b/core/res/res/layout/immersive_mode_cling.xml
similarity index 96%
rename from core/res/res/layout/transient_navigation_cling.xml
rename to core/res/res/layout/immersive_mode_cling.xml
index d33d965..f97225e 100644
--- a/core/res/res/layout/transient_navigation_cling.xml
+++ b/core/res/res/layout/immersive_mode_cling.xml
@@ -44,7 +44,7 @@
             <TextView
                 android:layout_width="match_parent"
                 android:layout_height="wrap_content"
-                android:text="@string/transient_navigation_confirmation"
+                android:text="@string/immersive_mode_confirmation"
                 android:textColor="#80000000"
                 android:textSize="16sp"
                 />
diff --git a/core/res/res/layout/toast_bar.xml b/core/res/res/layout/toast_bar.xml
deleted file mode 100644
index a31d7cb..0000000
--- a/core/res/res/layout/toast_bar.xml
+++ /dev/null
@@ -1,70 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-     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.
--->
-<FrameLayout
-    xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent">
-
-    <LinearLayout
-        android:background="@drawable/toast_bar_bg"
-        android:layout_height="50dp"
-        android:layout_width="match_parent">
-
-        <TextView
-            android:id="@android:id/message"
-            android:layout_width="0dp"
-            android:layout_height="match_parent"
-            android:layout_weight="1"
-            android:ellipsize="end"
-            android:gravity="center_vertical"
-            android:paddingLeft="16dp"
-            android:paddingRight="16dp"
-            android:singleLine="true"
-            android:textColor="@android:color/white"
-            android:textSize="14sp" />
-
-        <LinearLayout
-            android:id="@android:id/button1"
-            android:layout_width="wrap_content"
-            android:layout_height="match_parent"
-            android:background="?android:attr/selectableItemBackground"
-            android:clickable="true">
-
-            <View
-                android:layout_width="1dp"
-                android:layout_height="match_parent"
-                android:layout_marginBottom="10dp"
-                android:layout_marginRight="12dp"
-                android:layout_marginTop="10dp"
-                android:background="#aaaaaa" />
-
-            <TextView
-                android:id="@android:id/text1"
-                android:textSize="12sp"
-                android:textColor="#aaaaaa"
-                android:textStyle="bold"
-                android:layout_width="wrap_content"
-                android:layout_height="match_parent"
-                android:gravity="center_vertical"
-                android:paddingLeft="8dp"
-                android:paddingRight="20dp"
-                android:textAllCaps="true" />
-        </LinearLayout>
-
-    </LinearLayout>
-
-</FrameLayout>
diff --git a/core/res/res/values-land/dimens.xml b/core/res/res/values-land/dimens.xml
index 81b4c09..dc59f61 100644
--- a/core/res/res/values-land/dimens.xml
+++ b/core/res/res/values-land/dimens.xml
@@ -61,6 +61,6 @@
     Landscape's layout allows this to be smaller than for portrait. -->
     <dimen name="kg_squashed_layout_threshold">400dp</dimen>
 
-    <!-- width of TransientNavigationConfirmation (-1 for match_parent) -->
+    <!-- width of ImmersiveModeConfirmation (-1 for match_parent) -->
     <dimen name="immersive_mode_cling_width">380dp</dimen>
 </resources>
diff --git a/core/res/res/values-sw600dp/dimens.xml b/core/res/res/values-sw600dp/dimens.xml
index 6b5c505..d21f9b7 100644
--- a/core/res/res/values-sw600dp/dimens.xml
+++ b/core/res/res/values-sw600dp/dimens.xml
@@ -113,6 +113,6 @@
     <!-- Margin around the various security views -->
     <dimen name="keyguard_muliuser_selector_margin">12dp</dimen>
 
-    <!-- width of TransientNavigationConfirmation (-1 for match_parent) -->
+    <!-- width of ImmersiveModeConfirmation (-1 for match_parent) -->
     <dimen name="immersive_mode_cling_width">380dp</dimen>
 </resources>
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 2bcd820..196be74 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -1259,8 +1259,8 @@
     </string-array>
 
     <!-- Threshold (in ms) under which a screen off / screen on will be considered a reset of the
-         transient navigation confirmation prompt.-->
-    <integer name="config_transient_navigation_confirmation_panic">5000</integer>
+         immersive mode confirmation prompt.-->
+    <integer name="config_immersive_mode_confirmation_panic">5000</integer>
 
     <!-- For some operators, PDU has garbages. To fix it, need to use valid index -->
     <integer name="config_valid_wappush_index">-1</integer>
diff --git a/core/res/res/values/dimens.xml b/core/res/res/values/dimens.xml
index f43581e..aad6252 100644
--- a/core/res/res/values/dimens.xml
+++ b/core/res/res/values/dimens.xml
@@ -356,6 +356,6 @@
     <!-- Outline width for video subtitles. -->
     <dimen name="subtitle_outline_width">2dp</dimen>
 
-    <!-- width of TransientNavigationConfirmation (-1 for match_parent) -->
+    <!-- width of ImmersiveModeConfirmation (-1 for match_parent) -->
     <dimen name="immersive_mode_cling_width">-1px</dimen>
 </resources>
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index 92a6e52..e82ad1e 100644
--- a/core/res/res/values/strings.xml
+++ b/core/res/res/values/strings.xml
@@ -4486,7 +4486,7 @@
     <!-- PIN entry dialog tells the user to not enter a PIN for a while. [CHAR LIMIT=none] -->
     <string name="restr_pin_try_later">Try again later</string>
 
-    <!-- Cling help message when hiding the transient navigation bar [CHAR LIMIT=none] -->
-    <string name="transient_navigation_confirmation">Swipe down from the top to exit full screen.</string>
+    <!-- Cling help message when hiding the navigation bar entering immersive mode [CHAR LIMIT=none] -->
+    <string name="immersive_mode_confirmation" msgid="8554991488096662508">Swipe down from the top to exit full screen.</string>
 
 </resources>
diff --git a/core/res/res/values/styles.xml b/core/res/res/values/styles.xml
index c5dab3b..cb2fd6d 100644
--- a/core/res/res/values/styles.xml
+++ b/core/res/res/values/styles.xml
@@ -138,12 +138,6 @@
         <item name="windowExitAnimation">@anim/submenu_exit</item>
     </style>
 
-    <!-- {@hide} -->
-    <style name="Animation.ToastBar">
-        <item name="windowEnterAnimation">@anim/toast_bar_enter</item>
-        <item name="windowExitAnimation">@anim/toast_bar_exit</item>
-    </style>
-
     <style name="Animation.TypingFilter">
         <item name="windowEnterAnimation">@anim/grow_fade_in_center</item>
         <item name="windowExitAnimation">@anim/shrink_fade_out_center</item>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index 6c944cf..0b050c7 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -292,6 +292,7 @@
   <java-symbol type="integer" name="config_cursorWindowSize" />
   <java-symbol type="integer" name="config_extraFreeKbytesAdjust" />
   <java-symbol type="integer" name="config_extraFreeKbytesAbsolute" />
+  <java-symbol type="integer" name="config_immersive_mode_confirmation_panic" />
   <java-symbol type="integer" name="config_longPressOnPowerBehavior" />
   <java-symbol type="integer" name="config_lowMemoryKillerMinFreeKbytesAdjust" />
   <java-symbol type="integer" name="config_lowMemoryKillerMinFreeKbytesAbsolute" />
@@ -302,7 +303,6 @@
   <java-symbol type="integer" name="config_ntpThreshold" />
   <java-symbol type="integer" name="config_ntpTimeout" />
   <java-symbol type="integer" name="config_toastDefaultGravity" />
-  <java-symbol type="integer" name="config_transient_navigation_confirmation_panic" />
   <java-symbol type="integer" name="config_wifi_framework_scan_interval" />
   <java-symbol type="integer" name="config_wifi_supplicant_scan_interval" />
   <java-symbol type="integer" name="config_wifi_scan_interval_p2p_connected" />
@@ -1083,7 +1083,6 @@
   <java-symbol type="drawable" name="text_select_handle_left" />
   <java-symbol type="drawable" name="text_select_handle_middle" />
   <java-symbol type="drawable" name="text_select_handle_right" />
-  <java-symbol type="drawable" name="toast_bar_bg" />
   <java-symbol type="drawable" name="unknown_image" />
   <java-symbol type="drawable" name="unlock_default" />
   <java-symbol type="drawable" name="unlock_halo" />
@@ -1175,7 +1174,6 @@
   <java-symbol type="layout" name="textview_hint" />
   <java-symbol type="layout" name="time_picker" />
   <java-symbol type="layout" name="time_picker_dialog" />
-  <java-symbol type="layout" name="toast_bar" />
   <java-symbol type="layout" name="transient_notification" />
   <java-symbol type="layout" name="volume_adjust" />
   <java-symbol type="layout" name="volume_adjust_item" />
@@ -1202,7 +1200,7 @@
   <java-symbol type="layout" name="app_not_authorized" />
   <java-symbol type="layout" name="restrictions_pin_challenge" />
   <java-symbol type="layout" name="restrictions_pin_setup" />
-  <java-symbol type="layout" name="transient_navigation_cling" />
+  <java-symbol type="layout" name="immersive_mode_cling" />
 
   <java-symbol type="anim" name="slide_in_child_bottom" />
   <java-symbol type="anim" name="slide_in_right" />
@@ -1232,7 +1230,6 @@
   <java-symbol type="style" name="Animation.DropDownUp" />
   <java-symbol type="style" name="Animation.DropDownDown" />
   <java-symbol type="style" name="Animation.PopupWindow" />
-  <java-symbol type="style" name="Animation.ToastBar" />
   <java-symbol type="style" name="Animation.TypingFilter" />
   <java-symbol type="style" name="Animation.TypingFilterRestore" />
   <java-symbol type="style" name="Animation.Dream" />
diff --git a/policy/src/com/android/internal/policy/impl/TransientNavigationConfirmation.java b/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java
similarity index 89%
rename from policy/src/com/android/internal/policy/impl/TransientNavigationConfirmation.java
rename to policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java
index 3c7902c..dfdcdad5 100644
--- a/policy/src/com/android/internal/policy/impl/TransientNavigationConfirmation.java
+++ b/policy/src/com/android/internal/policy/impl/ImmersiveModeConfirmation.java
@@ -49,11 +49,11 @@
 import java.util.Arrays;
 
 /**
- *  Helper to manage showing/hiding a confirmation prompt when the transient navigation bar
- *  is hidden.
+ *  Helper to manage showing/hiding a confirmation prompt when the navigation bar is hidden
+ *  entering immersive mode.
  */
-public class TransientNavigationConfirmation {
-    private static final String TAG = "TransientNavigationConfirmation";
+public class ImmersiveModeConfirmation {
+    private static final String TAG = "ImmersiveModeConfirmation";
     private static final boolean DEBUG = false;
     private static final boolean DEBUG_SHOW_EVERY_TIME = false; // super annoying, use with caution
 
@@ -70,12 +70,12 @@
     private String mPanicPackage;
     private WindowManager mWindowManager;
 
-    public TransientNavigationConfirmation(Context context) {
+    public ImmersiveModeConfirmation(Context context) {
         mContext = context;
         mHandler = new H();
         mShowDelayMs = getNavBarExitDuration() * 3;
         mPanicThresholdMs = context.getResources()
-                .getInteger(R.integer.config_transient_navigation_confirmation_panic);
+                .getInteger(R.integer.config_immersive_mode_confirmation_panic);
         mWindowManager = (WindowManager)
                 mContext.getSystemService(Context.WINDOW_SERVICE);
     }
@@ -91,7 +91,7 @@
         String packages = null;
         try {
             packages = Settings.Secure.getStringForUser(mContext.getContentResolver(),
-                    Settings.Secure.TRANSIENT_NAV_CONFIRMATIONS,
+                    Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS,
                     UserHandle.USER_CURRENT);
             if (packages != null) {
                 mConfirmedPackages.addAll(Arrays.asList(packages.split(",")));
@@ -107,7 +107,7 @@
         try {
             final String packages = TextUtils.join(",", mConfirmedPackages);
             Settings.Secure.putStringForUser(mContext.getContentResolver(),
-                    Settings.Secure.TRANSIENT_NAV_CONFIRMATIONS,
+                    Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS,
                     packages,
                     UserHandle.USER_CURRENT);
             if (DEBUG) Slog.d(TAG, "Saved packages=" + packages);
@@ -116,12 +116,12 @@
         }
     }
 
-    public void transientNavigationChanged(String pkg, boolean isNavTransient) {
+    public void immersiveModeChanged(String pkg, boolean isImmersiveMode) {
         if (pkg == null) {
             return;
         }
         mHandler.removeMessages(H.SHOW);
-        if (isNavTransient) {
+        if (isImmersiveMode) {
             mLastPackage = pkg;
             if (DEBUG_SHOW_EVERY_TIME || !mConfirmedPackages.contains(pkg)) {
                 mHandler.sendMessageDelayed(mHandler.obtainMessage(H.SHOW, pkg), mShowDelayMs);
@@ -132,13 +132,13 @@
         }
     }
 
-    public void onPowerKeyDown(boolean isScreenOn, long time, boolean transientNavigationAllowed) {
+    public void onPowerKeyDown(boolean isScreenOn, long time, boolean inImmersiveMode) {
         if (mPanicPackage != null && !isScreenOn && (time - mPanicTime < mPanicThresholdMs)) {
             // turning the screen back on within the panic threshold
             unconfirmPackage(mPanicPackage);
         }
-        if (isScreenOn && transientNavigationAllowed) {
-            // turning the screen off, remember if we were hiding the transient nav
+        if (isScreenOn && inImmersiveMode) {
+            // turning the screen off, remember if we were in immersive mode
             mPanicTime = time;
             mPanicPackage = mLastPackage;
         } else {
@@ -153,7 +153,7 @@
 
     private void unconfirmPackage(String pkg) {
         if (pkg != null) {
-            if (DEBUG) Slog.d(TAG, "Unconfirming transient navigation for " + pkg);
+            if (DEBUG) Slog.d(TAG, "Unconfirming immersive mode confirmation for " + pkg);
             mConfirmedPackages.remove(pkg);
             saveSetting();
         }
@@ -161,8 +161,7 @@
 
     private void handleHide() {
         if (mClingWindow != null) {
-            if (DEBUG) Slog.d(TAG,
-                    "Hiding transient navigation confirmation for " + mPromptPackage);
+            if (DEBUG) Slog.d(TAG, "Hiding immersive mode confirmation for " + mPromptPackage);
             mWindowManager.removeView(mClingWindow);
             mClingWindow = null;
         }
@@ -179,7 +178,7 @@
                         | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
                 ,
                 PixelFormat.TRANSLUCENT);
-        lp.setTitle("TransientNavigationConfirmation");
+        lp.setTitle("ImmersiveModeConfirmation");
         lp.windowAnimations = com.android.internal.R.style.Animation_RecentApplications;
         lp.gravity = Gravity.FILL;
         return lp;
@@ -230,7 +229,7 @@
 
             // create the confirmation cling
             mClingLayout = (ViewGroup)
-                    View.inflate(getContext(), R.layout.transient_navigation_cling, null);
+                    View.inflate(getContext(), R.layout.immersive_mode_cling, null);
 
             final Button ok = (Button) mClingLayout.findViewById(R.id.ok);
             ok.setOnClickListener(new OnClickListener() {
@@ -292,7 +291,7 @@
 
     private void handleShow(String pkg) {
         mPromptPackage = pkg;
-        if (DEBUG) Slog.d(TAG, "Showing transient navigation confirmation for " + pkg);
+        if (DEBUG) Slog.d(TAG, "Showing immersive mode confirmation for " + pkg);
 
         mClingWindow = new ClingWindowView(mContext, confirmAction(pkg));
 
@@ -311,7 +310,7 @@
             @Override
             public void run() {
                 if (pkg != null && !mConfirmedPackages.contains(pkg)) {
-                    if (DEBUG) Slog.d(TAG, "Confirming transient navigation for " + pkg);
+                    if (DEBUG) Slog.d(TAG, "Confirming immersive mode for " + pkg);
                     mConfirmedPackages.add(pkg);
                     saveSetting();
                 }
diff --git a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
index 6dcaddc..5ac3ed0 100644
--- a/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
+++ b/policy/src/com/android/internal/policy/impl/PhoneWindowManager.java
@@ -532,7 +532,7 @@
                     Settings.Secure.DEFAULT_INPUT_METHOD), false, this,
                     UserHandle.USER_ALL);
             resolver.registerContentObserver(Settings.System.getUriFor(
-                    Settings.Secure.TRANSIENT_NAV_CONFIRMATIONS), false, this,
+                    Settings.Secure.IMMERSIVE_MODE_CONFIRMATIONS), false, this,
                     UserHandle.USER_ALL);
             updateSettings();
         }
@@ -570,7 +570,7 @@
             StatusBarManager.WINDOW_NAVIGATION_BAR,
             WindowManager.LayoutParams.FLAG_TRANSLUCENT_NAVIGATION);
 
-    private TransientNavigationConfirmation mTransientNavigationConfirmation;
+    private ImmersiveModeConfirmation mImmersiveModeConfirmation;
 
     private SystemGesturesPointerEventListener mSystemGestures;
 
@@ -953,7 +953,7 @@
                         // no-op
                     }
                 });
-        mTransientNavigationConfirmation = new TransientNavigationConfirmation(mContext);
+        mImmersiveModeConfirmation = new ImmersiveModeConfirmation(mContext);
         mWindowManagerFuncs.registerPointerEventListener(mSystemGestures);
 
         mVibrator = (Vibrator)context.getSystemService(Context.VIBRATOR_SERVICE);
@@ -1169,8 +1169,8 @@
                 mHasSoftInput = hasSoftInput;
                 updateRotation = true;
             }
-            if (mTransientNavigationConfirmation != null) {
-                mTransientNavigationConfirmation.loadSetting();
+            if (mImmersiveModeConfirmation != null) {
+                mImmersiveModeConfirmation.loadSetting();
             }
         }
         if (updateRotation) {
@@ -2699,15 +2699,17 @@
             final int sysui = mLastSystemUiFlags;
             boolean navVisible = (sysui & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) == 0;
             boolean navTranslucent = (sysui & View.NAVIGATION_BAR_TRANSLUCENT) != 0;
-            boolean transientAllowed = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
-            navTranslucent &= !transientAllowed;  // transient trumps translucent
+            boolean immersive = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
+            boolean immersiveSticky = (sysui & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
+            boolean navAllowedHidden = immersive || immersiveSticky;
+            navTranslucent &= !immersiveSticky;  // transient trumps translucent
             navTranslucent &= isTranslucentNavigationAllowed();
 
             // When the navigation bar isn't visible, we put up a fake
             // input window to catch all touch events.  This way we can
             // detect when the user presses anywhere to bring back the nav
             // bar and ensure the application doesn't see the event.
-            if (navVisible || transientAllowed) {
+            if (navVisible || navAllowedHidden) {
                 if (mHideNavFakeWindow != null) {
                     mHideNavFakeWindow.dismiss();
                     mHideNavFakeWindow = null;
@@ -3945,8 +3947,8 @@
             case KeyEvent.KEYCODE_POWER: {
                 result &= ~ACTION_PASS_TO_USER;
                 if (down) {
-                    mTransientNavigationConfirmation.onPowerKeyDown(isScreenOn, event.getDownTime(),
-                            isTransientNavigationAllowed(mLastSystemUiFlags));
+                    mImmersiveModeConfirmation.onPowerKeyDown(isScreenOn, event.getDownTime(),
+                            isImmersiveMode(mLastSystemUiFlags));
                     if (isScreenOn && !mPowerKeyTriggered
                             && (event.getFlags() & KeyEvent.FLAG_FALLBACK) == 0) {
                         mPowerKeyTriggered = true;
@@ -4225,7 +4227,7 @@
                 }
                 if (sb) mStatusBarController.showTransient();
                 if (nb) mNavigationBarController.showTransient();
-                mTransientNavigationConfirmation.confirmCurrentPrompt();
+                mImmersiveModeConfirmation.confirmCurrentPrompt();
                 updateSystemUiVisibilityLw();
             }
         }
@@ -5108,6 +5110,7 @@
             int flags = View.SYSTEM_UI_FLAG_FULLSCREEN
                     | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                     | View.SYSTEM_UI_FLAG_IMMERSIVE
+                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
                     | View.STATUS_BAR_TRANSLUCENT
                     | View.NAVIGATION_BAR_TRANSLUCENT;
             vis = (vis & ~flags) | (oldVis & flags);
@@ -5118,53 +5121,64 @@
         }
 
         // update status bar
-        boolean transientAllowed =
-                (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
+        boolean immersiveSticky =
+                (vis & View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY) != 0;
         boolean hideStatusBarWM =
                 mTopFullscreenOpaqueWindowState != null &&
                 (mTopFullscreenOpaqueWindowState.getAttrs().flags
                         & WindowManager.LayoutParams.FLAG_FULLSCREEN) != 0;
         boolean hideStatusBarSysui =
                 (vis & View.SYSTEM_UI_FLAG_FULLSCREEN) != 0;
+        boolean hideNavBarSysui =
+                (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
 
         boolean transientStatusBarAllowed =
                 mStatusBar != null && (
                 hideStatusBarWM
-                || (hideStatusBarSysui && transientAllowed)
+                || (hideStatusBarSysui && immersiveSticky)
                 || statusBarHasFocus);
 
-        if (mStatusBarController.isTransientShowing()
-                && !transientStatusBarAllowed && hideStatusBarSysui) {
+        boolean transientNavBarAllowed =
+                mNavigationBar != null &&
+                hideNavBarSysui && immersiveSticky;
+
+        boolean denyTransientStatus = mStatusBarController.isTransientShowing()
+                && !transientStatusBarAllowed && hideStatusBarSysui;
+        boolean denyTransientNav = mNavigationBarController.isTransientShowing()
+                && !transientNavBarAllowed;
+        if (denyTransientStatus || denyTransientNav) {
             // clear the clearable flags instead
-            int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
-            if (newVal != mResettingSystemUiFlags) {
-                mResettingSystemUiFlags = newVal;
-                mWindowManagerFuncs.reevaluateStatusBarVisibility();
-            }
+            clearClearableFlagsLw();
         }
 
         vis = mStatusBarController.updateVisibilityLw(transientStatusBarAllowed, oldVis, vis);
 
         // update navigation bar
-        boolean oldTransientNav = isTransientNavigationAllowed(oldVis);
-        boolean isTransientNav = isTransientNavigationAllowed(vis);
-        if (win != null && oldTransientNav != isTransientNav) {
+        boolean oldImmersiveMode = isImmersiveMode(oldVis);
+        boolean newImmersiveMode = isImmersiveMode(vis);
+        if (win != null && oldImmersiveMode != newImmersiveMode) {
             final String pkg = win.getOwningPackage();
-            mTransientNavigationConfirmation.transientNavigationChanged(pkg, isTransientNav);
+            mImmersiveModeConfirmation.immersiveModeChanged(pkg, newImmersiveMode);
         }
-        vis = mNavigationBarController.updateVisibilityLw(isTransientNav, oldVis, vis);
 
-        // don't send low profile updates if the system bars are hidden
-        if (mStatusBarController.isHidden() && mNavigationBarController.isHidden()) {
-            vis &= ~View.SYSTEM_UI_FLAG_LOW_PROFILE;
-        }
+        vis = mNavigationBarController.updateVisibilityLw(transientNavBarAllowed, oldVis, vis);
+
         return vis;
     }
 
-    private boolean isTransientNavigationAllowed(int vis) {
+    private void clearClearableFlagsLw() {
+        int newVal = mResettingSystemUiFlags | View.SYSTEM_UI_CLEARABLE_FLAGS;
+        if (newVal != mResettingSystemUiFlags) {
+            mResettingSystemUiFlags = newVal;
+            mWindowManagerFuncs.reevaluateStatusBarVisibility();
+        }
+    }
+
+    private boolean isImmersiveMode(int vis) {
+        final int flags = View.SYSTEM_UI_FLAG_IMMERSIVE | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
         return mNavigationBar != null
                 && (vis & View.SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0
-                && (vis & View.SYSTEM_UI_FLAG_IMMERSIVE) != 0;
+                && (vis & flags) != 0;
     }
 
     /**
diff --git a/services/java/com/android/server/NotificationManagerService.java b/services/java/com/android/server/NotificationManagerService.java
index 7431f1d..0438675 100644
--- a/services/java/com/android/server/NotificationManagerService.java
+++ b/services/java/com/android/server/NotificationManagerService.java
@@ -1550,11 +1550,9 @@
     private void scheduleTimeoutLocked(ToastRecord r)
     {
         mHandler.removeCallbacksAndMessages(r);
-        if (r.duration != Toast.LENGTH_INFINITE) {
-            Message m = Message.obtain(mHandler, MESSAGE_TIMEOUT, r);
-            long delay = r.duration == Toast.LENGTH_LONG ? LONG_DELAY : SHORT_DELAY;
-            mHandler.sendMessageDelayed(m, delay);
-        }
+        Message m = Message.obtain(mHandler, MESSAGE_TIMEOUT, r);
+        long delay = r.duration == Toast.LENGTH_LONG ? LONG_DELAY : SHORT_DELAY;
+        mHandler.sendMessageDelayed(m, delay);
     }
 
     private void handleTimeout(ToastRecord record)