Merge "New window cling for immersive mode." into klp-dev
diff --git a/core/res/res/drawable-hdpi/cling_arrow_up.png b/core/res/res/drawable-hdpi/cling_arrow_up.png
new file mode 100644
index 0000000..8ef2050
--- /dev/null
+++ b/core/res/res/drawable-hdpi/cling_arrow_up.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cling_bg.9.png b/core/res/res/drawable-hdpi/cling_bg.9.png
new file mode 100644
index 0000000..36fbfc8
--- /dev/null
+++ b/core/res/res/drawable-hdpi/cling_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cling_button_normal.9.png b/core/res/res/drawable-hdpi/cling_button_normal.9.png
new file mode 100644
index 0000000..e308382
--- /dev/null
+++ b/core/res/res/drawable-hdpi/cling_button_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-hdpi/cling_button_pressed.9.png b/core/res/res/drawable-hdpi/cling_button_pressed.9.png
new file mode 100644
index 0000000..4f9ca6f
--- /dev/null
+++ b/core/res/res/drawable-hdpi/cling_button_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cling_arrow_up.png b/core/res/res/drawable-mdpi/cling_arrow_up.png
new file mode 100644
index 0000000..ee6c378
--- /dev/null
+++ b/core/res/res/drawable-mdpi/cling_arrow_up.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cling_bg.9.png b/core/res/res/drawable-mdpi/cling_bg.9.png
new file mode 100644
index 0000000..4c0f139
--- /dev/null
+++ b/core/res/res/drawable-mdpi/cling_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cling_button_normal.9.png b/core/res/res/drawable-mdpi/cling_button_normal.9.png
new file mode 100644
index 0000000..a0b6f97
--- /dev/null
+++ b/core/res/res/drawable-mdpi/cling_button_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-mdpi/cling_button_pressed.9.png b/core/res/res/drawable-mdpi/cling_button_pressed.9.png
new file mode 100644
index 0000000..986e669
--- /dev/null
+++ b/core/res/res/drawable-mdpi/cling_button_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/cling_arrow_up.png b/core/res/res/drawable-xhdpi/cling_arrow_up.png
new file mode 100644
index 0000000..2803155
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/cling_arrow_up.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/cling_bg.9.png b/core/res/res/drawable-xhdpi/cling_bg.9.png
new file mode 100644
index 0000000..1cb4681
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/cling_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/cling_button_normal.9.png b/core/res/res/drawable-xhdpi/cling_button_normal.9.png
new file mode 100644
index 0000000..4192563
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/cling_button_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xhdpi/cling_button_pressed.9.png b/core/res/res/drawable-xhdpi/cling_button_pressed.9.png
new file mode 100644
index 0000000..d3ce469
--- /dev/null
+++ b/core/res/res/drawable-xhdpi/cling_button_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/cling_arrow_up.png b/core/res/res/drawable-xxhdpi/cling_arrow_up.png
new file mode 100644
index 0000000..1983f13
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/cling_arrow_up.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/cling_bg.9.png b/core/res/res/drawable-xxhdpi/cling_bg.9.png
new file mode 100644
index 0000000..7beae03
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/cling_bg.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/cling_button_normal.9.png b/core/res/res/drawable-xxhdpi/cling_button_normal.9.png
new file mode 100644
index 0000000..e412876
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/cling_button_normal.9.png
Binary files differ
diff --git a/core/res/res/drawable-xxhdpi/cling_button_pressed.9.png b/core/res/res/drawable-xxhdpi/cling_button_pressed.9.png
new file mode 100644
index 0000000..55e89da
--- /dev/null
+++ b/core/res/res/drawable-xxhdpi/cling_button_pressed.9.png
Binary files differ
diff --git a/core/res/res/drawable/cling_button.xml b/core/res/res/drawable/cling_button.xml
new file mode 100644
index 0000000..9ce191c
--- /dev/null
+++ b/core/res/res/drawable/cling_button.xml
@@ -0,0 +1,21 @@
+<?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.
+-->
+<selector xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true"
+          android:drawable="@drawable/cling_button_pressed" />
+    <item
+          android:drawable="@drawable/cling_button_normal" />
+</selector>
diff --git a/core/res/res/layout/transient_navigation_cling.xml b/core/res/res/layout/transient_navigation_cling.xml
new file mode 100644
index 0000000..d33d965
--- /dev/null
+++ b/core/res/res/layout/transient_navigation_cling.xml
@@ -0,0 +1,67 @@
+<?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.
+-->
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical"
+    android:padding="12dp"
+    >
+    <LinearLayout
+        android:id="@+id/text"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:orientation="vertical"
+        android:layout_marginTop="4dp"
+        android:padding="1dp"
+        >
+        <ImageView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_gravity="center_horizontal"
+            android:src="@drawable/cling_arrow_up"
+            />
+        <FrameLayout
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:background="@drawable/cling_bg"
+            android:paddingLeft="14dp"
+            android:paddingRight="14dp"
+            android:paddingTop="24dp"
+            android:paddingBottom="24dp">
+            <TextView
+                android:layout_width="match_parent"
+                android:layout_height="wrap_content"
+                android:text="@string/transient_navigation_confirmation"
+                android:textColor="#80000000"
+                android:textSize="16sp"
+                />
+        </FrameLayout>
+    </LinearLayout>
+
+    <Button
+        android:id="@+id/ok"
+        android:layout_width="160sp"
+        android:layout_height="wrap_content"
+        android:layout_gravity="right"
+        android:layout_marginTop="18dp"
+        android:gravity="center"
+        android:text="@string/ok"
+        android:background="@drawable/cling_button"
+        />
+
+</LinearLayout>
+
+
diff --git a/core/res/res/values/strings.xml b/core/res/res/values/strings.xml
index d57c232..92a6e52 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>
 
