Accessibility to toggle multiwindow mode

Encapsulating the logic to toggle multiwindow mode from recents,
and plumbing it through to accessibility global actions. Sending
accessibility events when windows bounds change. Exposing the
dock divider window type to accessibility services.

Bug: 27250995
Change-Id: Ib7491f1f853dc7f01bf5c5a4ac1f914f55d0608a
diff --git a/api/current.txt b/api/current.txt
index a082a23..af7dcd8 100644
--- a/api/current.txt
+++ b/api/current.txt
@@ -2662,6 +2662,7 @@
     field public static final int GLOBAL_ACTION_POWER_DIALOG = 6; // 0x6
     field public static final int GLOBAL_ACTION_QUICK_SETTINGS = 5; // 0x5
     field public static final int GLOBAL_ACTION_RECENTS = 3; // 0x3
+    field public static final int GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN = 7; // 0x7
     field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService";
     field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
   }
@@ -43984,6 +43985,7 @@
     field public static final int TYPE_ACCESSIBILITY_OVERLAY = 4; // 0x4
     field public static final int TYPE_APPLICATION = 1; // 0x1
     field public static final int TYPE_INPUT_METHOD = 2; // 0x2
+    field public static final int TYPE_SPLIT_SCREEN_DIVIDER = 5; // 0x5
     field public static final int TYPE_SYSTEM = 3; // 0x3
   }
 
diff --git a/api/system-current.txt b/api/system-current.txt
index e4437aa..d146a8a 100644
--- a/api/system-current.txt
+++ b/api/system-current.txt
@@ -2764,6 +2764,7 @@
     field public static final int GLOBAL_ACTION_POWER_DIALOG = 6; // 0x6
     field public static final int GLOBAL_ACTION_QUICK_SETTINGS = 5; // 0x5
     field public static final int GLOBAL_ACTION_RECENTS = 3; // 0x3
+    field public static final int GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN = 7; // 0x7
     field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService";
     field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
   }
@@ -46738,6 +46739,7 @@
     field public static final int TYPE_ACCESSIBILITY_OVERLAY = 4; // 0x4
     field public static final int TYPE_APPLICATION = 1; // 0x1
     field public static final int TYPE_INPUT_METHOD = 2; // 0x2
+    field public static final int TYPE_SPLIT_SCREEN_DIVIDER = 5; // 0x5
     field public static final int TYPE_SYSTEM = 3; // 0x3
   }
 
diff --git a/api/test-current.txt b/api/test-current.txt
index de1496b..fe74ec6 100644
--- a/api/test-current.txt
+++ b/api/test-current.txt
@@ -2662,6 +2662,7 @@
     field public static final int GLOBAL_ACTION_POWER_DIALOG = 6; // 0x6
     field public static final int GLOBAL_ACTION_QUICK_SETTINGS = 5; // 0x5
     field public static final int GLOBAL_ACTION_RECENTS = 3; // 0x3
+    field public static final int GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN = 7; // 0x7
     field public static final java.lang.String SERVICE_INTERFACE = "android.accessibilityservice.AccessibilityService";
     field public static final java.lang.String SERVICE_META_DATA = "android.accessibilityservice";
   }
@@ -44001,6 +44002,7 @@
     field public static final int TYPE_ACCESSIBILITY_OVERLAY = 4; // 0x4
     field public static final int TYPE_APPLICATION = 1; // 0x1
     field public static final int TYPE_INPUT_METHOD = 2; // 0x2
+    field public static final int TYPE_SPLIT_SCREEN_DIVIDER = 5; // 0x5
     field public static final int TYPE_SYSTEM = 3; // 0x3
   }
 
