Remove all size compat UIs when the keyguard becomes occluded

This is needed because when a non resizable activity is launched over the lockscreen and a size compat restart button is displayed (after fold/unfold), clicking on it results in undefined behavior that seems broken. The solution to hide the restart button in such cases was a UX decision.

Fix: 202712269
Test: atest WMShellUnitTests:SizeCompatUILayoutTest
Test: atest SystemUITests:WMShellTest
Change-Id: Iced3948e0d7a37feb2f3422a7f25a22aab20a888
This commit is contained in:
tomnatan
2021-11-04 15:41:59 +00:00
committed by Tom Natan
parent cdb38ec55d
commit 6ed662a9db
11 changed files with 252 additions and 55 deletions

View File

@@ -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;
@@ -151,13 +152,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

View File

@@ -0,0 +1,32 @@
/*
* 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);
}

View File

@@ -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
@@ -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;
@@ -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.
@@ -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) {
@@ -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
@@ -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) {
@@ -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;

View File

@@ -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();
@@ -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;
@@ -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;
}
@@ -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);
}

View File

@@ -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;
@@ -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;
@@ -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
@@ -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) {
@@ -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);
@@ -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);
}
}

View File

@@ -96,8 +96,8 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
@Test
public void testCreateSizeCompatButton() {
// Not create button if IME is showing.
mLayout.createSizeCompatButton(true /* isImeShowing */);
// Not create button if show is false.
mLayout.createSizeCompatButton(false /* show */);
verify(mLayout.mButtonWindowManager, never()).createSizeCompatButton();
assertNull(mLayout.mButton);
@@ -106,7 +106,7 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
// Not create hint popup.
mLayout.mShouldShowHint = false;
mLayout.createSizeCompatButton(false /* isImeShowing */);
mLayout.createSizeCompatButton(true /* show */);
verify(mLayout.mButtonWindowManager).createSizeCompatButton();
assertNotNull(mLayout.mButton);
@@ -116,7 +116,7 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
// Create hint popup.
mLayout.release();
mLayout.mShouldShowHint = true;
mLayout.createSizeCompatButton(false /* isImeShowing */);
mLayout.createSizeCompatButton(true /* show */);
verify(mLayout.mButtonWindowManager, times(2)).createSizeCompatButton();
assertNotNull(mLayout.mButton);
@@ -128,7 +128,7 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
@Test
public void testRelease() {
mLayout.createSizeCompatButton(false /* isImeShowing */);
mLayout.createSizeCompatButton(true /* show */);
final SizeCompatUIWindowManager hintWindowManager = mLayout.mHintWindowManager;
mLayout.release();
@@ -142,12 +142,11 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
@Test
public void testUpdateSizeCompatInfo() {
mLayout.createSizeCompatButton(false /* isImeShowing */);
mLayout.createSizeCompatButton(true /* show */);
// No diff
clearInvocations(mLayout);
mLayout.updateSizeCompatInfo(mTaskConfig, mTaskListener,
false /* isImeShowing */);
mLayout.updateSizeCompatInfo(mTaskConfig, mTaskListener, true /* show */);
verify(mLayout, never()).updateButtonSurfacePosition();
verify(mLayout, never()).release();
@@ -158,7 +157,7 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
final ShellTaskOrganizer.TaskListener newTaskListener = mock(
ShellTaskOrganizer.TaskListener.class);
mLayout.updateSizeCompatInfo(mTaskConfig, newTaskListener,
false /* isImeShowing */);
true /* show */);
verify(mLayout).release();
verify(mLayout).createSizeCompatButton(anyBoolean());
@@ -168,7 +167,7 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
final Configuration newTaskConfiguration = new Configuration();
newTaskConfiguration.windowConfiguration.setBounds(new Rect(0, 1000, 0, 2000));
mLayout.updateSizeCompatInfo(newTaskConfiguration, newTaskListener,
false /* isImeShowing */);
true /* show */);
verify(mLayout).updateButtonSurfacePosition();
verify(mLayout).updateHintSurfacePosition();
@@ -220,24 +219,24 @@ public class SizeCompatUILayoutTest extends ShellTestCase {
}
@Test
public void testUpdateImeVisibility() {
public void testUpdateVisibility() {
// Create button if it is not created.
mLayout.mButton = null;
mLayout.updateImeVisibility(false /* isImeShowing */);
mLayout.updateVisibility(true /* show */);
verify(mLayout).createSizeCompatButton(false /* isImeShowing */);
verify(mLayout).createSizeCompatButton(true /* show */);
// Hide button if ime is shown.
// Hide button.
clearInvocations(mLayout);
doReturn(View.VISIBLE).when(mButton).getVisibility();
mLayout.updateImeVisibility(true /* isImeShowing */);
mLayout.updateVisibility(false /* show */);
verify(mLayout, never()).createSizeCompatButton(anyBoolean());
verify(mButton).setVisibility(View.GONE);
// Show button if ime is not shown.
// Show button.
doReturn(View.GONE).when(mButton).getVisibility();
mLayout.updateImeVisibility(false /* isImeShowing */);
mLayout.updateVisibility(true /* show */);
verify(mLayout, never()).createSizeCompatButton(anyBoolean());
verify(mButton).setVisibility(View.VISIBLE);

View File

@@ -31,8 +31,6 @@ import com.android.systemui.dagger.WMComponent;
import com.android.systemui.navigationbar.gestural.BackGestureTfClassifierProvider;
import com.android.systemui.screenshot.ScreenshotNotificationSmartActionsProvider;
import com.android.wm.shell.transition.ShellTransitions;
import com.android.wm.shell.transition.Transitions;
import com.android.wm.shell.recents.RecentTasks;
import java.util.Optional;
import java.util.concurrent.ExecutionException;
@@ -122,7 +120,8 @@ public class SystemUIFactory {
.setStartingSurface(mWMComponent.getStartingSurface())
.setDisplayAreaHelper(mWMComponent.getDisplayAreaHelper())
.setTaskSurfaceHelper(mWMComponent.getTaskSurfaceHelper())
.setRecentTasks(mWMComponent.getRecentTasks());
.setRecentTasks(mWMComponent.getRecentTasks())
.setSizeCompatUI(Optional.of(mWMComponent.getSizeCompatUI()));
} else {
// TODO: Call on prepareSysUIComponentBuilder but not with real components. Other option
// is separating this logic into newly creating SystemUITestsFactory.
@@ -140,7 +139,8 @@ public class SystemUIFactory {
.setDisplayAreaHelper(Optional.ofNullable(null))
.setStartingSurface(Optional.ofNullable(null))
.setTaskSurfaceHelper(Optional.ofNullable(null))
.setRecentTasks(Optional.ofNullable(null));
.setRecentTasks(Optional.ofNullable(null))
.setSizeCompatUI(Optional.ofNullable(null));
}
mSysUIComponent = builder.build();
if (mInitializeComponents) {

View File

@@ -37,6 +37,7 @@ import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.recents.RecentTasks;
import com.android.wm.shell.sizecompatui.SizeCompatUI;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.startingsurface.StartingSurface;
import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelper;
@@ -107,6 +108,9 @@ public interface SysUIComponent {
@BindsInstance
Builder setRecentTasks(Optional<RecentTasks> r);
@BindsInstance
Builder setSizeCompatUI(Optional<SizeCompatUI> s);
SysUIComponent build();
}

View File

@@ -20,13 +20,13 @@ import android.content.Context;
import com.android.systemui.SystemUIFactory;
import com.android.systemui.tv.TvWMComponent;
import com.android.wm.shell.dagger.TvWMShellModule;
import com.android.wm.shell.dagger.WMShellModule;
import com.android.wm.shell.ShellCommandHandler;
import com.android.wm.shell.ShellInit;
import com.android.wm.shell.TaskViewFactory;
import com.android.wm.shell.apppairs.AppPairs;
import com.android.wm.shell.bubbles.Bubbles;
import com.android.wm.shell.dagger.TvWMShellModule;
import com.android.wm.shell.dagger.WMShellModule;
import com.android.wm.shell.dagger.WMSingleton;
import com.android.wm.shell.displayareahelper.DisplayAreaHelper;
import com.android.wm.shell.hidedisplaycutout.HideDisplayCutout;
@@ -34,6 +34,7 @@ import com.android.wm.shell.legacysplitscreen.LegacySplitScreen;
import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.recents.RecentTasks;
import com.android.wm.shell.sizecompatui.SizeCompatUI;
import com.android.wm.shell.splitscreen.SplitScreen;
import com.android.wm.shell.startingsurface.StartingSurface;
import com.android.wm.shell.tasksurfacehelper.TaskSurfaceHelper;
@@ -115,4 +116,7 @@ public interface WMComponent {
@WMSingleton
Optional<RecentTasks> getRecentTasks();
@WMSingleton
SizeCompatUI getSizeCompatUI();
}

View File

@@ -65,6 +65,7 @@ import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
import com.android.wm.shell.onehanded.OneHandedUiEventLogger;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.protolog.ShellProtoLogImpl;
import com.android.wm.shell.sizecompatui.SizeCompatUI;
import com.android.wm.shell.splitscreen.SplitScreen;
import java.io.FileDescriptor;
@@ -112,6 +113,7 @@ public final class WMShell extends SystemUI
private final Optional<OneHanded> mOneHandedOptional;
private final Optional<HideDisplayCutout> mHideDisplayCutoutOptional;
private final Optional<ShellCommandHandler> mShellCommandHandler;
private final Optional<SizeCompatUI> mSizeCompatUIOptional;
private final CommandQueue mCommandQueue;
private final ConfigurationController mConfigurationController;
@@ -128,6 +130,7 @@ public final class WMShell extends SystemUI
private KeyguardUpdateMonitorCallback mSplitScreenKeyguardCallback;
private KeyguardUpdateMonitorCallback mPipKeyguardCallback;
private KeyguardUpdateMonitorCallback mOneHandedKeyguardCallback;
private KeyguardUpdateMonitorCallback mSizeCompatUIKeyguardCallback;
private WakefulnessLifecycle.Observer mWakefulnessObserver;
@Inject
@@ -138,6 +141,7 @@ public final class WMShell extends SystemUI
Optional<OneHanded> oneHandedOptional,
Optional<HideDisplayCutout> hideDisplayCutoutOptional,
Optional<ShellCommandHandler> shellCommandHandler,
Optional<SizeCompatUI> sizeCompatUIOptional,
CommandQueue commandQueue,
ConfigurationController configurationController,
KeyguardUpdateMonitor keyguardUpdateMonitor,
@@ -162,6 +166,7 @@ public final class WMShell extends SystemUI
mWakefulnessLifecycle = wakefulnessLifecycle;
mProtoTracer = protoTracer;
mShellCommandHandler = shellCommandHandler;
mSizeCompatUIOptional = sizeCompatUIOptional;
mSysUiMainExecutor = sysUiMainExecutor;
}
@@ -176,6 +181,7 @@ public final class WMShell extends SystemUI
mSplitScreenOptional.ifPresent(this::initSplitScreen);
mOneHandedOptional.ifPresent(this::initOneHanded);
mHideDisplayCutoutOptional.ifPresent(this::initHideDisplayCutout);
mSizeCompatUIOptional.ifPresent(this::initSizeCompatUi);
}
@VisibleForTesting
@@ -367,6 +373,17 @@ public final class WMShell extends SystemUI
});
}
@VisibleForTesting
void initSizeCompatUi(SizeCompatUI sizeCompatUI) {
mSizeCompatUIKeyguardCallback = new KeyguardUpdateMonitorCallback() {
@Override
public void onKeyguardOccludedChanged(boolean occluded) {
sizeCompatUI.onKeyguardOccludedChanged(occluded);
}
};
mKeyguardUpdateMonitor.registerCallback(mSizeCompatUIKeyguardCallback);
}
@Override
public void writeToProto(SystemUiTraceProto proto) {
if (proto.wmShell == null) {

View File

@@ -41,6 +41,7 @@ import com.android.wm.shell.onehanded.OneHanded;
import com.android.wm.shell.onehanded.OneHandedEventCallback;
import com.android.wm.shell.onehanded.OneHandedTransitionCallback;
import com.android.wm.shell.pip.Pip;
import com.android.wm.shell.sizecompatui.SizeCompatUI;
import com.android.wm.shell.splitscreen.SplitScreen;
import org.junit.Before;
@@ -76,6 +77,7 @@ public class WMShellTest extends SysuiTestCase {
@Mock WakefulnessLifecycle mWakefulnessLifecycle;
@Mock ProtoTracer mProtoTracer;
@Mock ShellCommandHandler mShellCommandHandler;
@Mock SizeCompatUI mSizeCompatUI;
@Mock ShellExecutor mSysUiMainExecutor;
@Before
@@ -84,10 +86,10 @@ public class WMShellTest extends SysuiTestCase {
mWMShell = new WMShell(mContext, Optional.of(mPip), Optional.of(mLegacySplitScreen),
Optional.of(mSplitScreen), Optional.of(mOneHanded), Optional.of(mHideDisplayCutout),
Optional.of(mShellCommandHandler), mCommandQueue, mConfigurationController,
mKeyguardUpdateMonitor, mNavigationModeController,
mScreenLifecycle, mSysUiState, mProtoTracer, mWakefulnessLifecycle,
mSysUiMainExecutor);
Optional.of(mShellCommandHandler), Optional.of(mSizeCompatUI),
mCommandQueue, mConfigurationController, mKeyguardUpdateMonitor,
mNavigationModeController, mScreenLifecycle, mSysUiState, mProtoTracer,
mWakefulnessLifecycle, mSysUiMainExecutor);
}
@Test
@@ -129,4 +131,11 @@ public class WMShellTest extends SysuiTestCase {
verify(mConfigurationController).addCallback(
any(ConfigurationController.ConfigurationListener.class));
}
@Test
public void initSizeCompatUI_registersCallbacks() {
mWMShell.initSizeCompatUi(mSizeCompatUI);
verify(mKeyguardUpdateMonitor).registerCallback(any(KeyguardUpdateMonitorCallback.class));
}
}