Loading libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java +58 −11 Original line number Original line Diff line number Diff line Loading @@ -43,6 +43,7 @@ import android.view.animation.PathInterpolator; import com.android.internal.view.IInputMethodManager; import com.android.internal.view.IInputMethodManager; import java.util.ArrayList; import java.util.ArrayList; import java.util.concurrent.Executor; /** /** * Manages IME control at the display-level. This occurs when IME comes up in multi-window mode. * Manages IME control at the display-level. This occurs when IME comes up in multi-window mode. Loading @@ -62,15 +63,21 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged private static final int FLOATING_IME_BOTTOM_INSET = -80; private static final int FLOATING_IME_BOTTOM_INSET = -80; protected final IWindowManager mWmService; protected final IWindowManager mWmService; protected final Handler mHandler; protected final Executor mExecutor; private final TransactionPool mTransactionPool; private final TransactionPool mTransactionPool; private final DisplayController mDisplayController; private final DisplayController mDisplayController; private final SparseArray<PerDisplay> mImePerDisplay = new SparseArray<>(); private final SparseArray<PerDisplay> mImePerDisplay = new SparseArray<>(); private final ArrayList<ImePositionProcessor> mPositionProcessors = new ArrayList<>(); private final ArrayList<ImePositionProcessor> mPositionProcessors = new ArrayList<>(); @Deprecated public DisplayImeController(IWindowManager wmService, DisplayController displayController, public DisplayImeController(IWindowManager wmService, DisplayController displayController, Handler mainHandler, TransactionPool transactionPool) { Handler mainHandler, TransactionPool transactionPool) { mHandler = mainHandler; this(wmService, displayController, mainHandler::post, transactionPool); } public DisplayImeController(IWindowManager wmService, DisplayController displayController, Executor mainExecutor, TransactionPool transactionPool) { mExecutor = mainExecutor; mWmService = wmService; mWmService = wmService; mTransactionPool = transactionPool; mTransactionPool = transactionPool; mDisplayController = displayController; mDisplayController = displayController; Loading Loading @@ -197,7 +204,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged @Override @Override public void insetsChanged(InsetsState insetsState) { public void insetsChanged(InsetsState insetsState) { mHandler.post(() -> { mExecutor.execute(() -> { if (mInsetsState.equals(insetsState)) { if (mInsetsState.equals(insetsState)) { return; return; } } Loading @@ -224,29 +231,53 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged continue; continue; } } if (activeControl.getType() == InsetsState.ITYPE_IME) { if (activeControl.getType() == InsetsState.ITYPE_IME) { mHandler.post(() -> { mExecutor.execute(() -> { final Point lastSurfacePosition = mImeSourceControl != null final Point lastSurfacePosition = mImeSourceControl != null ? mImeSourceControl.getSurfacePosition() : null; ? mImeSourceControl.getSurfacePosition() : null; final boolean positionChanged = !activeControl.getSurfacePosition().equals(lastSurfacePosition); final boolean leashChanged = !haveSameLeash(mImeSourceControl, activeControl); mImeSourceControl = activeControl; mImeSourceControl = activeControl; if (!activeControl.getSurfacePosition().equals(lastSurfacePosition) if (mAnimation != null) { && mAnimation != null) { if (positionChanged) { startAnimation(mImeShowing, true /* forceRestart */); startAnimation(mImeShowing, true /* forceRestart */); } else if (!mImeShowing) { } } else { if (leashChanged) { applyVisibilityToLeash(); } if (!mImeShowing) { removeImeSurface(); removeImeSurface(); } } } }); }); } } } } } } } } private void applyVisibilityToLeash() { SurfaceControl leash = mImeSourceControl.getLeash(); if (leash != null) { SurfaceControl.Transaction t = mTransactionPool.acquire(); if (mImeShowing) { t.show(leash); } else { t.hide(leash); } t.apply(); mTransactionPool.release(t); } } @Override @Override public void showInsets(int types, boolean fromIme) { public void showInsets(int types, boolean fromIme) { if ((types & WindowInsets.Type.ime()) == 0) { if ((types & WindowInsets.Type.ime()) == 0) { return; return; } } if (DEBUG) Slog.d(TAG, "Got showInsets for ime"); if (DEBUG) Slog.d(TAG, "Got showInsets for ime"); mHandler.post(() -> startAnimation(true /* show */, false /* forceRestart */)); mExecutor.execute(() -> startAnimation(true /* show */, false /* forceRestart */)); } } @Override @Override Loading @@ -255,7 +286,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged return; return; } } if (DEBUG) Slog.d(TAG, "Got hideInsets for ime"); if (DEBUG) Slog.d(TAG, "Got hideInsets for ime"); mHandler.post(() -> startAnimation(false /* show */, false /* forceRestart */)); mExecutor.execute(() -> startAnimation(false /* show */, false /* forceRestart */)); } } @Override @Override Loading Loading @@ -495,4 +526,20 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged return IInputMethodManager.Stub.asInterface( return IInputMethodManager.Stub.asInterface( ServiceManager.getService(Context.INPUT_METHOD_SERVICE)); ServiceManager.getService(Context.INPUT_METHOD_SERVICE)); } } private static boolean haveSameLeash(InsetsSourceControl a, InsetsSourceControl b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (a.getLeash() == b.getLeash()) { return true; } if (a.getLeash() == null || b.getLeash() == null) { return false; } return a.getLeash().isSameSurface(b.getLeash()); } } } libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java 0 → 100644 +86 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.common; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.InsetsState.ITYPE_IME; import static android.view.Surface.ROTATION_0; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import android.graphics.Point; import android.view.InsetsSourceControl; import android.view.InsetsState; import android.view.SurfaceControl; import androidx.test.filters.SmallTest; import com.android.internal.view.IInputMethodManager; import org.junit.Before; import org.junit.Test; @SmallTest public class DisplayImeControllerTest { private SurfaceControl.Transaction mT; private DisplayImeController.PerDisplay mPerDisplay; private IInputMethodManager mMock; @Before public void setUp() throws Exception { mT = mock(SurfaceControl.Transaction.class); mMock = mock(IInputMethodManager.class); mPerDisplay = new DisplayImeController(null, null, Runnable::run, new TransactionPool() { @Override public SurfaceControl.Transaction acquire() { return mT; } @Override public void release(SurfaceControl.Transaction t) { } }) { @Override public IInputMethodManager getImms() { return mMock; } }.new PerDisplay(DEFAULT_DISPLAY, ROTATION_0); } @Test public void reappliesVisibilityToChangedLeash() { verifyZeroInteractions(mT); mPerDisplay.mImeShowing = false; mPerDisplay.insetsControlChanged(new InsetsState(), new InsetsSourceControl[] { new InsetsSourceControl(ITYPE_IME, mock(SurfaceControl.class), new Point(0, 0)) }); verify(mT).hide(any()); mPerDisplay.mImeShowing = true; mPerDisplay.insetsControlChanged(new InsetsState(), new InsetsSourceControl[] { new InsetsSourceControl(ITYPE_IME, mock(SurfaceControl.class), new Point(0, 0)) }); verify(mT).show(any()); } } packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java +3 −1 Original line number Original line Diff line number Diff line Loading @@ -50,6 +50,7 @@ public class DisplaySystemBarsController extends DisplayImeController { private final Context mContext; private final Context mContext; private final DisplayController mDisplayController; private final DisplayController mDisplayController; private final Handler mHandler; private SparseArray<PerDisplay> mPerDisplaySparseArray; private SparseArray<PerDisplay> mPerDisplaySparseArray; public DisplaySystemBarsController( public DisplaySystemBarsController( Loading @@ -58,9 +59,10 @@ public class DisplaySystemBarsController extends DisplayImeController { DisplayController displayController, DisplayController displayController, @Main Handler mainHandler, @Main Handler mainHandler, TransactionPool transactionPool) { TransactionPool transactionPool) { super(wmService, displayController, mainHandler, transactionPool); super(wmService, displayController, (r) -> mainHandler.post(r), transactionPool); mContext = context; mContext = context; mDisplayController = displayController; mDisplayController = displayController; mHandler = mainHandler; } } @Override @Override Loading packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java +5 −2 Original line number Original line Diff line number Diff line Loading @@ -32,6 +32,8 @@ import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.splitscreen.SplitScreenController; import java.util.concurrent.Executor; import dagger.Module; import dagger.Module; import dagger.Provides; import dagger.Provides; Loading @@ -45,9 +47,10 @@ public class TvWMShellModule { @SysUISingleton @SysUISingleton @Provides @Provides static DisplayImeController provideDisplayImeController(IWindowManager wmService, static DisplayImeController provideDisplayImeController(IWindowManager wmService, DisplayController displayController, @Main Handler mainHandler, DisplayController displayController, @Main Executor mainExecutor, TransactionPool transactionPool) { TransactionPool transactionPool) { return new DisplayImeController(wmService, displayController, mainHandler, transactionPool); return new DisplayImeController(wmService, displayController, mainExecutor, transactionPool); } } static SplitScreen provideSplitScreen(Context context, static SplitScreen provideSplitScreen(Context context, Loading packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java +4 −2 Original line number Original line Diff line number Diff line Loading @@ -45,6 +45,7 @@ import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.splitscreen.SplitScreenController; import java.util.Optional; import java.util.Optional; import java.util.concurrent.Executor; import dagger.Module; import dagger.Module; import dagger.Provides; import dagger.Provides; Loading @@ -59,9 +60,10 @@ public class WMShellModule { @SysUISingleton @SysUISingleton @Provides @Provides static DisplayImeController provideDisplayImeController(IWindowManager wmService, static DisplayImeController provideDisplayImeController(IWindowManager wmService, DisplayController displayController, @Main Handler mainHandler, DisplayController displayController, @Main Executor mainExecutor, TransactionPool transactionPool) { TransactionPool transactionPool) { return new DisplayImeController(wmService, displayController, mainHandler, transactionPool); return new DisplayImeController(wmService, displayController, mainExecutor, transactionPool); } } @SysUISingleton @SysUISingleton Loading Loading
libs/WindowManager/Shell/src/com/android/wm/shell/common/DisplayImeController.java +58 −11 Original line number Original line Diff line number Diff line Loading @@ -43,6 +43,7 @@ import android.view.animation.PathInterpolator; import com.android.internal.view.IInputMethodManager; import com.android.internal.view.IInputMethodManager; import java.util.ArrayList; import java.util.ArrayList; import java.util.concurrent.Executor; /** /** * Manages IME control at the display-level. This occurs when IME comes up in multi-window mode. * Manages IME control at the display-level. This occurs when IME comes up in multi-window mode. Loading @@ -62,15 +63,21 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged private static final int FLOATING_IME_BOTTOM_INSET = -80; private static final int FLOATING_IME_BOTTOM_INSET = -80; protected final IWindowManager mWmService; protected final IWindowManager mWmService; protected final Handler mHandler; protected final Executor mExecutor; private final TransactionPool mTransactionPool; private final TransactionPool mTransactionPool; private final DisplayController mDisplayController; private final DisplayController mDisplayController; private final SparseArray<PerDisplay> mImePerDisplay = new SparseArray<>(); private final SparseArray<PerDisplay> mImePerDisplay = new SparseArray<>(); private final ArrayList<ImePositionProcessor> mPositionProcessors = new ArrayList<>(); private final ArrayList<ImePositionProcessor> mPositionProcessors = new ArrayList<>(); @Deprecated public DisplayImeController(IWindowManager wmService, DisplayController displayController, public DisplayImeController(IWindowManager wmService, DisplayController displayController, Handler mainHandler, TransactionPool transactionPool) { Handler mainHandler, TransactionPool transactionPool) { mHandler = mainHandler; this(wmService, displayController, mainHandler::post, transactionPool); } public DisplayImeController(IWindowManager wmService, DisplayController displayController, Executor mainExecutor, TransactionPool transactionPool) { mExecutor = mainExecutor; mWmService = wmService; mWmService = wmService; mTransactionPool = transactionPool; mTransactionPool = transactionPool; mDisplayController = displayController; mDisplayController = displayController; Loading Loading @@ -197,7 +204,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged @Override @Override public void insetsChanged(InsetsState insetsState) { public void insetsChanged(InsetsState insetsState) { mHandler.post(() -> { mExecutor.execute(() -> { if (mInsetsState.equals(insetsState)) { if (mInsetsState.equals(insetsState)) { return; return; } } Loading @@ -224,29 +231,53 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged continue; continue; } } if (activeControl.getType() == InsetsState.ITYPE_IME) { if (activeControl.getType() == InsetsState.ITYPE_IME) { mHandler.post(() -> { mExecutor.execute(() -> { final Point lastSurfacePosition = mImeSourceControl != null final Point lastSurfacePosition = mImeSourceControl != null ? mImeSourceControl.getSurfacePosition() : null; ? mImeSourceControl.getSurfacePosition() : null; final boolean positionChanged = !activeControl.getSurfacePosition().equals(lastSurfacePosition); final boolean leashChanged = !haveSameLeash(mImeSourceControl, activeControl); mImeSourceControl = activeControl; mImeSourceControl = activeControl; if (!activeControl.getSurfacePosition().equals(lastSurfacePosition) if (mAnimation != null) { && mAnimation != null) { if (positionChanged) { startAnimation(mImeShowing, true /* forceRestart */); startAnimation(mImeShowing, true /* forceRestart */); } else if (!mImeShowing) { } } else { if (leashChanged) { applyVisibilityToLeash(); } if (!mImeShowing) { removeImeSurface(); removeImeSurface(); } } } }); }); } } } } } } } } private void applyVisibilityToLeash() { SurfaceControl leash = mImeSourceControl.getLeash(); if (leash != null) { SurfaceControl.Transaction t = mTransactionPool.acquire(); if (mImeShowing) { t.show(leash); } else { t.hide(leash); } t.apply(); mTransactionPool.release(t); } } @Override @Override public void showInsets(int types, boolean fromIme) { public void showInsets(int types, boolean fromIme) { if ((types & WindowInsets.Type.ime()) == 0) { if ((types & WindowInsets.Type.ime()) == 0) { return; return; } } if (DEBUG) Slog.d(TAG, "Got showInsets for ime"); if (DEBUG) Slog.d(TAG, "Got showInsets for ime"); mHandler.post(() -> startAnimation(true /* show */, false /* forceRestart */)); mExecutor.execute(() -> startAnimation(true /* show */, false /* forceRestart */)); } } @Override @Override Loading @@ -255,7 +286,7 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged return; return; } } if (DEBUG) Slog.d(TAG, "Got hideInsets for ime"); if (DEBUG) Slog.d(TAG, "Got hideInsets for ime"); mHandler.post(() -> startAnimation(false /* show */, false /* forceRestart */)); mExecutor.execute(() -> startAnimation(false /* show */, false /* forceRestart */)); } } @Override @Override Loading Loading @@ -495,4 +526,20 @@ public class DisplayImeController implements DisplayController.OnDisplaysChanged return IInputMethodManager.Stub.asInterface( return IInputMethodManager.Stub.asInterface( ServiceManager.getService(Context.INPUT_METHOD_SERVICE)); ServiceManager.getService(Context.INPUT_METHOD_SERVICE)); } } private static boolean haveSameLeash(InsetsSourceControl a, InsetsSourceControl b) { if (a == b) { return true; } if (a == null || b == null) { return false; } if (a.getLeash() == b.getLeash()) { return true; } if (a.getLeash() == null || b.getLeash() == null) { return false; } return a.getLeash().isSameSurface(b.getLeash()); } } }
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/common/DisplayImeControllerTest.java 0 → 100644 +86 −0 Original line number Original line Diff line number Diff line /* * Copyright (C) 2020 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.wm.shell.common; import static android.view.Display.DEFAULT_DISPLAY; import static android.view.InsetsState.ITYPE_IME; import static android.view.Surface.ROTATION_0; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.verifyZeroInteractions; import android.graphics.Point; import android.view.InsetsSourceControl; import android.view.InsetsState; import android.view.SurfaceControl; import androidx.test.filters.SmallTest; import com.android.internal.view.IInputMethodManager; import org.junit.Before; import org.junit.Test; @SmallTest public class DisplayImeControllerTest { private SurfaceControl.Transaction mT; private DisplayImeController.PerDisplay mPerDisplay; private IInputMethodManager mMock; @Before public void setUp() throws Exception { mT = mock(SurfaceControl.Transaction.class); mMock = mock(IInputMethodManager.class); mPerDisplay = new DisplayImeController(null, null, Runnable::run, new TransactionPool() { @Override public SurfaceControl.Transaction acquire() { return mT; } @Override public void release(SurfaceControl.Transaction t) { } }) { @Override public IInputMethodManager getImms() { return mMock; } }.new PerDisplay(DEFAULT_DISPLAY, ROTATION_0); } @Test public void reappliesVisibilityToChangedLeash() { verifyZeroInteractions(mT); mPerDisplay.mImeShowing = false; mPerDisplay.insetsControlChanged(new InsetsState(), new InsetsSourceControl[] { new InsetsSourceControl(ITYPE_IME, mock(SurfaceControl.class), new Point(0, 0)) }); verify(mT).hide(any()); mPerDisplay.mImeShowing = true; mPerDisplay.insetsControlChanged(new InsetsState(), new InsetsSourceControl[] { new InsetsSourceControl(ITYPE_IME, mock(SurfaceControl.class), new Point(0, 0)) }); verify(mT).show(any()); } }
packages/CarSystemUI/src/com/android/systemui/wm/DisplaySystemBarsController.java +3 −1 Original line number Original line Diff line number Diff line Loading @@ -50,6 +50,7 @@ public class DisplaySystemBarsController extends DisplayImeController { private final Context mContext; private final Context mContext; private final DisplayController mDisplayController; private final DisplayController mDisplayController; private final Handler mHandler; private SparseArray<PerDisplay> mPerDisplaySparseArray; private SparseArray<PerDisplay> mPerDisplaySparseArray; public DisplaySystemBarsController( public DisplaySystemBarsController( Loading @@ -58,9 +59,10 @@ public class DisplaySystemBarsController extends DisplayImeController { DisplayController displayController, DisplayController displayController, @Main Handler mainHandler, @Main Handler mainHandler, TransactionPool transactionPool) { TransactionPool transactionPool) { super(wmService, displayController, mainHandler, transactionPool); super(wmService, displayController, (r) -> mainHandler.post(r), transactionPool); mContext = context; mContext = context; mDisplayController = displayController; mDisplayController = displayController; mHandler = mainHandler; } } @Override @Override Loading
packages/SystemUI/src/com/android/systemui/wmshell/TvWMShellModule.java +5 −2 Original line number Original line Diff line number Diff line Loading @@ -32,6 +32,8 @@ import com.android.wm.shell.common.TransactionPool; import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.splitscreen.SplitScreenController; import java.util.concurrent.Executor; import dagger.Module; import dagger.Module; import dagger.Provides; import dagger.Provides; Loading @@ -45,9 +47,10 @@ public class TvWMShellModule { @SysUISingleton @SysUISingleton @Provides @Provides static DisplayImeController provideDisplayImeController(IWindowManager wmService, static DisplayImeController provideDisplayImeController(IWindowManager wmService, DisplayController displayController, @Main Handler mainHandler, DisplayController displayController, @Main Executor mainExecutor, TransactionPool transactionPool) { TransactionPool transactionPool) { return new DisplayImeController(wmService, displayController, mainHandler, transactionPool); return new DisplayImeController(wmService, displayController, mainExecutor, transactionPool); } } static SplitScreen provideSplitScreen(Context context, static SplitScreen provideSplitScreen(Context context, Loading
packages/SystemUI/src/com/android/systemui/wmshell/WMShellModule.java +4 −2 Original line number Original line Diff line number Diff line Loading @@ -45,6 +45,7 @@ import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.splitscreen.SplitScreenController; import com.android.wm.shell.splitscreen.SplitScreenController; import java.util.Optional; import java.util.Optional; import java.util.concurrent.Executor; import dagger.Module; import dagger.Module; import dagger.Provides; import dagger.Provides; Loading @@ -59,9 +60,10 @@ public class WMShellModule { @SysUISingleton @SysUISingleton @Provides @Provides static DisplayImeController provideDisplayImeController(IWindowManager wmService, static DisplayImeController provideDisplayImeController(IWindowManager wmService, DisplayController displayController, @Main Handler mainHandler, DisplayController displayController, @Main Executor mainExecutor, TransactionPool transactionPool) { TransactionPool transactionPool) { return new DisplayImeController(wmService, displayController, mainHandler, transactionPool); return new DisplayImeController(wmService, displayController, mainExecutor, transactionPool); } } @SysUISingleton @SysUISingleton Loading