diff --git a/core/java/android/accessibilityservice/AccessibilityService.java b/core/java/android/accessibilityservice/AccessibilityService.java
index 4bc6b97..fb5f5b9 100644
--- a/core/java/android/accessibilityservice/AccessibilityService.java
+++ b/core/java/android/accessibilityservice/AccessibilityService.java
@@ -334,7 +334,7 @@
     public static final int GLOBAL_ACTION_HOME = 2;
 
     /**
-     * Action to open the recent apps.
+     * Action to toggle showing the overview of recent apps
      */
     public static final int GLOBAL_ACTION_RECENTS = 3;
 
@@ -353,6 +353,11 @@
      */
     public static final int GLOBAL_ACTION_POWER_DIALOG = 6;
 
+    /**
+     * Action to toggle docking the current app's window
+     */
+    public static final int GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN = 7;
+
     private static final String LOG_TAG = "AccessibilityService";
 
     /**
diff --git a/core/java/android/view/accessibility/AccessibilityWindowInfo.java b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
index a75e8a7..ad78b68 100644
--- a/core/java/android/view/accessibility/AccessibilityWindowInfo.java
+++ b/core/java/android/view/accessibility/AccessibilityWindowInfo.java
@@ -64,6 +64,12 @@
      */
     public static final int TYPE_ACCESSIBILITY_OVERLAY = 4;
 
+    /**
+     * Window type: A system window used to divide the screen in split-screen mode.
+     * This type of window is present only in split-screen mode.
+     */
+    public static final int TYPE_SPLIT_SCREEN_DIVIDER = 5;
+
     private static final int UNDEFINED = -1;
 
     private static final int BOOLEAN_PROPERTY_ACTIVE = 1 << 0;
@@ -551,6 +557,9 @@
             case TYPE_ACCESSIBILITY_OVERLAY: {
                 return "TYPE_ACCESSIBILITY_OVERLAY";
             }
+            case TYPE_SPLIT_SCREEN_DIVIDER: {
+                return "TYPE_SPLIT_SCREEN_DIVIDER";
+            }
             default:
                 return "<UNKNOWN>";
         }
diff --git a/core/java/com/android/internal/statusbar/IStatusBar.aidl b/core/java/com/android/internal/statusbar/IStatusBar.aidl
index 08d4fba..64c5b8d 100644
--- a/core/java/com/android/internal/statusbar/IStatusBar.aidl
+++ b/core/java/com/android/internal/statusbar/IStatusBar.aidl
@@ -60,6 +60,7 @@
     void showRecentApps(boolean triggeredFromAltTab);
     void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
     void toggleRecentApps();
+    void toggleSplitScreen();
     void preloadRecentApps();
     void cancelPreloadRecentApps();
     void showScreenPinningRequest();
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
index 2bebac2..b8d5f32 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/BaseStatusBar.java
@@ -1118,6 +1118,11 @@
     }
 
     @Override
+    public void toggleSplitScreen() {
+        toggleSplitScreenMode();
+    }
+
+    @Override
     public void preloadRecentApps() {
         int msg = MSG_PRELOAD_RECENT_APPS;
         mHandler.removeMessages(msg);
@@ -1187,6 +1192,13 @@
         }
     };
 
+    /**
+     * Toggle docking the app window
+     *
+     * @return {@code true} if the app window is docked after the toggle, {@code false} otherwise.
+     */
+    protected abstract boolean toggleSplitScreenMode();
+
     /** Proxy for RecentsComponent */
 
     protected void showRecents(boolean triggeredFromAltTab) {
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
index 3b960ee..6a98488 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/CommandQueue.java
@@ -72,6 +72,7 @@
     private static final int MSG_ADD_QS_TILE                   = 27 << MSG_SHIFT;
     private static final int MSG_REMOVE_QS_TILE                = 28 << MSG_SHIFT;
     private static final int MSG_CLICK_QS_TILE                 = 29 << MSG_SHIFT;
+    private static final int MSG_TOGGLE_APP_SPLIT_SCREEN       = 30 << MSG_SHIFT;
 
     public static final int FLAG_EXCLUDE_NONE = 0;
     public static final int FLAG_EXCLUDE_SEARCH_PANEL = 1 << 0;
@@ -104,6 +105,7 @@
         public void showRecentApps(boolean triggeredFromAltTab);
         public void hideRecentApps(boolean triggeredFromAltTab, boolean triggeredFromHomeKey);
         public void toggleRecentApps();
+        public void toggleSplitScreen();
         public void preloadRecentApps();
         public void toggleKeyboardShortcutsMenu();
         public void cancelPreloadRecentApps();
@@ -223,6 +225,13 @@
         }
     }
 
