diff --git a/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java b/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java index c9ec34fd5f088..bbab4388f17d3 100644 --- a/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java +++ b/packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java @@ -16,12 +16,14 @@ package com.android.systemui.wm; +import android.content.Context; import android.os.Handler; import android.os.RemoteException; import android.util.ArraySet; import android.util.Slog; import android.util.SparseArray; import android.view.IDisplayWindowInsetsController; +import android.view.IWindowManager; import android.view.InsetsController; import android.view.InsetsSourceControl; import android.view.InsetsState; @@ -48,30 +50,32 @@ public class DisplaySystemBarsController extends DisplayImeController { private static final String TAG = "DisplaySystemBarsController"; + private final Context mContext; + private final Handler mHandler; + private SparseArray mPerDisplaySparseArray; @Inject public DisplaySystemBarsController( - SystemWindows syswin, + Context context, + IWindowManager wmService, DisplayController displayController, @Main Handler mainHandler, TransactionPool transactionPool) { - super(syswin, displayController, mainHandler, transactionPool); + super(wmService, displayController, mainHandler::post, transactionPool); + mContext = context; + mHandler = mainHandler; } @Override public void onDisplayAdded(int displayId) { PerDisplay pd = new PerDisplay(displayId); - try { - mSystemWindows.mWmService.setDisplayWindowInsetsController(displayId, pd); - } catch (RemoteException e) { - Slog.w(TAG, "Unable to set insets controller on display " + displayId); - } + pd.register(); // Lazy loading policy control filters instead of during boot. if (mPerDisplaySparseArray == null) { mPerDisplaySparseArray = new SparseArray<>(); - BarControlPolicy.reloadFromSetting(mSystemWindows.mContext); - BarControlPolicy.registerContentObserver(mSystemWindows.mContext, mHandler, () -> { + BarControlPolicy.reloadFromSetting(mContext); + BarControlPolicy.registerContentObserver(mContext, mHandler, () -> { int size = mPerDisplaySparseArray.size(); for (int i = 0; i < size; i++) { mPerDisplaySparseArray.valueAt(i).modifyDisplayWindowInsets(); @@ -84,7 +88,7 @@ public class DisplaySystemBarsController extends DisplayImeController { @Override public void onDisplayRemoved(int displayId) { try { - mSystemWindows.mWmService.setDisplayWindowInsetsController(displayId, null); + mWmService.setDisplayWindowInsetsController(displayId, null); } catch (RemoteException e) { Slog.w(TAG, "Unable to remove insets controller on display " + displayId); } @@ -100,11 +104,10 @@ public class DisplaySystemBarsController extends DisplayImeController { String mPackageName; PerDisplay(int displayId) { - super(displayId, - mSystemWindows.mDisplayController.getDisplayLayout(displayId).rotation()); + super(displayId, mDisplayController.getDisplayLayout(displayId).rotation()); mDisplayId = displayId; mInsetsController = new InsetsController( - new DisplaySystemBarsInsetsControllerHost(mHandler, this)); + new DisplaySystemBarsInsetsControllerHost(mHandler, mInsetsControllerImpl)); } @Override @@ -166,7 +169,7 @@ public class DisplaySystemBarsController extends DisplayImeController { showInsets(barVisibilities[0], /* fromIme= */ false); hideInsets(barVisibilities[1], /* fromIme= */ false); try { - mSystemWindows.mWmService.modifyDisplayWindowInsets(mDisplayId, mInsetsState); + mWmService.modifyDisplayWindowInsets(mDisplayId, mInsetsState); } catch (RemoteException e) { Slog.w(TAG, "Unable to update window manager service."); } diff --git a/packages/CarSystemUI/tests/src/com/android/systemui/wm/DisplaySystemBarsControllerTest.java b/packages/CarSystemUI/tests/src/com/android/systemui/wm/DisplaySystemBarsControllerTest.java index 29cc8eec4bc3e..765a4e7900b5c 100644 --- a/packages/CarSystemUI/tests/src/com/android/systemui/wm/DisplaySystemBarsControllerTest.java +++ b/packages/CarSystemUI/tests/src/com/android/systemui/wm/DisplaySystemBarsControllerTest.java @@ -21,6 +21,7 @@ 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.Mockito.when; import android.car.settings.CarSettings; import android.os.Handler; @@ -29,6 +30,7 @@ import android.provider.Settings; import android.testing.AndroidTestingRunner; import android.testing.TestableLooper; import android.view.IWindowManager; +import android.view.Surface; import androidx.test.filters.SmallTest; @@ -60,15 +62,20 @@ public class DisplaySystemBarsControllerTest extends SysuiTestCase { private Handler mHandler; @Mock private TransactionPool mTransactionPool; + @Mock + private DisplayLayout mDisplayLayout; @Before public void setUp() { MockitoAnnotations.initMocks(this); mSystemWindows.mContext = mContext; mSystemWindows.mWmService = mIWindowManager; + when(mDisplayLayout.rotation()).thenReturn(Surface.ROTATION_0); + when(mDisplayController.getDisplayLayout(DISPLAY_ID)).thenReturn(mDisplayLayout); mController = new DisplaySystemBarsController( - mSystemWindows, + mContext, + mIWindowManager, mDisplayController, mHandler, mTransactionPool @@ -81,7 +88,8 @@ public class DisplaySystemBarsControllerTest extends SysuiTestCase { mController.onDisplayAdded(DISPLAY_ID); verify(mIWindowManager).setDisplayWindowInsetsController( - eq(DISPLAY_ID), any(DisplaySystemBarsController.PerDisplay.class)); + eq(DISPLAY_ID), + any(DisplayImeController.PerDisplay.DisplayWindowInsetsControllerImpl.class)); } @Test diff --git a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java index ab4da83518e40..20e09a2df1cbe 100644 --- a/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java +++ b/packages/SystemUI/src/com/android/systemui/wm/DisplayImeController.java @@ -24,12 +24,12 @@ import android.content.Context; import android.content.res.Configuration; import android.graphics.Point; import android.graphics.Rect; -import android.os.Handler; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Slog; import android.util.SparseArray; import android.view.IDisplayWindowInsetsController; +import android.view.IWindowManager; import android.view.InsetsSource; import android.view.InsetsSourceControl; import android.view.InsetsState; @@ -39,11 +39,15 @@ import android.view.WindowInsets; import android.view.animation.Interpolator; import android.view.animation.PathInterpolator; +import androidx.annotation.BinderThread; +import androidx.annotation.VisibleForTesting; + import com.android.internal.view.IInputMethodManager; import com.android.systemui.TransactionPool; import com.android.systemui.dagger.qualifiers.Main; import java.util.ArrayList; +import java.util.concurrent.Executor; import javax.inject.Inject; import javax.inject.Singleton; @@ -66,20 +70,22 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged private static final int DIRECTION_HIDE = 2; private static final int FLOATING_IME_BOTTOM_INSET = -80; - SystemWindows mSystemWindows; - final Handler mHandler; + protected final IWindowManager mWmService; + protected final Executor mMainExecutor; final TransactionPool mTransactionPool; + final DisplayController mDisplayController; final SparseArray mImePerDisplay = new SparseArray<>(); final ArrayList mPositionProcessors = new ArrayList<>(); @Inject - public DisplayImeController(SystemWindows syswin, DisplayController displayController, - @Main Handler mainHandler, TransactionPool transactionPool) { - mHandler = mainHandler; - mSystemWindows = syswin; + public DisplayImeController(IWindowManager wmService, DisplayController displayController, + @Main Executor mainExecutor, TransactionPool transactionPool) { + mWmService = wmService; + mMainExecutor = mainExecutor; mTransactionPool = transactionPool; + mDisplayController = displayController; displayController.addDisplayWindowListener(this); } @@ -88,12 +94,8 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged // Add's a system-ui window-manager specifically for ime. This type is special because // WM will defer IME inset handling to it in multi-window scenarious. PerDisplay pd = new PerDisplay(displayId, - mSystemWindows.mDisplayController.getDisplayLayout(displayId).rotation()); - try { - mSystemWindows.mWmService.setDisplayWindowInsetsController(displayId, pd); - } catch (RemoteException e) { - Slog.w(TAG, "Unable to set insets controller on display " + displayId); - } + mDisplayController.getDisplayLayout(displayId).rotation()); + pd.register(); mImePerDisplay.put(displayId, pd); } @@ -103,7 +105,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged if (pd == null) { return; } - if (mSystemWindows.mDisplayController.getDisplayLayout(displayId).rotation() + if (mDisplayController.getDisplayLayout(displayId).rotation() != pd.mRotation && isImeShowing(displayId)) { pd.startAnimation(true, false /* forceRestart */); } @@ -112,7 +114,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged @Override public void onDisplayRemoved(int displayId) { try { - mSystemWindows.mWmService.setDisplayWindowInsetsController(displayId, null); + mWmService.setDisplayWindowInsetsController(displayId, null); } catch (RemoteException e) { Slog.w(TAG, "Unable to remove insets controller on display " + displayId); } @@ -180,9 +182,12 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged } } - class PerDisplay extends IDisplayWindowInsetsController.Stub { + /** An implementation of {@link IDisplayWindowInsetsController} for a given display id. */ + public class PerDisplay { final int mDisplayId; final InsetsState mInsetsState = new InsetsState(); + protected final DisplayWindowInsetsControllerImpl mInsetsControllerImpl = + new DisplayWindowInsetsControllerImpl(); InsetsSourceControl mImeSourceControl = null; int mAnimationDirection = DIRECTION_NONE; ValueAnimator mAnimation = null; @@ -196,28 +201,32 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged mRotation = initialRotation; } - @Override - public void insetsChanged(InsetsState insetsState) { - mHandler.post(() -> { - if (mInsetsState.equals(insetsState)) { - return; - } - - mImeShowing = insetsState.getSourceOrDefaultVisibility(InsetsState.ITYPE_IME); - - final InsetsSource newSource = insetsState.getSource(InsetsState.ITYPE_IME); - final Rect newFrame = newSource.getFrame(); - final Rect oldFrame = mInsetsState.getSource(InsetsState.ITYPE_IME).getFrame(); - - mInsetsState.set(insetsState, true /* copySources */); - if (mImeShowing && !newFrame.equals(oldFrame) && newSource.isVisible()) { - if (DEBUG) Slog.d(TAG, "insetsChanged when IME showing, restart animation"); - startAnimation(mImeShowing, true /* forceRestart */); - } - }); + public void register() { + try { + mWmService.setDisplayWindowInsetsController(mDisplayId, mInsetsControllerImpl); + } catch (RemoteException e) { + Slog.w(TAG, "Unable to set insets controller on display " + mDisplayId); + } + } + + public void insetsChanged(InsetsState insetsState) { + if (mInsetsState.equals(insetsState)) { + return; + } + + mImeShowing = insetsState.getSourceOrDefaultVisibility(InsetsState.ITYPE_IME); + + final InsetsSource newSource = insetsState.getSource(InsetsState.ITYPE_IME); + final Rect newFrame = newSource.getFrame(); + final Rect oldFrame = mInsetsState.getSource(InsetsState.ITYPE_IME).getFrame(); + + mInsetsState.set(insetsState, true /* copySources */); + if (mImeShowing && !newFrame.equals(oldFrame) && newSource.isVisible()) { + if (DEBUG) Slog.d(TAG, "insetsChanged when IME showing, restart animation"); + startAnimation(mImeShowing, true /* forceRestart */); + } } - @Override public void insetsControlChanged(InsetsState insetsState, InsetsSourceControl[] activeControls) { insetsChanged(insetsState); @@ -227,27 +236,25 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged continue; } if (activeControl.getType() == InsetsState.ITYPE_IME) { - mHandler.post(() -> { - final Point lastSurfacePosition = mImeSourceControl != null - ? mImeSourceControl.getSurfacePosition() : null; - final boolean positionChanged = - !activeControl.getSurfacePosition().equals(lastSurfacePosition); - final boolean leashChanged = - !haveSameLeash(mImeSourceControl, activeControl); - mImeSourceControl = activeControl; - if (mAnimation != null) { - if (positionChanged) { - startAnimation(mImeShowing, true /* forceRestart */); - } - } else { - if (leashChanged) { - applyVisibilityToLeash(); - } - if (!mImeShowing) { - removeImeSurface(); - } + final Point lastSurfacePosition = mImeSourceControl != null + ? mImeSourceControl.getSurfacePosition() : null; + final boolean positionChanged = + !activeControl.getSurfacePosition().equals(lastSurfacePosition); + final boolean leashChanged = + !haveSameLeash(mImeSourceControl, activeControl); + mImeSourceControl = activeControl; + if (mAnimation != null) { + if (positionChanged) { + startAnimation(mImeShowing, true /* forceRestart */); } - }); + } else { + if (leashChanged) { + applyVisibilityToLeash(); + } + if (!mImeShowing) { + removeImeSurface(); + } + } } } } @@ -267,25 +274,22 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged } } - @Override public void showInsets(int types, boolean fromIme) { if ((types & WindowInsets.Type.ime()) == 0) { return; } if (DEBUG) Slog.d(TAG, "Got showInsets for ime"); - mHandler.post(() -> startAnimation(true /* show */, false /* forceRestart */)); + startAnimation(true /* show */, false /* forceRestart */); } - @Override public void hideInsets(int types, boolean fromIme) { if ((types & WindowInsets.Type.ime()) == 0) { return; } if (DEBUG) Slog.d(TAG, "Got hideInsets for ime"); - mHandler.post(() -> startAnimation(false /* show */, false /* forceRestart */)); + startAnimation(false /* show */, false /* forceRestart */); } - @Override public void topFocusedWindowChanged(String packageName) { // no-op } @@ -296,7 +300,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged private void setVisibleDirectly(boolean visible) { mInsetsState.getSource(InsetsState.ITYPE_IME).setVisible(visible); try { - mSystemWindows.mWmService.modifyDisplayWindowInsets(mDisplayId, mInsetsState); + mWmService.modifyDisplayWindowInsets(mDisplayId, mInsetsState); } catch (RemoteException e) { } } @@ -315,7 +319,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged // an IME inset). For now, we assume that no non-floating IME will be <= this nav bar // frame height so any reported frame that is <= nav-bar frame height is assumed to // be floating. - return frame.height() <= mSystemWindows.mDisplayController.getDisplayLayout(mDisplayId) + return frame.height() <= mDisplayController.getDisplayLayout(mDisplayId) .navBarFrameHeight(); } @@ -331,7 +335,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged // pretend the ime has some size just below the screen. mImeFrame.set(newFrame); final int floatingInset = (int) ( - mSystemWindows.mDisplayController.getDisplayLayout(mDisplayId).density() + mDisplayController.getDisplayLayout(mDisplayId).density() * FLOATING_IME_BOTTOM_INSET); mImeFrame.bottom -= floatingInset; } else if (newFrame.height() != 0) { @@ -448,6 +452,47 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged setVisibleDirectly(true /* visible */); } } + + @VisibleForTesting + @BinderThread + public class DisplayWindowInsetsControllerImpl + extends IDisplayWindowInsetsController.Stub { + @Override + public void topFocusedWindowChanged(String packageName) throws RemoteException { + mMainExecutor.execute(() -> { + PerDisplay.this.topFocusedWindowChanged(packageName); + }); + } + + @Override + public void insetsChanged(InsetsState insetsState) throws RemoteException { + mMainExecutor.execute(() -> { + PerDisplay.this.insetsChanged(insetsState); + }); + } + + @Override + public void insetsControlChanged(InsetsState insetsState, + InsetsSourceControl[] activeControls) throws RemoteException { + mMainExecutor.execute(() -> { + PerDisplay.this.insetsControlChanged(insetsState, activeControls); + }); + } + + @Override + public void showInsets(int types, boolean fromIme) throws RemoteException { + mMainExecutor.execute(() -> { + PerDisplay.this.showInsets(types, fromIme); + }); + } + + @Override + public void hideInsets(int types, boolean fromIme) throws RemoteException { + mMainExecutor.execute(() -> { + PerDisplay.this.hideInsets(types, fromIme); + }); + } + } } void removeImeSurface() {