-    <!-- Toast bar message when hiding the transient navigation bar [CHAR LIMIT=45] -->
-    <string name="transient_navigation_confirmation">Swipe down from the top to exit full screen</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>
 
 </resources>
diff --git a/core/res/res/values/symbols.xml b/core/res/res/values/symbols.xml
index cc1cfd3..675fe21 100644
--- a/core/res/res/values/symbols.xml
+++ b/core/res/res/values/symbols.xml
@@ -1094,6 +1094,9 @@
   <java-symbol type="drawable" name="notification_template_icon_low_bg" />
   <java-symbol type="drawable" name="ic_media_route_on_holo_dark" />
   <java-symbol type="drawable" name="ic_media_route_disabled_holo_dark" />
+  <java-symbol type="drawable" name="cling_button" />
+  <java-symbol type="drawable" name="cling_arrow_up" />
+  <java-symbol type="drawable" name="cling_bg" />
 
   <java-symbol type="layout" name="action_bar_home" />
   <java-symbol type="layout" name="action_bar_title_item" />
@@ -1197,6 +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="anim" name="slide_in_child_bottom" />
   <java-symbol type="anim" name="slide_in_right" />
diff --git a/policy/src/com/android/internal/policy/impl/TransientNavigationConfirmation.java b/policy/src/com/android/internal/policy/impl/TransientNavigationConfirmation.java
index 8613088..a6381a7 100644
--- a/policy/src/com/android/internal/policy/impl/TransientNavigationConfirmation.java
+++ b/policy/src/com/android/internal/policy/impl/TransientNavigationConfirmation.java
@@ -16,18 +16,31 @@
 
 package com.android.internal.policy.impl;
 
+import android.animation.Animator;
+import android.animation.ArgbEvaluator;
+import android.animation.ValueAnimator;
+import android.app.ActivityManager;
 import android.content.Context;
+import android.graphics.PixelFormat;
+import android.graphics.drawable.ColorDrawable;
 import android.os.Handler;
 import android.os.Message;
 import android.os.UserHandle;
 import android.provider.Settings;
 import android.text.TextUtils;
 import android.util.ArraySet;
+import android.util.DisplayMetrics;
 import android.util.Slog;
+import android.view.Gravity;
+import android.view.MotionEvent;
 import android.view.View;
+import android.view.ViewGroup;
+import android.view.WindowManager;
 import android.view.animation.Animation;
 import android.view.animation.AnimationUtils;
-import android.widget.Toast;
+import android.view.animation.DecelerateInterpolator;
+import android.widget.Button;
+import android.widget.FrameLayout;
 
 import com.android.internal.R;
 
