Pass non-IME controls to InsetsController

The InsetSourceControls need to be passed to the InsetsController.
Without the controls, the InsetsController will be unable to properly
animate in/out the system bars. However, because the parent
DisplayImeController handles the ime animations itself, those controls
should not be passed to the InsetsController to prevent access after the
leash is released.

Bug: 229256359
Test: manual, atest DisplaySystemBarsControllerTest
Change-Id: Ifde6e0b8d67536724e8053b8dd42a40d648f9a60
diff --git a/src/com/android/systemui/wm/DisplaySystemBarsController.java b/src/com/android/systemui/wm/DisplaySystemBarsController.java
index f017108..7668085 100644
--- a/src/com/android/systemui/wm/DisplaySystemBarsController.java
+++ b/src/com/android/systemui/wm/DisplaySystemBarsController.java
@@ -25,6 +25,7 @@
 import android.view.IDisplayWindowInsetsController;
 import android.view.IWindowManager;
 import android.view.InsetsController;
+import android.view.InsetsSourceControl;
 import android.view.InsetsState;
 import android.view.InsetsVisibilities;
 import android.view.WindowInsets.Type;
@@ -37,6 +38,7 @@
 import com.android.wm.shell.common.DisplayInsetsController;
 import com.android.wm.shell.common.TransactionPool;
 
+import java.util.Arrays;
 import java.util.Objects;
 
 /**
@@ -52,7 +54,8 @@
     private final Context mContext;
     private final DisplayController mDisplayController;
     private final Handler mHandler;
-    private SparseArray<PerDisplay> mPerDisplaySparseArray;
+    @VisibleForTesting
+    SparseArray<PerDisplay> mPerDisplaySparseArray;
 
     public DisplaySystemBarsController(
             Context context,
@@ -140,6 +143,22 @@
         }
 
         @Override
+        public void insetsControlChanged(InsetsState insetsState,
+                InsetsSourceControl[] activeControls) {
+            InsetsSourceControl[] nonImeControls = null;
+            // Need to filter out IME control to prevent control after leash is released
+            if (activeControls != null) {
+                nonImeControls = Arrays.stream(activeControls).filter(
+                        c -> c.getType() != InsetsState.ITYPE_IME).toArray(
+                        InsetsSourceControl[]::new);
+            }
+            mInsetsController.onControlsChanged(nonImeControls);
+            // After passing the controls to the InsetsController, pass the original controls to
+            // the parent DisplayImeController to handle IME controls.
+            super.insetsControlChanged(insetsState, activeControls);
+        }
+
+        @Override
         public void topFocusedWindowChanged(String packageName,
                 InsetsVisibilities requestedVisibilities) {
             if (Objects.equals(mPackageName, packageName)) {
diff --git a/src/com/android/systemui/wm/DisplaySystemBarsInsetsControllerHost.java b/src/com/android/systemui/wm/DisplaySystemBarsInsetsControllerHost.java
index d7c91b2..272adf3 100644
--- a/src/com/android/systemui/wm/DisplaySystemBarsInsetsControllerHost.java
+++ b/src/com/android/systemui/wm/DisplaySystemBarsInsetsControllerHost.java
@@ -16,6 +16,8 @@
 
 package com.android.systemui.wm;
 
+import static android.view.WindowInsetsController.BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
+
 import android.annotation.NonNull;
 import android.os.Handler;
 import android.os.IBinder;
@@ -128,7 +130,7 @@
 
     @Override
     public @WindowInsetsController.Behavior int getSystemBarsBehavior() {
-        return 0;
+        return BEHAVIOR_SHOW_TRANSIENT_BARS_BY_SWIPE;
     }
 
     @Override
diff --git a/tests/src/com/android/systemui/wm/DisplaySystemBarsControllerTest.java b/tests/src/com/android/systemui/wm/DisplaySystemBarsControllerTest.java
index e3cb903..94fef67 100644
--- a/tests/src/com/android/systemui/wm/DisplaySystemBarsControllerTest.java
+++ b/tests/src/com/android/systemui/wm/DisplaySystemBarsControllerTest.java
@@ -16,26 +16,32 @@
 
 package com.android.systemui.wm;
 
+import static android.view.InsetsState.ITYPE_IME;
+import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
+import static android.view.InsetsState.ITYPE_STATUS_BAR;
+
 import static com.google.common.truth.Truth.assertThat;
 
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.eq;
-import static org.mockito.Mockito.verify;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.when;
 
 import android.car.settings.CarSettings;
+import android.graphics.Insets;
+import android.graphics.Point;
 import android.os.Handler;
-import android.os.RemoteException;
 import android.provider.Settings;
 import android.testing.AndroidTestingRunner;
 import android.testing.TestableLooper;
 import android.view.IWindowManager;
+import android.view.InsetsSourceControl;
+import android.view.InsetsState;
 
 import androidx.test.filters.SmallTest;
 
 import com.android.systemui.SysuiTestCase;
 import com.android.wm.shell.common.DisplayController;
-import com.android.wm.shell.common.DisplayImeController;
 import com.android.wm.shell.common.DisplayInsetsController;
+import com.android.wm.shell.common.DisplayLayout;
 import com.android.wm.shell.common.TransactionPool;
 
 import org.junit.Before;
@@ -58,6 +64,8 @@
     @Mock
     private DisplayController mDisplayController;
     @Mock
+    private DisplayLayout mDisplayLayout;
+    @Mock
     private DisplayInsetsController mDisplayInsetsController;
     @Mock
     private Handler mHandler;
@@ -67,6 +75,8 @@
     @Before
     public void setUp() {
         MockitoAnnotations.initMocks(this);
+        when(mDisplayLayout.rotation()).thenReturn(0);
+        when(mDisplayController.getDisplayLayout(anyInt())).thenReturn(mDisplayLayout);
 
         mController = new DisplaySystemBarsController(
                 mContext,
@@ -91,4 +101,22 @@
 
         assertThat(BarControlPolicy.sSettingValue).isEqualTo(text);
     }
+
+    @Test
+    public void onControlsChanged_parentClassGetsImeControls() {
+        mController.onDisplayAdded(DISPLAY_ID);
+        assertThat(mController.mPerDisplaySparseArray.size()).isEqualTo(1);
+        DisplaySystemBarsController.PerDisplay display = mController.mPerDisplaySparseArray.get(
+                DISPLAY_ID);
+        assertThat(display).isNotNull();
+
+        InsetsSourceControl[] controls = new InsetsSourceControl[] {
+            new InsetsSourceControl(ITYPE_STATUS_BAR, null, new Point(), Insets.NONE),
+            new InsetsSourceControl(ITYPE_NAVIGATION_BAR, null, new Point(), Insets.NONE),
+            new InsetsSourceControl(ITYPE_IME, null, new Point(), Insets.NONE)
+        };
+        display.insetsControlChanged(new InsetsState(), controls);
+
+        assertThat(display.getImeSourceControl()).isNotNull();
+    }
 }