+    public void toggleSplitScreen() {
+        synchronized (mLock) {
+            mHandler.removeMessages(MSG_TOGGLE_APP_SPLIT_SCREEN);
+            mHandler.obtainMessage(MSG_TOGGLE_APP_SPLIT_SCREEN, 0, 0, null).sendToTarget();
+        }
+    }
+
     public void toggleRecentApps() {
         synchronized (mLock) {
             mHandler.removeMessages(MSG_TOGGLE_RECENT_APPS);
@@ -464,6 +473,9 @@
                 case MSG_CLICK_QS_TILE:
                     mCallbacks.clickTile((ComponentName) msg.obj);
                     break;
+                case MSG_TOGGLE_APP_SPLIT_SCREEN:
+                    mCallbacks.toggleSplitScreen();
+                    break;
             }
         }
     }
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 3aa576f..832aefe 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/phone/PhoneStatusBar.java
@@ -1141,31 +1141,42 @@
 
         @Override
         public boolean onLongClick(View v) {
-            if (mRecents != null) {
-                int dockSide = WindowManagerProxy.getInstance().getDockSide();
-                if (dockSide == WindowManager.DOCKED_INVALID) {
-                    Point realSize = new Point();
-                    mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY)
-                            .getRealSize(realSize);
-                    Rect initialBounds= new Rect(0, 0, realSize.x, realSize.y);
-                    boolean docked = mRecents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE,
-                            ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
-                            initialBounds);
-                    if (docked) {
-                        MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS);
-                        return true;
-                    }
-                } else {
-                    EventBus.getDefault().send(new UndockingTaskEvent());
-                    MetricsLogger.action(mContext, MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS);
-                    return true;
-                }
-
+            if (mRecents == null) {
+                return false;
+            }
+            boolean initiallyDocked = WindowManagerProxy.getInstance().getDockSide()
+                    == WindowManager.DOCKED_INVALID;
+            boolean dockedAtEnd = toggleSplitScreenMode();
+            if (dockedAtEnd != initiallyDocked) {
+                int logAction = dockedAtEnd ? MetricsEvent.ACTION_WINDOW_DOCK_LONGPRESS
+                        : MetricsEvent.ACTION_WINDOW_UNDOCK_LONGPRESS;
+                MetricsLogger.action(mContext, logAction);
+                return true;
             }
             return false;
         }
     };
 
+    @Override
+    protected boolean toggleSplitScreenMode() {
+        if (mRecents == null) {
+            return false;
+        }
+        int dockSide = WindowManagerProxy.getInstance().getDockSide();
+        if (dockSide == WindowManager.DOCKED_INVALID) {
+            Point realSize = new Point();
+            mContext.getSystemService(DisplayManager.class).getDisplay(Display.DEFAULT_DISPLAY)
+                    .getRealSize(realSize);
+            Rect initialBounds= new Rect(0, 0, realSize.x, realSize.y);
+            return mRecents.dockTopTask(NavigationBarGestureHelper.DRAG_MODE_NONE,
+                    ActivityManager.DOCKED_STACK_CREATE_MODE_TOP_OR_LEFT,
+                    initialBounds);
+        } else {
+            EventBus.getDefault().send(new UndockingTaskEvent());
+            return false;
+        }
+    }
+
     private final View.OnLongClickListener mLongPressHomeListener
             = new View.OnLongClickListener() {
         @Override
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
index 110258c..0ed6ef8 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/tv/TvStatusBar.java
@@ -116,6 +116,11 @@
     }
 
     @Override
