Loading libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java +10 −2 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ import com.android.wm.shell.pip.phone.PipAppOpsListener; import com.android.wm.shell.pip.phone.PipTouchHandler; import com.android.wm.shell.recents.RecentTasks; import com.android.wm.shell.recents.RecentTasksController; import com.android.wm.shell.sizecompatui.SizeCompatUI; import com.android.wm.shell.sizecompatui.SizeCompatUIController; import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.splitscreen.SplitScreenController; Loading Loading @@ -169,13 +170,20 @@ public abstract class WMShellBaseModule { return new ShellTaskOrganizer(mainExecutor, context, sizeCompatUI, recentTasksOptional); } @WMSingleton @Provides static SizeCompatUI provideSizeCompatUI(SizeCompatUIController sizeCompatUIController) { return sizeCompatUIController.asSizeCompatUI(); } @WMSingleton @Provides static SizeCompatUIController provideSizeCompatUIController(Context context, DisplayController displayController, DisplayInsetsController displayInsetsController, DisplayImeController imeController, SyncTransactionQueue syncQueue) { DisplayImeController imeController, SyncTransactionQueue syncQueue, @ShellMainThread ShellExecutor mainExecutor) { return new SizeCompatUIController(context, displayController, displayInsetsController, imeController, syncQueue); imeController, syncQueue, mainExecutor); } @WMSingleton Loading libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUI.java 0 → 100644 +32 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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.sizecompatui; import com.android.wm.shell.common.annotations.ExternalThread; /** * Interface to engage size compat UI. */ @ExternalThread public interface SizeCompatUI { /** * Called when the keyguard occluded state changes. Removes all size compat UIs if the * keyguard is now occluded. * @param occluded indicates if the keyguard is now occluded. */ void onKeyguardOccludedChanged(boolean occluded); } libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java +54 −6 Original line number Diff line number Diff line Loading @@ -35,13 +35,16 @@ import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.DisplayInsetsController.OnInsetsChangedListener; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.annotations.ExternalThread; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.function.Consumer; import java.util.function.Predicate; /** * Controls to show/update restart-activity buttons on Tasks based on whether the foreground Loading Loading @@ -78,26 +81,37 @@ public class SizeCompatUIController implements OnDisplaysChangedListener, private final DisplayInsetsController mDisplayInsetsController; private final DisplayImeController mImeController; private final SyncTransactionQueue mSyncQueue; private final ShellExecutor mMainExecutor; private final SizeCompatUIImpl mImpl = new SizeCompatUIImpl(); private SizeCompatUICallback mCallback; /** Only show once automatically in the process life. */ private boolean mHasShownHint; /** Indicates if the keyguard is currently occluded, in which case size compat UIs shouldn't * be shown. */ private boolean mKeyguardOccluded; public SizeCompatUIController(Context context, DisplayController displayController, DisplayInsetsController displayInsetsController, DisplayImeController imeController, SyncTransactionQueue syncQueue) { SyncTransactionQueue syncQueue, ShellExecutor mainExecutor) { mContext = context; mDisplayController = displayController; mDisplayInsetsController = displayInsetsController; mImeController = imeController; mSyncQueue = syncQueue; mMainExecutor = mainExecutor; mDisplayController.addDisplayWindowListener(this); mImeController.addPositionProcessor(this); } public SizeCompatUI asSizeCompatUI() { return mImpl; } /** Sets the callback for UI interactions. */ public void setSizeCompatUICallback(SizeCompatUICallback callback) { mCallback = callback; Loading @@ -106,6 +120,7 @@ public class SizeCompatUIController implements OnDisplaysChangedListener, /** * Called when the Task info changed. Creates and updates the size compat UI if there is an * activity in size compat, or removes the UI if there is no size compat activity. * * @param displayId display the task and activity are in. * @param taskId task the activity is in. * @param taskConfig task config to place the size compat UI with. Loading Loading @@ -180,7 +195,19 @@ public class SizeCompatUIController implements OnDisplaysChangedListener, } // Hide the size compat UIs when input method is showing. forAllLayoutsOnDisplay(displayId, layout -> layout.updateImeVisibility(isShowing)); forAllLayoutsOnDisplay(displayId, layout -> layout.updateVisibility(showOnDisplay(displayId))); } @VisibleForTesting void onKeyguardOccludedChanged(boolean occluded) { mKeyguardOccluded = occluded; // Hide the size compat UIs when keyguard is occluded. forAllLayouts(layout -> layout.updateVisibility(showOnDisplay(layout.getDisplayId()))); } private boolean showOnDisplay(int displayId) { return !mKeyguardOccluded && !isImeShowingOnDisplay(displayId); } private boolean isImeShowingOnDisplay(int displayId) { Loading @@ -198,7 +225,7 @@ public class SizeCompatUIController implements OnDisplaysChangedListener, final SizeCompatUILayout layout = createLayout(context, displayId, taskId, taskConfig, taskListener); mActiveLayouts.put(taskId, layout); layout.createSizeCompatButton(isImeShowingOnDisplay(displayId)); layout.createSizeCompatButton(showOnDisplay(displayId)); } @VisibleForTesting Loading @@ -218,8 +245,7 @@ public class SizeCompatUIController implements OnDisplaysChangedListener, if (layout == null) { return; } layout.updateSizeCompatInfo(taskConfig, taskListener, isImeShowingOnDisplay(layout.getDisplayId())); layout.updateSizeCompatInfo(taskConfig, taskListener, showOnDisplay(layout.getDisplayId())); } private void removeLayout(int taskId) { Loading Loading @@ -250,15 +276,37 @@ public class SizeCompatUIController implements OnDisplaysChangedListener, } private void forAllLayoutsOnDisplay(int displayId, Consumer<SizeCompatUILayout> callback) { forAllLayouts(layout -> layout.getDisplayId() == displayId, callback); } private void forAllLayouts(Consumer<SizeCompatUILayout> callback) { forAllLayouts(layout -> true, callback); } private void forAllLayouts(Predicate<SizeCompatUILayout> condition, Consumer<SizeCompatUILayout> callback) { for (int i = 0; i < mActiveLayouts.size(); i++) { final int taskId = mActiveLayouts.keyAt(i); final SizeCompatUILayout layout = mActiveLayouts.get(taskId); if (layout != null && layout.getDisplayId() == displayId) { if (layout != null && condition.test(layout)) { callback.accept(layout); } } } /** * The interface for calls from outside the Shell, within the host process. */ @ExternalThread private class SizeCompatUIImpl implements SizeCompatUI { @Override public void onKeyguardOccludedChanged(boolean occluded) { mMainExecutor.execute(() -> { SizeCompatUIController.this.onKeyguardOccludedChanged(occluded); }); } } /** An implementation of {@link OnInsetsChangedListener} for a given display id. */ private class PerDisplayOnInsetsChangedListener implements OnInsetsChangedListener { final int mDisplayId; Loading libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java +10 −10 Original line number Diff line number Diff line Loading @@ -103,9 +103,9 @@ class SizeCompatUILayout { } /** Creates the activity restart button window. */ void createSizeCompatButton(boolean isImeShowing) { if (isImeShowing || mButton != null) { // When ime is showing, wait until ime is dismiss to create UI. void createSizeCompatButton(boolean show) { if (!show || mButton != null) { // Wait until button should be visible. return; } mButton = mButtonWindowManager.createSizeCompatButton(); Loading Loading @@ -154,7 +154,7 @@ class SizeCompatUILayout { /** Called when size compat info changed. */ void updateSizeCompatInfo(Configuration taskConfig, ShellTaskOrganizer.TaskListener taskListener, boolean isImeShowing) { ShellTaskOrganizer.TaskListener taskListener, boolean show) { final Configuration prevTaskConfig = mTaskConfig; final ShellTaskOrganizer.TaskListener prevTaskListener = mTaskListener; mTaskConfig = taskConfig; Loading @@ -170,7 +170,7 @@ class SizeCompatUILayout { if (mButton == null || prevTaskListener != taskListener) { // TaskListener changed, recreate the button for new surface parent. release(); createSizeCompatButton(isImeShowing); createSizeCompatButton(show); return; } Loading Loading @@ -204,16 +204,16 @@ class SizeCompatUILayout { } } /** Called when IME visibility changed. */ void updateImeVisibility(boolean isImeShowing) { /** Called when the visibility of the UI should change. */ void updateVisibility(boolean show) { if (mButton == null) { // Button may not be created because ime is previous showing. createSizeCompatButton(isImeShowing); // Button may not have been created because it was hidden previously. createSizeCompatButton(show); return; } // Hide size compat UIs when IME is showing. final int newVisibility = isImeShowing ? View.GONE : View.VISIBLE; final int newVisibility = show ? View.VISIBLE : View.GONE; if (mButton.getVisibility() != newVisibility) { mButton.setVisibility(newVisibility); } Loading libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUIControllerTest.java +86 −10 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.content.Context; Loading @@ -43,6 +44,7 @@ import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.DisplayInsetsController.OnInsetsChangedListener; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import org.junit.Before; Loading Loading @@ -72,6 +74,7 @@ public class SizeCompatUIControllerTest extends ShellTestCase { private @Mock DisplayImeController mMockImeController; private @Mock ShellTaskOrganizer.TaskListener mMockTaskListener; private @Mock SyncTransactionQueue mMockSyncQueue; private @Mock ShellExecutor mMockExecutor; private @Mock SizeCompatUILayout mMockLayout; @Captor Loading @@ -85,7 +88,7 @@ public class SizeCompatUIControllerTest extends ShellTestCase { doReturn(DISPLAY_ID).when(mMockLayout).getDisplayId(); doReturn(TASK_ID).when(mMockLayout).getTaskId(); mController = new SizeCompatUIController(mContext, mMockDisplayController, mMockDisplayInsetsController, mMockImeController, mMockSyncQueue) { mMockDisplayInsetsController, mMockImeController, mMockSyncQueue, mMockExecutor) { @Override SizeCompatUILayout createLayout(Context context, int displayId, int taskId, Configuration taskConfig, ShellTaskOrganizer.TaskListener taskListener) { Loading @@ -106,19 +109,17 @@ public class SizeCompatUIControllerTest extends ShellTestCase { final Configuration taskConfig = new Configuration(); // Verify that the restart button is added with non-null size compat info. mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); verify(mController).createLayout(any(), eq(DISPLAY_ID), eq(TASK_ID), eq(taskConfig), eq(mMockTaskListener)); // Verify that the restart button is updated with non-null new size compat info. final Configuration newTaskConfig = new Configuration(); mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, newTaskConfig, mMockTaskListener); mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, newTaskConfig, mMockTaskListener); verify(mMockLayout).updateSizeCompatInfo(taskConfig, mMockTaskListener, false /* isImeShowing */); true /* show */); // Verify that the restart button is removed with null size compat info. mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, null, mMockTaskListener); Loading Loading @@ -196,15 +197,90 @@ public class SizeCompatUIControllerTest extends ShellTestCase { @Test public void testChangeButtonVisibilityOnImeShowHide() { final Configuration taskConfig = new Configuration(); mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); // Verify that the restart button is hidden after IME is showing. mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */); verify(mMockLayout).updateImeVisibility(true); verify(mMockLayout).updateVisibility(false); // Verify button remains hidden while IME is showing. mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); verify(mMockLayout).updateSizeCompatInfo(taskConfig, mMockTaskListener, false /* show */); // Verify button is shown after IME is hidden. mController.onImeVisibilityChanged(DISPLAY_ID, false /* isShowing */); verify(mMockLayout).updateImeVisibility(false); verify(mMockLayout).updateVisibility(true); } @Test public void testChangeButtonVisibilityOnKeyguardOccludedChanged() { final Configuration taskConfig = new Configuration(); mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); // Verify that the restart button is hidden after keyguard becomes occluded. mController.onKeyguardOccludedChanged(true); verify(mMockLayout).updateVisibility(false); // Verify button remains hidden while keyguard is occluded. mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); verify(mMockLayout).updateSizeCompatInfo(taskConfig, mMockTaskListener, false /* show */); // Verify button is shown after keyguard becomes not occluded. mController.onKeyguardOccludedChanged(false); verify(mMockLayout).updateVisibility(true); } @Test public void testButtonRemainsHiddenOnKeyguardOccludedFalseWhenImeIsShowing() { final Configuration taskConfig = new Configuration(); mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */); mController.onKeyguardOccludedChanged(true); verify(mMockLayout, times(2)).updateVisibility(false); clearInvocations(mMockLayout); // Verify button remains hidden after keyguard becomes not occluded since IME is showing. mController.onKeyguardOccludedChanged(false); verify(mMockLayout).updateVisibility(false); // Verify button is shown after IME is not showing. mController.onImeVisibilityChanged(DISPLAY_ID, false /* isShowing */); verify(mMockLayout).updateVisibility(true); } @Test public void testButtonRemainsHiddenOnImeHideWhenKeyguardIsOccluded() { final Configuration taskConfig = new Configuration(); mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */); mController.onKeyguardOccludedChanged(true); verify(mMockLayout, times(2)).updateVisibility(false); clearInvocations(mMockLayout); // Verify button remains hidden after IME is hidden since keyguard is occluded. mController.onImeVisibilityChanged(DISPLAY_ID, false /* isShowing */); verify(mMockLayout).updateVisibility(false); // Verify button is shown after keyguard becomes not occluded. mController.onKeyguardOccludedChanged(false); verify(mMockLayout).updateVisibility(true); } } Loading
libs/WindowManager/Shell/src/com/android/wm/shell/dagger/WMShellBaseModule.java +10 −2 Original line number Diff line number Diff line Loading @@ -74,6 +74,7 @@ import com.android.wm.shell.pip.phone.PipAppOpsListener; import com.android.wm.shell.pip.phone.PipTouchHandler; import com.android.wm.shell.recents.RecentTasks; import com.android.wm.shell.recents.RecentTasksController; import com.android.wm.shell.sizecompatui.SizeCompatUI; import com.android.wm.shell.sizecompatui.SizeCompatUIController; import com.android.wm.shell.splitscreen.SplitScreen; import com.android.wm.shell.splitscreen.SplitScreenController; Loading Loading @@ -169,13 +170,20 @@ public abstract class WMShellBaseModule { return new ShellTaskOrganizer(mainExecutor, context, sizeCompatUI, recentTasksOptional); } @WMSingleton @Provides static SizeCompatUI provideSizeCompatUI(SizeCompatUIController sizeCompatUIController) { return sizeCompatUIController.asSizeCompatUI(); } @WMSingleton @Provides static SizeCompatUIController provideSizeCompatUIController(Context context, DisplayController displayController, DisplayInsetsController displayInsetsController, DisplayImeController imeController, SyncTransactionQueue syncQueue) { DisplayImeController imeController, SyncTransactionQueue syncQueue, @ShellMainThread ShellExecutor mainExecutor) { return new SizeCompatUIController(context, displayController, displayInsetsController, imeController, syncQueue); imeController, syncQueue, mainExecutor); } @WMSingleton Loading
libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUI.java 0 → 100644 +32 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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.sizecompatui; import com.android.wm.shell.common.annotations.ExternalThread; /** * Interface to engage size compat UI. */ @ExternalThread public interface SizeCompatUI { /** * Called when the keyguard occluded state changes. Removes all size compat UIs if the * keyguard is now occluded. * @param occluded indicates if the keyguard is now occluded. */ void onKeyguardOccludedChanged(boolean occluded); }
libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUIController.java +54 −6 Original line number Diff line number Diff line Loading @@ -35,13 +35,16 @@ import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.DisplayInsetsController.OnInsetsChangedListener; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import com.android.wm.shell.common.annotations.ExternalThread; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.List; import java.util.Set; import java.util.function.Consumer; import java.util.function.Predicate; /** * Controls to show/update restart-activity buttons on Tasks based on whether the foreground Loading Loading @@ -78,26 +81,37 @@ public class SizeCompatUIController implements OnDisplaysChangedListener, private final DisplayInsetsController mDisplayInsetsController; private final DisplayImeController mImeController; private final SyncTransactionQueue mSyncQueue; private final ShellExecutor mMainExecutor; private final SizeCompatUIImpl mImpl = new SizeCompatUIImpl(); private SizeCompatUICallback mCallback; /** Only show once automatically in the process life. */ private boolean mHasShownHint; /** Indicates if the keyguard is currently occluded, in which case size compat UIs shouldn't * be shown. */ private boolean mKeyguardOccluded; public SizeCompatUIController(Context context, DisplayController displayController, DisplayInsetsController displayInsetsController, DisplayImeController imeController, SyncTransactionQueue syncQueue) { SyncTransactionQueue syncQueue, ShellExecutor mainExecutor) { mContext = context; mDisplayController = displayController; mDisplayInsetsController = displayInsetsController; mImeController = imeController; mSyncQueue = syncQueue; mMainExecutor = mainExecutor; mDisplayController.addDisplayWindowListener(this); mImeController.addPositionProcessor(this); } public SizeCompatUI asSizeCompatUI() { return mImpl; } /** Sets the callback for UI interactions. */ public void setSizeCompatUICallback(SizeCompatUICallback callback) { mCallback = callback; Loading @@ -106,6 +120,7 @@ public class SizeCompatUIController implements OnDisplaysChangedListener, /** * Called when the Task info changed. Creates and updates the size compat UI if there is an * activity in size compat, or removes the UI if there is no size compat activity. * * @param displayId display the task and activity are in. * @param taskId task the activity is in. * @param taskConfig task config to place the size compat UI with. Loading Loading @@ -180,7 +195,19 @@ public class SizeCompatUIController implements OnDisplaysChangedListener, } // Hide the size compat UIs when input method is showing. forAllLayoutsOnDisplay(displayId, layout -> layout.updateImeVisibility(isShowing)); forAllLayoutsOnDisplay(displayId, layout -> layout.updateVisibility(showOnDisplay(displayId))); } @VisibleForTesting void onKeyguardOccludedChanged(boolean occluded) { mKeyguardOccluded = occluded; // Hide the size compat UIs when keyguard is occluded. forAllLayouts(layout -> layout.updateVisibility(showOnDisplay(layout.getDisplayId()))); } private boolean showOnDisplay(int displayId) { return !mKeyguardOccluded && !isImeShowingOnDisplay(displayId); } private boolean isImeShowingOnDisplay(int displayId) { Loading @@ -198,7 +225,7 @@ public class SizeCompatUIController implements OnDisplaysChangedListener, final SizeCompatUILayout layout = createLayout(context, displayId, taskId, taskConfig, taskListener); mActiveLayouts.put(taskId, layout); layout.createSizeCompatButton(isImeShowingOnDisplay(displayId)); layout.createSizeCompatButton(showOnDisplay(displayId)); } @VisibleForTesting Loading @@ -218,8 +245,7 @@ public class SizeCompatUIController implements OnDisplaysChangedListener, if (layout == null) { return; } layout.updateSizeCompatInfo(taskConfig, taskListener, isImeShowingOnDisplay(layout.getDisplayId())); layout.updateSizeCompatInfo(taskConfig, taskListener, showOnDisplay(layout.getDisplayId())); } private void removeLayout(int taskId) { Loading Loading @@ -250,15 +276,37 @@ public class SizeCompatUIController implements OnDisplaysChangedListener, } private void forAllLayoutsOnDisplay(int displayId, Consumer<SizeCompatUILayout> callback) { forAllLayouts(layout -> layout.getDisplayId() == displayId, callback); } private void forAllLayouts(Consumer<SizeCompatUILayout> callback) { forAllLayouts(layout -> true, callback); } private void forAllLayouts(Predicate<SizeCompatUILayout> condition, Consumer<SizeCompatUILayout> callback) { for (int i = 0; i < mActiveLayouts.size(); i++) { final int taskId = mActiveLayouts.keyAt(i); final SizeCompatUILayout layout = mActiveLayouts.get(taskId); if (layout != null && layout.getDisplayId() == displayId) { if (layout != null && condition.test(layout)) { callback.accept(layout); } } } /** * The interface for calls from outside the Shell, within the host process. */ @ExternalThread private class SizeCompatUIImpl implements SizeCompatUI { @Override public void onKeyguardOccludedChanged(boolean occluded) { mMainExecutor.execute(() -> { SizeCompatUIController.this.onKeyguardOccludedChanged(occluded); }); } } /** An implementation of {@link OnInsetsChangedListener} for a given display id. */ private class PerDisplayOnInsetsChangedListener implements OnInsetsChangedListener { final int mDisplayId; Loading
libs/WindowManager/Shell/src/com/android/wm/shell/sizecompatui/SizeCompatUILayout.java +10 −10 Original line number Diff line number Diff line Loading @@ -103,9 +103,9 @@ class SizeCompatUILayout { } /** Creates the activity restart button window. */ void createSizeCompatButton(boolean isImeShowing) { if (isImeShowing || mButton != null) { // When ime is showing, wait until ime is dismiss to create UI. void createSizeCompatButton(boolean show) { if (!show || mButton != null) { // Wait until button should be visible. return; } mButton = mButtonWindowManager.createSizeCompatButton(); Loading Loading @@ -154,7 +154,7 @@ class SizeCompatUILayout { /** Called when size compat info changed. */ void updateSizeCompatInfo(Configuration taskConfig, ShellTaskOrganizer.TaskListener taskListener, boolean isImeShowing) { ShellTaskOrganizer.TaskListener taskListener, boolean show) { final Configuration prevTaskConfig = mTaskConfig; final ShellTaskOrganizer.TaskListener prevTaskListener = mTaskListener; mTaskConfig = taskConfig; Loading @@ -170,7 +170,7 @@ class SizeCompatUILayout { if (mButton == null || prevTaskListener != taskListener) { // TaskListener changed, recreate the button for new surface parent. release(); createSizeCompatButton(isImeShowing); createSizeCompatButton(show); return; } Loading Loading @@ -204,16 +204,16 @@ class SizeCompatUILayout { } } /** Called when IME visibility changed. */ void updateImeVisibility(boolean isImeShowing) { /** Called when the visibility of the UI should change. */ void updateVisibility(boolean show) { if (mButton == null) { // Button may not be created because ime is previous showing. createSizeCompatButton(isImeShowing); // Button may not have been created because it was hidden previously. createSizeCompatButton(show); return; } // Hide size compat UIs when IME is showing. final int newVisibility = isImeShowing ? View.GONE : View.VISIBLE; final int newVisibility = show ? View.VISIBLE : View.GONE; if (mButton.getVisibility() != newVisibility) { mButton.setVisibility(newVisibility); } Loading
libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/sizecompatui/SizeCompatUIControllerTest.java +86 −10 Original line number Diff line number Diff line Loading @@ -26,6 +26,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; import android.content.Context; Loading @@ -43,6 +44,7 @@ import com.android.wm.shell.common.DisplayImeController; import com.android.wm.shell.common.DisplayInsetsController; import com.android.wm.shell.common.DisplayInsetsController.OnInsetsChangedListener; import com.android.wm.shell.common.DisplayLayout; import com.android.wm.shell.common.ShellExecutor; import com.android.wm.shell.common.SyncTransactionQueue; import org.junit.Before; Loading Loading @@ -72,6 +74,7 @@ public class SizeCompatUIControllerTest extends ShellTestCase { private @Mock DisplayImeController mMockImeController; private @Mock ShellTaskOrganizer.TaskListener mMockTaskListener; private @Mock SyncTransactionQueue mMockSyncQueue; private @Mock ShellExecutor mMockExecutor; private @Mock SizeCompatUILayout mMockLayout; @Captor Loading @@ -85,7 +88,7 @@ public class SizeCompatUIControllerTest extends ShellTestCase { doReturn(DISPLAY_ID).when(mMockLayout).getDisplayId(); doReturn(TASK_ID).when(mMockLayout).getTaskId(); mController = new SizeCompatUIController(mContext, mMockDisplayController, mMockDisplayInsetsController, mMockImeController, mMockSyncQueue) { mMockDisplayInsetsController, mMockImeController, mMockSyncQueue, mMockExecutor) { @Override SizeCompatUILayout createLayout(Context context, int displayId, int taskId, Configuration taskConfig, ShellTaskOrganizer.TaskListener taskListener) { Loading @@ -106,19 +109,17 @@ public class SizeCompatUIControllerTest extends ShellTestCase { final Configuration taskConfig = new Configuration(); // Verify that the restart button is added with non-null size compat info. mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); verify(mController).createLayout(any(), eq(DISPLAY_ID), eq(TASK_ID), eq(taskConfig), eq(mMockTaskListener)); // Verify that the restart button is updated with non-null new size compat info. final Configuration newTaskConfig = new Configuration(); mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, newTaskConfig, mMockTaskListener); mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, newTaskConfig, mMockTaskListener); verify(mMockLayout).updateSizeCompatInfo(taskConfig, mMockTaskListener, false /* isImeShowing */); true /* show */); // Verify that the restart button is removed with null size compat info. mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, null, mMockTaskListener); Loading Loading @@ -196,15 +197,90 @@ public class SizeCompatUIControllerTest extends ShellTestCase { @Test public void testChangeButtonVisibilityOnImeShowHide() { final Configuration taskConfig = new Configuration(); mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); // Verify that the restart button is hidden after IME is showing. mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */); verify(mMockLayout).updateImeVisibility(true); verify(mMockLayout).updateVisibility(false); // Verify button remains hidden while IME is showing. mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); verify(mMockLayout).updateSizeCompatInfo(taskConfig, mMockTaskListener, false /* show */); // Verify button is shown after IME is hidden. mController.onImeVisibilityChanged(DISPLAY_ID, false /* isShowing */); verify(mMockLayout).updateImeVisibility(false); verify(mMockLayout).updateVisibility(true); } @Test public void testChangeButtonVisibilityOnKeyguardOccludedChanged() { final Configuration taskConfig = new Configuration(); mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); // Verify that the restart button is hidden after keyguard becomes occluded. mController.onKeyguardOccludedChanged(true); verify(mMockLayout).updateVisibility(false); // Verify button remains hidden while keyguard is occluded. mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); verify(mMockLayout).updateSizeCompatInfo(taskConfig, mMockTaskListener, false /* show */); // Verify button is shown after keyguard becomes not occluded. mController.onKeyguardOccludedChanged(false); verify(mMockLayout).updateVisibility(true); } @Test public void testButtonRemainsHiddenOnKeyguardOccludedFalseWhenImeIsShowing() { final Configuration taskConfig = new Configuration(); mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */); mController.onKeyguardOccludedChanged(true); verify(mMockLayout, times(2)).updateVisibility(false); clearInvocations(mMockLayout); // Verify button remains hidden after keyguard becomes not occluded since IME is showing. mController.onKeyguardOccludedChanged(false); verify(mMockLayout).updateVisibility(false); // Verify button is shown after IME is not showing. mController.onImeVisibilityChanged(DISPLAY_ID, false /* isShowing */); verify(mMockLayout).updateVisibility(true); } @Test public void testButtonRemainsHiddenOnImeHideWhenKeyguardIsOccluded() { final Configuration taskConfig = new Configuration(); mController.onSizeCompatInfoChanged(DISPLAY_ID, TASK_ID, taskConfig, mMockTaskListener); mController.onImeVisibilityChanged(DISPLAY_ID, true /* isShowing */); mController.onKeyguardOccludedChanged(true); verify(mMockLayout, times(2)).updateVisibility(false); clearInvocations(mMockLayout); // Verify button remains hidden after IME is hidden since keyguard is occluded. mController.onImeVisibilityChanged(DISPLAY_ID, false /* isShowing */); verify(mMockLayout).updateVisibility(false); // Verify button is shown after keyguard becomes not occluded. mController.onKeyguardOccludedChanged(false); verify(mMockLayout).updateVisibility(true); } }