@@ -40,6 +53,7 @@
 public class TransientNavigationConfirmation {
     private static final String TAG = "TransientNavigationConfirmation";
     private static final boolean DEBUG = false;
+    private static final boolean DEBUG_SHOW_EVERY_TIME = false; // super annoying, use with caution
 
     private final Context mContext;
     private final H mHandler;
@@ -47,11 +61,12 @@
     private final long mShowDelayMs;
     private final long mPanicThresholdMs;
 
-    private Toast mToast;
+    private ClingWindowView mClingWindow;
     private String mLastPackage;
     private String mPromptPackage;
     private long mPanicTime;
     private String mPanicPackage;
+    private WindowManager mWindowManager;
 
     public TransientNavigationConfirmation(Context context) {
         mContext = context;
@@ -59,6 +74,8 @@
         mShowDelayMs = getNavBarExitDuration() * 3;
         mPanicThresholdMs = context.getResources()
                 .getInteger(R.integer.config_transient_navigation_confirmation_panic);
+        mWindowManager = (WindowManager)
+                mContext.getSystemService(Context.WINDOW_SERVICE);
     }
 
     private long getNavBarExitDuration() {
@@ -104,7 +121,7 @@
         mHandler.removeMessages(H.SHOW);
         if (isNavTransient) {
             mLastPackage = pkg;
-            if (!mConfirmedPackages.contains(pkg)) {
+            if (DEBUG_SHOW_EVERY_TIME || !mConfirmedPackages.contains(pkg)) {
                 mHandler.sendMessageDelayed(mHandler.obtainMessage(H.SHOW, pkg), mShowDelayMs);
             }
         } else {
@@ -141,11 +158,90 @@
     }
 
     private void handleHide() {
-        if (mToast != null) {
+        if (mClingWindow != null) {
             if (DEBUG) Slog.d(TAG,
                     "Hiding transient navigation confirmation for " + mPromptPackage);
-            mToast.cancel();
-            mToast = null;
+            mWindowManager.removeView(mClingWindow);
+            mClingWindow = null;
+        }
+    }
+
+    private class ClingWindowView extends FrameLayout {
+        private static final int BGCOLOR = 0x80000000;
+        private static final int OFFSET_DP = 48;
+
+        private final ColorDrawable mColor = new ColorDrawable(0);
+        private ValueAnimator mColorAnim;
+
+        public ClingWindowView(Context context) {
+            super(context);
+            setClickable(true);
+            setBackground(mColor);
+        }
+
+        @Override
+        public void onAttachedToWindow() {
+            super.onAttachedToWindow();
+
+            DisplayMetrics metrics = new DisplayMetrics();
+            mWindowManager.getDefaultDisplay().getMetrics(metrics);
+            float density = metrics.density;
+
+            // create the confirmation cling
+            final ViewGroup clingLayout = (ViewGroup)
+                    View.inflate(getContext(), R.layout.transient_navigation_cling, null);
+
+            final Button ok = (Button) clingLayout.findViewById(R.id.ok);
+            ok.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    handleHide();
+                }
+            });
+            addView(clingLayout, new FrameLayout.LayoutParams(
+                    FrameLayout.LayoutParams.MATCH_PARENT,
+                    FrameLayout.LayoutParams.WRAP_CONTENT
+            ));
+
+            if (ActivityManager.isHighEndGfx()) {
+                final View bubble = clingLayout.findViewById(R.id.text);
+                bubble.setAlpha(0f);
+                bubble.setTranslationY(-OFFSET_DP*density);
+                bubble.animate()
+                        .alpha(1f)
+                        .translationY(0)
+                        .setDuration(300)
+                        .setInterpolator(new DecelerateInterpolator())
+                        .start();
+
+                ok.setAlpha(0f);
+                ok.setTranslationY(-OFFSET_DP*density);
+                ok.animate().alpha(1f)
+                        .translationY(0)
+                        .setDuration(300)
+                        .setStartDelay(200)
+                        .setInterpolator(new DecelerateInterpolator())
+                        .start();
+
+                mColorAnim = ValueAnimator.ofObject(new ArgbEvaluator(), 0, BGCOLOR);
+                mColorAnim.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
+                    @Override
+                    public void onAnimationUpdate(ValueAnimator animation) {
+                        final int c = (Integer) animation.getAnimatedValue();
+                        mColor.setColor(c);
+                    }
+                });
+                mColorAnim.setDuration(1000);
+                mColorAnim.start();
+            } else {
+                mColor.setColor(BGCOLOR);
+            }
+        }
+
+        @Override
+        public boolean onTouchEvent(MotionEvent motion) {
+            Slog.v(TAG, "ClingWindowView.onTouchEvent");
+            return true;
         }
     }
 
@@ -153,16 +249,28 @@
         mPromptPackage = pkg;
         if (DEBUG) Slog.d(TAG, "Showing transient navigation confirmation for " + pkg);
 
-        // create the confirmation toast bar
-        final int msg = R.string.transient_navigation_confirmation;
-        mToast = Toast.makeBar(mContext, msg, Toast.LENGTH_INFINITE);
-        mToast.setAction(R.string.ok, confirmAction(pkg));
+        mClingWindow = new ClingWindowView(mContext);
 
         // we will be hiding the nav bar, so layout as if it's already hidden
-        mToast.getView().setSystemUiVisibility(View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION);
+        mClingWindow.setSystemUiVisibility(
+                View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
+              | View.SYSTEM_UI_FLAG_LAYOUT_STABLE);
 
         // show the confirmation
-        mToast.show();
+        WindowManager.LayoutParams lp = new WindowManager.LayoutParams(
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                ViewGroup.LayoutParams.MATCH_PARENT,
+                WindowManager.LayoutParams.TYPE_TOAST,
+                0
+                        | WindowManager.LayoutParams.FLAG_LAYOUT_IN_SCREEN
+                        | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE
+                        | WindowManager.LayoutParams.FLAG_HARDWARE_ACCELERATED
+                ,
+                PixelFormat.TRANSLUCENT);
+        lp.setTitle("TransientNavigationConfirmation");
+        lp.windowAnimations = com.android.internal.R.style.Animation_RecentApplications;
+        lp.gravity = Gravity.FILL;
+        mWindowManager.addView(mClingWindow, lp);
     }
 
     private Runnable confirmAction(final String pkg) {