Experiment for snapping PIP to closest edge.

Test: Enable in SysUI tuner, drag PIP.  This is only experimental to help
      figure out what UX we want to keep.

Change-Id: I0d6f2f0c5909d6a76aae4a8fb84c5076f6996fdd
diff --git a/core/java/android/view/IPinnedStackController.aidl b/core/java/android/view/IPinnedStackController.aidl
index 830591d..a81eef8 100644
--- a/core/java/android/view/IPinnedStackController.aidl
+++ b/core/java/android/view/IPinnedStackController.aidl
@@ -30,4 +30,9 @@
      * Notifies the controller that the user is currently interacting with the PIP.
      */
     oneway void setInInteractiveMode(boolean inInteractiveMode);
+
+    /**
+     * Notifies the controller that the desired snap mode is to the closest edge.
+     */
+    oneway void setSnapToEdge(boolean snapToEdge);
 }
diff --git a/core/java/com/android/internal/policy/PipSnapAlgorithm.java b/core/java/com/android/internal/policy/PipSnapAlgorithm.java
index 45b7b01..cbacf26 100644
--- a/core/java/com/android/internal/policy/PipSnapAlgorithm.java
+++ b/core/java/com/android/internal/policy/PipSnapAlgorithm.java
@@ -46,7 +46,8 @@
     private final Context mContext;
 
     private final ArrayList<Integer> mSnapGravities = new ArrayList<>();
-    private final int mSnapMode = SNAP_MODE_CORNERS_ONLY;
+    private final int mDefaultSnapMode = SNAP_MODE_CORNERS_ONLY;
+    private int mSnapMode = mDefaultSnapMode;
 
     private Scroller mScroller;
     private int mOrientation = Configuration.ORIENTATION_UNDEFINED;
@@ -65,6 +66,13 @@
     }
 
     /**
+     * Enables snapping to the closest edge.
+     */
+    public void setSnapToEdge(boolean snapToEdge) {
+        mSnapMode = snapToEdge ? SNAP_MODE_EDGE : mDefaultSnapMode;
+    }
+
+    /**
      * @return the closest absolute snap stack bounds for the given {@param stackBounds} moving at
      * the given {@param velocityX} and {@param velocityY}.  The {@param movementBounds} should be
      * those for the given {@param stackBounds}.
diff --git a/packages/SystemUI/res/values/strings.xml b/packages/SystemUI/res/values/strings.xml
index 1ca5a36..37a7e38 100644
--- a/packages/SystemUI/res/values/strings.xml
+++ b/packages/SystemUI/res/values/strings.xml
@@ -1706,4 +1706,12 @@
         not appear on production builds ever. -->
     <string name="pip_tap_through_summary" translatable="false">Tap once to interact with the activity</string>
 
+    <!-- PIP snap to closest edge. Non-translatable since it should
+        not appear on production builds ever. -->
+    <string name="pip_snap_mode_edge_title" translatable="false">Snap to closest edge</string>
+
+    <!-- PIP snap to closest edge. Non-translatable since it should
+        not appear on production builds ever. -->
+    <string name="pip_snap_mode_edge_summary" translatable="false">Snap to the closest edge</string>
+
 </resources>
diff --git a/packages/SystemUI/res/xml/tuner_prefs.xml b/packages/SystemUI/res/xml/tuner_prefs.xml
index 9c71b4f..f09d6e9 100644
--- a/packages/SystemUI/res/xml/tuner_prefs.xml
+++ b/packages/SystemUI/res/xml/tuner_prefs.xml
@@ -143,6 +143,12 @@
             android:summary="@string/pip_tap_through_summary"
             sysui:defValue="false" />
 
+        <com.android.systemui.tuner.TunerSwitch
+            android:key="pip_snap_mode_edge"
+            android:title="@string/pip_snap_mode_edge_title"
+            android:summary="@string/pip_snap_mode_edge_summary"
+            sysui:defValue="false" />
+
     </PreferenceScreen>
 
     <PreferenceScreen
diff --git a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
index 0a8e039..a359380 100644
--- a/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
+++ b/packages/SystemUI/src/com/android/systemui/pip/phone/PipTouchHandler.java
@@ -63,6 +63,7 @@
     private static final String TUNER_KEY_SWIPE_TO_DISMISS = "pip_swipe_to_dismiss";
     private static final String TUNER_KEY_DRAG_TO_DISMISS = "pip_drag_to_dismiss";
     private static final String TUNER_KEY_TAP_THROUGH = "pip_tap_through";
+    private static final String TUNER_KEY_SNAP_MODE_EDGE = "pip_snap_mode_edge";
 
     private static final int SNAP_STACK_DURATION = 225;
     private static final int DISMISS_STACK_DURATION = 375;
@@ -85,6 +86,7 @@
     private boolean mEnableSwipeToDismiss = true;
     private boolean mEnableDragToDismiss = true;
     private boolean mEnableTapThrough = false;
+    private boolean mEnableSnapToEdge = false;
 
     private final Rect mPinnedStackBounds = new Rect();
     private final Rect mBoundedPinnedStackBounds = new Rect();
@@ -187,7 +189,7 @@
 
         // Register any tuner settings changes
         TunerService.get(context).addTunable(this, TUNER_KEY_SWIPE_TO_DISMISS,
-            TUNER_KEY_DRAG_TO_DISMISS, TUNER_KEY_TAP_THROUGH);
+            TUNER_KEY_DRAG_TO_DISMISS, TUNER_KEY_TAP_THROUGH, TUNER_KEY_SNAP_MODE_EDGE);
     }
 
     @Override
@@ -198,6 +200,8 @@
             mEnableDragToDismiss = true;
             mEnableTapThrough = false;
             mIsTappingThrough = false;
+            mEnableSnapToEdge = false;
+            setSnapToEdge(false);
             return;
         }
         switch (key) {
@@ -211,6 +215,10 @@
                 mEnableTapThrough = Integer.parseInt(newValue) != 0;
                 mIsTappingThrough = false;
                 break;
+            case TUNER_KEY_SNAP_MODE_EDGE:
+                mEnableSnapToEdge = Integer.parseInt(newValue) != 0;
+                setSnapToEdge(mEnableSnapToEdge);
+                break;
         }
     }
 
@@ -429,6 +437,18 @@
     }
 
     /**
+     * Sets the snap-to-edge state.
+     */
+    private void setSnapToEdge(boolean snapToEdge) {
+        mSnapAlgorithm.setSnapToEdge(snapToEdge);
+        try {
+            mPinnedStackController.setSnapToEdge(snapToEdge);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Could not set snap mode to edge", e);
+        }
+    }
+
+    /**
      * Flings the PIP to the closest snap target.
      */
     private void flingToSnapTarget(float velocity, float velocityX, float velocityY) {
diff --git a/services/core/java/com/android/server/wm/PinnedStackController.java b/services/core/java/com/android/server/wm/PinnedStackController.java
index faca8db..1ccf722 100644
--- a/services/core/java/com/android/server/wm/PinnedStackController.java
+++ b/services/core/java/com/android/server/wm/PinnedStackController.java
@@ -99,6 +99,13 @@
                 mInInteractiveMode = inInteractiveMode;
             });
         }
+
+        @Override
+        public void setSnapToEdge(final boolean snapToEdge) {
+            mHandler.post(() -> {
+                mSnapAlgorithm.setSnapToEdge(snapToEdge);
+            });
+        }
     }
 
     /**