Disable swipe-to-dismiss for not cancelable dialogs.

Bug: 33249829
Change-Id: Ib3d2c9982ece22d1b080b821eaf306f6b686d099
diff --git a/core/java/android/app/Dialog.java b/core/java/android/app/Dialog.java
index 6e2c464..f29e576 100644
--- a/core/java/android/app/Dialog.java
+++ b/core/java/android/app/Dialog.java
@@ -200,6 +200,7 @@
             @Nullable Message cancelCallback) {
         this(context);
         mCancelable = cancelable;
+        updateWindowForCancelable();
         mCancelMessage = cancelCallback;
     }
 
@@ -207,6 +208,7 @@
             @Nullable OnCancelListener cancelListener) {
         this(context);
         mCancelable = cancelable;
+        updateWindowForCancelable();
         setOnCancelListener(cancelListener);
     }
 
@@ -1187,6 +1189,7 @@
      */
     public void setCancelable(boolean flag) {
         mCancelable = flag;
+        updateWindowForCancelable();
     }
 
     /**
@@ -1200,6 +1203,7 @@
     public void setCanceledOnTouchOutside(boolean cancel) {
         if (cancel && !mCancelable) {
             mCancelable = true;
+            updateWindowForCancelable();
         }
         
         mWindow.setCloseOnTouchOutside(cancel);
@@ -1351,4 +1355,8 @@
             }
         }
     }
+
+    private void updateWindowForCancelable() {
+        mWindow.setCloseOnSwipeEnabled(mCancelable);
+    }
 }
diff --git a/core/java/android/view/Window.java b/core/java/android/view/Window.java
index 85c16b8..1cca074 100644
--- a/core/java/android/view/Window.java
+++ b/core/java/android/view/Window.java
@@ -302,6 +302,7 @@
     private boolean mDestroyed;
 
     private boolean mOverlayWithDecorCaptionEnabled = false;
+    private boolean mCloseOnSwipeEnabled = false;
 
     // The current window attributes.
     private final WindowManager.LayoutParams mWindowAttributes =
@@ -2208,4 +2209,21 @@
      * @hide
      */
     public abstract void reportActivityRelaunched();
+
+    /**
+     * Called to set flag to check if the close on swipe is enabled. This will only function if
+     * FEATURE_SWIPE_TO_DISMISS has been set.
+     * @hide
+     */
+    public void setCloseOnSwipeEnabled(boolean closeOnSwipeEnabled) {
+        mCloseOnSwipeEnabled = closeOnSwipeEnabled;
+    }
+
+    /**
+     * @return {@code true} if the close on swipe is enabled.
+     * @hide
+     */
+    public boolean isCloseOnSwipeEnabled() {
+        return mCloseOnSwipeEnabled;
+    }
 }
diff --git a/core/java/com/android/internal/policy/PhoneWindow.java b/core/java/com/android/internal/policy/PhoneWindow.java
index 878f3a6..713190d 100644
--- a/core/java/com/android/internal/policy/PhoneWindow.java
+++ b/core/java/com/android/internal/policy/PhoneWindow.java
@@ -2495,6 +2495,7 @@
         // System.out.println("Features: 0x" + Integer.toHexString(features));
         if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
             layoutResource = R.layout.screen_swipe_dismiss;
+            setCloseOnSwipeEnabled(true);
         } else if ((features & ((1 << FEATURE_LEFT_ICON) | (1 << FEATURE_RIGHT_ICON))) != 0) {
             if (mIsFloating) {
                 TypedValue res = new TypedValue();
@@ -2566,7 +2567,7 @@
         }
 
         if ((features & (1 << FEATURE_SWIPE_TO_DISMISS)) != 0) {
-            registerSwipeCallbacks();
+            registerSwipeCallbacks(contentParent);
         }
 
         // Remaining setup -- of background and title -- that only applies
@@ -2980,9 +2981,12 @@
         return (mRightIconView = (ImageView)findViewById(R.id.right_icon));
     }
 
-    private void registerSwipeCallbacks() {
-        SwipeDismissLayout swipeDismiss =
-                (SwipeDismissLayout) findViewById(R.id.content);
+    private void registerSwipeCallbacks(ViewGroup contentParent) {
+        if (!(contentParent instanceof SwipeDismissLayout)) {
+            Log.w(TAG, "contentParent is not a SwipeDismissLayout: " + contentParent);
+            return;
+        }
+        SwipeDismissLayout swipeDismiss = (SwipeDismissLayout) contentParent;
         swipeDismiss.setOnDismissedListener(new SwipeDismissLayout.OnDismissedListener() {
             @Override
             public void onDismissed(SwipeDismissLayout layout) {
@@ -3021,6 +3025,16 @@
                 });
     }
 
+    /** @hide */
+    @Override
+    public void setCloseOnSwipeEnabled(boolean closeOnSwipeEnabled) {
+        if (hasFeature(Window.FEATURE_SWIPE_TO_DISMISS) // swipe-to-dismiss feature is requested
+                && mContentParent instanceof SwipeDismissLayout) { // check casting mContentParent
+            ((SwipeDismissLayout) mContentParent).setDismissable(closeOnSwipeEnabled);
+        }
+        super.setCloseOnSwipeEnabled(closeOnSwipeEnabled);
+    }
+
     /**
      * Helper method for calling the {@link Callback#onPanelClosed(int, Menu)}
      * callback. This method will grab whatever extra state is needed for the
diff --git a/core/java/com/android/internal/widget/SwipeDismissLayout.java b/core/java/com/android/internal/widget/SwipeDismissLayout.java
index d88f479..31e67bd 100644
--- a/core/java/com/android/internal/widget/SwipeDismissLayout.java
+++ b/core/java/com/android/internal/widget/SwipeDismissLayout.java
@@ -110,6 +110,8 @@
 
     private float mLastX;
 
+    private boolean mDismissable = true;
+
     public SwipeDismissLayout(Context context) {
         super(context);
         init(context);
@@ -166,6 +168,10 @@
 
     @Override
     public boolean onInterceptTouchEvent(MotionEvent ev) {
+        if (!mDismissable) {
+            return super.onInterceptTouchEvent(ev);
+        }
+
         // offset because the view is translated during swipe
         ev.offsetLocation(mTranslationX, 0);
 
@@ -225,7 +231,7 @@
 
     @Override
     public boolean onTouchEvent(MotionEvent ev) {
-        if (mVelocityTracker == null) {
+        if (mVelocityTracker == null || !mDismissable) {
             return super.onTouchEvent(ev);
         }
         // offset because the view is translated during swipe
@@ -363,4 +369,13 @@
 
         return checkV && v.canScrollHorizontally((int) -dx);
     }
+
+    public void setDismissable(boolean dismissable) {
+        if (!dismissable && mDismissable) {
+            cancel();
+            resetMembers();
+        }
+
+        mDismissable = dismissable;
+    }
 }