+    protected boolean toggleSplitScreenMode() {
+        return false;
+    }
+
+    @Override
     public void maybeEscalateHeadsUp() {
     }
 
diff --git a/services/accessibility/Android.mk b/services/accessibility/Android.mk
index d98fc28..ce89aa7 100644
--- a/services/accessibility/Android.mk
+++ b/services/accessibility/Android.mk
@@ -7,4 +7,6 @@
 LOCAL_SRC_FILES += \
       $(call all-java-files-under,java)
 
+LOCAL_JAVA_LIBRARIES := services.core
+
 include $(BUILD_STATIC_JAVA_LIBRARY)
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
index 4be6833..cc20ed4 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityManagerService.java
@@ -94,6 +94,7 @@
 import com.android.internal.statusbar.IStatusBarService;
 import com.android.server.LocalServices;
 
+import com.android.server.statusbar.StatusBarManagerInternal;
 import org.xmlpull.v1.XmlPullParserException;
 
 import java.io.FileDescriptor;
@@ -2754,6 +2755,9 @@
                     case AccessibilityService.GLOBAL_ACTION_POWER_DIALOG: {
                         showGlobalActions();
                     } return true;
+                    case AccessibilityService.GLOBAL_ACTION_TOGGLE_SPLIT_SCREEN: {
+                        toggleSplitScreen();
+                    } return true;
                 }
                 return false;
             } finally {
@@ -3225,6 +3229,10 @@
             mWindowManagerService.showGlobalActions();
         }
 
+        private void toggleSplitScreen() {
+            LocalServices.getService(StatusBarManagerInternal.class).toggleSplitScreen();
+        }
+
         private IAccessibilityInteractionConnection getConnectionLocked(int windowId) {
             if (DEBUG) {
                 Slog.i(LOG_TAG, "Trying to get interaction connection to windowId: " + windowId);
@@ -3441,11 +3449,14 @@
                 case WindowManager.LayoutParams.TYPE_SYSTEM_ALERT:
                 case WindowManager.LayoutParams.TYPE_SYSTEM_DIALOG:
                 case WindowManager.LayoutParams.TYPE_SYSTEM_ERROR:
-                case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY:
-                case WindowManager.LayoutParams.TYPE_DOCK_DIVIDER: {
+                case WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY: {
                     return AccessibilityWindowInfo.TYPE_SYSTEM;
                 }
 
+                case WindowManager.LayoutParams.TYPE_DOCK_DIVIDER: {
+                    return AccessibilityWindowInfo.TYPE_SPLIT_SCREEN_DIVIDER;
+                }
+
                 case WindowManager.LayoutParams.TYPE_ACCESSIBILITY_OVERLAY: {
                     return AccessibilityWindowInfo.TYPE_ACCESSIBILITY_OVERLAY;
                 }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
index cbbcdae..6bda4ed 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerInternal.java
@@ -33,4 +33,5 @@
     void topAppWindowChanged(boolean menuVisible);
     void setSystemUiVisibility(int vis, int fullscreenStackVis, int dockedStackVis, int mask,
             Rect fullscreenBounds, Rect dockedBounds, String cause);
+    void toggleSplitScreen();
 }
diff --git a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
index 6eab8d4..d24e1af 100644
--- a/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
+++ b/services/core/java/com/android/server/statusbar/StatusBarManagerService.java
@@ -204,6 +204,16 @@
             StatusBarManagerService.this.setSystemUiVisibility(vis, fullscreenStackVis,
                     dockedStackVis, mask, fullscreenBounds, dockedBounds, cause);
         }
+
+        @Override
+        public void toggleSplitScreen() {
+            enforceStatusBarService();
+            if (mBar != null) {
+                try {
+                    mBar.toggleSplitScreen();
+                } catch (RemoteException ex) {}
+            }
+        }
     };
 
     // ================================================================================