Merge "Add ANIM_FROM_STYLE to the list of animations that the default Shell transition handler can run." into main
diff --git a/core/java/android/view/InsetsFrameProvider.java b/core/java/android/view/InsetsFrameProvider.java
index fe98fab..075571c 100644
--- a/core/java/android/view/InsetsFrameProvider.java
+++ b/core/java/android/view/InsetsFrameProvider.java
@@ -162,6 +162,12 @@
return mSource;
}
+ /** Set the flags of this provider. */
+ public InsetsFrameProvider setFlags(@Flags int flags) {
+ mFlags = flags;
+ return this;
+ }
+
public InsetsFrameProvider setFlags(@Flags int flags, @Flags int mask) {
mFlags = (mFlags & ~mask) | (flags & mask);
return this;
diff --git a/core/java/android/view/ViewRootImpl.java b/core/java/android/view/ViewRootImpl.java
index d224217..a6c6c18 100644
--- a/core/java/android/view/ViewRootImpl.java
+++ b/core/java/android/view/ViewRootImpl.java
@@ -130,6 +130,7 @@
import static com.android.text.flags.Flags.disableHandwritingInitiatorForIme;
import static com.android.window.flags.Flags.activityWindowInfoFlag;
import static com.android.window.flags.Flags.enableBufferTransformHintFromDisplay;
+import static com.android.window.flags.Flags.enableCaptionCompatInsetForceConsumption;
import static com.android.window.flags.Flags.insetsControlChangedItem;
import static com.android.window.flags.Flags.insetsControlSeq;
import static com.android.window.flags.Flags.setScPropertiesInClient;
@@ -3189,7 +3190,9 @@
inOutParams.privateFlags &= ~PRIVATE_FLAG_FIT_INSETS_CONTROLLED;
}
- private void controlInsetsForCompatibility(WindowManager.LayoutParams params) {
+ /** Updates the {@link InsetsType}s to hide or show based on layout params. */
+ @VisibleForTesting
+ public void controlInsetsForCompatibility(WindowManager.LayoutParams params) {
final int sysUiVis = params.systemUiVisibility | params.subtreeSystemUiVisibility;
final int flags = params.flags;
final boolean matchParent = params.width == MATCH_PARENT && params.height == MATCH_PARENT;
@@ -3200,6 +3203,9 @@
|| ((flags & FLAG_FULLSCREEN) != 0 && matchParent && nonAttachedAppWindow);
final boolean navWasHiddenByFlags = (mTypesHiddenByFlags & Type.navigationBars()) != 0;
final boolean navIsHiddenByFlags = (sysUiVis & SYSTEM_UI_FLAG_HIDE_NAVIGATION) != 0;
+ final boolean captionWasHiddenByFlags = (mTypesHiddenByFlags & Type.captionBar()) != 0;
+ final boolean captionIsHiddenByFlags = (sysUiVis & SYSTEM_UI_FLAG_FULLSCREEN) != 0
+ || ((flags & FLAG_FULLSCREEN) != 0 && matchParent && nonAttachedAppWindow);
@InsetsType int typesToHide = 0;
@InsetsType int typesToShow = 0;
@@ -3213,6 +3219,13 @@
} else if (!navIsHiddenByFlags && navWasHiddenByFlags) {
typesToShow |= Type.navigationBars();
}
+ if (captionIsHiddenByFlags && !captionWasHiddenByFlags
+ && enableCaptionCompatInsetForceConsumption()) {
+ typesToHide |= Type.captionBar();
+ } else if (!captionIsHiddenByFlags && captionWasHiddenByFlags
+ && enableCaptionCompatInsetForceConsumption()) {
+ typesToShow |= Type.captionBar();
+ }
if (typesToHide != 0) {
getInsetsController().hide(typesToHide);
}
diff --git a/core/java/android/window/TransitionInfo.java b/core/java/android/window/TransitionInfo.java
index 8ded608..1083f64 100644
--- a/core/java/android/window/TransitionInfo.java
+++ b/core/java/android/window/TransitionInfo.java
@@ -205,7 +205,7 @@
FLAG_SYNC,
FLAG_CONFIG_AT_END,
FLAG_FIRST_CUSTOM
- })
+ }, flag = true)
public @interface ChangeFlags {}
private final @TransitionType int mType;
diff --git a/core/java/android/window/WindowContainerTransaction.java b/core/java/android/window/WindowContainerTransaction.java
index cd033ca..e9d77f8 100644
--- a/core/java/android/window/WindowContainerTransaction.java
+++ b/core/java/android/window/WindowContainerTransaction.java
@@ -42,6 +42,7 @@
import android.os.Parcelable;
import android.util.ArrayMap;
import android.view.InsetsFrameProvider;
+import android.view.InsetsSource;
import android.view.SurfaceControl;
import android.view.WindowInsets.Type.InsetsType;
@@ -714,14 +715,16 @@
@NonNull
public WindowContainerTransaction addInsetsSource(
@NonNull WindowContainerToken receiver,
- IBinder owner, int index, @InsetsType int type, Rect frame, Rect[] boundingRects) {
+ IBinder owner, int index, @InsetsType int type, Rect frame, Rect[] boundingRects,
+ @InsetsSource.Flags int flags) {
final HierarchyOp hierarchyOp =
new HierarchyOp.Builder(HierarchyOp.HIERARCHY_OP_TYPE_ADD_INSETS_FRAME_PROVIDER)
.setContainer(receiver.asBinder())
.setInsetsFrameProvider(new InsetsFrameProvider(owner, index, type)
.setSource(InsetsFrameProvider.SOURCE_ARBITRARY_RECTANGLE)
.setArbitraryRectangle(frame)
- .setBoundingRects(boundingRects))
+ .setBoundingRects(boundingRects)
+ .setFlags(flags))
.setInsetsFrameOwner(owner)
.build();
mHierarchyOps.add(hierarchyOp);
diff --git a/core/java/com/android/internal/policy/DecorView.java b/core/java/com/android/internal/policy/DecorView.java
index 63ff598..87e22ed 100644
--- a/core/java/com/android/internal/policy/DecorView.java
+++ b/core/java/com/android/internal/policy/DecorView.java
@@ -109,6 +109,7 @@
import com.android.internal.widget.ActionBarContextView;
import com.android.internal.widget.BackgroundFallback;
import com.android.internal.widget.floatingtoolbar.FloatingToolbar;
+import com.android.window.flags.Flags;
import java.util.List;
import java.util.function.Consumer;
@@ -1193,7 +1194,8 @@
// If we should always consume system bars, only consume that if the app wanted to go to
// fullscreen, as otherwise we can expect the app to handle it.
boolean fullscreen = (sysUiVisibility & SYSTEM_UI_FLAG_FULLSCREEN) != 0
- || (attrs.flags & FLAG_FULLSCREEN) != 0
+ || (attrs.flags & FLAG_FULLSCREEN) != 0;
+ final boolean hideStatusBar = fullscreen
|| (requestedVisibleTypes & WindowInsets.Type.statusBars()) == 0;
boolean consumingStatusBar =
((sysUiVisibility & SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN) == 0
@@ -1203,9 +1205,20 @@
&& mForceWindowDrawsBarBackgrounds
&& mLastTopInset != 0)
|| ((mLastForceConsumingTypes & WindowInsets.Type.statusBars()) != 0
- && fullscreen);
+ && hideStatusBar);
- int consumedTop = consumingStatusBar ? mLastTopInset : 0;
+ final boolean hideCaptionBar = fullscreen
+ || (requestedVisibleTypes & WindowInsets.Type.captionBar()) == 0;
+ final boolean consumingCaptionBar =
+ ((mLastForceConsumingTypes & WindowInsets.Type.captionBar()) != 0
+ && hideCaptionBar);
+
+ final int consumedTop;
+ if (Flags.enableCaptionCompatInsetForceConsumption()) {
+ consumedTop = (consumingStatusBar || consumingCaptionBar) ? mLastTopInset : 0;
+ } else {
+ consumedTop = consumingStatusBar ? mLastTopInset : 0;
+ }
int consumedRight = consumingNavBar ? mLastRightInset : 0;
int consumedBottom = consumingNavBar ? mLastBottomInset : 0;
int consumedLeft = consumingNavBar ? mLastLeftInset : 0;
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java
index e277a8d..ea02de9d 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipMotionHelper.java
@@ -816,6 +816,26 @@
mPipBoundsState.getMotionBoundsState().onPhysicsAnimationEnded();
mSpringingToTouch = false;
mDismissalPending = false;
+
+ // Check whether new bounds after fling imply we need to update stash state too.
+ stashEndActionIfNeeded();
+ }
+
+ private void stashEndActionIfNeeded() {
+ boolean isStashing = mPipBoundsState.getBounds().right > mPipBoundsState
+ .getDisplayBounds().width() || mPipBoundsState.getBounds().left < 0;
+ if (!isStashing) {
+ return;
+ }
+
+ if (mPipBoundsState.getBounds().left < 0
+ && mPipBoundsState.getStashedState() != STASH_TYPE_LEFT) {
+ mPipBoundsState.setStashed(STASH_TYPE_LEFT);
+ } else if (mPipBoundsState.getBounds().left >= 0
+ && mPipBoundsState.getStashedState() != STASH_TYPE_RIGHT) {
+ mPipBoundsState.setStashed(STASH_TYPE_RIGHT);
+ }
+ mMenuController.hideMenu();
}
/**
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java
index 0c4ed26..53b80e8 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/pip2/phone/PipTouchHandler.java
@@ -106,9 +106,6 @@
private float mStashVelocityThreshold;
- // The reference inset bounds, used to determine the dismiss fraction
- private final Rect mInsetBounds = new Rect();
-
// Used to workaround an issue where the WM rotation happens before we are notified, allowing
// us to send stale bounds
private int mDeferResizeToNormalBoundsUntilRotation = -1;
@@ -206,17 +203,10 @@
mMotionHelper, mainExecutor);
mTouchState = new PipTouchState(ViewConfiguration.get(context),
() -> {
- if (mPipBoundsState.isStashed()) {
- animateToUnStashedState();
- mPipUiEventLogger.log(
- PipUiEventLogger.PipUiEventEnum.PICTURE_IN_PICTURE_STASH_UNSTASHED);
- mPipBoundsState.setStashed(STASH_TYPE_NONE);
- } else {
- mMenuController.showMenuWithPossibleDelay(MENU_STATE_FULL,
- mPipBoundsState.getBounds(), true /* allowMenuTimeout */,
- willResizeMenu(),
- shouldShowResizeHandle());
- }
+ mMenuController.showMenuWithPossibleDelay(MENU_STATE_FULL,
+ mPipBoundsState.getBounds(), true /* allowMenuTimeout */,
+ willResizeMenu(),
+ shouldShowResizeHandle());
},
menuController::hideMenu,
mainExecutor);
@@ -438,7 +428,6 @@
mPipBoundsState.setNormalMovementBounds(normalMovementBounds);
mPipBoundsState.setExpandedMovementBounds(expandedMovementBounds);
mDisplayRotation = displayRotation;
- mInsetBounds.set(insetBounds);
updateMovementBounds();
mMovementBoundsExtraOffsets = extraOffset;
@@ -748,10 +737,13 @@
final Rect pipBounds = mPipBoundsState.getBounds();
final boolean onLeftEdge = pipBounds.left < mPipBoundsState.getDisplayBounds().left;
final Rect unStashedBounds = new Rect(0, pipBounds.top, 0, pipBounds.bottom);
- unStashedBounds.left = onLeftEdge ? mInsetBounds.left
- : mInsetBounds.right - pipBounds.width();
- unStashedBounds.right = onLeftEdge ? mInsetBounds.left + pipBounds.width()
- : mInsetBounds.right;
+
+ Rect insetBounds = new Rect();
+ mPipBoundsAlgorithm.getInsetBounds(insetBounds);
+ unStashedBounds.left = onLeftEdge ? insetBounds.left
+ : insetBounds.right - pipBounds.width();
+ unStashedBounds.right = onLeftEdge ? insetBounds.left + pipBounds.width()
+ : insetBounds.right;
mMotionHelper.animateToUnStashedBounds(unStashedBounds);
}
@@ -899,8 +891,7 @@
// Reset the touch state on up before the fling settles
mTouchState.reset();
if (mEnableStash && shouldStash(vel, getPossiblyMotionBounds())) {
- // mMotionHelper.stashToEdge(vel.x, vel.y,
- // this::stashEndAction /* endAction */);
+ mMotionHelper.stashToEdge(vel.x, vel.y, null /* endAction */);
} else {
if (mPipBoundsState.isStashed()) {
// Reset stashed state if previously stashed
@@ -1030,8 +1021,10 @@
* resized.
*/
private void updateMovementBounds() {
+ Rect insetBounds = new Rect();
+ mPipBoundsAlgorithm.getInsetBounds(insetBounds);
mPipBoundsAlgorithm.getMovementBounds(mPipBoundsState.getBounds(),
- mInsetBounds, mPipBoundsState.getMovementBounds(), mIsImeShowing ? mImeHeight : 0);
+ insetBounds, mPipBoundsState.getMovementBounds(), mIsImeShowing ? mImeHeight : 0);
mMotionHelper.onMovementBoundsChanged();
}
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
index a126cbe..9750d3e 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/taskview/TaskViewTaskController.java
@@ -535,7 +535,8 @@
WindowContainerTransaction wct = new WindowContainerTransaction();
if (mCaptionInsets != null) {
wct.addInsetsSource(mTaskToken, mCaptionInsetsOwner, 0,
- WindowInsets.Type.captionBar(), mCaptionInsets, null /* boundingRects */);
+ WindowInsets.Type.captionBar(), mCaptionInsets, null /* boundingRects */,
+ 0 /* flags */);
} else {
wct.removeInsetsSource(mTaskToken, mCaptionInsetsOwner, 0,
WindowInsets.Type.captionBar());
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
index 21307a2..5b4208a 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/transition/Transitions.java
@@ -31,6 +31,7 @@
import static android.view.WindowManager.transitTypeToString;
import static android.window.TransitionInfo.FLAGS_IS_NON_APP_WINDOW;
import static android.window.TransitionInfo.FLAG_BACK_GESTURE_ANIMATED;
+import static android.window.TransitionInfo.FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY;
import static android.window.TransitionInfo.FLAG_IS_BEHIND_STARTING_WINDOW;
import static android.window.TransitionInfo.FLAG_IS_OCCLUDED;
import static android.window.TransitionInfo.FLAG_IS_WALLPAPER;
@@ -806,14 +807,16 @@
final int changeSize = info.getChanges().size();
boolean taskChange = false;
boolean transferStartingWindow = false;
- int noAnimationBehindStartingWindow = 0;
+ int animBehindStartingWindow = 0;
boolean allOccluded = changeSize > 0;
for (int i = changeSize - 1; i >= 0; --i) {
final TransitionInfo.Change change = info.getChanges().get(i);
taskChange |= change.getTaskInfo() != null;
transferStartingWindow |= change.hasFlags(FLAG_STARTING_WINDOW_TRANSFER_RECIPIENT);
- if (change.hasAllFlags(FLAG_IS_BEHIND_STARTING_WINDOW | FLAG_NO_ANIMATION)) {
- noAnimationBehindStartingWindow++;
+ if (change.hasAllFlags(FLAG_IS_BEHIND_STARTING_WINDOW | FLAG_NO_ANIMATION)
+ || change.hasAllFlags(
+ FLAG_IS_BEHIND_STARTING_WINDOW | FLAG_IN_TASK_WITH_EMBEDDED_ACTIVITY)) {
+ animBehindStartingWindow++;
}
if (!change.hasFlags(FLAG_IS_OCCLUDED)) {
allOccluded = false;
@@ -831,11 +834,11 @@
// There does not need animation when:
// A. Transfer starting window. Apply transfer starting window directly if there is no other
// task change. Since this is an activity->activity situation, we can detect it by selecting
- // transitions with only 2 changes where
- // 1. neither are tasks, and
+ // transitions with changes where
+ // 1. none are tasks, and
// 2. one is a starting-window recipient, or all change is behind starting window.
- if (!taskChange && (transferStartingWindow || noAnimationBehindStartingWindow == changeSize)
- && changeSize == 2
+ if (!taskChange && (transferStartingWindow || animBehindStartingWindow == changeSize)
+ && changeSize >= 1
// B. It's visibility change if the TRANSIT_TO_BACK/TO_FRONT happened when all
// changes are underneath another change.
|| ((info.getType() == TRANSIT_TO_BACK || info.getType() == TRANSIT_TO_FRONT)
diff --git a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
index 03dbbb3..e86f6a1 100644
--- a/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
+++ b/libs/WindowManager/Shell/src/com/android/wm/shell/windowdecor/WindowDecoration.java
@@ -19,6 +19,7 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
import static android.content.res.Configuration.DENSITY_DPI_UNDEFINED;
+import static android.view.InsetsSource.FLAG_FORCE_CONSUMING;
import static android.view.WindowInsets.Type.captionBar;
import static android.view.WindowInsets.Type.mandatorySystemGestures;
import static android.view.WindowInsets.Type.statusBars;
@@ -53,6 +54,7 @@
import android.window.WindowContainerTransaction;
import com.android.internal.annotations.VisibleForTesting;
+import com.android.window.flags.Flags;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.common.DisplayController;
import com.android.wm.shell.shared.desktopmode.DesktopModeStatus;
@@ -759,9 +761,12 @@
}
void addOrUpdate(WindowContainerTransaction wct) {
- wct.addInsetsSource(mToken, mOwner, INDEX, captionBar(), mFrame, mBoundingRects);
+ final @InsetsSource.Flags int captionSourceFlags =
+ Flags.enableCaptionCompatInsetForceConsumption() ? FLAG_FORCE_CONSUMING : 0;
+ wct.addInsetsSource(mToken, mOwner, INDEX, captionBar(), mFrame, mBoundingRects,
+ captionSourceFlags);
wct.addInsetsSource(mToken, mOwner, INDEX, mandatorySystemGestures(), mFrame,
- mBoundingRects);
+ mBoundingRects, 0 /* flags */);
}
void remove(WindowContainerTransaction wct) {
diff --git a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
index 31c6479..2d1bf14 100644
--- a/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
+++ b/libs/WindowManager/Shell/tests/unittest/src/com/android/wm/shell/windowdecor/WindowDecorationTests.java
@@ -18,6 +18,8 @@
import static android.app.WindowConfiguration.WINDOWING_MODE_FREEFORM;
import static android.app.WindowConfiguration.WINDOWING_MODE_FULLSCREEN;
+import static android.platform.test.flag.junit.SetFlagsRule.DefaultInitValueType.DEVICE_DEFAULT;
+import static android.view.InsetsSource.FLAG_FORCE_CONSUMING;
import static android.view.WindowInsets.Type.captionBar;
import static android.view.WindowInsets.Type.mandatorySystemGestures;
import static android.view.WindowInsets.Type.statusBars;
@@ -54,6 +56,8 @@
import android.graphics.Color;
import android.graphics.Point;
import android.graphics.Rect;
+import android.platform.test.annotations.EnableFlags;
+import android.platform.test.flag.junit.SetFlagsRule;
import android.testing.AndroidTestingRunner;
import android.util.DisplayMetrics;
import android.view.AttachedSurfaceControl;
@@ -71,6 +75,7 @@
import androidx.test.filters.SmallTest;
import com.android.dx.mockito.inline.extended.StaticMockitoSession;
+import com.android.window.flags.Flags;
import com.android.wm.shell.ShellTaskOrganizer;
import com.android.wm.shell.ShellTestCase;
import com.android.wm.shell.TestRunningTaskInfoBuilder;
@@ -80,6 +85,7 @@
import com.android.wm.shell.windowdecor.additionalviewcontainer.AdditionalViewContainer;
import org.junit.Before;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -105,6 +111,9 @@
private static final int CORNER_RADIUS = 20;
private static final int STATUS_BAR_INSET_SOURCE_ID = 0;
+ @Rule
+ public final SetFlagsRule mSetFlagsRule = new SetFlagsRule(DEVICE_DEFAULT);
+
private final WindowDecoration.RelayoutResult<TestView> mRelayoutResult =
new WindowDecoration.RelayoutResult<>();
@@ -260,7 +269,8 @@
eq(0 /* index */),
eq(WindowInsets.Type.captionBar()),
eq(new Rect(100, 300, 400, 364)),
- any());
+ any(),
+ anyInt());
verify(mMockSurfaceControlStartT).setCornerRadius(mMockTaskSurface, CORNER_RADIUS);
verify(mMockSurfaceControlFinishT).setCornerRadius(mMockTaskSurface, CORNER_RADIUS);
@@ -565,9 +575,9 @@
windowDecor.relayout(taskInfo);
verify(mMockWindowContainerTransaction).addInsetsSource(eq(taskInfo.token), any(),
- eq(0) /* index */, eq(captionBar()), any(), any());
+ eq(0) /* index */, eq(captionBar()), any(), any(), anyInt());
verify(mMockWindowContainerTransaction).addInsetsSource(eq(taskInfo.token), any(),
- eq(0) /* index */, eq(mandatorySystemGestures()), any(), any());
+ eq(0) /* index */, eq(mandatorySystemGestures()), any(), any(), anyInt());
}
@Test
@@ -654,9 +664,9 @@
// Never added.
verify(mMockWindowContainerTransaction, never()).addInsetsSource(eq(taskInfo.token), any(),
- eq(0) /* index */, eq(captionBar()), any(), any());
+ eq(0) /* index */, eq(captionBar()), any(), any(), anyInt());
verify(mMockWindowContainerTransaction, never()).addInsetsSource(eq(taskInfo.token), any(),
- eq(0) /* index */, eq(mandatorySystemGestures()), any(), any());
+ eq(0) /* index */, eq(mandatorySystemGestures()), any(), any(), anyInt());
// No need to remove them if they were never added.
verify(mMockWindowContainerTransaction, never()).removeInsetsSource(eq(taskInfo.token),
any(), eq(0) /* index */, eq(captionBar()));
@@ -681,9 +691,9 @@
mInsetsState.getOrCreateSource(STATUS_BAR_INSET_SOURCE_ID, captionBar()).setVisible(true);
windowDecor.relayout(taskInfo);
verify(mMockWindowContainerTransaction).addInsetsSource(eq(taskInfo.token), any(),
- eq(0) /* index */, eq(captionBar()), any(), any());
+ eq(0) /* index */, eq(captionBar()), any(), any(), anyInt());
verify(mMockWindowContainerTransaction).addInsetsSource(eq(taskInfo.token), any(),
- eq(0) /* index */, eq(mandatorySystemGestures()), any(), any());
+ eq(0) /* index */, eq(mandatorySystemGestures()), any(), any(), anyInt());
windowDecor.close();
@@ -738,9 +748,9 @@
// Insets should be applied twice.
verify(mMockWindowContainerTransaction, times(2)).addInsetsSource(eq(token), any(),
- eq(0) /* index */, eq(captionBar()), any(), any());
+ eq(0) /* index */, eq(captionBar()), any(), any(), anyInt());
verify(mMockWindowContainerTransaction, times(2)).addInsetsSource(eq(token), any(),
- eq(0) /* index */, eq(mandatorySystemGestures()), any(), any());
+ eq(0) /* index */, eq(mandatorySystemGestures()), any(), any(), anyInt());
}
@Test
@@ -765,9 +775,30 @@
// Insets should only need to be applied once.
verify(mMockWindowContainerTransaction, times(1)).addInsetsSource(eq(token), any(),
- eq(0) /* index */, eq(captionBar()), any(), any());
+ eq(0) /* index */, eq(captionBar()), any(), any(), anyInt());
verify(mMockWindowContainerTransaction, times(1)).addInsetsSource(eq(token), any(),
- eq(0) /* index */, eq(mandatorySystemGestures()), any(), any());
+ eq(0) /* index */, eq(mandatorySystemGestures()), any(), any(), anyInt());
+ }
+
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION)
+ public void testRelayout_captionInsetForceConsume() {
+ final Display defaultDisplay = mock(Display.class);
+ doReturn(defaultDisplay).when(mMockDisplayController)
+ .getDisplay(Display.DEFAULT_DISPLAY);
+ final WindowContainerToken token = TestRunningTaskInfoBuilder.createMockWCToken();
+ final TestRunningTaskInfoBuilder builder = new TestRunningTaskInfoBuilder()
+ .setDisplayId(Display.DEFAULT_DISPLAY)
+ .setVisible(true);
+
+ final ActivityManager.RunningTaskInfo taskInfo =
+ builder.setToken(token).setBounds(new Rect(0, 0, 1000, 1000)).build();
+ final TestWindowDecoration windowDecor = createWindowDecoration(taskInfo);
+ windowDecor.relayout(taskInfo);
+
+ // Caption inset source should be force-consuming.
+ verify(mMockWindowContainerTransaction).addInsetsSource(eq(token), any(),
+ eq(0) /* index */, eq(captionBar()), any(), any(), eq(FLAG_FORCE_CONSUMING));
}
@Test
diff --git a/libs/hwui/Android.bp b/libs/hwui/Android.bp
index 341599e..e302fa8 100644
--- a/libs/hwui/Android.bp
+++ b/libs/hwui/Android.bp
@@ -114,16 +114,12 @@
"libbase",
"libharfbuzz_ng",
"libminikin",
- "server_configurable_flags",
- "libaconfig_storage_read_api_cc"
],
static_libs: [
"libui-types",
],
- whole_static_libs: ["hwui_flags_cc_lib"],
-
target: {
android: {
shared_libs: [
@@ -145,6 +141,8 @@
"libsync",
"libui",
"aconfig_text_flags_c_lib",
+ "server_configurable_flags",
+ "libaconfig_storage_read_api_cc",
],
static_libs: [
"libEGL_blobCache",
@@ -155,6 +153,7 @@
"libstatssocket_lazy",
"libtonemap",
],
+ whole_static_libs: ["hwui_flags_cc_lib"],
},
host: {
static_libs: [
@@ -419,7 +418,6 @@
],
static_libs: [
- "libnativehelper_lazy",
"libziparchive_for_incfs",
],
@@ -446,6 +444,7 @@
],
static_libs: [
"libgif",
+ "libnativehelper_lazy",
"libstatslog_hwui",
"libstatspull_lazy",
"libstatssocket_lazy",
@@ -464,6 +463,7 @@
],
static_libs: [
"libandroidfw",
+ "libnativehelper_jvm",
],
},
},
diff --git a/libs/hwui/apex/LayoutlibLoader.cpp b/libs/hwui/apex/LayoutlibLoader.cpp
index 70a9ef0..073bc8d 100644
--- a/libs/hwui/apex/LayoutlibLoader.cpp
+++ b/libs/hwui/apex/LayoutlibLoader.cpp
@@ -41,6 +41,7 @@
extern int register_android_graphics_RenderEffect(JNIEnv* env);
extern int register_android_graphics_Typeface(JNIEnv* env);
extern int register_android_graphics_YuvImage(JNIEnv* env);
+extern int register_android_graphics_drawable_AnimatedImageDrawable(JNIEnv* env);
namespace android {
@@ -51,6 +52,8 @@
extern int register_android_graphics_ColorSpace(JNIEnv* env);
extern int register_android_graphics_DrawFilter(JNIEnv* env);
extern int register_android_graphics_FontFamily(JNIEnv* env);
+extern int register_android_graphics_Gainmap(JNIEnv* env);
+extern int register_android_graphics_HardwareRendererObserver(JNIEnv* env);
extern int register_android_graphics_Matrix(JNIEnv* env);
extern int register_android_graphics_Paint(JNIEnv* env);
extern int register_android_graphics_Path(JNIEnv* env);
@@ -72,6 +75,7 @@
extern int register_android_util_PathParser(JNIEnv* env);
extern int register_android_view_DisplayListCanvas(JNIEnv* env);
extern int register_android_view_RenderNode(JNIEnv* env);
+extern int register_android_view_ThreadedRenderer(JNIEnv* env);
#define REG_JNI(name) { name }
struct RegJNIRec {
@@ -95,7 +99,11 @@
REG_JNI(register_android_graphics_CreateJavaOutputStreamAdaptor)},
{"android.graphics.DrawFilter", REG_JNI(register_android_graphics_DrawFilter)},
{"android.graphics.FontFamily", REG_JNI(register_android_graphics_FontFamily)},
+ {"android.graphics.Gainmap", REG_JNI(register_android_graphics_Gainmap)},
{"android.graphics.Graphics", REG_JNI(register_android_graphics_Graphics)},
+ {"android.graphics.HardwareRenderer", REG_JNI(register_android_view_ThreadedRenderer)},
+ {"android.graphics.HardwareRendererObserver",
+ REG_JNI(register_android_graphics_HardwareRendererObserver)},
{"android.graphics.ImageDecoder", REG_JNI(register_android_graphics_ImageDecoder)},
{"android.graphics.Interpolator", REG_JNI(register_android_graphics_Interpolator)},
{"android.graphics.MaskFilter", REG_JNI(register_android_graphics_MaskFilter)},
@@ -118,6 +126,8 @@
REG_JNI(register_android_graphics_animation_NativeInterpolatorFactory)},
{"android.graphics.animation.RenderNodeAnimator",
REG_JNI(register_android_graphics_animation_RenderNodeAnimator)},
+ {"android.graphics.drawable.AnimatedImageDrawable",
+ REG_JNI(register_android_graphics_drawable_AnimatedImageDrawable)},
{"android.graphics.drawable.AnimatedVectorDrawable",
REG_JNI(register_android_graphics_drawable_AnimatedVectorDrawable)},
{"android.graphics.drawable.VectorDrawable",
diff --git a/libs/hwui/hwui/DrawTextFunctor.h b/libs/hwui/hwui/DrawTextFunctor.h
index cfca480..0efb2c8 100644
--- a/libs/hwui/hwui/DrawTextFunctor.h
+++ b/libs/hwui/hwui/DrawTextFunctor.h
@@ -17,7 +17,6 @@
#include <SkFontMetrics.h>
#include <SkRRect.h>
#include <SkTextBlob.h>
-#include <com_android_graphics_hwui_flags.h>
#include "../utils/Color.h"
#include "Canvas.h"
@@ -30,7 +29,19 @@
#include "hwui/PaintFilter.h"
#include "pipeline/skia/SkiaRecordingCanvas.h"
+#ifdef __ANDROID__
+#include <com_android_graphics_hwui_flags.h>
namespace flags = com::android::graphics::hwui::flags;
+#else
+namespace flags {
+constexpr bool high_contrast_text_luminance() {
+ return false;
+}
+constexpr bool high_contrast_text_small_text_rect() {
+ return false;
+}
+} // namespace flags
+#endif
namespace android {
diff --git a/location/Android.bp b/location/Android.bp
index c0e102a..bc02d1f 100644
--- a/location/Android.bp
+++ b/location/Android.bp
@@ -30,9 +30,6 @@
"app-compat-annotations",
"unsupportedappusage", // for android.compat.annotation.UnsupportedAppUsage
],
- hidden_api_packages: [
- "com.android.internal.location",
- ],
aidl: {
include_dirs: [
"frameworks/base/location/java",
diff --git a/packages/SystemUI/tests/utils/src/com/android/app/admin/DevicePolicyManagerKosmos.kt b/location/java/com/android/internal/location/package-info.java
similarity index 73%
rename from packages/SystemUI/tests/utils/src/com/android/app/admin/DevicePolicyManagerKosmos.kt
rename to location/java/com/android/internal/location/package-info.java
index f51e122..25573c1 100644
--- a/packages/SystemUI/tests/utils/src/com/android/app/admin/DevicePolicyManagerKosmos.kt
+++ b/location/java/com/android/internal/location/package-info.java
@@ -14,9 +14,9 @@
* limitations under the License.
*/
-package com.android.app.admin
-
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.util.mockito.mock
-
-val Kosmos.devicePolicyManager by Kosmos.Fixture { mock<android.app.admin.DevicePolicyManager>() }
+/**
+ * Exclude from API surfaces
+ *
+ * @hide
+ */
+package com.android.internal.location;
diff --git a/nfc/Android.bp b/nfc/Android.bp
index 13ac231..0282e6f 100644
--- a/nfc/Android.bp
+++ b/nfc/Android.bp
@@ -61,9 +61,6 @@
"android.nfc",
"com.android.nfc",
],
- hidden_api_packages: [
- "com.android.nfc",
- ],
impl_library_visibility: [
"//frameworks/base:__subpackages__",
"//cts/hostsidetests/multidevices/nfc:__subpackages__",
diff --git a/packages/CrashRecovery/aconfig/flags.aconfig b/packages/CrashRecovery/aconfig/flags.aconfig
index 225f8c6..52e0cbb 100644
--- a/packages/CrashRecovery/aconfig/flags.aconfig
+++ b/packages/CrashRecovery/aconfig/flags.aconfig
@@ -31,3 +31,11 @@
description: "Deletes flag and settings resets"
bug: "333847376"
}
+
+flag {
+ name: "refactor_crashrecovery"
+ namespace: "modularization"
+ description: "Refactor required CrashRecovery code"
+ bug: "289203818"
+ is_fixed_read_only: true
+}
diff --git a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
index 2cc9112..03a2b75 100644
--- a/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
+++ b/packages/SettingsLib/src/com/android/settingslib/notification/modes/ZenMode.java
@@ -286,11 +286,7 @@
mRule, oldCondition, conditionId));
}
- public boolean canEditName() {
- return !isManualDnd();
- }
-
- public boolean canEditIcon() {
+ public boolean canEditNameAndIcon() {
return !isManualDnd();
}
diff --git a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
index 9e54312..e705f97 100644
--- a/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
+++ b/packages/SettingsLib/tests/robotests/src/com/android/settingslib/notification/modes/ZenModeTest.java
@@ -56,12 +56,14 @@
assertThat(zenMode.getId()).isEqualTo("id");
assertThat(zenMode.getRule()).isEqualTo(ZEN_RULE);
assertThat(zenMode.isManualDnd()).isFalse();
+ assertThat(zenMode.canEditNameAndIcon()).isTrue();
assertThat(zenMode.canBeDeleted()).isTrue();
assertThat(zenMode.isActive()).isTrue();
ZenMode manualMode = ZenMode.manualDndMode(ZEN_RULE, false);
assertThat(manualMode.getId()).isEqualTo(ZenMode.MANUAL_DND_MODE_ID);
assertThat(manualMode.isManualDnd()).isTrue();
+ assertThat(manualMode.canEditNameAndIcon()).isFalse();
assertThat(manualMode.canBeDeleted()).isFalse();
assertThat(manualMode.isActive()).isFalse();
}
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt
index 0a4c6fd..7400711 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/DefaultBlueprint.kt
@@ -67,8 +67,7 @@
@Composable
override fun SceneScope.Content(modifier: Modifier) {
val isUdfpsVisible = viewModel.isUdfpsVisible
- val shouldUseSplitNotificationShade by
- viewModel.shouldUseSplitNotificationShade.collectAsStateWithLifecycle()
+ val isShadeLayoutWide by viewModel.isShadeLayoutWide.collectAsStateWithLifecycle()
val unfoldTranslations by viewModel.unfoldTranslations.collectAsStateWithLifecycle()
LockscreenLongPress(
@@ -100,7 +99,7 @@
}
)
}
- if (shouldUseSplitNotificationShade) {
+ if (isShadeLayoutWide) {
with(notificationSection) {
Notifications(
burnInParams = null,
@@ -112,7 +111,7 @@
}
}
}
- if (!shouldUseSplitNotificationShade) {
+ if (!isShadeLayoutWide) {
with(notificationSection) {
Notifications(
burnInParams = null,
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ShortcutsBesideUdfpsBlueprint.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ShortcutsBesideUdfpsBlueprint.kt
index 065f2a2..72cf832 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ShortcutsBesideUdfpsBlueprint.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/blueprint/ShortcutsBesideUdfpsBlueprint.kt
@@ -69,8 +69,7 @@
@Composable
override fun SceneScope.Content(modifier: Modifier) {
val isUdfpsVisible = viewModel.isUdfpsVisible
- val shouldUseSplitNotificationShade by
- viewModel.shouldUseSplitNotificationShade.collectAsStateWithLifecycle()
+ val isShadeLayoutWide by viewModel.isShadeLayoutWide.collectAsStateWithLifecycle()
val unfoldTranslations by viewModel.unfoldTranslations.collectAsStateWithLifecycle()
LockscreenLongPress(
@@ -102,7 +101,7 @@
},
)
}
- if (shouldUseSplitNotificationShade) {
+ if (isShadeLayoutWide) {
with(notificationSection) {
Notifications(
burnInParams = null,
@@ -114,7 +113,7 @@
}
}
}
- if (!shouldUseSplitNotificationShade) {
+ if (!isShadeLayoutWide) {
with(notificationSection) {
Notifications(
burnInParams = null,
diff --git a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt
index 7f80dfa..a1f2042 100644
--- a/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt
+++ b/packages/SystemUI/compose/features/src/com/android/systemui/keyguard/ui/composable/section/NotificationSection.kt
@@ -90,8 +90,8 @@
*/
@Composable
fun SceneScope.Notifications(burnInParams: BurnInParameters?, modifier: Modifier = Modifier) {
- val shouldUseSplitNotificationShade by
- lockscreenContentViewModel.shouldUseSplitNotificationShade.collectAsStateWithLifecycle()
+ val isShadeLayoutWide by
+ lockscreenContentViewModel.isShadeLayoutWide.collectAsStateWithLifecycle()
val areNotificationsVisible by
lockscreenContentViewModel.areNotificationsVisible.collectAsStateWithLifecycle()
val splitShadeTopMargin: Dp =
@@ -111,9 +111,7 @@
modifier =
modifier
.fillMaxWidth()
- .thenIf(shouldUseSplitNotificationShade) {
- Modifier.padding(top = splitShadeTopMargin)
- }
+ .thenIf(isShadeLayoutWide) { Modifier.padding(top = splitShadeTopMargin) }
.let {
if (burnInParams == null) {
it
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorTest.kt
index 26b56a1..4862104 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractorTest.kt
@@ -37,7 +37,6 @@
import com.android.systemui.media.controls.data.repository.mediaFilterRepository
import com.android.systemui.media.controls.shared.model.MediaData
import com.android.systemui.shade.data.repository.shadeRepository
-import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
import com.android.systemui.statusbar.notification.data.repository.setActiveNotifs
import com.android.systemui.statusbar.notification.stack.data.repository.headsUpNotificationRepository
@@ -81,10 +80,10 @@
testScope.runTest {
val value by collectLastValue(underTest.clockShouldBeCentered)
kosmos.keyguardInteractor.setClockShouldBeCentered(true)
- assertThat(value).isEqualTo(true)
+ assertThat(value).isTrue()
kosmos.keyguardInteractor.setClockShouldBeCentered(false)
- assertThat(value).isEqualTo(false)
+ assertThat(value).isFalse()
}
@Test
@@ -103,7 +102,7 @@
fun clockSize_SceneContainerFlagOn_shadeModeSingle_hasNotifs_SMALL() =
testScope.runTest {
val value by collectLastValue(underTest.clockSize)
- kosmos.shadeRepository.setShadeMode(ShadeMode.Single)
+ kosmos.shadeRepository.setShadeLayoutWide(false)
kosmos.activeNotificationListRepository.setActiveNotifs(1)
assertThat(value).isEqualTo(ClockSize.SMALL)
}
@@ -113,7 +112,7 @@
fun clockSize_SceneContainerFlagOn_shadeModeSingle_hasMedia_SMALL() =
testScope.runTest {
val value by collectLastValue(underTest.clockSize)
- kosmos.shadeRepository.setShadeMode(ShadeMode.Single)
+ kosmos.shadeRepository.setShadeLayoutWide(false)
val userMedia = MediaData().copy(active = true)
kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia)
assertThat(value).isEqualTo(ClockSize.SMALL)
@@ -125,7 +124,7 @@
testScope.runTest {
val value by collectLastValue(underTest.clockSize)
val userMedia = MediaData().copy(active = true)
- kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
+ kosmos.shadeRepository.setShadeLayoutWide(true)
kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia)
kosmos.keyguardRepository.setIsDozing(false)
assertThat(value).isEqualTo(ClockSize.SMALL)
@@ -136,7 +135,7 @@
fun clockSize_SceneContainerFlagOn_shadeModeSplit_noMedia_LARGE() =
testScope.runTest {
val value by collectLastValue(underTest.clockSize)
- kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
+ kosmos.shadeRepository.setShadeLayoutWide(true)
kosmos.keyguardRepository.setIsDozing(false)
assertThat(value).isEqualTo(ClockSize.LARGE)
}
@@ -147,7 +146,7 @@
testScope.runTest {
val value by collectLastValue(underTest.clockSize)
val userMedia = MediaData().copy(active = true)
- kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
+ kosmos.shadeRepository.setShadeLayoutWide(true)
kosmos.mediaFilterRepository.addSelectedUserMediaEntry(userMedia)
kosmos.keyguardRepository.setIsDozing(true)
assertThat(value).isEqualTo(ClockSize.LARGE)
@@ -158,8 +157,8 @@
fun clockShouldBeCentered_sceneContainerFlagOn_notSplitMode_true() =
testScope.runTest {
val value by collectLastValue(underTest.clockShouldBeCentered)
- kosmos.shadeRepository.setShadeMode(ShadeMode.Single)
- assertThat(value).isEqualTo(true)
+ kosmos.shadeRepository.setShadeLayoutWide(false)
+ assertThat(value).isTrue()
}
@Test
@@ -167,9 +166,9 @@
fun clockShouldBeCentered_sceneContainerFlagOn_splitMode_noActiveNotifications_true() =
testScope.runTest {
val value by collectLastValue(underTest.clockShouldBeCentered)
- kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
+ kosmos.shadeRepository.setShadeLayoutWide(true)
kosmos.activeNotificationListRepository.setActiveNotifs(0)
- assertThat(value).isEqualTo(true)
+ assertThat(value).isTrue()
}
@Test
@@ -177,10 +176,10 @@
fun clockShouldBeCentered_sceneContainerFlagOn_splitMode_isActiveDreamLockscreenHosted_true() =
testScope.runTest {
val value by collectLastValue(underTest.clockShouldBeCentered)
- kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
+ kosmos.shadeRepository.setShadeLayoutWide(true)
kosmos.activeNotificationListRepository.setActiveNotifs(1)
kosmos.keyguardRepository.setIsActiveDreamLockscreenHosted(true)
- assertThat(value).isEqualTo(true)
+ assertThat(value).isTrue()
}
@Test
@@ -188,11 +187,11 @@
fun clockShouldBeCentered_sceneContainerFlagOn_splitMode_hasPulsingNotifications_false() =
testScope.runTest {
val value by collectLastValue(underTest.clockShouldBeCentered)
- kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
+ kosmos.shadeRepository.setShadeLayoutWide(true)
kosmos.activeNotificationListRepository.setActiveNotifs(1)
kosmos.headsUpNotificationRepository.isHeadsUpAnimatingAway.value = true
kosmos.keyguardRepository.setIsDozing(true)
- assertThat(value).isEqualTo(false)
+ assertThat(value).isFalse()
}
@Test
@@ -200,10 +199,10 @@
fun clockShouldBeCentered_sceneContainerFlagOn_splitMode_onAod_true() =
testScope.runTest {
val value by collectLastValue(underTest.clockShouldBeCentered)
- kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
+ kosmos.shadeRepository.setShadeLayoutWide(true)
kosmos.activeNotificationListRepository.setActiveNotifs(1)
transitionTo(KeyguardState.LOCKSCREEN, KeyguardState.AOD)
- assertThat(value).isEqualTo(true)
+ assertThat(value).isTrue()
}
@Test
@@ -211,10 +210,10 @@
fun clockShouldBeCentered_sceneContainerFlagOn_splitMode_offAod_false() =
testScope.runTest {
val value by collectLastValue(underTest.clockShouldBeCentered)
- kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
+ kosmos.shadeRepository.setShadeLayoutWide(true)
kosmos.activeNotificationListRepository.setActiveNotifs(1)
transitionTo(KeyguardState.AOD, KeyguardState.LOCKSCREEN)
- assertThat(value).isEqualTo(false)
+ assertThat(value).isFalse()
}
private suspend fun transitionTo(from: KeyguardState, to: KeyguardState) {
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
index 875e9e0..50772ee 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModelTest.kt
@@ -37,7 +37,6 @@
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.data.repository.shadeRepository
-import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.testKosmos
import com.android.systemui.unfold.fakeUnfoldTransitionProgressProvider
import com.android.systemui.util.mockito.whenever
@@ -76,7 +75,7 @@
fun setup() {
with(kosmos) {
fakeFeatureFlagsClassic.set(Flags.LOCK_SCREEN_LONG_PRESS_ENABLED, true)
- shadeRepository.setShadeMode(ShadeMode.Single)
+ shadeRepository.setShadeLayoutWide(false)
underTest = lockscreenContentViewModel
}
}
@@ -126,7 +125,7 @@
with(kosmos) {
testScope.runTest {
val areNotificationsVisible by collectLastValue(underTest.areNotificationsVisible)
- shadeRepository.setShadeMode(ShadeMode.Split)
+ shadeRepository.setShadeLayoutWide(true)
fakeKeyguardClockRepository.setClockSize(ClockSize.LARGE)
assertThat(areNotificationsVisible).isTrue()
@@ -156,24 +155,24 @@
}
@Test
- fun shouldUseSplitNotificationShade_withConfigTrue_true() =
+ fun isShadeLayoutWide_withConfigTrue_true() =
with(kosmos) {
testScope.runTest {
- val shouldUseSplitNotificationShade by
- collectLastValue(underTest.shouldUseSplitNotificationShade)
- shadeRepository.setShadeMode(ShadeMode.Split)
- assertThat(shouldUseSplitNotificationShade).isTrue()
+ val isShadeLayoutWide by collectLastValue(underTest.isShadeLayoutWide)
+ shadeRepository.setShadeLayoutWide(true)
+
+ assertThat(isShadeLayoutWide).isTrue()
}
}
@Test
- fun shouldUseSplitNotificationShade_withConfigFalse_false() =
+ fun isShadeLayoutWide_withConfigFalse_false() =
with(kosmos) {
testScope.runTest {
- val shouldUseSplitNotificationShade by
- collectLastValue(underTest.shouldUseSplitNotificationShade)
- shadeRepository.setShadeMode(ShadeMode.Single)
- assertThat(shouldUseSplitNotificationShade).isFalse()
+ val isShadeLayoutWide by collectLastValue(underTest.isShadeLayoutWide)
+ shadeRepository.setShadeLayoutWide(false)
+
+ assertThat(isShadeLayoutWide).isFalse()
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
index 4eb146d..3db9ef1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenSceneViewModelTest.kt
@@ -44,7 +44,6 @@
import com.android.systemui.scene.shared.model.TransitionKeys
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.shade.domain.interactor.shadeInteractor
-import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.notification.stack.ui.viewmodel.notificationsPlaceholderViewModel
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.mock
@@ -182,13 +181,7 @@
}
)
sceneInteractor.changeScene(Scenes.Lockscreen, "reason")
- kosmos.shadeRepository.setShadeMode(
- if (isSingleShade) {
- ShadeMode.Single
- } else {
- ShadeMode.Split
- }
- )
+ kosmos.shadeRepository.setShadeLayoutWide(!isSingleShade)
kosmos.setCommunalAvailable(isCommunalAvailable)
kosmos.fakePowerRepository.updateWakefulness(
rawState =
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt
index b35b7bc..09580c5 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/qs/ui/adapter/QSSceneAdapterImplTest.kt
@@ -38,7 +38,6 @@
import com.android.systemui.settings.brightness.MirrorController
import com.android.systemui.shade.data.repository.fakeShadeRepository
import com.android.systemui.shade.domain.interactor.shadeInteractor
-import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.capture
@@ -558,7 +557,7 @@
fun dispatchSplitShade() =
testScope.runTest {
val shadeRepository = kosmos.fakeShadeRepository
- shadeRepository.setShadeMode(ShadeMode.Single)
+ shadeRepository.setShadeLayoutWide(false)
val qsImpl by collectLastValue(underTest.qsImpl)
underTest.inflate(context)
@@ -566,7 +565,7 @@
verify(qsImpl!!).setInSplitShade(false)
- shadeRepository.setShadeMode(ShadeMode.Split)
+ shadeRepository.setShadeLayoutWide(true)
runCurrent()
verify(qsImpl!!).setInSplitShade(true)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneSceneViewModelTest.kt
index 545a0c7..0ab6a82 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneSceneViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/scene/ui/viewmodel/GoneSceneViewModelTest.kt
@@ -28,7 +28,6 @@
import com.android.systemui.scene.shared.model.TransitionKeys.ToSplitShade
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.shade.domain.interactor.shadeInteractor
-import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.testKosmos
import com.google.common.truth.Truth.assertThat
import kotlinx.coroutines.ExperimentalCoroutinesApi
@@ -63,7 +62,7 @@
fun downTransitionKey_splitShadeEnabled_isGoneToSplitShade() =
testScope.runTest {
val destinationScenes by collectLastValue(underTest.destinationScenes)
- shadeRepository.setShadeMode(ShadeMode.Split)
+ shadeRepository.setShadeLayoutWide(true)
runCurrent()
assertThat(destinationScenes?.get(Swipe(SwipeDirection.Down))?.transitionKey)
@@ -74,7 +73,7 @@
fun downTransitionKey_splitShadeDisabled_isNull() =
testScope.runTest {
val destinationScenes by collectLastValue(underTest.destinationScenes)
- shadeRepository.setShadeMode(ShadeMode.Single)
+ shadeRepository.setShadeLayoutWide(false)
runCurrent()
assertThat(destinationScenes?.get(Swipe(SwipeDirection.Down))?.transitionKey).isNull()
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt
index 78c4def..3283ea1 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImplTest.kt
@@ -19,6 +19,8 @@
import android.app.StatusBarManager.DISABLE2_NONE
import android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE
import android.app.StatusBarManager.DISABLE2_QUICK_SETTINGS
+import android.platform.test.annotations.DisableFlags
+import android.platform.test.annotations.EnableFlags
import android.platform.test.flag.junit.FlagsParameterization
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
@@ -37,7 +39,10 @@
import com.android.systemui.power.data.repository.fakePowerRepository
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.power.shared.model.WakefulnessState
+import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.shade.shadeTestUtil
+import com.android.systemui.shade.shared.flag.DualShade
+import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel
import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository
import com.android.systemui.statusbar.phone.dozeParameters
@@ -452,4 +457,44 @@
val isShadeTouchable by collectLastValue(underTest.isShadeTouchable)
assertThat(isShadeTouchable).isTrue()
}
+
+ @Test
+ @DisableFlags(DualShade.FLAG_NAME)
+ fun legacyShadeMode_narrowScreen_singleShade() =
+ testScope.runTest {
+ val shadeMode by collectLastValue(underTest.shadeMode)
+ kosmos.shadeRepository.setShadeLayoutWide(false)
+
+ assertThat(shadeMode).isEqualTo(ShadeMode.Single)
+ }
+
+ @Test
+ @DisableFlags(DualShade.FLAG_NAME)
+ fun legacyShadeMode_wideScreen_splitShade() =
+ testScope.runTest {
+ val shadeMode by collectLastValue(underTest.shadeMode)
+ kosmos.shadeRepository.setShadeLayoutWide(true)
+
+ assertThat(shadeMode).isEqualTo(ShadeMode.Split)
+ }
+
+ @Test
+ @EnableFlags(DualShade.FLAG_NAME)
+ fun shadeMode_wideScreen_isDual() =
+ testScope.runTest {
+ val shadeMode by collectLastValue(underTest.shadeMode)
+ kosmos.shadeRepository.setShadeLayoutWide(true)
+
+ assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
+ }
+
+ @Test
+ @EnableFlags(DualShade.FLAG_NAME)
+ fun shadeMode_narrowScreen_isDual() =
+ testScope.runTest {
+ val shadeMode by collectLastValue(underTest.shadeMode)
+ kosmos.shadeRepository.setShadeLayoutWide(false)
+
+ assertThat(shadeMode).isEqualTo(ShadeMode.Dual)
+ }
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt
index b1bffdb..8a43198 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImplTest.kt
@@ -29,7 +29,6 @@
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.shade.data.repository.shadeRepository
-import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.testKosmos
import com.google.common.truth.Truth
import com.google.common.truth.Truth.assertThat
@@ -568,21 +567,6 @@
sceneInteractor.setTransitionState(transitionState)
// THEN interacting is false
- Truth.assertThat(interacting).isFalse()
- }
-
- @Test
- fun shadeMode() =
- testScope.runTest {
- val shadeMode by collectLastValue(underTest.shadeMode)
-
- shadeRepository.setShadeMode(ShadeMode.Split)
- assertThat(shadeMode).isEqualTo(ShadeMode.Split)
-
- shadeRepository.setShadeMode(ShadeMode.Single)
- assertThat(shadeMode).isEqualTo(ShadeMode.Single)
-
- shadeRepository.setShadeMode(ShadeMode.Split)
- assertThat(shadeMode).isEqualTo(ShadeMode.Split)
+ assertThat(interacting).isFalse()
}
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
index 673d5ef..da22c6d 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/shade/ui/viewmodel/ShadeSceneViewModelTest.kt
@@ -16,6 +16,7 @@
package com.android.systemui.shade.ui.viewmodel
+import android.platform.test.annotations.DisableFlags
import android.testing.TestableLooper
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
@@ -38,7 +39,6 @@
import com.android.systemui.media.controls.data.repository.mediaFilterRepository
import com.android.systemui.media.controls.shared.model.MediaData
import com.android.systemui.qs.ui.adapter.fakeQSSceneAdapter
-import com.android.systemui.qs.ui.adapter.qsSceneAdapter
import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.scene.domain.resolver.homeSceneFamilyResolver
@@ -47,6 +47,7 @@
import com.android.systemui.scene.shared.model.TransitionKeys.ToSplitShade
import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.shade.domain.startable.shadeStartable
+import com.android.systemui.shade.shared.flag.DualShade
import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.testKosmos
import com.android.systemui.unfold.fakeUnfoldTransitionProgressProvider
@@ -66,6 +67,7 @@
@RunWith(AndroidJUnit4::class)
@TestableLooper.RunWithLooper
@EnableSceneContainer
+@DisableFlags(DualShade.FLAG_NAME)
class ShadeSceneViewModelTest : SysuiTestCase() {
private val kosmos = testKosmos()
@@ -157,7 +159,7 @@
fun upTransitionKey_splitShadeEnabled_isGoneToSplitShade() =
testScope.runTest {
val destinationScenes by collectLastValue(underTest.destinationScenes)
- shadeRepository.setShadeMode(ShadeMode.Split)
+ shadeRepository.setShadeLayoutWide(true)
runCurrent()
assertThat(destinationScenes?.get(Swipe(SwipeDirection.Up))?.transitionKey)
@@ -168,7 +170,7 @@
fun upTransitionKey_splitShadeDisable_isNull() =
testScope.runTest {
val destinationScenes by collectLastValue(underTest.destinationScenes)
- shadeRepository.setShadeMode(ShadeMode.Single)
+ shadeRepository.setShadeLayoutWide(false)
runCurrent()
assertThat(destinationScenes?.get(Swipe(SwipeDirection.Up))?.transitionKey).isNull()
@@ -268,13 +270,13 @@
testScope.runTest {
val shadeMode by collectLastValue(underTest.shadeMode)
- shadeRepository.setShadeMode(ShadeMode.Split)
+ shadeRepository.setShadeLayoutWide(true)
assertThat(shadeMode).isEqualTo(ShadeMode.Split)
- shadeRepository.setShadeMode(ShadeMode.Single)
+ shadeRepository.setShadeLayoutWide(false)
assertThat(shadeMode).isEqualTo(ShadeMode.Single)
- shadeRepository.setShadeMode(ShadeMode.Split)
+ shadeRepository.setShadeLayoutWide(true)
assertThat(shadeMode).isEqualTo(ShadeMode.Split)
}
diff --git a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorTest.kt b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorTest.kt
index 50b77dc..1356e93 100644
--- a/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorTest.kt
+++ b/packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/notification/stack/domain/interactor/NotificationStackAppearanceInteractorTest.kt
@@ -22,7 +22,6 @@
import com.android.systemui.coroutines.collectLastValue
import com.android.systemui.kosmos.testScope
import com.android.systemui.shade.data.repository.shadeRepository
-import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimBounds
import com.android.systemui.statusbar.notification.stack.shared.model.ShadeScrimRounding
import com.android.systemui.testKosmos
@@ -66,11 +65,11 @@
testScope.runTest {
val stackRounding by collectLastValue(underTest.shadeScrimRounding)
- kosmos.shadeRepository.setShadeMode(ShadeMode.Single)
+ kosmos.shadeRepository.setShadeLayoutWide(false)
assertThat(stackRounding)
.isEqualTo(ShadeScrimRounding(isTopRounded = true, isBottomRounded = false))
- kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
+ kosmos.shadeRepository.setShadeLayoutWide(true)
assertThat(stackRounding)
.isEqualTo(ShadeScrimRounding(isTopRounded = true, isBottomRounded = true))
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
index 9f33113..c4b70d8 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardService.java
@@ -81,7 +81,6 @@
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.keyguard.domain.interactor.KeyguardEnabledInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardInteractor;
-import com.android.systemui.keyguard.domain.interactor.KeyguardWakeDirectlyToGoneInteractor;
import com.android.systemui.keyguard.ui.binder.KeyguardSurfaceBehindParamsApplier;
import com.android.systemui.keyguard.ui.binder.KeyguardSurfaceBehindViewBinder;
import com.android.systemui.keyguard.ui.binder.WindowManagerLockscreenVisibilityViewBinder;
@@ -318,7 +317,7 @@
private final WindowManagerOcclusionManager mWmOcclusionManager;
private final KeyguardEnabledInteractor mKeyguardEnabledInteractor;
- private final KeyguardWakeDirectlyToGoneInteractor mKeyguardWakeDirectlyToGoneInteractor;
+
private final Lazy<FoldGracePeriodProvider> mFoldGracePeriodProvider = new Lazy<>() {
@Override
public FoldGracePeriodProvider get() {
@@ -345,8 +344,7 @@
@Main Executor mainExecutor,
KeyguardInteractor keyguardInteractor,
KeyguardEnabledInteractor keyguardEnabledInteractor,
- Lazy<KeyguardStateCallbackStartable> keyguardStateCallbackStartableLazy,
- KeyguardWakeDirectlyToGoneInteractor keyguardWakeDirectlyToGoneInteractor) {
+ Lazy<KeyguardStateCallbackStartable> keyguardStateCallbackStartableLazy) {
super();
mKeyguardViewMediator = keyguardViewMediator;
mKeyguardLifecyclesDispatcher = keyguardLifecyclesDispatcher;
@@ -374,7 +372,6 @@
mWmOcclusionManager = windowManagerOcclusionManager;
mKeyguardEnabledInteractor = keyguardEnabledInteractor;
- mKeyguardWakeDirectlyToGoneInteractor = keyguardWakeDirectlyToGoneInteractor;
}
@Override
@@ -489,7 +486,6 @@
public void onDreamingStarted() {
trace("onDreamingStarted");
checkPermission();
- mKeyguardWakeDirectlyToGoneInteractor.onDreamingStarted();
mKeyguardInteractor.setDreaming(true);
mKeyguardViewMediator.onDreamingStarted();
}
@@ -498,7 +494,6 @@
public void onDreamingStopped() {
trace("onDreamingStopped");
checkPermission();
- mKeyguardWakeDirectlyToGoneInteractor.onDreamingStopped();
mKeyguardInteractor.setDreaming(false);
mKeyguardViewMediator.onDreamingStopped();
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
index ae751db..f837d8e 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/data/repository/KeyguardRepository.kt
@@ -127,30 +127,6 @@
*/
val isKeyguardEnabled: StateFlow<Boolean>
- /**
- * Whether we can transition directly back to GONE from AOD/DOZING without any authentication
- * events (such as a fingerprint wake and unlock), even though authentication would normally be
- * required. This means that if you tap the screen or press the power button, you'll return
- * directly to the unlocked app content without seeing the lockscreen, even if a secure
- * authentication method (PIN/password/biometrics) is set.
- *
- * This is true in these cases:
- * - The screen timed out, but the "lock after screen timeout" duration (default 5 seconds) has
- * not yet elapsed.
- * - The power button was pressed, but "power button instantly locks" is not enabled, and the
- * "lock after screen timeout" duration has not elapsed.
- *
- * Note that this value specifically tells us if we can *ignore* authentication that would
- * otherwise be required to transition from AOD/DOZING -> GONE. AOD/DOZING -> GONE is also
- * possible if keyguard is disabled, either from an app request or because security is set to
- * "none", but in that case, auth is not required so this boolean is not relevant.
- *
- * See [KeyguardWakeToGoneInteractor].
- */
- val canIgnoreAuthAndReturnToGone: StateFlow<Boolean>
-
- fun setCanIgnoreAuthAndReturnToGone(canWake: Boolean)
-
/** Is the always-on display available to be used? */
val isAodAvailable: StateFlow<Boolean>
@@ -410,13 +386,6 @@
MutableStateFlow(!lockPatternUtils.isLockScreenDisabled(userTracker.userId))
override val isKeyguardEnabled: StateFlow<Boolean> = _isKeyguardEnabled.asStateFlow()
- private val _canIgnoreAuthAndReturnToGone = MutableStateFlow(false)
- override val canIgnoreAuthAndReturnToGone = _canIgnoreAuthAndReturnToGone.asStateFlow()
-
- override fun setCanIgnoreAuthAndReturnToGone(canWakeToGone: Boolean) {
- _canIgnoreAuthAndReturnToGone.value = canWakeToGone
- }
-
private val _isDozing = MutableStateFlow(statusBarStateController.isDozing)
override val isDozing: StateFlow<Boolean> = _isDozing.asStateFlow()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
index 893835a..1426cba 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractor.kt
@@ -53,7 +53,6 @@
powerInteractor: PowerInteractor,
keyguardOcclusionInteractor: KeyguardOcclusionInteractor,
val deviceEntryRepository: DeviceEntryRepository,
- private val wakeToGoneInteractor: KeyguardWakeDirectlyToGoneInteractor,
) :
TransitionInteractor(
fromState = KeyguardState.AOD,
@@ -99,7 +98,6 @@
keyguardInteractor.primaryBouncerShowing,
keyguardInteractor.isKeyguardOccluded,
canDismissLockscreen,
- wakeToGoneInteractor.canWakeDirectlyToGone,
)
.collect {
(
@@ -109,7 +107,6 @@
primaryBouncerShowing,
isKeyguardOccludedLegacy,
canDismissLockscreen,
- canWakeDirectlyToGone,
) ->
if (!maybeHandleInsecurePowerGesture()) {
val shouldTransitionToLockscreen =
@@ -134,7 +131,8 @@
val shouldTransitionToGone =
(!KeyguardWmStateRefactor.isEnabled && canDismissLockscreen) ||
- (KeyguardWmStateRefactor.isEnabled && canWakeDirectlyToGone)
+ (KeyguardWmStateRefactor.isEnabled &&
+ !deviceEntryRepository.isLockscreenEnabled())
if (shouldTransitionToGone) {
// TODO(b/336576536): Check if adaptation for scene framework is needed
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
index aee65a8..76e88a2 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractor.kt
@@ -55,7 +55,6 @@
private val communalInteractor: CommunalInteractor,
keyguardOcclusionInteractor: KeyguardOcclusionInteractor,
val deviceEntryRepository: DeviceEntryRepository,
- private val wakeToGoneInteractor: KeyguardWakeDirectlyToGoneInteractor,
) :
TransitionInteractor(
fromState = KeyguardState.DOZING,
@@ -182,7 +181,7 @@
.sample(
communalInteractor.isIdleOnCommunal,
keyguardInteractor.biometricUnlockState,
- wakeToGoneInteractor.canWakeDirectlyToGone,
+ canTransitionToGoneOnWake,
keyguardInteractor.primaryBouncerShowing,
)
.collect {
@@ -190,14 +189,27 @@
_,
isIdleOnCommunal,
biometricUnlockState,
- canWakeDirectlyToGone,
+ canDismissLockscreen,
primaryBouncerShowing) ->
if (
!maybeStartTransitionToOccludedOrInsecureCamera() &&
// Handled by dismissFromDozing().
!isWakeAndUnlock(biometricUnlockState.mode)
) {
- if (canWakeDirectlyToGone) {
+ if (!KeyguardWmStateRefactor.isEnabled && canDismissLockscreen) {
+ if (SceneContainerFlag.isEnabled) {
+ // TODO(b/336576536): Check if adaptation for scene framework is
+ // needed
+ } else {
+ startTransitionTo(
+ KeyguardState.GONE,
+ ownerReason = "waking from dozing"
+ )
+ }
+ } else if (
+ KeyguardWmStateRefactor.isEnabled &&
+ !deviceEntryRepository.isLockscreenEnabled()
+ ) {
if (SceneContainerFlag.isEnabled) {
// TODO(b/336576536): Check if adaptation for scene framework is
// needed
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
index cfb161c..0e76487 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractor.kt
@@ -23,7 +23,6 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Background
import com.android.systemui.dagger.qualifiers.Main
-import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
import com.android.systemui.keyguard.KeyguardWmStateRefactor
import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
@@ -38,14 +37,11 @@
import kotlin.time.Duration.Companion.seconds
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.FlowPreview
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.debounce
-import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.launch
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class FromDreamingTransitionInteractor
@Inject
@@ -60,7 +56,6 @@
private val glanceableHubTransitions: GlanceableHubTransitions,
powerInteractor: PowerInteractor,
keyguardOcclusionInteractor: KeyguardOcclusionInteractor,
- private val deviceEntryInteractor: DeviceEntryInteractor,
) :
TransitionInteractor(
fromState = KeyguardState.DREAMING,
@@ -77,7 +72,7 @@
listenForDreamingToOccluded()
listenForDreamingToGoneWhenDismissable()
listenForDreamingToGoneFromBiometricUnlock()
- listenForDreamingToLockscreenOrGone()
+ listenForDreamingToLockscreen()
listenForDreamingToAodOrDozing()
listenForTransitionToCamera(scope, keyguardInteractor)
listenForDreamingToGlanceableHub()
@@ -137,7 +132,17 @@
@OptIn(FlowPreview::class)
private fun listenForDreamingToOccluded() {
- if (!KeyguardWmStateRefactor.isEnabled) {
+ if (KeyguardWmStateRefactor.isEnabled) {
+ scope.launch {
+ combine(
+ keyguardInteractor.isDreaming,
+ keyguardOcclusionInteractor.isShowWhenLockedActivityOnTop,
+ ::Pair
+ )
+ .filterRelevantKeyguardStateAnd { (isDreaming, _) -> !isDreaming }
+ .collect { maybeStartTransitionToOccludedOrInsecureCamera() }
+ }
+ } else {
scope.launch {
combine(
keyguardInteractor.isKeyguardOccluded,
@@ -163,41 +168,21 @@
}
}
- private fun listenForDreamingToLockscreenOrGone() {
+ private fun listenForDreamingToLockscreen() {
if (!KeyguardWmStateRefactor.isEnabled) {
return
}
scope.launch {
- keyguardInteractor.isDreaming
- .filter { !it }
- .sample(deviceEntryInteractor.isUnlocked, ::Pair)
- .collect { (_, dismissable) ->
- // TODO(b/349837588): Add check for -> OCCLUDED.
- if (dismissable) {
- startTransitionTo(
- KeyguardState.GONE,
- ownerReason = "No longer dreaming; dismissable"
- )
- } else {
- startTransitionTo(
- KeyguardState.LOCKSCREEN,
- ownerReason = "No longer dreaming"
- )
- }
- }
+ keyguardOcclusionInteractor.isShowWhenLockedActivityOnTop
+ .filterRelevantKeyguardStateAnd { onTop -> !onTop }
+ .collect { startTransitionTo(KeyguardState.LOCKSCREEN) }
}
}
private fun listenForDreamingToGoneWhenDismissable() {
- if (SceneContainerFlag.isEnabled) {
- return // TODO(b/336576536): Check if adaptation for scene framework is needed
- }
-
- if (KeyguardWmStateRefactor.isEnabled) {
- return
- }
-
+ // TODO(b/336576536): Check if adaptation for scene framework is needed
+ if (SceneContainerFlag.isEnabled) return
scope.launch {
keyguardInteractor.isAbleToDream
.sampleCombine(
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt
index 41c3959..e2bb540 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractor.kt
@@ -19,7 +19,6 @@
package com.android.systemui.keyguard.domain.interactor
-import android.content.Context
import com.android.systemui.CoreStartable
import com.android.systemui.biometrics.domain.interactor.FingerprintPropertyInteractor
import com.android.systemui.common.ui.domain.interactor.ConfigurationInteractor
@@ -32,15 +31,12 @@
import com.android.systemui.keyguard.ui.view.layout.blueprints.SplitShadeKeyguardBlueprint
import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Config
import com.android.systemui.keyguard.ui.view.layout.blueprints.transitions.IntraBlueprintTransition.Type
-import com.android.systemui.keyguard.ui.view.layout.sections.ClockSection
import com.android.systemui.keyguard.ui.view.layout.sections.SmartspaceSection
import com.android.systemui.shade.domain.interactor.ShadeInteractor
-import com.android.systemui.shade.shared.model.ShadeMode
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.StateFlow
-import kotlinx.coroutines.flow.collect
import kotlinx.coroutines.flow.filter
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.launch
@@ -51,13 +47,10 @@
constructor(
private val keyguardBlueprintRepository: KeyguardBlueprintRepository,
@Application private val applicationScope: CoroutineScope,
- private val context: Context,
- private val shadeInteractor: ShadeInteractor,
- private val clockInteractor: KeyguardClockInteractor,
+ shadeInteractor: ShadeInteractor,
private val configurationInteractor: ConfigurationInteractor,
private val fingerprintPropertyInteractor: FingerprintPropertyInteractor,
private val smartspaceSection: SmartspaceSection,
- private val clockSection: ClockSection,
) : CoreStartable {
/** The current blueprint for the lockscreen. */
val blueprint: StateFlow<KeyguardBlueprint> = keyguardBlueprintRepository.blueprint
@@ -70,8 +63,8 @@
/** Current BlueprintId */
val blueprintId =
- shadeInteractor.shadeMode.map { shadeMode ->
- val useSplitShade = shadeMode == ShadeMode.Split && !ComposeLockscreen.isEnabled
+ shadeInteractor.isShadeLayoutWide.map { isShadeLayoutWide ->
+ val useSplitShade = isShadeLayoutWide && !ComposeLockscreen.isEnabled
when {
useSplitShade -> SplitShadeKeyguardBlueprint.ID
else -> DefaultKeyguardBlueprint.DEFAULT
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
index 142b1a0..ab432d6 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardClockInteractor.kt
@@ -45,6 +45,7 @@
import kotlinx.coroutines.flow.stateIn
private val TAG = KeyguardClockInteractor::class.simpleName
+
/** Manages and encapsulates the clock components of the lockscreen root view. */
@SysUISingleton
class KeyguardClockInteractor
@@ -77,16 +78,16 @@
val clockSize: StateFlow<ClockSize> =
if (SceneContainerFlag.isEnabled) {
combine(
- shadeInteractor.shadeMode,
+ shadeInteractor.isShadeLayoutWide,
activeNotificationsInteractor.areAnyNotificationsPresent,
mediaCarouselInteractor.hasActiveMediaOrRecommendation,
keyguardInteractor.isDozing,
isOnAod,
- ) { shadeMode, hasNotifs, hasMedia, isDozing, isOnAod ->
+ ) { isShadeLayoutWide, hasNotifs, hasMedia, isDozing, isOnAod ->
return@combine when {
keyguardClockRepository.shouldForceSmallClock && !isOnAod -> ClockSize.SMALL
- shadeMode == ShadeMode.Single && (hasNotifs || hasMedia) -> ClockSize.SMALL
- shadeMode == ShadeMode.Single -> ClockSize.LARGE
+ !isShadeLayoutWide && (hasNotifs || hasMedia) -> ClockSize.SMALL
+ !isShadeLayoutWide -> ClockSize.LARGE
hasMedia && !isDozing -> ClockSize.SMALL
else -> ClockSize.LARGE
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractor.kt
deleted file mode 100644
index 6a1b7cf..0000000
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractor.kt
+++ /dev/null
@@ -1,367 +0,0 @@
-/*
- * Copyright (C) 2024 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.systemui.keyguard.domain.interactor
-
-import android.annotation.SuppressLint
-import android.app.AlarmManager
-import android.app.PendingIntent
-import android.content.BroadcastReceiver
-import android.content.Context
-import android.content.Intent
-import android.content.IntentFilter
-import android.provider.Settings
-import android.provider.Settings.Secure
-import com.android.internal.widget.LockPatternUtils
-import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.dagger.qualifiers.Application
-import com.android.systemui.keyguard.KeyguardViewMediator
-import com.android.systemui.keyguard.data.repository.KeyguardRepository
-import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
-import com.android.systemui.keyguard.shared.model.KeyguardState
-import com.android.systemui.keyguard.shared.model.KeyguardState.Companion.deviceIsAsleepInState
-import com.android.systemui.keyguard.shared.model.KeyguardState.Companion.deviceIsAwakeInState
-import com.android.systemui.power.domain.interactor.PowerInteractor
-import com.android.systemui.power.shared.model.WakeSleepReason
-import com.android.systemui.user.domain.interactor.SelectedUserInteractor
-import com.android.systemui.util.kotlin.sample
-import com.android.systemui.util.settings.SecureSettings
-import com.android.systemui.util.settings.SystemSettings
-import com.android.systemui.util.time.SystemClock
-import javax.inject.Inject
-import kotlin.math.max
-import kotlin.math.min
-import kotlinx.coroutines.CoroutineScope
-import kotlinx.coroutines.flow.Flow
-import kotlinx.coroutines.flow.combine
-import kotlinx.coroutines.flow.distinctUntilChanged
-import kotlinx.coroutines.flow.distinctUntilChangedBy
-import kotlinx.coroutines.flow.map
-import kotlinx.coroutines.launch
-
-/**
- * Logic related to the ability to wake directly to GONE from asleep (AOD/DOZING), without going
- * through LOCKSCREEN or a BOUNCER state.
- *
- * This is possible in the following scenarios:
- * - The lockscreen is disabled, either from an app request (SUW does this), or by the security
- * "None" setting.
- * - A biometric authentication event occurred while we were asleep (fingerprint auth, etc). This
- * specifically is referred to throughout the codebase as "wake and unlock".
- * - The screen timed out, but the "lock after screen timeout" duration has not elapsed.
- * - The power button was pressed, but "power button instantly locks" is disabled and the "lock
- * after screen timeout" duration has not elapsed.
- *
- * In these cases, no (further) authentication is required, and we can transition directly from
- * AOD/DOZING -> GONE.
- */
-@SysUISingleton
-class KeyguardWakeDirectlyToGoneInteractor
-@Inject
-constructor(
- @Application private val scope: CoroutineScope,
- private val context: Context,
- private val repository: KeyguardRepository,
- private val systemClock: SystemClock,
- private val alarmManager: AlarmManager,
- private val transitionInteractor: KeyguardTransitionInteractor,
- private val powerInteractor: PowerInteractor,
- private val secureSettings: SecureSettings,
- private val lockPatternUtils: LockPatternUtils,
- private val systemSettings: SystemSettings,
- private val selectedUserInteractor: SelectedUserInteractor,
-) {
-
- /**
- * Whether the lockscreen was disabled as of the last wake/sleep event, according to
- * LockPatternUtils.
- *
- * This will always be true if [repository.isKeyguardServiceEnabled]=false, but it can also be
- * true when the keyguard service is enabled if the lockscreen has been disabled via adb using
- * the `adb shell locksettings set-disabled true` command, which is often done in tests.
- *
- * Unlike keyguardServiceEnabled, changes to this value should *not* immediately show or hide
- * the keyguard. If the lockscreen is disabled in this way, it will just not show on the next
- * sleep/wake.
- */
- private val isLockscreenDisabled: Flow<Boolean> =
- powerInteractor.isAwake.map { isLockscreenDisabled() }
-
- /**
- * Whether we can wake from AOD/DOZING directly to GONE, bypassing LOCKSCREEN/BOUNCER states.
- *
- * This is possible in the following cases:
- * - Keyguard is disabled, either from an app request or from security being set to "None".
- * - We're wake and unlocking (fingerprint auth occurred while asleep).
- * - We're allowed to ignore auth and return to GONE, due to timeouts not elapsing.
- */
- val canWakeDirectlyToGone =
- combine(
- repository.isKeyguardEnabled,
- isLockscreenDisabled,
- repository.biometricUnlockState,
- repository.canIgnoreAuthAndReturnToGone,
- ) {
- keyguardEnabled,
- isLockscreenDisabled,
- biometricUnlockState,
- canIgnoreAuthAndReturnToGone ->
- (!keyguardEnabled || isLockscreenDisabled) ||
- BiometricUnlockMode.isWakeAndUnlock(biometricUnlockState.mode) ||
- canIgnoreAuthAndReturnToGone
- }
- .distinctUntilChanged()
-
- /**
- * Counter that is incremented every time we wake up or stop dreaming. Upon sleeping/dreaming,
- * we put the current value of this counter into the intent extras of the timeout alarm intent.
- * If this value has changed by the time we receive the intent, it is discarded since it's out
- * of date.
- */
- var timeoutCounter = 0
-
- var isAwake = false
-
- private val broadcastReceiver: BroadcastReceiver =
- object : BroadcastReceiver() {
- override fun onReceive(context: Context, intent: Intent) {
- if (DELAYED_KEYGUARD_ACTION == intent.action) {
- val sequence = intent.getIntExtra(SEQ_EXTRA_KEY, 0)
- synchronized(this) {
- if (timeoutCounter == sequence) {
- // If the sequence # matches, we have not woken up or stopped dreaming
- // since
- // the alarm was set. That means this is still relevant - the lock
- // timeout
- // has elapsed, so let the repository know that we can no longer return
- // to
- // GONE without authenticating.
- repository.setCanIgnoreAuthAndReturnToGone(false)
- }
- }
- }
- }
- }
-
- init {
- setOrCancelAlarmFromWakefulness()
- listenForWakeToClearCanIgnoreAuth()
- registerBroadcastReceiver()
- }
-
- fun onDreamingStarted() {
- // If we start dreaming while awake, lock after the normal timeout.
- if (isAwake) {
- setResetCanIgnoreAuthAlarm()
- }
- }
-
- fun onDreamingStopped() {
- // Cancel the timeout if we stop dreaming while awake.
- if (isAwake) {
- cancelCanIgnoreAuthAlarm()
- }
- }
-
- private fun setOrCancelAlarmFromWakefulness() {
- scope.launch {
- powerInteractor.detailedWakefulness
- .distinctUntilChangedBy { it.isAwake() }
- .sample(transitionInteractor.currentKeyguardState, ::Pair)
- .collect { (wakefulness, currentState) ->
- // Save isAwake for use in onDreamingStarted/onDreamingStopped.
- this@KeyguardWakeDirectlyToGoneInteractor.isAwake = wakefulness.isAwake()
-
- // If we're sleeping from GONE, check the timeout and lock instantly settings.
- // These are not relevant if we're coming from non-GONE states.
- if (!isAwake && currentState == KeyguardState.GONE) {
- val lockTimeoutDuration = getCanIgnoreAuthAndReturnToGoneDuration()
-
- // If the screen timed out and went to sleep, and the lock timeout is > 0ms,
- // then we can return to GONE until that duration elapses. If the power
- // button was pressed but "instantly locks" is disabled, then we can also
- // return to GONE until the timeout duration elapses.
- if (
- (wakefulness.lastSleepReason == WakeSleepReason.TIMEOUT &&
- lockTimeoutDuration > 0) ||
- (wakefulness.lastSleepReason == WakeSleepReason.POWER_BUTTON &&
- !willLockImmediately())
- ) {
-
- // Let the repository know that we can return to GONE until we notify
- // it otherwise.
- repository.setCanIgnoreAuthAndReturnToGone(true)
- setResetCanIgnoreAuthAlarm()
- }
- } else if (isAwake) {
- // If we're waking up, ignore the alarm if it goes off since it's no longer
- // relevant. Once a wake KeyguardTransition is started, we'll also clear the
- // canIgnoreAuthAndReturnToGone value in listenForWakeToClearCanIgnoreAuth.
- cancelCanIgnoreAuthAlarm()
- }
- }
- }
- }
-
- /** Clears the canIgnoreAuthAndReturnToGone value upon waking. */
- private fun listenForWakeToClearCanIgnoreAuth() {
- scope.launch {
- transitionInteractor
- .isInTransitionWhere(
- fromStatePredicate = { deviceIsAsleepInState(it) },
- toStatePredicate = { deviceIsAwakeInState(it) },
- )
- .collect {
- // This value is reset when the timeout alarm fires, but if the device is woken
- // back up before then, it needs to be reset here. The alarm is cancelled
- // immediately upon waking up, but since this value is used by keyguard
- // transition internals to decide whether we can transition to GONE, wait until
- // that decision is made before resetting it.
- repository.setCanIgnoreAuthAndReturnToGone(false)
- }
- }
- }
-
- /**
- * Registers the broadcast receiver to receive the alarm intent.
- *
- * TODO(b/351817381): Investigate using BroadcastDispatcher vs. ignoring this lint warning.
- */
- @SuppressLint("WrongConstant", "RegisterReceiverViaContext")
- private fun registerBroadcastReceiver() {
- val delayedActionFilter = IntentFilter()
- delayedActionFilter.addAction(KeyguardViewMediator.DELAYED_KEYGUARD_ACTION)
- // TODO(b/346803756): Listen for DELAYED_LOCK_PROFILE_ACTION.
- delayedActionFilter.priority = IntentFilter.SYSTEM_HIGH_PRIORITY
- context.registerReceiver(
- broadcastReceiver,
- delayedActionFilter,
- SYSTEMUI_PERMISSION,
- null /* scheduler */,
- Context.RECEIVER_EXPORTED_UNAUDITED
- )
- }
-
- /** Set an alarm for */
- private fun setResetCanIgnoreAuthAlarm() {
- val intent =
- Intent(DELAYED_KEYGUARD_ACTION).apply {
- setPackage(context.packageName)
- putExtra(SEQ_EXTRA_KEY, timeoutCounter)
- addFlags(Intent.FLAG_RECEIVER_FOREGROUND)
- }
-
- val sender =
- PendingIntent.getBroadcast(
- context,
- 0,
- intent,
- PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE
- )
-
- val time = systemClock.elapsedRealtime() + getCanIgnoreAuthAndReturnToGoneDuration()
- alarmManager.setExactAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP, time, sender)
-
- // TODO(b/346803756): Migrate support for child profiles.
- }
-
- /**
- * Cancel the timeout by incrementing the counter so that we ignore the intent when it's
- * received.
- */
- private fun cancelCanIgnoreAuthAlarm() {
- timeoutCounter++
- }
-
- /**
- * Whether pressing the power button locks the device immediately; vs. waiting for a specified
- * timeout first.
- */
- private fun willLockImmediately(
- userId: Int = selectedUserInteractor.getSelectedUserId()
- ): Boolean {
- return lockPatternUtils.getPowerButtonInstantlyLocks(userId) ||
- !lockPatternUtils.isSecure(userId)
- }
-
- /**
- * Returns whether the lockscreen is disabled, either because the keyguard service is disabled
- * or because an adb command has disabled the lockscreen.
- */
- private fun isLockscreenDisabled(
- userId: Int = selectedUserInteractor.getSelectedUserId()
- ): Boolean {
- return lockPatternUtils.isLockScreenDisabled(userId)
- }
-
- /**
- * Returns the duration within which we can return to GONE without auth after a screen timeout
- * (or power button press, if lock instantly is disabled).
- *
- * This takes into account the user's settings as well as device policy maximums.
- */
- private fun getCanIgnoreAuthAndReturnToGoneDuration(
- userId: Int = selectedUserInteractor.getSelectedUserId()
- ): Long {
- // The timeout duration from settings (Security > Device Unlock > Gear icon > "Lock after
- // screen timeout".
- val durationSetting: Long =
- secureSettings
- .getIntForUser(
- Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT,
- KEYGUARD_CAN_IGNORE_AUTH_DURATION,
- userId
- )
- .toLong()
-
- // Device policy maximum timeout.
- val durationDevicePolicyMax =
- lockPatternUtils.devicePolicyManager.getMaximumTimeToLock(null, userId)
-
- return if (durationDevicePolicyMax <= 0) {
- durationSetting
- } else {
- var displayTimeout =
- systemSettings
- .getIntForUser(
- Settings.System.SCREEN_OFF_TIMEOUT,
- KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT,
- userId
- )
- .toLong()
-
- // Ignore negative values. I don't know why this would be negative, but this check has
- // been around since 2016 and I see no upside to removing it.
- displayTimeout = max(displayTimeout, 0)
-
- // Respect the shorter of: the device policy (maximum duration between last user action
- // and fully locking) or the "Lock after screen timeout" setting.
- max(min(durationDevicePolicyMax - displayTimeout, durationSetting), 0)
- }
- }
-
- companion object {
- private const val DELAYED_KEYGUARD_ACTION =
- "com.android.internal.policy.impl.PhoneWindowManager.DELAYED_KEYGUARD"
- private const val DELAYED_LOCK_PROFILE_ACTION =
- "com.android.internal.policy.impl.PhoneWindowManager.DELAYED_LOCK"
- private const val SYSTEMUI_PERMISSION = "com.android.systemui.permission.SELF"
- private const val SEQ_EXTRA_KEY = "count"
-
- private const val KEYGUARD_CAN_IGNORE_AUTH_DURATION = 5000
- private const val KEYGUARD_DISPLAY_TIMEOUT_DELAY_DEFAULT = 30000
- }
-}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt
index e1b333d..523370c 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractor.kt
@@ -21,17 +21,14 @@
import com.android.compose.animation.scene.ObservableTransitionState
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.deviceentry.domain.interactor.DeviceEntryInteractor
-import com.android.systemui.keyguard.data.repository.KeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
import com.android.systemui.keyguard.shared.model.Edge
import com.android.systemui.keyguard.shared.model.KeyguardState
-import com.android.systemui.keyguard.shared.model.KeyguardState.Companion.deviceIsAsleepInState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.flag.SceneContainerFlag
import com.android.systemui.scene.shared.model.Scenes
import com.android.systemui.statusbar.notification.domain.interactor.NotificationLaunchAnimationInteractor
-import com.android.systemui.util.kotlin.Utils.Companion.toTriple
import com.android.systemui.util.kotlin.sample
import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated
import dagger.Lazy
@@ -44,13 +41,11 @@
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
-@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class WindowManagerLockscreenVisibilityInteractor
@Inject
constructor(
keyguardInteractor: KeyguardInteractor,
- transitionRepository: KeyguardTransitionRepository,
transitionInteractor: KeyguardTransitionInteractor,
surfaceBehindInteractor: KeyguardSurfaceBehindInteractor,
fromLockscreenInteractor: FromLockscreenTransitionInteractor,
@@ -59,15 +54,9 @@
notificationLaunchAnimationInteractor: NotificationLaunchAnimationInteractor,
sceneInteractor: Lazy<SceneInteractor>,
deviceEntryInteractor: Lazy<DeviceEntryInteractor>,
- wakeToGoneInteractor: KeyguardWakeDirectlyToGoneInteractor,
) {
private val defaultSurfaceBehindVisibility =
- combine(
- transitionInteractor.finishedKeyguardState,
- wakeToGoneInteractor.canWakeDirectlyToGone,
- ) { finishedState, canWakeDirectlyToGone ->
- isSurfaceVisible(finishedState) || canWakeDirectlyToGone
- }
+ transitionInteractor.finishedKeyguardState.map(::isSurfaceVisible)
/**
* Surface visibility provided by the From*TransitionInteractor responsible for the currently
@@ -215,13 +204,9 @@
if (SceneContainerFlag.isEnabled) {
isDeviceNotEntered
} else {
- combine(
- transitionInteractor.currentKeyguardState,
- wakeToGoneInteractor.canWakeDirectlyToGone,
- ::Pair
- )
- .sample(transitionInteractor.startedStepWithPrecedingStep, ::toTriple)
- .map { (currentState, canWakeDirectlyToGone, startedWithPrev) ->
+ transitionInteractor.currentKeyguardState
+ .sample(transitionInteractor.startedStepWithPrecedingStep, ::Pair)
+ .map { (currentState, startedWithPrev) ->
val startedFromStep = startedWithPrev.previousValue
val startedStep = startedWithPrev.newValue
val returningToGoneAfterCancellation =
@@ -229,33 +214,16 @@
startedFromStep.transitionState == TransitionState.CANCELED &&
startedFromStep.from == KeyguardState.GONE
- val transitionInfo = transitionRepository.currentTransitionInfoInternal.value
- val wakingDirectlyToGone =
- deviceIsAsleepInState(transitionInfo.from) &&
- transitionInfo.to == KeyguardState.GONE
-
- if (returningToGoneAfterCancellation || wakingDirectlyToGone) {
- // GONE -> AOD/DOZING (cancel) -> GONE is the camera launch transition,
- // which means we never want to show the lockscreen throughout the
- // transition. Same for waking directly to gone, due to the lockscreen being
- // disabled or because the device was woken back up before the lock timeout
- // duration elapsed.
- KeyguardState.lockscreenVisibleInState(KeyguardState.GONE)
- } else if (canWakeDirectlyToGone) {
- // Never show the lockscreen if we can wake directly to GONE. This means
- // that the lock timeout has not yet elapsed, or the keyguard is disabled.
- // In either case, we don't show the activity lock screen until one of those
- // conditions changes.
- false
- } else if (
- currentState == KeyguardState.DREAMING &&
- deviceEntryInteractor.get().isUnlocked.value
- ) {
- // Dreams dismiss keyguard and return to GONE if they can.
- false
+ if (!returningToGoneAfterCancellation) {
+ // By default, apply the lockscreen visibility of the current state.
+ deviceEntryInteractor.get().isLockscreenEnabled() &&
+ KeyguardState.lockscreenVisibleInState(currentState)
} else {
- // Otherwise, use the visibility of the current state.
- KeyguardState.lockscreenVisibleInState(currentState)
+ // If we're transitioning to GONE after a prior canceled transition from
+ // GONE, then this is the camera launch transition from an asleep state back
+ // to GONE. We don't want to show the lockscreen since we're aborting the
+ // lock and going back to GONE.
+ KeyguardState.lockscreenVisibleInState(KeyguardState.GONE)
}
}
.distinctUntilChanged()
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt
index 573b75e..73028c5 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModel.kt
@@ -30,7 +30,6 @@
import com.android.systemui.keyguard.shared.model.ClockSizeSetting
import com.android.systemui.res.R
import com.android.systemui.shade.domain.interactor.ShadeInteractor
-import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.notification.icon.ui.viewmodel.NotificationIconContainerAlwaysOnDisplayViewModel
import com.android.systemui.statusbar.ui.SystemBarUtilsProxy
import javax.inject.Inject
@@ -119,26 +118,25 @@
combine(
isLargeClockVisible,
clockShouldBeCentered,
- shadeInteractor.shadeMode,
+ shadeInteractor.isShadeLayoutWide,
currentClock,
- ) { isLargeClockVisible, clockShouldBeCentered, shadeMode, currentClock ->
- val shouldUseSplitShade = shadeMode == ShadeMode.Split
+ ) { isLargeClockVisible, clockShouldBeCentered, isShadeLayoutWide, currentClock ->
if (currentClock?.config?.useCustomClockScene == true) {
when {
- shouldUseSplitShade && clockShouldBeCentered ->
+ isShadeLayoutWide && clockShouldBeCentered ->
ClockLayout.WEATHER_LARGE_CLOCK
- shouldUseSplitShade && isLargeClockVisible ->
+ isShadeLayoutWide && isLargeClockVisible ->
ClockLayout.SPLIT_SHADE_WEATHER_LARGE_CLOCK
- shouldUseSplitShade -> ClockLayout.SPLIT_SHADE_SMALL_CLOCK
+ isShadeLayoutWide -> ClockLayout.SPLIT_SHADE_SMALL_CLOCK
isLargeClockVisible -> ClockLayout.WEATHER_LARGE_CLOCK
else -> ClockLayout.SMALL_CLOCK
}
} else {
when {
- shouldUseSplitShade && clockShouldBeCentered -> ClockLayout.LARGE_CLOCK
- shouldUseSplitShade && isLargeClockVisible ->
+ isShadeLayoutWide && clockShouldBeCentered -> ClockLayout.LARGE_CLOCK
+ isShadeLayoutWide && isLargeClockVisible ->
ClockLayout.SPLIT_SHADE_LARGE_CLOCK
- shouldUseSplitShade -> ClockLayout.SPLIT_SHADE_SMALL_CLOCK
+ isShadeLayoutWide -> ClockLayout.SPLIT_SHADE_SMALL_CLOCK
isLargeClockVisible -> ClockLayout.LARGE_CLOCK
else -> ClockLayout.SMALL_CLOCK
}
@@ -164,7 +162,7 @@
/** Calculates the top margin for the small clock. */
fun getSmallClockTopMargin(): Int {
val statusBarHeight = systemBarUtils.getStatusBarHeaderHeightKeyguard()
- return if (shadeInteractor.shadeMode.value == ShadeMode.Split) {
+ return if (shadeInteractor.isShadeLayoutWide.value) {
resources.getDimensionPixelSize(R.dimen.keyguard_split_shade_top_margin) -
if (ComposeLockscreen.isEnabled) statusBarHeight else 0
} else {
@@ -176,7 +174,7 @@
val smallClockTopMargin =
combine(
configurationInteractor.onAnyConfigurationChange,
- shadeInteractor.shadeMode,
+ shadeInteractor.isShadeLayoutWide,
) { _, _ ->
getSmallClockTopMargin()
}
diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt
index 8a29f96..3b337fc 100644
--- a/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt
+++ b/packages/SystemUI/src/com/android/systemui/keyguard/ui/viewmodel/LockscreenContentViewModel.kt
@@ -27,7 +27,6 @@
import com.android.systemui.res.R
import com.android.systemui.scene.domain.interactor.SceneContainerOcclusionInteractor
import com.android.systemui.shade.domain.interactor.ShadeInteractor
-import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.unfold.domain.interactor.UnfoldTransitionInteractor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
@@ -56,21 +55,14 @@
val isUdfpsVisible: Boolean
get() = authController.isUdfpsSupported
- val shouldUseSplitNotificationShade: StateFlow<Boolean> =
- shadeInteractor.shadeMode
- .map { it == ShadeMode.Split }
- .stateIn(
- scope = applicationScope,
- started = SharingStarted.WhileSubscribed(),
- initialValue = false,
- )
+ val isShadeLayoutWide: StateFlow<Boolean> = shadeInteractor.isShadeLayoutWide
val areNotificationsVisible: StateFlow<Boolean> =
combine(
clockSize,
- shouldUseSplitNotificationShade,
- ) { clockSize, shouldUseSplitNotificationShade ->
- clockSize == ClockSize.SMALL || shouldUseSplitNotificationShade
+ shadeInteractor.isShadeLayoutWide,
+ ) { clockSize, isShadeLayoutWide ->
+ clockSize == ClockSize.SMALL || isShadeLayoutWide
}
.stateIn(
scope = applicationScope,
diff --git a/packages/SystemUI/src/com/android/systemui/power/shared/model/WakeSleepReason.kt b/packages/SystemUI/src/com/android/systemui/power/shared/model/WakeSleepReason.kt
index 776a8f4..75055668 100644
--- a/packages/SystemUI/src/com/android/systemui/power/shared/model/WakeSleepReason.kt
+++ b/packages/SystemUI/src/com/android/systemui/power/shared/model/WakeSleepReason.kt
@@ -54,10 +54,7 @@
OTHER(isTouch = false, PowerManager.WAKE_REASON_UNKNOWN),
/** Device goes to sleep due to folding of a foldable device. */
- FOLD(isTouch = false, PowerManager.GO_TO_SLEEP_REASON_DEVICE_FOLD),
-
- /** Device goes to sleep because it timed out. */
- TIMEOUT(isTouch = false, PowerManager.GO_TO_SLEEP_REASON_TIMEOUT);
+ FOLD(isTouch = false, PowerManager.GO_TO_SLEEP_REASON_DEVICE_FOLD);
companion object {
fun fromPowerManagerWakeReason(reason: Int): WakeSleepReason {
@@ -78,7 +75,6 @@
fun fromPowerManagerSleepReason(reason: Int): WakeSleepReason {
return when (reason) {
PowerManager.GO_TO_SLEEP_REASON_POWER_BUTTON -> POWER_BUTTON
- PowerManager.GO_TO_SLEEP_REASON_TIMEOUT -> TIMEOUT
PowerManager.GO_TO_SLEEP_REASON_DEVICE_FOLD -> FOLD
else -> OTHER
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
index 4d43ad5..a4fed873 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/data/repository/ShadeRepository.kt
@@ -19,8 +19,6 @@
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.res.R
-import com.android.systemui.shade.shared.flag.DualShade
-import com.android.systemui.shade.shared.model.ShadeMode
import javax.inject.Inject
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
@@ -105,18 +103,26 @@
@Deprecated("Use ShadeInteractor.isQsBypassingShade instead")
val legacyExpandImmediate: StateFlow<Boolean>
- val shadeMode: StateFlow<ShadeMode>
-
/** Whether dual shade should be aligned to the bottom (true) or to the top (false). */
val isDualShadeAlignedToBottom: Boolean
+ /**
+ * Whether the shade layout should be wide (true) or narrow (false).
+ *
+ * In a wide layout, notifications and quick settings each take up only half the screen width
+ * (whether they are shown at the same time or not). In a narrow layout, they can each be as
+ * wide as the entire screen.
+ */
+ val isShadeLayoutWide: StateFlow<Boolean>
+
/** True when QS is taking up the entire screen, i.e. fully expanded on a non-unfolded phone. */
@Deprecated("Use ShadeInteractor instead") val legacyQsFullscreen: StateFlow<Boolean>
/** NPVC.mClosing as a flow. */
@Deprecated("Use ShadeAnimationInteractor instead") val legacyIsClosing: StateFlow<Boolean>
- fun setShadeMode(mode: ShadeMode)
+ /** Sets whether the shade layout should be wide (true) or narrow (false). */
+ fun setShadeLayoutWide(isShadeLayoutWide: Boolean)
/** Sets whether a closing animation is happening. */
@Deprecated("Use ShadeAnimationInteractor instead") fun setLegacyIsClosing(isClosing: Boolean)
@@ -183,6 +189,7 @@
class ShadeRepositoryImpl @Inject constructor(@Application applicationContext: Context) :
ShadeRepository {
private val _qsExpansion = MutableStateFlow(0f)
+ @Deprecated("Use ShadeInteractor.qsExpansion instead")
override val qsExpansion: StateFlow<Float> = _qsExpansion.asStateFlow()
private val _lockscreenShadeExpansion = MutableStateFlow(0f)
@@ -204,6 +211,7 @@
@Deprecated("Use ShadeInteractor instead")
override val legacyShadeTracking: StateFlow<Boolean> = _legacyShadeTracking.asStateFlow()
+ @Deprecated("Use ShadeInteractor.isUserInteractingWithShade instead")
override val legacyLockscreenShadeTracking = MutableStateFlow(false)
private val _legacyQsTracking = MutableStateFlow(false)
@@ -227,20 +235,22 @@
@Deprecated("Use ShadeInteractor instead")
override val legacyQsFullscreen: StateFlow<Boolean> = _legacyQsFullscreen.asStateFlow()
- val _shadeMode = MutableStateFlow(if (DualShade.isEnabled) ShadeMode.Dual else ShadeMode.Single)
- override val shadeMode: StateFlow<ShadeMode> = _shadeMode.asStateFlow()
+ private val _isShadeLayoutWide = MutableStateFlow(false)
+ override val isShadeLayoutWide: StateFlow<Boolean> = _isShadeLayoutWide.asStateFlow()
override val isDualShadeAlignedToBottom =
applicationContext.resources.getBoolean(R.bool.config_dualShadeAlignedToBottom)
- override fun setShadeMode(shadeMode: ShadeMode) {
- _shadeMode.value = shadeMode
+ override fun setShadeLayoutWide(isShadeLayoutWide: Boolean) {
+ _isShadeLayoutWide.value = isShadeLayoutWide
}
+ @Deprecated("Use ShadeInteractor instead")
override fun setLegacyQsFullscreen(legacyQsFullscreen: Boolean) {
_legacyQsFullscreen.value = legacyQsFullscreen
}
+ @Deprecated("Use ShadeInteractor instead")
override fun setLegacyExpandImmediate(legacyExpandImmediate: Boolean) {
_legacyExpandImmediate.value = legacyExpandImmediate
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
index ef0a842..c1f8a0b 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractor.kt
@@ -52,9 +52,21 @@
/** Are touches allowed on the notification panel? */
val isShadeTouchable: Flow<Boolean>
- /** Emits true if the shade can be expanded from QQS to QS and false otherwise. */
+ /** Whether the shade can be expanded from QQS to QS. */
val isExpandToQsEnabled: Flow<Boolean>
+ /** The version of the shade layout to use. */
+ val shadeMode: StateFlow<ShadeMode>
+
+ /**
+ * Whether the shade layout should be wide (true) or narrow (false).
+ *
+ * In a wide layout, notifications and quick settings each take up only half the screen width
+ * (whether they are shown at the same time or not). In a narrow layout, they can each be as
+ * wide as the entire screen.
+ */
+ val isShadeLayoutWide: StateFlow<Boolean>
+
/** How to align the shade content. */
val shadeAlignment: ShadeAlignment
}
@@ -113,8 +125,6 @@
* animating.
*/
val isUserInteractingWithQs: Flow<Boolean>
-
- val shadeMode: StateFlow<ShadeMode>
}
fun createAnyExpansionFlow(
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt
index 6226d07..e77aca9 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorEmptyImpl.kt
@@ -47,5 +47,6 @@
override val isShadeTouchable: Flow<Boolean> = inactiveFlowBoolean
override val isExpandToQsEnabled: Flow<Boolean> = inactiveFlowBoolean
override val shadeMode: StateFlow<ShadeMode> = MutableStateFlow(ShadeMode.Single)
+ override val isShadeLayoutWide: StateFlow<Boolean> = inactiveFlowBoolean
override val shadeAlignment: ShadeAlignment = ShadeAlignment.Top
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt
index 55f019b..684a484 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorImpl.kt
@@ -25,7 +25,9 @@
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.shade.data.repository.ShadeRepository
+import com.android.systemui.shade.shared.flag.DualShade
import com.android.systemui.shade.shared.model.ShadeAlignment
+import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.disableflags.data.repository.DisableFlagsRepository
import com.android.systemui.statusbar.phone.DozeParameters
import com.android.systemui.statusbar.policy.data.repository.UserSetupRepository
@@ -60,8 +62,7 @@
) : ShadeInteractor, BaseShadeInteractor by baseShadeInteractor {
override val isShadeEnabled: StateFlow<Boolean> =
disableFlagsRepository.disableFlags
- .map { isDisabledByFlags -> isDisabledByFlags.isShadeEnabled() }
- .distinctUntilChanged()
+ .map { it.isShadeEnabled() }
.stateIn(scope, SharingStarted.Eagerly, initialValue = false)
override val isQsEnabled: StateFlow<Boolean> =
@@ -102,6 +103,17 @@
}
}
+ override val isShadeLayoutWide: StateFlow<Boolean> = shadeRepository.isShadeLayoutWide
+
+ override val shadeMode: StateFlow<ShadeMode> =
+ isShadeLayoutWide
+ .map(this::determineShadeMode)
+ .stateIn(
+ scope,
+ SharingStarted.Eagerly,
+ initialValue = determineShadeMode(isShadeLayoutWide.value)
+ )
+
override val shadeAlignment: ShadeAlignment =
if (shadeRepository.isDualShadeAlignedToBottom) {
ShadeAlignment.Bottom
@@ -125,4 +137,12 @@
disableFlags.isQuickSettingsEnabled() &&
!isDozing
}
+
+ private fun determineShadeMode(isShadeLayoutWide: Boolean): ShadeMode {
+ return when {
+ DualShade.isEnabled -> ShadeMode.Dual
+ isShadeLayoutWide -> ShadeMode.Split
+ else -> ShadeMode.Single
+ }
+ }
}
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImpl.kt
index 7d46d2b..f39ee9a 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorLegacyImpl.kt
@@ -21,7 +21,6 @@
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.keyguard.shared.model.StatusBarState
import com.android.systemui.shade.data.repository.ShadeRepository
-import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
@@ -105,8 +104,6 @@
override val isUserInteractingWithQs: Flow<Boolean> =
userInteractingFlow(repository.legacyQsTracking, repository.qsExpansion)
- override val shadeMode: StateFlow<ShadeMode> = repository.shadeMode
-
/**
* Return a flow for whether a user is interacting with an expandable shade component using
* tracking and expansion flows. NOTE: expansion must be a `StateFlow` to guarantee that
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt
index d5b4f4d..b2142a5 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/interactor/ShadeInteractorSceneContainerImpl.kt
@@ -22,8 +22,6 @@
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.scene.domain.interactor.SceneInteractor
import com.android.systemui.scene.shared.model.SceneFamilies
-import com.android.systemui.shade.data.repository.ShadeRepository
-import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.notification.stack.domain.interactor.SharedNotificationContainerInteractor
import com.android.systemui.utils.coroutines.flow.flatMapLatestConflated
import javax.inject.Inject
@@ -45,10 +43,7 @@
@Application scope: CoroutineScope,
sceneInteractor: SceneInteractor,
sharedNotificationContainerInteractor: SharedNotificationContainerInteractor,
- shadeRepository: ShadeRepository,
) : BaseShadeInteractor {
- override val shadeMode: StateFlow<ShadeMode> = shadeRepository.shadeMode
-
override val shadeExpansion: StateFlow<Float> =
sceneBasedExpansion(sceneInteractor, SceneFamilies.NotifShade)
.stateIn(scope, SharingStarted.Eagerly, 0f)
diff --git a/packages/SystemUI/src/com/android/systemui/shade/domain/startable/ShadeStartable.kt b/packages/SystemUI/src/com/android/systemui/shade/domain/startable/ShadeStartable.kt
index 354d379..5eb3a1c 100644
--- a/packages/SystemUI/src/com/android/systemui/shade/domain/startable/ShadeStartable.kt
+++ b/packages/SystemUI/src/com/android/systemui/shade/domain/startable/ShadeStartable.kt
@@ -29,8 +29,6 @@
import com.android.systemui.shade.TouchLogger.Companion.logTouchesTo
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.shade.domain.interactor.PanelExpansionInteractor
-import com.android.systemui.shade.shared.flag.DualShade
-import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.shade.transition.ScrimShadeTransitionController
import com.android.systemui.statusbar.PulseExpansionHandler
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayoutController
@@ -40,7 +38,6 @@
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.launchIn
-import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import kotlinx.coroutines.launch
@@ -63,7 +60,7 @@
) : CoreStartable {
override fun start() {
- hydrateShadeMode()
+ hydrateShadeLayoutWidth()
hydrateShadeExpansionStateManager()
logTouchesTo(touchLog)
scrimShadeTransitionController.init()
@@ -86,22 +83,17 @@
}
}
- private fun hydrateShadeMode() {
- if (DualShade.isEnabled) {
- shadeRepository.setShadeMode(ShadeMode.Dual)
- return
- }
+ private fun hydrateShadeLayoutWidth() {
applicationScope.launch {
configurationRepository.onAnyConfigurationChange
// Force initial collection.
.onStart { emit(Unit) }
- .map { applicationContext.resources }
- .map { resources ->
- splitShadeStateController.shouldUseSplitNotificationShade(resources)
- }
- .collect { isSplitShade ->
- shadeRepository.setShadeMode(
- if (isSplitShade) ShadeMode.Split else ShadeMode.Single
+ .collect {
+ val resources = applicationContext.resources
+ // The configuration for 'shouldUseSplitNotificationShade' dictates the width of
+ // the shade in both split-shade and dual-shade modes.
+ shadeRepository.setShadeLayoutWide(
+ splitShadeStateController.shouldUseSplitNotificationShade(resources)
)
}
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
index e505ef7..0957e5a 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/StatusBarStateControllerImpl.java
@@ -51,6 +51,7 @@
import com.android.systemui.keyguard.MigrateClocksToBlueprint;
import com.android.systemui.keyguard.domain.interactor.KeyguardClockInteractor;
import com.android.systemui.keyguard.domain.interactor.KeyguardTransitionInteractor;
+import com.android.systemui.keyguard.shared.model.KeyguardState;
import com.android.systemui.plugins.statusbar.StatusBarStateController.StateListener;
import com.android.systemui.res.R;
import com.android.systemui.scene.domain.interactor.SceneContainerOcclusionInteractor;
@@ -223,6 +224,10 @@
mSceneContainerOcclusionInteractorLazy.get().getInvisibleDueToOcclusion(),
this::calculateStateFromSceneFramework),
this::onStatusBarStateChanged);
+
+ mJavaAdapter.alwaysCollectFlow(
+ mKeyguardTransitionInteractorLazy.get().transitionValue(KeyguardState.AOD),
+ this::onAodKeyguardStateTransitionValueChanged);
}
}
@@ -693,6 +698,14 @@
updateStateAndNotifyListeners(newState);
}
+ private void onAodKeyguardStateTransitionValueChanged(float value) {
+ if (SceneContainerFlag.isUnexpectedlyInLegacyMode()) {
+ return;
+ }
+
+ setDozeAmountInternal(value);
+ }
+
private static final Map<SceneKey, Integer> sStatusBarStateByLockedSceneKey = Map.of(
Scenes.Lockscreen, StatusBarState.KEYGUARD,
Scenes.Bouncer, StatusBarState.KEYGUARD,
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
index 132d0f0..1789ad6 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/NotificationStackScrollLayout.java
@@ -6462,7 +6462,6 @@
};
public HeadsUpTouchHelper.Callback getHeadsUpCallback() {
- SceneContainerFlag.assertInLegacyMode();
return mHeadsUpCallback;
}
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
index 497ffca..6881d11 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/notification/stack/ui/viewbinder/SharedNotificationContainerBinder.kt
@@ -38,12 +38,14 @@
import javax.inject.Inject
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.DisposableHandle
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
/** Binds the shared notification container to its view-model. */
+@OptIn(ExperimentalCoroutinesApi::class)
@SysUISingleton
class SharedNotificationContainerBinder
@Inject
diff --git a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SplitShadeStateController.kt b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SplitShadeStateController.kt
index d120a1b..72d093c 100644
--- a/packages/SystemUI/src/com/android/systemui/statusbar/policy/SplitShadeStateController.kt
+++ b/packages/SystemUI/src/com/android/systemui/statusbar/policy/SplitShadeStateController.kt
@@ -22,10 +22,10 @@
/** Returns true if the device should use the split notification shade. */
@Deprecated(
- message = "This is deprecated, please use ShadeInteractor#isSplitShade instead",
+ message = "This is deprecated, please use ShadeInteractor#shadeMode instead",
replaceWith =
ReplaceWith(
- "shadeInteractor.isSplitShade",
+ "shadeInteractor.shadeMode",
"com.android.systemui.shade.domain.interactor.ShadeInteractor",
),
)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorTest.kt
index 032794c..42ab25f 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorTest.kt
@@ -56,7 +56,6 @@
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
-import org.junit.Ignore
import org.junit.runner.RunWith
import org.mockito.Mockito.reset
import org.mockito.Mockito.spy
@@ -98,7 +97,6 @@
@Test
@EnableFlags(Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR)
- @Ignore("Until b/349837588 is fixed")
fun testTransitionToOccluded_ifDreamEnds_occludingActivityOnTop() =
testScope.runTest {
kosmos.fakeKeyguardRepository.setDreaming(true)
@@ -158,7 +156,6 @@
reset(transitionRepository)
kosmos.keyguardOcclusionRepository.setShowWhenLockedActivityInfo(onTop = false)
- kosmos.fakeKeyguardRepository.setDreaming(false)
runCurrent()
assertThat(transitionRepository)
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/InWindowLauncherUnlockAnimationInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/InWindowLauncherUnlockAnimationInteractorTest.kt
index ea5a41f..459e41d 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/InWindowLauncherUnlockAnimationInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/InWindowLauncherUnlockAnimationInteractorTest.kt
@@ -18,22 +18,25 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.systemui.SysUITestModule
import com.android.systemui.SysuiTestCase
+import com.android.systemui.TestMocksModule
+import com.android.systemui.biometrics.domain.BiometricsDomainLayerModule
import com.android.systemui.coroutines.collectValues
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.keyguard.data.repository.FakeKeyguardSurfaceBehindRepository
import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.data.repository.inWindowLauncherUnlockAnimationRepository
-import com.android.systemui.keyguard.data.repository.keyguardSurfaceBehindRepository
+import com.android.systemui.keyguard.data.repository.InWindowLauncherUnlockAnimationRepository
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
import com.android.systemui.keyguard.util.mockTopActivityClassName
-import com.android.systemui.kosmos.applicationCoroutineScope
-import com.android.systemui.kosmos.testScope
import com.android.systemui.shared.system.ActivityManagerWrapper
-import com.android.systemui.shared.system.activityManagerWrapper
-import com.android.systemui.testKosmos
+import com.android.systemui.user.domain.UserDomainLayerModule
+import dagger.BindsInstance
+import dagger.Component
import junit.framework.Assert.assertEquals
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -46,16 +49,10 @@
@RunWith(AndroidJUnit4::class)
@kotlinx.coroutines.ExperimentalCoroutinesApi
class InWindowLauncherUnlockAnimationInteractorTest : SysuiTestCase() {
- private val kosmos = testKosmos()
- private val underTest =
- InWindowLauncherUnlockAnimationInteractor(
- kosmos.inWindowLauncherUnlockAnimationRepository,
- kosmos.applicationCoroutineScope,
- kosmos.keyguardTransitionInteractor,
- { kosmos.keyguardSurfaceBehindRepository },
- kosmos.activityManagerWrapper,
- )
- private val testScope = kosmos.testScope
+ private lateinit var underTest: InWindowLauncherUnlockAnimationInteractor
+
+ private lateinit var testComponent: TestComponent
+ private lateinit var testScope: TestScope
private lateinit var transitionRepository: FakeKeyguardTransitionRepository
@Mock private lateinit var activityManagerWrapper: ActivityManagerWrapper
@@ -65,9 +62,19 @@
fun setUp() {
MockitoAnnotations.initMocks(this)
- transitionRepository = kosmos.fakeKeyguardTransitionRepository
+ testComponent =
+ DaggerInWindowLauncherUnlockAnimationInteractorTest_TestComponent.factory()
+ .create(
+ test = this,
+ mocks =
+ TestMocksModule(
+ activityManagerWrapper = activityManagerWrapper,
+ ),
+ )
+ underTest = testComponent.underTest
+ testScope = testComponent.testScope
+ transitionRepository = testComponent.transitionRepository
- activityManagerWrapper = kosmos.activityManagerWrapper
activityManagerWrapper.mockTopActivityClassName(launcherClassName)
}
@@ -85,7 +92,7 @@
)
// Put launcher on top
- kosmos.inWindowLauncherUnlockAnimationRepository.setLauncherActivityClass(
+ testComponent.inWindowLauncherUnlockAnimationRepository.setLauncherActivityClass(
launcherClassName
)
activityManagerWrapper.mockTopActivityClassName(launcherClassName)
@@ -168,7 +175,7 @@
)
// Put not launcher on top
- kosmos.inWindowLauncherUnlockAnimationRepository.setLauncherActivityClass(
+ testComponent.inWindowLauncherUnlockAnimationRepository.setLauncherActivityClass(
launcherClassName
)
activityManagerWrapper.mockTopActivityClassName("not_launcher")
@@ -245,7 +252,7 @@
)
// Put launcher on top
- kosmos.inWindowLauncherUnlockAnimationRepository.setLauncherActivityClass(
+ testComponent.inWindowLauncherUnlockAnimationRepository.setLauncherActivityClass(
launcherClassName
)
activityManagerWrapper.mockTopActivityClassName(launcherClassName)
@@ -289,7 +296,7 @@
)
// Put Launcher on top and begin transitioning to GONE.
- kosmos.inWindowLauncherUnlockAnimationRepository.setLauncherActivityClass(
+ testComponent.inWindowLauncherUnlockAnimationRepository.setLauncherActivityClass(
launcherClassName
)
activityManagerWrapper.mockTopActivityClassName(launcherClassName)
@@ -309,7 +316,7 @@
values
)
- kosmos.keyguardSurfaceBehindRepository.setSurfaceRemoteAnimationTargetAvailable(true)
+ testComponent.surfaceBehindRepository.setSurfaceRemoteAnimationTargetAvailable(true)
runCurrent()
assertEquals(
@@ -353,7 +360,7 @@
)
// Put Launcher on top and begin transitioning to GONE.
- kosmos.inWindowLauncherUnlockAnimationRepository.setLauncherActivityClass(
+ testComponent.inWindowLauncherUnlockAnimationRepository.setLauncherActivityClass(
launcherClassName
)
activityManagerWrapper.mockTopActivityClassName(launcherClassName)
@@ -395,7 +402,7 @@
)
// Put Launcher on top and begin transitioning to GONE.
- kosmos.inWindowLauncherUnlockAnimationRepository.setLauncherActivityClass(
+ testComponent.inWindowLauncherUnlockAnimationRepository.setLauncherActivityClass(
launcherClassName
)
activityManagerWrapper.mockTopActivityClassName(launcherClassName)
@@ -420,7 +427,7 @@
to = KeyguardState.AOD,
)
)
- kosmos.keyguardSurfaceBehindRepository.setSurfaceRemoteAnimationTargetAvailable(true)
+ testComponent.surfaceBehindRepository.setSurfaceRemoteAnimationTargetAvailable(true)
runCurrent()
assertEquals(
@@ -430,4 +437,29 @@
values
)
}
+
+ @SysUISingleton
+ @Component(
+ modules =
+ [
+ SysUITestModule::class,
+ BiometricsDomainLayerModule::class,
+ UserDomainLayerModule::class,
+ ]
+ )
+ interface TestComponent {
+ val underTest: InWindowLauncherUnlockAnimationInteractor
+ val testScope: TestScope
+ val transitionRepository: FakeKeyguardTransitionRepository
+ val surfaceBehindRepository: FakeKeyguardSurfaceBehindRepository
+ val inWindowLauncherUnlockAnimationRepository: InWindowLauncherUnlockAnimationRepository
+
+ @Component.Factory
+ interface Factory {
+ fun create(
+ @BindsInstance test: SysuiTestCase,
+ mocks: TestMocksModule,
+ ): TestComponent
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt
index f0ad510..59f16d7 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorTest.kt
@@ -36,7 +36,6 @@
import com.android.systemui.plugins.clocks.ClockConfig
import com.android.systemui.plugins.clocks.ClockController
import com.android.systemui.shade.data.repository.shadeRepository
-import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.whenever
@@ -84,7 +83,7 @@
fun testAppliesDefaultBlueprint() {
testScope.runTest {
val blueprintId by collectLastValue(underTest.blueprintId)
- kosmos.shadeRepository.setShadeMode(ShadeMode.Single)
+ kosmos.shadeRepository.setShadeLayoutWide(false)
configurationRepository.onConfigurationChange()
runCurrent()
@@ -98,7 +97,7 @@
fun testAppliesSplitShadeBlueprint() {
testScope.runTest {
val blueprintId by collectLastValue(underTest.blueprintId)
- kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
+ kosmos.shadeRepository.setShadeLayoutWide(true)
configurationRepository.onConfigurationChange()
runCurrent()
@@ -112,7 +111,7 @@
fun testDoesNotApplySplitShadeBlueprint() {
testScope.runTest {
val blueprintId by collectLastValue(underTest.blueprintId)
- kosmos.shadeRepository.setShadeMode(ShadeMode.Split)
+ kosmos.shadeRepository.setShadeLayoutWide(true)
clockRepository.setCurrentClock(clockController)
configurationRepository.onConfigurationChange()
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractorTest.kt
deleted file mode 100644
index 22181f8..0000000
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractorTest.kt
+++ /dev/null
@@ -1,370 +0,0 @@
-/*
- * Copyright (C) 2024 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.systemui.keyguard.domain.interactor
-
-import android.app.AlarmManager
-import android.app.admin.alarmManager
-import android.app.admin.devicePolicyManager
-import android.content.BroadcastReceiver
-import android.content.Intent
-import android.content.mockedContext
-import android.os.PowerManager
-import android.os.UserHandle
-import android.provider.Settings
-import androidx.test.ext.junit.runners.AndroidJUnit4
-import androidx.test.filters.SmallTest
-import com.android.internal.widget.lockPatternUtils
-import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectValues
-import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
-import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.shared.model.BiometricUnlockMode
-import com.android.systemui.keyguard.shared.model.KeyguardState
-import com.android.systemui.kosmos.testScope
-import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAsleepForTest
-import com.android.systemui.power.domain.interactor.PowerInteractor.Companion.setAwakeForTest
-import com.android.systemui.power.domain.interactor.powerInteractor
-import com.android.systemui.testKosmos
-import com.android.systemui.util.settings.fakeSettings
-import junit.framework.Assert.assertEquals
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
-import org.junit.Test
-import org.junit.runner.RunWith
-import org.mockito.ArgumentMatchers.anyInt
-import org.mockito.ArgumentMatchers.anyLong
-import org.mockito.kotlin.any
-import org.mockito.kotlin.doAnswer
-import org.mockito.kotlin.eq
-import org.mockito.kotlin.mock
-import org.mockito.kotlin.verify
-import org.mockito.kotlin.whenever
-
-@OptIn(ExperimentalCoroutinesApi::class)
-@SmallTest
-@RunWith(AndroidJUnit4::class)
-class KeyguardWakeDirectlyToGoneInteractorTest : SysuiTestCase() {
-
- private var lastRegisteredBroadcastReceiver: BroadcastReceiver? = null
- private val kosmos =
- testKosmos().apply {
- whenever(mockedContext.user).thenReturn(mock<UserHandle>())
- doAnswer { invocation ->
- lastRegisteredBroadcastReceiver = invocation.arguments[0] as BroadcastReceiver
- }
- .whenever(mockedContext)
- .registerReceiver(any(), any(), any(), any(), any())
- }
-
- private val testScope = kosmos.testScope
- private val underTest = kosmos.keyguardWakeDirectlyToGoneInteractor
- private val lockPatternUtils = kosmos.lockPatternUtils
- private val repository = kosmos.fakeKeyguardRepository
- private val transitionRepository = kosmos.fakeKeyguardTransitionRepository
-
- @Test
- fun testCanWakeDirectlyToGone_keyguardServiceEnabledThenDisabled() =
- testScope.runTest {
- val canWake by collectValues(underTest.canWakeDirectlyToGone)
-
- assertEquals(
- listOf(
- false, // Defaults to false.
- ),
- canWake
- )
-
- repository.setKeyguardEnabled(false)
- runCurrent()
-
- assertEquals(
- listOf(
- false, // Default to false.
- true, // True now that keyguard service is disabled
- ),
- canWake
- )
-
- repository.setKeyguardEnabled(true)
- runCurrent()
-
- assertEquals(
- listOf(
- false,
- true,
- false,
- ),
- canWake
- )
- }
-
- @Test
- fun testCanWakeDirectlyToGone_lockscreenDisabledThenEnabled() =
- testScope.runTest {
- val canWake by collectValues(underTest.canWakeDirectlyToGone)
-
- assertEquals(
- listOf(
- false, // Defaults to false.
- ),
- canWake
- )
-
- whenever(lockPatternUtils.isLockScreenDisabled(anyInt())).thenReturn(true)
- runCurrent()
-
- assertEquals(
- listOf(
- // Still false - isLockScreenDisabled only causes canWakeDirectlyToGone to
- // update on the next wake/sleep event.
- false,
- ),
- canWake
- )
-
- kosmos.powerInteractor.setAsleepForTest()
- runCurrent()
-
- assertEquals(
- listOf(
- false,
- // True since we slept after setting isLockScreenDisabled=true
- true,
- ),
- canWake
- )
-
- kosmos.powerInteractor.setAwakeForTest()
- runCurrent()
-
- kosmos.powerInteractor.setAsleepForTest()
- runCurrent()
-
- assertEquals(
- listOf(
- false,
- true,
- ),
- canWake
- )
-
- whenever(lockPatternUtils.isLockScreenDisabled(anyInt())).thenReturn(false)
- kosmos.powerInteractor.setAwakeForTest()
- runCurrent()
-
- assertEquals(
- listOf(
- false,
- true,
- false,
- ),
- canWake
- )
- }
-
- @Test
- fun testCanWakeDirectlyToGone_wakeAndUnlock() =
- testScope.runTest {
- val canWake by collectValues(underTest.canWakeDirectlyToGone)
-
- assertEquals(
- listOf(
- false, // Defaults to false.
- ),
- canWake
- )
-
- repository.setBiometricUnlockState(BiometricUnlockMode.WAKE_AND_UNLOCK)
- runCurrent()
-
- assertEquals(listOf(false, true), canWake)
-
- repository.setBiometricUnlockState(BiometricUnlockMode.NONE)
- runCurrent()
-
- assertEquals(listOf(false, true, false), canWake)
- }
-
- @Test
- fun testCanWakeDirectlyToGone_andSetsAlarm_ifPowerButtonDoesNotLockImmediately() =
- testScope.runTest {
- val canWake by collectValues(underTest.canWakeDirectlyToGone)
-
- assertEquals(
- listOf(
- false, // Defaults to false.
- ),
- canWake
- )
-
- repository.setCanIgnoreAuthAndReturnToGone(true)
- runCurrent()
-
- assertEquals(listOf(false, true), canWake)
-
- repository.setCanIgnoreAuthAndReturnToGone(false)
- runCurrent()
-
- assertEquals(listOf(false, true, false), canWake)
- }
-
- @Test
- fun testSetsCanIgnoreAuth_andSetsAlarm_whenTimingOut() =
- testScope.runTest {
- val canWake by collectValues(underTest.canWakeDirectlyToGone)
-
- assertEquals(
- listOf(
- false, // Defaults to false.
- ),
- canWake
- )
-
- whenever(kosmos.devicePolicyManager.getMaximumTimeToLock(eq(null), anyInt()))
- .thenReturn(-1)
- kosmos.fakeSettings.putInt(Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 500)
-
- transitionRepository.sendTransitionSteps(
- from = KeyguardState.LOCKSCREEN,
- to = KeyguardState.GONE,
- testScope,
- )
-
- kosmos.powerInteractor.setAsleepForTest(
- sleepReason = PowerManager.GO_TO_SLEEP_REASON_TIMEOUT
- )
- runCurrent()
-
- assertEquals(
- listOf(
- false,
- true,
- ),
- canWake
- )
-
- verify(kosmos.alarmManager)
- .setExactAndAllowWhileIdle(
- eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
- anyLong(),
- any(),
- )
- }
-
- @Test
- fun testCancelsFirstAlarm_onWake_withSecondAlarmSet() =
- testScope.runTest {
- val canWake by collectValues(underTest.canWakeDirectlyToGone)
-
- assertEquals(
- listOf(
- false, // Defaults to false.
- ),
- canWake
- )
-
- whenever(kosmos.devicePolicyManager.getMaximumTimeToLock(eq(null), anyInt()))
- .thenReturn(-1)
- kosmos.fakeSettings.putInt(Settings.Secure.LOCK_SCREEN_LOCK_AFTER_TIMEOUT, 500)
-
- transitionRepository.sendTransitionSteps(
- from = KeyguardState.LOCKSCREEN,
- to = KeyguardState.GONE,
- testScope,
- )
-
- kosmos.powerInteractor.setAsleepForTest(
- sleepReason = PowerManager.GO_TO_SLEEP_REASON_TIMEOUT
- )
- transitionRepository.sendTransitionSteps(
- from = KeyguardState.LOCKSCREEN,
- to = KeyguardState.AOD,
- testScope = testScope,
- )
- runCurrent()
-
- assertEquals(
- listOf(
- false,
- // Timed out, so we can ignore auth/return to GONE.
- true,
- ),
- canWake
- )
-
- verify(kosmos.alarmManager)
- .setExactAndAllowWhileIdle(
- eq(AlarmManager.ELAPSED_REALTIME_WAKEUP),
- anyLong(),
- any(),
- )
-
- kosmos.powerInteractor.setAwakeForTest()
- transitionRepository.sendTransitionSteps(
- from = KeyguardState.AOD,
- to = KeyguardState.GONE,
- testScope = testScope,
- )
- runCurrent()
-
- assertEquals(
- listOf(
- false,
- true,
- // Should be canceled by the wakeup, but there would still be an
- // alarm in flight that should be canceled.
- false,
- ),
- canWake
- )
-
- kosmos.powerInteractor.setAsleepForTest(
- sleepReason = PowerManager.GO_TO_SLEEP_REASON_TIMEOUT
- )
- runCurrent()
-
- assertEquals(
- listOf(
- false,
- true,
- false,
- // Back to sleep.
- true,
- ),
- canWake
- )
-
- // Simulate the first sleep's alarm coming in.
- lastRegisteredBroadcastReceiver?.onReceive(
- kosmos.mockedContext,
- Intent("com.android.internal.policy.impl.PhoneWindowManager.DELAYED_KEYGUARD")
- )
- runCurrent()
-
- // It should not have any effect.
- assertEquals(
- listOf(
- false,
- true,
- false,
- true,
- ),
- canWake
- )
- }
-}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/InWindowLauncherUnlockAnimationManagerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/InWindowLauncherUnlockAnimationManagerTest.kt
index 0cfc20d..c7f4416 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/InWindowLauncherUnlockAnimationManagerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/binder/InWindowLauncherUnlockAnimationManagerTest.kt
@@ -18,15 +18,17 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.systemui.SysUITestModule
import com.android.systemui.SysuiTestCase
-import com.android.systemui.keyguard.domain.interactor.inWindowLauncherUnlockAnimationInteractor
+import com.android.systemui.biometrics.domain.BiometricsDomainLayerModule
+import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.keyguard.ui.view.InWindowLauncherUnlockAnimationManager
-import com.android.systemui.keyguard.ui.viewmodel.InWindowLauncherAnimationViewModel
-import com.android.systemui.kosmos.applicationCoroutineScope
-import com.android.systemui.kosmos.testScope
import com.android.systemui.shared.system.smartspace.ILauncherUnlockAnimationController
-import com.android.systemui.testKosmos
+import com.android.systemui.user.domain.UserDomainLayerModule
import com.android.systemui.util.mockito.any
+import dagger.BindsInstance
+import dagger.Component
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
import org.junit.Before
import org.junit.Test
@@ -43,9 +45,10 @@
@RunWith(AndroidJUnit4::class)
@kotlinx.coroutines.ExperimentalCoroutinesApi
class InWindowLauncherUnlockAnimationManagerTest : SysuiTestCase() {
- private val kosmos = testKosmos()
private lateinit var underTest: InWindowLauncherUnlockAnimationManager
- private val testScope = kosmos.testScope
+
+ private lateinit var testComponent: TestComponent
+ private lateinit var testScope: TestScope
@Mock private lateinit var launcherUnlockAnimationController: ILauncherUnlockAnimationController
@@ -53,14 +56,14 @@
fun setUp() {
MockitoAnnotations.initMocks(this)
- underTest =
- InWindowLauncherUnlockAnimationManager(
- kosmos.inWindowLauncherUnlockAnimationInteractor,
- InWindowLauncherAnimationViewModel(
- kosmos.inWindowLauncherUnlockAnimationInteractor
- ),
- kosmos.applicationCoroutineScope
- )
+ testComponent =
+ DaggerInWindowLauncherUnlockAnimationManagerTest_TestComponent.factory()
+ .create(
+ test = this,
+ )
+ underTest = testComponent.underTest
+ testScope = testComponent.testScope
+
underTest.setLauncherUnlockController("launcherClass", launcherUnlockAnimationController)
}
@@ -111,4 +114,25 @@
verifyNoMoreInteractions(launcherUnlockAnimationController)
}
+
+ @SysUISingleton
+ @Component(
+ modules =
+ [
+ SysUITestModule::class,
+ BiometricsDomainLayerModule::class,
+ UserDomainLayerModule::class,
+ ]
+ )
+ interface TestComponent {
+ val underTest: InWindowLauncherUnlockAnimationManager
+ val testScope: TestScope
+
+ @Component.Factory
+ interface Factory {
+ fun create(
+ @BindsInstance test: SysuiTestCase,
+ ): TestComponent
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt
index 4a39a9b..6e381ca 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/view/layout/sections/ClockSectionTest.kt
@@ -39,7 +39,6 @@
import com.android.systemui.kosmos.testScope
import com.android.systemui.res.R
import com.android.systemui.shade.data.repository.shadeRepository
-import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationsKeyguardInteractor
import com.android.systemui.statusbar.policy.fakeConfigurationController
import com.android.systemui.statusbar.ui.fakeSystemBarUtilsProxy
@@ -48,6 +47,7 @@
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
+import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.advanceUntilIdle
import kotlinx.coroutines.test.runTest
import org.junit.Before
@@ -57,6 +57,7 @@
import org.mockito.ArgumentMatchers.anyString
import org.mockito.MockitoAnnotations
+@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(AndroidJUnit4::class)
@SmallTest
class ClockSectionTest : SysuiTestCase() {
@@ -127,7 +128,7 @@
fun testApplyDefaultConstraints_LargeClock_SplitShade() =
kosmos.testScope.runTest {
with(kosmos) {
- shadeRepository.setShadeMode(ShadeMode.Split)
+ shadeRepository.setShadeLayoutWide(true)
keyguardClockInteractor.setClockSize(ClockSize.LARGE)
advanceUntilIdle()
}
@@ -143,11 +144,11 @@
fun testApplyDefaultConstraints_LargeClock_NonSplitShade() =
kosmos.testScope.runTest {
with(kosmos) {
- val collectedShadeMode by collectLastValue(shadeRepository.shadeMode)
+ val isShadeLayoutWide by collectLastValue(shadeRepository.isShadeLayoutWide)
val isLargeClockVisible by
collectLastValue(keyguardClockViewModel.isLargeClockVisible)
- shadeRepository.setShadeMode(ShadeMode.Single)
+ shadeRepository.setShadeLayoutWide(false)
keyguardClockInteractor.setClockSize(ClockSize.LARGE)
fakeKeyguardRepository.setClockShouldBeCentered(true)
notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
@@ -168,11 +169,11 @@
kosmos.testScope.runTest {
with(kosmos) {
DIMENSION_BY_IDENTIFIER = listOf() // Remove Smartspace from mock
- val collectedShadeMode by collectLastValue(shadeRepository.shadeMode)
+ val isShadeLayoutWide by collectLastValue(shadeRepository.isShadeLayoutWide)
val isLargeClockVisible by
collectLastValue(keyguardClockViewModel.isLargeClockVisible)
- shadeRepository.setShadeMode(ShadeMode.Split)
+ shadeRepository.setShadeLayoutWide(true)
keyguardClockInteractor.setClockSize(ClockSize.LARGE)
fakeKeyguardRepository.setClockShouldBeCentered(true)
notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
@@ -193,11 +194,11 @@
kosmos.testScope.runTest {
with(kosmos) {
DIMENSION_BY_IDENTIFIER = listOf() // Remove Smartspace from mock
- val collectedShadeMode by collectLastValue(shadeRepository.shadeMode)
+ val isShadeLayoutWide by collectLastValue(shadeRepository.isShadeLayoutWide)
val isLargeClockVisible by
collectLastValue(keyguardClockViewModel.isLargeClockVisible)
- shadeRepository.setShadeMode(ShadeMode.Single)
+ shadeRepository.setShadeLayoutWide(false)
keyguardClockInteractor.setClockSize(ClockSize.LARGE)
fakeKeyguardRepository.setClockShouldBeCentered(true)
notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
@@ -217,11 +218,11 @@
fun testApplyDefaultConstraints_SmallClock_SplitShade() =
kosmos.testScope.runTest {
with(kosmos) {
- val collectedShadeMode by collectLastValue(shadeRepository.shadeMode)
+ val isShadeLayoutWide by collectLastValue(shadeRepository.isShadeLayoutWide)
val isLargeClockVisible by
collectLastValue(keyguardClockViewModel.isLargeClockVisible)
- shadeRepository.setShadeMode(ShadeMode.Split)
+ shadeRepository.setShadeLayoutWide(true)
keyguardClockInteractor.setClockSize(ClockSize.SMALL)
fakeKeyguardRepository.setClockShouldBeCentered(true)
notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
@@ -241,11 +242,11 @@
fun testApplyDefaultConstraints_SmallClock_NonSplitShade() =
kosmos.testScope.runTest {
with(kosmos) {
- val collectedShadeMode by collectLastValue(shadeRepository.shadeMode)
+ val isShadeLayoutWide by collectLastValue(shadeRepository.isShadeLayoutWide)
val isLargeClockVisible by
collectLastValue(keyguardClockViewModel.isLargeClockVisible)
- shadeRepository.setShadeMode(ShadeMode.Single)
+ shadeRepository.setShadeLayoutWide(false)
keyguardClockInteractor.setClockSize(ClockSize.SMALL)
fakeKeyguardRepository.setClockShouldBeCentered(true)
notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
@@ -334,7 +335,7 @@
}
companion object {
- private val SMART_SPACE_DATE_WEATHER_HEIGHT = 10
- private val ENHANCED_SMART_SPACE_HEIGHT = 11
+ private const val SMART_SPACE_DATE_WEATHER_HEIGHT = 10
+ private const val ENHANCED_SMART_SPACE_HEIGHT = 11
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt
index 40663ce..17e1b53 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/keyguard/ui/viewmodel/KeyguardClockViewModelTest.kt
@@ -38,7 +38,6 @@
import com.android.systemui.plugins.clocks.ClockFaceController
import com.android.systemui.res.R
import com.android.systemui.shade.data.repository.shadeRepository
-import com.android.systemui.shade.shared.model.ShadeMode
import com.android.systemui.statusbar.ui.fakeSystemBarUtilsProxy
import com.android.systemui.testKosmos
import com.android.systemui.util.mockito.whenever
@@ -88,7 +87,7 @@
val currentClockLayout by collectLastValue(underTest.currentClockLayout)
with(kosmos) {
- shadeRepository.setShadeMode(ShadeMode.Split)
+ shadeRepository.setShadeLayoutWide(true)
keyguardRepository.setClockShouldBeCentered(true)
keyguardClockRepository.setClockSize(ClockSize.LARGE)
}
@@ -103,7 +102,7 @@
val currentClockLayout by collectLastValue(underTest.currentClockLayout)
with(kosmos) {
- shadeRepository.setShadeMode(ShadeMode.Split)
+ shadeRepository.setShadeLayoutWide(true)
keyguardRepository.setClockShouldBeCentered(false)
keyguardClockRepository.setClockSize(ClockSize.LARGE)
}
@@ -118,7 +117,7 @@
val currentClockLayout by collectLastValue(underTest.currentClockLayout)
with(kosmos) {
- shadeRepository.setShadeMode(ShadeMode.Split)
+ shadeRepository.setShadeLayoutWide(true)
keyguardRepository.setClockShouldBeCentered(false)
keyguardClockRepository.setClockSize(ClockSize.SMALL)
}
@@ -133,7 +132,7 @@
val currentClockLayout by collectLastValue(underTest.currentClockLayout)
with(kosmos) {
- shadeRepository.setShadeMode(ShadeMode.Single)
+ shadeRepository.setShadeLayoutWide(false)
keyguardClockRepository.setClockSize(ClockSize.SMALL)
}
@@ -146,7 +145,7 @@
val currentClockLayout by collectLastValue(underTest.currentClockLayout)
with(kosmos) {
- shadeRepository.setShadeMode(ShadeMode.Single)
+ shadeRepository.setShadeLayoutWide(false)
keyguardClockRepository.setClockSize(ClockSize.LARGE)
}
@@ -234,7 +233,7 @@
fun testSmallClockTop_splitShade_composeLockscreenOn() =
testScope.runTest {
with(kosmos) {
- shadeRepository.setShadeMode(ShadeMode.Split)
+ shadeRepository.setShadeLayoutWide(true)
fakeSystemBarUtilsProxy.fakeKeyguardStatusBarHeight = KEYGUARD_STATUS_BAR_HEIGHT
}
@@ -249,7 +248,7 @@
fun testSmallClockTop_splitShade_composeLockscreenOff() =
testScope.runTest {
with(kosmos) {
- shadeRepository.setShadeMode(ShadeMode.Split)
+ shadeRepository.setShadeLayoutWide(true)
fakeSystemBarUtilsProxy.fakeKeyguardStatusBarHeight = KEYGUARD_STATUS_BAR_HEIGHT
}
@@ -262,7 +261,7 @@
fun testSmallClockTop_nonSplitShade_composeLockscreenOn() =
testScope.runTest {
with(kosmos) {
- shadeRepository.setShadeMode(ShadeMode.Single)
+ shadeRepository.setShadeLayoutWide(false)
fakeSystemBarUtilsProxy.fakeKeyguardStatusBarHeight = KEYGUARD_STATUS_BAR_HEIGHT
}
@@ -275,7 +274,7 @@
fun testSmallClockTop_nonSplitShade_composeLockscreenOff() =
testScope.runTest {
with(kosmos) {
- shadeRepository.setShadeMode(ShadeMode.Single)
+ shadeRepository.setShadeLayoutWide(false)
fakeSystemBarUtilsProxy.fakeKeyguardStatusBarHeight = KEYGUARD_STATUS_BAR_HEIGHT
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
index 97acc6e..7d4918a 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/shade/data/repository/ShadeRepositoryImplTest.kt
@@ -19,8 +19,8 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
+import com.android.systemui.coroutines.collectLastValue
import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runTest
@@ -28,7 +28,6 @@
import org.junit.Test
import org.junit.runner.RunWith
-@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
class ShadeRepositoryImplTest : SysuiTestCase() {
@@ -91,37 +90,37 @@
@Test
fun updateLegacyShadeTracking() =
testScope.runTest {
- assertThat(underTest.legacyShadeTracking.value).isEqualTo(false)
+ assertThat(underTest.legacyShadeTracking.value).isFalse()
underTest.setLegacyShadeTracking(true)
- assertThat(underTest.legacyShadeTracking.value).isEqualTo(true)
+ assertThat(underTest.legacyShadeTracking.value).isTrue()
}
@Test
fun updateLegacyLockscreenShadeTracking() =
testScope.runTest {
- assertThat(underTest.legacyLockscreenShadeTracking.value).isEqualTo(false)
+ assertThat(underTest.legacyLockscreenShadeTracking.value).isFalse()
underTest.setLegacyLockscreenShadeTracking(true)
- assertThat(underTest.legacyLockscreenShadeTracking.value).isEqualTo(true)
+ assertThat(underTest.legacyLockscreenShadeTracking.value).isTrue()
}
@Test
fun updateLegacyQsTracking() =
testScope.runTest {
- assertThat(underTest.legacyQsTracking.value).isEqualTo(false)
+ assertThat(underTest.legacyQsTracking.value).isFalse()
underTest.setLegacyQsTracking(true)
- assertThat(underTest.legacyQsTracking.value).isEqualTo(true)
+ assertThat(underTest.legacyQsTracking.value).isTrue()
}
@Test
fun updateLegacyExpandedOrAwaitingInputTransfer() =
testScope.runTest {
- assertThat(underTest.legacyExpandedOrAwaitingInputTransfer.value).isEqualTo(false)
+ assertThat(underTest.legacyExpandedOrAwaitingInputTransfer.value).isFalse()
underTest.setLegacyExpandedOrAwaitingInputTransfer(true)
- assertThat(underTest.legacyExpandedOrAwaitingInputTransfer.value).isEqualTo(true)
+ assertThat(underTest.legacyExpandedOrAwaitingInputTransfer.value).isTrue()
}
@Test
@@ -142,36 +141,46 @@
@Test
fun updateLegacyIsQsExpanded() =
testScope.runTest {
- assertThat(underTest.legacyIsQsExpanded.value).isEqualTo(false)
+ assertThat(underTest.legacyIsQsExpanded.value).isFalse()
underTest.setLegacyIsQsExpanded(true)
- assertThat(underTest.legacyIsQsExpanded.value).isEqualTo(true)
+ assertThat(underTest.legacyIsQsExpanded.value).isTrue()
}
@Test
fun updateLegacyExpandImmediate() =
testScope.runTest {
- assertThat(underTest.legacyExpandImmediate.value).isEqualTo(false)
+ assertThat(underTest.legacyExpandImmediate.value).isFalse()
underTest.setLegacyExpandImmediate(true)
- assertThat(underTest.legacyExpandImmediate.value).isEqualTo(true)
+ assertThat(underTest.legacyExpandImmediate.value).isTrue()
}
@Test
fun updateLegacyQsFullscreen() =
testScope.runTest {
- assertThat(underTest.legacyQsFullscreen.value).isEqualTo(false)
+ assertThat(underTest.legacyQsFullscreen.value).isFalse()
underTest.setLegacyQsFullscreen(true)
- assertThat(underTest.legacyQsFullscreen.value).isEqualTo(true)
+ assertThat(underTest.legacyQsFullscreen.value).isTrue()
}
@Test
fun updateLegacyIsClosing() =
testScope.runTest {
- assertThat(underTest.legacyIsClosing.value).isEqualTo(false)
+ assertThat(underTest.legacyIsClosing.value).isFalse()
underTest.setLegacyIsClosing(true)
- assertThat(underTest.legacyIsClosing.value).isEqualTo(true)
+ assertThat(underTest.legacyIsClosing.value).isTrue()
+ }
+
+ @Test
+ fun isShadeLayoutWide() =
+ testScope.runTest {
+ val isShadeLayoutWide by collectLastValue(underTest.isShadeLayoutWide)
+ assertThat(isShadeLayoutWide).isFalse()
+
+ underTest.setShadeLayoutWide(true)
+ assertThat(isShadeLayoutWide).isTrue()
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
index 9e6a498..69e8f47 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/LockscreenShadeTransitionControllerTest.kt
@@ -6,23 +6,26 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.ExpandHelper
+import com.android.systemui.SysUITestModule
import com.android.systemui.SysuiTestCase
+import com.android.systemui.TestMocksModule
+import com.android.systemui.biometrics.domain.BiometricsDomainLayerModule
import com.android.systemui.classifier.FalsingCollectorFake
import com.android.systemui.classifier.FalsingManagerFake
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FakeFeatureFlagsClassicModule
import com.android.systemui.flags.Flags
-import com.android.systemui.flags.fakeFeatureFlagsClassic
import com.android.systemui.keyguard.domain.interactor.NaturalScrollingSettingObserver
-import com.android.systemui.kosmos.testScope
import com.android.systemui.media.controls.ui.controller.MediaHierarchyManager
import com.android.systemui.plugins.qs.QS
+import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.qs.ui.adapter.FakeQSSceneAdapter
import com.android.systemui.res.R
-import com.android.systemui.shade.data.repository.shadeRepository
import com.android.systemui.shade.domain.interactor.ShadeLockscreenInteractor
-import com.android.systemui.shade.domain.interactor.shadeInteractor
+import com.android.systemui.shade.data.repository.FakeShadeRepository
+import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel
-import com.android.systemui.statusbar.disableflags.data.repository.disableFlagsRepository
-import com.android.systemui.statusbar.disableflags.data.repository.fakeDisableFlagsRepository
+import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.NotificationTestHelper
import com.android.systemui.statusbar.notification.stack.NotificationStackScrollLayout
@@ -30,16 +33,17 @@
import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.ScrimController
+import com.android.systemui.statusbar.policy.FakeConfigurationController
import com.android.systemui.statusbar.policy.ResourcesSplitShadeStateController
-import com.android.systemui.statusbar.policy.configurationController
-import com.android.systemui.statusbar.policy.fakeConfigurationController
-import com.android.systemui.testKosmos
+import com.android.systemui.user.domain.UserDomainLayerModule
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.argumentCaptor
import com.android.systemui.util.mockito.mock
+import dagger.BindsInstance
+import dagger.Component
import kotlinx.coroutines.ExperimentalCoroutinesApi
+import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
import org.junit.After
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
@@ -61,8 +65,8 @@
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyZeroInteractions
-import org.mockito.Mockito.`when` as whenever
import org.mockito.junit.MockitoJUnit
+import org.mockito.Mockito.`when` as whenever
private fun <T> anyObject(): T {
return Mockito.anyObject<T>()
@@ -73,14 +77,15 @@
@RunWith(AndroidJUnit4::class)
@OptIn(ExperimentalCoroutinesApi::class)
class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
- private val kosmos =
- testKosmos().apply {
- fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, false) }
- }
+
private lateinit var transitionController: LockscreenShadeTransitionController
- private val configurationController = kosmos.fakeConfigurationController
- private val disableFlagsRepository = kosmos.fakeDisableFlagsRepository
- private val testScope = kosmos.testScope
+ private lateinit var testComponent: TestComponent
+ private val configurationController
+ get() = testComponent.configurationController
+ private val disableFlagsRepository
+ get() = testComponent.disableFlagsRepository
+ private val testScope
+ get() = testComponent.testScope
private val qsSceneAdapter = FakeQSSceneAdapter({ mock() })
@@ -129,6 +134,26 @@
whenever(keyguardBypassController.bypassEnabled).thenReturn(false)
whenever(naturalScrollingSettingObserver.isNaturalScrollingEnabled).thenReturn(true)
+ testComponent =
+ DaggerLockscreenShadeTransitionControllerTest_TestComponent.factory()
+ .create(
+ test = this,
+ featureFlags =
+ FakeFeatureFlagsClassicModule {
+ set(Flags.FULL_SCREEN_USER_SWITCHER, false)
+ },
+ mocks =
+ TestMocksModule(
+ notificationShadeDepthController = depthController,
+ keyguardBypassController = keyguardBypassController,
+ mediaHierarchyManager = mediaHierarchyManager,
+ notificationLockscreenUserManager = lockScreenUserManager,
+ notificationStackScrollLayoutController = nsslController,
+ scrimController = scrimController,
+ statusBarStateController = statusbarStateController,
+ )
+ )
+
transitionController =
LockscreenShadeTransitionController(
statusBarStateController = statusbarStateController,
@@ -166,10 +191,10 @@
falsingManager = FalsingManagerFake(),
dumpManager = mock(),
qsTransitionControllerFactory = { qsTransitionController },
- shadeRepository = kosmos.shadeRepository,
- shadeInteractor = kosmos.shadeInteractor,
+ shadeRepository = testComponent.shadeRepository,
+ shadeInteractor = testComponent.shadeInteractor,
splitShadeStateController = ResourcesSplitShadeStateController(),
- shadeLockscreenInteractorLazy = { shadeLockscreenInteractor },
+ shadeLockscreenInteractorLazy = {shadeLockscreenInteractor},
naturalScrollingSettingObserver = naturalScrollingSettingObserver,
lazyQSSceneAdapter = { qsSceneAdapter }
)
@@ -189,424 +214,387 @@
}
@Test
- fun testCantDragDownWhenQSExpanded() =
- testScope.runTest {
- assertTrue("Can't drag down on keyguard", transitionController.canDragDown())
- whenever(qS.isFullyCollapsed).thenReturn(false)
- assertFalse("Can drag down when QS is expanded", transitionController.canDragDown())
- }
+ fun testCantDragDownWhenQSExpanded() {
+ assertTrue("Can't drag down on keyguard", transitionController.canDragDown())
+ whenever(qS.isFullyCollapsed).thenReturn(false)
+ assertFalse("Can drag down when QS is expanded", transitionController.canDragDown())
+ }
@Test
- fun testCanDragDownInLockedDownShade() =
- testScope.runTest {
- whenever(statusbarStateController.state).thenReturn(StatusBarState.SHADE_LOCKED)
- assertFalse("Can drag down in shade locked", transitionController.canDragDown())
- whenever(nsslController.isInLockedDownShade).thenReturn(true)
- assertTrue("Can't drag down in locked down shade", transitionController.canDragDown())
- }
+ fun testCanDragDownInLockedDownShade() {
+ whenever(statusbarStateController.state).thenReturn(StatusBarState.SHADE_LOCKED)
+ assertFalse("Can drag down in shade locked", transitionController.canDragDown())
+ whenever(nsslController.isInLockedDownShade).thenReturn(true)
+ assertTrue("Can't drag down in locked down shade", transitionController.canDragDown())
+ }
@Test
- fun testGoingToLockedShade() =
- testScope.runTest {
- transitionController.goToLockedShade(null)
- verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
- }
+ fun testGoingToLockedShade() {
+ transitionController.goToLockedShade(null)
+ verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
+ }
@Test
- fun testWakingToShadeLockedWhenDozing() =
- testScope.runTest {
- whenever(statusbarStateController.isDozing).thenReturn(true)
- transitionController.goToLockedShade(null)
- verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
- assertTrue("Not waking to shade locked", transitionController.isWakingToShadeLocked)
- }
+ fun testWakingToShadeLockedWhenDozing() {
+ whenever(statusbarStateController.isDozing).thenReturn(true)
+ transitionController.goToLockedShade(null)
+ verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
+ assertTrue("Not waking to shade locked", transitionController.isWakingToShadeLocked)
+ }
@Test
- fun testNotWakingToShadeLockedWhenNotDozing() =
- testScope.runTest {
- whenever(statusbarStateController.isDozing).thenReturn(false)
- transitionController.goToLockedShade(null)
- verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
- assertFalse(
- "Waking to shade locked when not dozing",
- transitionController.isWakingToShadeLocked
+ fun testNotWakingToShadeLockedWhenNotDozing() {
+ whenever(statusbarStateController.isDozing).thenReturn(false)
+ transitionController.goToLockedShade(null)
+ verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
+ assertFalse(
+ "Waking to shade locked when not dozing",
+ transitionController.isWakingToShadeLocked
+ )
+ }
+
+ @Test
+ fun testGoToLockedShadeOnlyOnKeyguard() {
+ whenever(statusbarStateController.state).thenReturn(StatusBarState.SHADE_LOCKED)
+ transitionController.goToLockedShade(null)
+ whenever(statusbarStateController.state).thenReturn(StatusBarState.SHADE)
+ transitionController.goToLockedShade(null)
+ verify(statusbarStateController, never()).setState(anyInt())
+ }
+
+ @Test
+ fun testDontGoWhenShadeDisabled() {
+ disableFlagsRepository.disableFlags.value =
+ DisableFlagsModel(
+ disable2 = DISABLE2_NOTIFICATION_SHADE,
)
- }
+ testScope.runCurrent()
+ transitionController.goToLockedShade(null)
+ verify(statusbarStateController, never()).setState(anyInt())
+ }
@Test
- fun testGoToLockedShadeOnlyOnKeyguard() =
- testScope.runTest {
- whenever(statusbarStateController.state).thenReturn(StatusBarState.SHADE_LOCKED)
- transitionController.goToLockedShade(null)
- whenever(statusbarStateController.state).thenReturn(StatusBarState.SHADE)
- transitionController.goToLockedShade(null)
- verify(statusbarStateController, never()).setState(anyInt())
- }
+ fun testUserExpandsViewOnGoingToFullShade() {
+ assertFalse("Row shouldn't be user expanded yet", row.isUserExpanded)
+ transitionController.goToLockedShade(row)
+ assertTrue("Row wasn't user expanded on drag down", row.isUserExpanded)
+ }
@Test
- fun testDontGoWhenShadeDisabled() =
- testScope.runTest {
- disableFlagsRepository.disableFlags.value =
- DisableFlagsModel(
- disable2 = DISABLE2_NOTIFICATION_SHADE,
- )
- testScope.runCurrent()
- transitionController.goToLockedShade(null)
- verify(statusbarStateController, never()).setState(anyInt())
- }
+ fun testTriggeringBouncerNoNotificationsOnLockscreen() {
+ whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false)
+ transitionController.goToLockedShade(null)
+ verify(statusbarStateController, never()).setState(anyInt())
+ verify(statusbarStateController).setLeaveOpenOnKeyguardHide(true)
+ verify(centralSurfaces).showBouncerWithDimissAndCancelIfKeyguard(anyObject(), anyObject())
+ }
@Test
- fun testUserExpandsViewOnGoingToFullShade() =
- testScope.runTest {
- assertFalse("Row shouldn't be user expanded yet", row.isUserExpanded)
- transitionController.goToLockedShade(row)
- assertTrue("Row wasn't user expanded on drag down", row.isUserExpanded)
- }
+ fun testGoToLockedShadeCreatesQSAnimation() {
+ transitionController.goToLockedShade(null)
+ verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
+ verify(shadeLockscreenInteractor).transitionToExpandedShade(anyLong())
+ assertNotNull(transitionController.dragDownAnimator)
+ }
@Test
- fun testTriggeringBouncerNoNotificationsOnLockscreen() =
- testScope.runTest {
- whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false)
- transitionController.goToLockedShade(null)
- verify(statusbarStateController, never()).setState(anyInt())
- verify(statusbarStateController).setLeaveOpenOnKeyguardHide(true)
- verify(centralSurfaces)
- .showBouncerWithDimissAndCancelIfKeyguard(anyObject(), anyObject())
- }
+ fun testGoToLockedShadeDoesntCreateQSAnimation() {
+ transitionController.goToLockedShade(null, needsQSAnimation = false)
+ verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
+ verify(shadeLockscreenInteractor).transitionToExpandedShade(anyLong())
+ assertNull(transitionController.dragDownAnimator)
+ }
@Test
- fun testGoToLockedShadeCreatesQSAnimation() =
- testScope.runTest {
- transitionController.goToLockedShade(null)
- verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
- verify(shadeLockscreenInteractor).transitionToExpandedShade(anyLong())
- assertNotNull(transitionController.dragDownAnimator)
- }
+ fun testGoToLockedShadeAlwaysCreatesQSAnimationInSplitShade() {
+ enableSplitShade()
+ transitionController.goToLockedShade(null, needsQSAnimation = true)
+ verify(shadeLockscreenInteractor).transitionToExpandedShade(anyLong())
+ assertNotNull(transitionController.dragDownAnimator)
+ }
@Test
- fun testGoToLockedShadeDoesntCreateQSAnimation() =
- testScope.runTest {
- transitionController.goToLockedShade(null, needsQSAnimation = false)
- verify(statusbarStateController).setState(StatusBarState.SHADE_LOCKED)
- verify(shadeLockscreenInteractor).transitionToExpandedShade(anyLong())
- assertNull(transitionController.dragDownAnimator)
- }
+ fun testGoToLockedShadeCancelDoesntLeaveShadeOpenOnKeyguardHide() {
+ whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false)
+ whenever(lockScreenUserManager.isLockscreenPublicMode(any())).thenReturn(true)
+ transitionController.goToLockedShade(null)
+ val captor = argumentCaptor<Runnable>()
+ verify(centralSurfaces).showBouncerWithDimissAndCancelIfKeyguard(isNull(), captor.capture())
+ captor.value.run()
+ verify(statusbarStateController).setLeaveOpenOnKeyguardHide(false)
+ }
@Test
- fun testGoToLockedShadeAlwaysCreatesQSAnimationInSplitShade() =
- testScope.runTest {
- enableSplitShade()
- transitionController.goToLockedShade(null, needsQSAnimation = true)
- verify(shadeLockscreenInteractor).transitionToExpandedShade(anyLong())
- assertNotNull(transitionController.dragDownAnimator)
- }
+ fun testDragDownAmountDoesntCallOutInLockedDownShade() {
+ whenever(nsslController.isInLockedDownShade).thenReturn(true)
+ transitionController.dragDownAmount = 10f
+ verify(nsslController, never()).setTransitionToFullShadeAmount(anyFloat())
+ verify(mediaHierarchyManager, never()).setTransitionToFullShadeAmount(anyFloat())
+ verify(scrimController, never()).setTransitionToFullShadeProgress(anyFloat(), anyFloat())
+ verify(transitionControllerCallback, never())
+ .setTransitionToFullShadeAmount(anyFloat(), anyBoolean(), anyLong())
+ verify(qsTransitionController, never()).dragDownAmount = anyFloat()
+ }
@Test
- fun testGoToLockedShadeCancelDoesntLeaveShadeOpenOnKeyguardHide() =
- testScope.runTest {
- whenever(lockScreenUserManager.shouldShowLockscreenNotifications()).thenReturn(false)
- whenever(lockScreenUserManager.isLockscreenPublicMode(any())).thenReturn(true)
- transitionController.goToLockedShade(null)
- val captor = argumentCaptor<Runnable>()
- verify(centralSurfaces)
- .showBouncerWithDimissAndCancelIfKeyguard(isNull(), captor.capture())
- captor.value.run()
- verify(statusbarStateController).setLeaveOpenOnKeyguardHide(false)
- }
+ fun testDragDownAmountCallsOut() {
+ transitionController.dragDownAmount = 10f
+ verify(nsslController).setTransitionToFullShadeAmount(anyFloat())
+ verify(mediaHierarchyManager).setTransitionToFullShadeAmount(anyFloat())
+ verify(scrimController).setTransitionToFullShadeProgress(anyFloat(), anyFloat())
+ verify(transitionControllerCallback)
+ .setTransitionToFullShadeAmount(anyFloat(), anyBoolean(), anyLong())
+ verify(qsTransitionController).dragDownAmount = 10f
+ verify(depthController).transitionToFullShadeProgress = anyFloat()
+ }
@Test
- fun testDragDownAmountDoesntCallOutInLockedDownShade() =
- testScope.runTest {
- whenever(nsslController.isInLockedDownShade).thenReturn(true)
- transitionController.dragDownAmount = 10f
- verify(nsslController, never()).setTransitionToFullShadeAmount(anyFloat())
- verify(mediaHierarchyManager, never()).setTransitionToFullShadeAmount(anyFloat())
- verify(scrimController, never())
- .setTransitionToFullShadeProgress(anyFloat(), anyFloat())
- verify(transitionControllerCallback, never())
- .setTransitionToFullShadeAmount(anyFloat(), anyBoolean(), anyLong())
- verify(qsTransitionController, never()).dragDownAmount = anyFloat()
- }
+ fun testDragDownAmount_depthDistanceIsZero_setsProgressToZero() {
+ context
+ .getOrCreateTestableResources()
+ .addOverride(R.dimen.lockscreen_shade_depth_controller_transition_distance, 0)
+ configurationController.notifyConfigurationChanged()
+
+ transitionController.dragDownAmount = 10f
+
+ verify(depthController).transitionToFullShadeProgress = 0f
+ }
@Test
- fun testDragDownAmountCallsOut() =
- testScope.runTest {
- transitionController.dragDownAmount = 10f
- verify(nsslController).setTransitionToFullShadeAmount(anyFloat())
- verify(mediaHierarchyManager).setTransitionToFullShadeAmount(anyFloat())
- verify(scrimController).setTransitionToFullShadeProgress(anyFloat(), anyFloat())
- verify(transitionControllerCallback)
- .setTransitionToFullShadeAmount(anyFloat(), anyBoolean(), anyLong())
- verify(qsTransitionController).dragDownAmount = 10f
- verify(depthController).transitionToFullShadeProgress = anyFloat()
- }
+ fun testDragDownAmount_depthDistanceNonZero_setsProgressBasedOnDistance() {
+ context
+ .getOrCreateTestableResources()
+ .addOverride(R.dimen.lockscreen_shade_depth_controller_transition_distance, 100)
+ configurationController.notifyConfigurationChanged()
+
+ transitionController.dragDownAmount = 10f
+
+ verify(depthController).transitionToFullShadeProgress = 0.1f
+ }
@Test
- fun testDragDownAmount_depthDistanceIsZero_setsProgressToZero() =
- testScope.runTest {
- context
- .getOrCreateTestableResources()
- .addOverride(R.dimen.lockscreen_shade_depth_controller_transition_distance, 0)
- configurationController.notifyConfigurationChanged()
+ fun setDragAmount_setsKeyguardTransitionProgress() {
+ transitionController.dragDownAmount = 10f
- transitionController.dragDownAmount = 10f
-
- verify(depthController).transitionToFullShadeProgress = 0f
- }
+ verify(shadeLockscreenInteractor).setKeyguardTransitionProgress(anyFloat(), anyInt())
+ }
@Test
- fun testDragDownAmount_depthDistanceNonZero_setsProgressBasedOnDistance() =
- testScope.runTest {
- context
- .getOrCreateTestableResources()
- .addOverride(R.dimen.lockscreen_shade_depth_controller_transition_distance, 100)
- configurationController.notifyConfigurationChanged()
+ fun setDragAmount_setsKeyguardAlphaBasedOnDistance() {
+ val alphaDistance =
+ context.resources.getDimensionPixelSize(
+ R.dimen.lockscreen_shade_npvc_keyguard_content_alpha_transition_distance
+ )
+ transitionController.dragDownAmount = 10f
- transitionController.dragDownAmount = 10f
-
- verify(depthController).transitionToFullShadeProgress = 0.1f
- }
+ val expectedAlpha = 1 - 10f / alphaDistance
+ verify(shadeLockscreenInteractor).setKeyguardTransitionProgress(eq(expectedAlpha), anyInt())
+ }
@Test
- fun setDragAmount_setsKeyguardTransitionProgress() =
- testScope.runTest {
- transitionController.dragDownAmount = 10f
+ fun setDragAmount_notInSplitShade_setsKeyguardTranslationToZero() {
+ val mediaTranslationY = 123
+ disableSplitShade()
+ whenever(mediaHierarchyManager.isCurrentlyInGuidedTransformation()).thenReturn(true)
+ whenever(mediaHierarchyManager.getGuidedTransformationTranslationY())
+ .thenReturn(mediaTranslationY)
- verify(shadeLockscreenInteractor).setKeyguardTransitionProgress(anyFloat(), anyInt())
- }
+ transitionController.dragDownAmount = 10f
+
+ verify(shadeLockscreenInteractor).setKeyguardTransitionProgress(anyFloat(), eq(0))
+ }
@Test
- fun setDragAmount_setsKeyguardAlphaBasedOnDistance() =
- testScope.runTest {
- val alphaDistance =
- context.resources.getDimensionPixelSize(
- R.dimen.lockscreen_shade_npvc_keyguard_content_alpha_transition_distance
- )
- transitionController.dragDownAmount = 10f
+ fun setDragAmount_inSplitShade_setsKeyguardTranslationBasedOnMediaTranslation() {
+ val mediaTranslationY = 123
+ enableSplitShade()
+ whenever(mediaHierarchyManager.isCurrentlyInGuidedTransformation()).thenReturn(true)
+ whenever(mediaHierarchyManager.getGuidedTransformationTranslationY())
+ .thenReturn(mediaTranslationY)
- val expectedAlpha = 1 - 10f / alphaDistance
- verify(shadeLockscreenInteractor)
- .setKeyguardTransitionProgress(eq(expectedAlpha), anyInt())
- }
+ transitionController.dragDownAmount = 10f
- @Test
- fun setDragAmount_notInSplitShade_setsKeyguardTranslationToZero() =
- testScope.runTest {
- val mediaTranslationY = 123
- disableSplitShade()
- whenever(mediaHierarchyManager.isCurrentlyInGuidedTransformation()).thenReturn(true)
- whenever(mediaHierarchyManager.getGuidedTransformationTranslationY())
- .thenReturn(mediaTranslationY)
-
- transitionController.dragDownAmount = 10f
-
- verify(shadeLockscreenInteractor).setKeyguardTransitionProgress(anyFloat(), eq(0))
- }
-
- @Test
- fun setDragAmount_inSplitShade_setsKeyguardTranslationBasedOnMediaTranslation() =
- testScope.runTest {
- val mediaTranslationY = 123
- enableSplitShade()
- whenever(mediaHierarchyManager.isCurrentlyInGuidedTransformation()).thenReturn(true)
- whenever(mediaHierarchyManager.getGuidedTransformationTranslationY())
- .thenReturn(mediaTranslationY)
-
- transitionController.dragDownAmount = 10f
-
- verify(shadeLockscreenInteractor)
+ verify(shadeLockscreenInteractor)
.setKeyguardTransitionProgress(anyFloat(), eq(mediaTranslationY))
- }
+ }
@Test
- fun setDragAmount_inSplitShade_mediaNotShowing_setsKeyguardTranslationBasedOnDistance() =
- testScope.runTest {
- enableSplitShade()
- whenever(mediaHierarchyManager.isCurrentlyInGuidedTransformation()).thenReturn(false)
- whenever(mediaHierarchyManager.getGuidedTransformationTranslationY()).thenReturn(123)
+ fun setDragAmount_inSplitShade_mediaNotShowing_setsKeyguardTranslationBasedOnDistance() {
+ enableSplitShade()
+ whenever(mediaHierarchyManager.isCurrentlyInGuidedTransformation()).thenReturn(false)
+ whenever(mediaHierarchyManager.getGuidedTransformationTranslationY()).thenReturn(123)
- transitionController.dragDownAmount = 10f
+ transitionController.dragDownAmount = 10f
- val distance =
- context.resources.getDimensionPixelSize(
- R.dimen.lockscreen_shade_keyguard_transition_distance
- )
- val offset =
- context.resources.getDimensionPixelSize(
- R.dimen.lockscreen_shade_keyguard_transition_vertical_offset
- )
- val expectedTranslation = 10f / distance * offset
- verify(shadeLockscreenInteractor)
- .setKeyguardTransitionProgress(anyFloat(), eq(expectedTranslation.toInt()))
- }
-
- @Test
- fun setDragDownAmount_setsValueOnMediaHierarchyManager() =
- testScope.runTest {
- transitionController.dragDownAmount = 10f
-
- verify(mediaHierarchyManager).setTransitionToFullShadeAmount(10f)
- }
-
- @Test
- fun setDragAmount_setsScrimProgressBasedOnScrimDistance() =
- testScope.runTest {
- val distance = 10
- context.orCreateTestableResources.addOverride(
- R.dimen.lockscreen_shade_scrim_transition_distance,
- distance
+ val distance =
+ context.resources.getDimensionPixelSize(
+ R.dimen.lockscreen_shade_keyguard_transition_distance
)
- configurationController.notifyConfigurationChanged()
-
- transitionController.dragDownAmount = 5f
-
- verify(scrimController)
- .transitionToFullShadeProgress(
- progress = eq(0.5f),
- lockScreenNotificationsProgress = anyFloat()
- )
- }
-
- @Test
- fun setDragAmount_setsNotificationsScrimProgressBasedOnNotificationsScrimDistanceAndDelay() =
- testScope.runTest {
- val distance = 100
- val delay = 10
- context.orCreateTestableResources.addOverride(
- R.dimen.lockscreen_shade_notifications_scrim_transition_distance,
- distance
+ val offset =
+ context.resources.getDimensionPixelSize(
+ R.dimen.lockscreen_shade_keyguard_transition_vertical_offset
)
- context.orCreateTestableResources.addOverride(
- R.dimen.lockscreen_shade_notifications_scrim_transition_delay,
- delay
+ val expectedTranslation = 10f / distance * offset
+ verify(shadeLockscreenInteractor)
+ .setKeyguardTransitionProgress(anyFloat(), eq(expectedTranslation.toInt()))
+ }
+
+ @Test
+ fun setDragDownAmount_setsValueOnMediaHierarchyManager() {
+ transitionController.dragDownAmount = 10f
+
+ verify(mediaHierarchyManager).setTransitionToFullShadeAmount(10f)
+ }
+
+ @Test
+ fun setDragAmount_setsScrimProgressBasedOnScrimDistance() {
+ val distance = 10
+ context.orCreateTestableResources.addOverride(
+ R.dimen.lockscreen_shade_scrim_transition_distance,
+ distance
+ )
+ configurationController.notifyConfigurationChanged()
+
+ transitionController.dragDownAmount = 5f
+
+ verify(scrimController)
+ .transitionToFullShadeProgress(
+ progress = eq(0.5f),
+ lockScreenNotificationsProgress = anyFloat()
)
- configurationController.notifyConfigurationChanged()
-
- transitionController.dragDownAmount = 20f
-
- verify(scrimController)
- .transitionToFullShadeProgress(
- progress = anyFloat(),
- lockScreenNotificationsProgress = eq(0.1f)
- )
- }
+ }
@Test
- fun setDragAmount_dragAmountLessThanNotifDelayDistance_setsNotificationsScrimProgressToZero() =
- testScope.runTest {
- val distance = 100
- val delay = 50
- context.orCreateTestableResources.addOverride(
- R.dimen.lockscreen_shade_notifications_scrim_transition_distance,
- distance
+ fun setDragAmount_setsNotificationsScrimProgressBasedOnNotificationsScrimDistanceAndDelay() {
+ val distance = 100
+ val delay = 10
+ context.orCreateTestableResources.addOverride(
+ R.dimen.lockscreen_shade_notifications_scrim_transition_distance,
+ distance
+ )
+ context.orCreateTestableResources.addOverride(
+ R.dimen.lockscreen_shade_notifications_scrim_transition_delay,
+ delay
+ )
+ configurationController.notifyConfigurationChanged()
+
+ transitionController.dragDownAmount = 20f
+
+ verify(scrimController)
+ .transitionToFullShadeProgress(
+ progress = anyFloat(),
+ lockScreenNotificationsProgress = eq(0.1f)
)
- context.orCreateTestableResources.addOverride(
- R.dimen.lockscreen_shade_notifications_scrim_transition_delay,
- delay
+ }
+
+ @Test
+ fun setDragAmount_dragAmountLessThanNotifDelayDistance_setsNotificationsScrimProgressToZero() {
+ val distance = 100
+ val delay = 50
+ context.orCreateTestableResources.addOverride(
+ R.dimen.lockscreen_shade_notifications_scrim_transition_distance,
+ distance
+ )
+ context.orCreateTestableResources.addOverride(
+ R.dimen.lockscreen_shade_notifications_scrim_transition_delay,
+ delay
+ )
+ configurationController.notifyConfigurationChanged()
+
+ transitionController.dragDownAmount = 20f
+
+ verify(scrimController)
+ .transitionToFullShadeProgress(
+ progress = anyFloat(),
+ lockScreenNotificationsProgress = eq(0f)
)
- configurationController.notifyConfigurationChanged()
-
- transitionController.dragDownAmount = 20f
-
- verify(scrimController)
- .transitionToFullShadeProgress(
- progress = anyFloat(),
- lockScreenNotificationsProgress = eq(0f)
- )
- }
+ }
@Test
- fun setDragAmount_dragAmountMoreThanTotalDistance_setsNotificationsScrimProgressToOne() =
- testScope.runTest {
- val distance = 100
- val delay = 50
- context.orCreateTestableResources.addOverride(
- R.dimen.lockscreen_shade_notifications_scrim_transition_distance,
- distance
+ fun setDragAmount_dragAmountMoreThanTotalDistance_setsNotificationsScrimProgressToOne() {
+ val distance = 100
+ val delay = 50
+ context.orCreateTestableResources.addOverride(
+ R.dimen.lockscreen_shade_notifications_scrim_transition_distance,
+ distance
+ )
+ context.orCreateTestableResources.addOverride(
+ R.dimen.lockscreen_shade_notifications_scrim_transition_delay,
+ delay
+ )
+ configurationController.notifyConfigurationChanged()
+
+ transitionController.dragDownAmount = 999999f
+
+ verify(scrimController)
+ .transitionToFullShadeProgress(
+ progress = anyFloat(),
+ lockScreenNotificationsProgress = eq(1f)
)
- context.orCreateTestableResources.addOverride(
- R.dimen.lockscreen_shade_notifications_scrim_transition_delay,
- delay
+ }
+
+ @Test
+ fun setDragDownAmount_inSplitShade_setsValueOnMediaHierarchyManager() {
+ enableSplitShade()
+
+ transitionController.dragDownAmount = 10f
+
+ verify(mediaHierarchyManager).setTransitionToFullShadeAmount(10f)
+ }
+
+ @Test
+ fun setDragAmount_notInSplitShade_forwardsToSingleShadeOverScroller() {
+ disableSplitShade()
+
+ transitionController.dragDownAmount = 10f
+
+ verify(singleShadeOverScroller).expansionDragDownAmount = 10f
+ verifyZeroInteractions(splitShadeOverScroller)
+ }
+
+ @Test
+ fun setDragAmount_inSplitShade_forwardsToSplitShadeOverScroller() {
+ enableSplitShade()
+
+ transitionController.dragDownAmount = 10f
+
+ verify(splitShadeOverScroller).expansionDragDownAmount = 10f
+ verifyZeroInteractions(singleShadeOverScroller)
+ }
+
+ @Test
+ fun setDragDownAmount_inSplitShade_setsKeyguardStatusBarAlphaBasedOnDistance() {
+ val alphaDistance =
+ context.resources.getDimensionPixelSize(
+ R.dimen.lockscreen_shade_npvc_keyguard_content_alpha_transition_distance
)
- configurationController.notifyConfigurationChanged()
+ val dragDownAmount = 10f
+ enableSplitShade()
- transitionController.dragDownAmount = 999999f
+ transitionController.dragDownAmount = dragDownAmount
- verify(scrimController)
- .transitionToFullShadeProgress(
- progress = anyFloat(),
- lockScreenNotificationsProgress = eq(1f)
- )
- }
+ val expectedAlpha = 1 - dragDownAmount / alphaDistance
+ verify(shadeLockscreenInteractor).setKeyguardStatusBarAlpha(expectedAlpha)
+ }
@Test
- fun setDragDownAmount_inSplitShade_setsValueOnMediaHierarchyManager() =
- testScope.runTest {
- enableSplitShade()
+ fun setDragDownAmount_notInSplitShade_setsKeyguardStatusBarAlphaToMinusOne() {
+ disableSplitShade()
- transitionController.dragDownAmount = 10f
+ transitionController.dragDownAmount = 10f
- verify(mediaHierarchyManager).setTransitionToFullShadeAmount(10f)
- }
+ verify(shadeLockscreenInteractor).setKeyguardStatusBarAlpha(-1f)
+ }
@Test
- fun setDragAmount_notInSplitShade_forwardsToSingleShadeOverScroller() =
- testScope.runTest {
- disableSplitShade()
+ fun nullQs_canDragDownFromAdapter() {
+ transitionController.qS = null
- transitionController.dragDownAmount = 10f
-
- verify(singleShadeOverScroller).expansionDragDownAmount = 10f
- verifyZeroInteractions(splitShadeOverScroller)
- }
-
- @Test
- fun setDragAmount_inSplitShade_forwardsToSplitShadeOverScroller() =
- testScope.runTest {
- enableSplitShade()
-
- transitionController.dragDownAmount = 10f
-
- verify(splitShadeOverScroller).expansionDragDownAmount = 10f
- verifyZeroInteractions(singleShadeOverScroller)
- }
-
- @Test
- fun setDragDownAmount_inSplitShade_setsKeyguardStatusBarAlphaBasedOnDistance() =
- testScope.runTest {
- val alphaDistance =
- context.resources.getDimensionPixelSize(
- R.dimen.lockscreen_shade_npvc_keyguard_content_alpha_transition_distance
- )
- val dragDownAmount = 10f
- enableSplitShade()
-
- transitionController.dragDownAmount = dragDownAmount
-
- val expectedAlpha = 1 - dragDownAmount / alphaDistance
- verify(shadeLockscreenInteractor).setKeyguardStatusBarAlpha(expectedAlpha)
- }
-
- @Test
- fun setDragDownAmount_notInSplitShade_setsKeyguardStatusBarAlphaToMinusOne() =
- testScope.runTest {
- disableSplitShade()
-
- transitionController.dragDownAmount = 10f
-
- verify(shadeLockscreenInteractor).setKeyguardStatusBarAlpha(-1f)
- }
-
- @Test
- fun nullQs_canDragDownFromAdapter() =
- testScope.runTest {
- transitionController.qS = null
-
- qsSceneAdapter.isQsFullyCollapsed = true
- assertTrue("Can't drag down on keyguard", transitionController.canDragDown())
- qsSceneAdapter.isQsFullyCollapsed = false
- assertFalse("Can drag down when QS is expanded", transitionController.canDragDown())
- }
+ qsSceneAdapter.isQsFullyCollapsed = true
+ assertTrue("Can't drag down on keyguard", transitionController.canDragDown())
+ qsSceneAdapter.isQsFullyCollapsed = false
+ assertFalse("Can drag down when QS is expanded", transitionController.canDragDown())
+ }
private fun enableSplitShade() {
setSplitShadeEnabled(true)
@@ -631,4 +619,32 @@
) {
setTransitionToFullShadeProgress(progress, lockScreenNotificationsProgress)
}
+
+ @SysUISingleton
+ @Component(
+ modules =
+ [
+ SysUITestModule::class,
+ UserDomainLayerModule::class,
+ BiometricsDomainLayerModule::class,
+ ]
+ )
+ interface TestComponent {
+
+ val configurationController: FakeConfigurationController
+ val disableFlagsRepository: FakeDisableFlagsRepository
+ val powerInteractor: PowerInteractor
+ val shadeInteractor: ShadeInteractor
+ val shadeRepository: FakeShadeRepository
+ val testScope: TestScope
+
+ @Component.Factory
+ interface Factory {
+ fun create(
+ @BindsInstance test: SysuiTestCase,
+ featureFlags: FakeFeatureFlagsClassicModule,
+ mocks: TestMocksModule,
+ ): TestComponent
+ }
+ }
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractorTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractorTest.kt
index f07303e..26f5370 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractorTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/domain/interactor/NotificationIconsInteractorTest.kt
@@ -17,19 +17,21 @@
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
+import com.android.systemui.SysUITestComponent
+import com.android.systemui.SysUITestModule
import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectLastValue
-import com.android.systemui.deviceentry.data.repository.fakeDeviceEntryRepository
-import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
-import com.android.systemui.kosmos.testDispatcher
-import com.android.systemui.kosmos.testScope
-import com.android.systemui.statusbar.data.repository.notificationListenerSettingsRepository
+import com.android.systemui.TestMocksModule
+import com.android.systemui.biometrics.domain.BiometricsDomainLayerModule
+import com.android.systemui.collectLastValue
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.deviceentry.data.repository.FakeDeviceEntryRepository
+import com.android.systemui.runTest
+import com.android.systemui.statusbar.data.repository.NotificationListenerSettingsRepository
import com.android.systemui.statusbar.notification.data.model.activeNotificationModel
+import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationListRepository
import com.android.systemui.statusbar.notification.data.repository.ActiveNotificationsStore
-import com.android.systemui.statusbar.notification.data.repository.activeNotificationListRepository
-import com.android.systemui.statusbar.notification.data.repository.notificationsKeyguardViewStateRepository
-import com.android.systemui.statusbar.notification.domain.interactor.activeNotificationsInteractor
-import com.android.systemui.statusbar.notification.domain.interactor.headsUpNotificationIconInteractor
+import com.android.systemui.statusbar.notification.domain.interactor.HeadsUpNotificationIconInteractor
+import com.android.systemui.statusbar.notification.domain.interactor.NotificationsKeyguardInteractor
import com.android.systemui.statusbar.notification.shared.byIsAmbient
import com.android.systemui.statusbar.notification.shared.byIsLastMessageFromReply
import com.android.systemui.statusbar.notification.shared.byIsPulsing
@@ -37,15 +39,15 @@
import com.android.systemui.statusbar.notification.shared.byIsSilent
import com.android.systemui.statusbar.notification.shared.byIsSuppressedFromStatusBar
import com.android.systemui.statusbar.notification.shared.byKey
-import com.android.systemui.statusbar.notification.stack.domain.interactor.notificationsKeyguardInteractor
-import com.android.systemui.testKosmos
+import com.android.systemui.user.domain.UserDomainLayerModule
import com.android.systemui.util.mockito.eq
+import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
-import com.android.wm.shell.bubbles.bubbles
-import com.android.wm.shell.bubbles.bubblesOptional
+import com.android.wm.shell.bubbles.Bubbles
import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.runTest
+import dagger.BindsInstance
+import dagger.Component
+import java.util.Optional
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
@@ -53,22 +55,29 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class NotificationIconsInteractorTest : SysuiTestCase() {
- private val kosmos = testKosmos()
- private val testScope = kosmos.testScope
- private val activeNotificationListRepository = kosmos.activeNotificationListRepository
- private val notificationsKeyguardInteractor = kosmos.notificationsKeyguardInteractor
- private val underTest =
- NotificationIconsInteractor(
- kosmos.activeNotificationsInteractor,
- kosmos.bubblesOptional,
- kosmos.headsUpNotificationIconInteractor,
- kosmos.notificationsKeyguardViewStateRepository
- )
+ private val bubbles: Bubbles = mock()
+
+ @Component(modules = [SysUITestModule::class])
+ @SysUISingleton
+ interface TestComponent : SysUITestComponent<NotificationIconsInteractor> {
+
+ val activeNotificationListRepository: ActiveNotificationListRepository
+ val notificationsKeyguardInteractor: NotificationsKeyguardInteractor
+
+ @Component.Factory
+ interface Factory {
+ fun create(@BindsInstance test: SysuiTestCase, mocks: TestMocksModule): TestComponent
+ }
+ }
+
+ val testComponent: TestComponent =
+ DaggerNotificationIconsInteractorTest_TestComponent.factory()
+ .create(test = this, mocks = TestMocksModule(bubbles = Optional.of(bubbles)))
@Before
fun setup() {
- testScope.apply {
+ testComponent.apply {
activeNotificationListRepository.activeNotifications.value =
ActiveNotificationsStore.Builder()
.apply { testIcons.forEach(::addIndividualNotif) }
@@ -78,22 +87,22 @@
@Test
fun filteredEntrySet() =
- testScope.runTest {
+ testComponent.runTest {
val filteredSet by collectLastValue(underTest.filteredNotifSet())
assertThat(filteredSet).containsExactlyElementsIn(testIcons)
}
@Test
fun filteredEntrySet_noExpandedBubbles() =
- testScope.runTest {
- whenever(kosmos.bubbles.isBubbleExpanded(eq("notif1"))).thenReturn(true)
+ testComponent.runTest {
+ whenever(bubbles.isBubbleExpanded(eq("notif1"))).thenReturn(true)
val filteredSet by collectLastValue(underTest.filteredNotifSet())
assertThat(filteredSet).comparingElementsUsing(byKey).doesNotContain("notif1")
}
@Test
fun filteredEntrySet_noAmbient() =
- testScope.runTest {
+ testComponent.runTest {
val filteredSet by collectLastValue(underTest.filteredNotifSet(showAmbient = false))
assertThat(filteredSet).comparingElementsUsing(byIsAmbient).doesNotContain(true)
assertThat(filteredSet)
@@ -103,21 +112,21 @@
@Test
fun filteredEntrySet_noLowPriority() =
- testScope.runTest {
+ testComponent.runTest {
val filteredSet by collectLastValue(underTest.filteredNotifSet(showLowPriority = false))
assertThat(filteredSet).comparingElementsUsing(byIsSilent).doesNotContain(true)
}
@Test
fun filteredEntrySet_noDismissed() =
- testScope.runTest {
+ testComponent.runTest {
val filteredSet by collectLastValue(underTest.filteredNotifSet(showDismissed = false))
assertThat(filteredSet).comparingElementsUsing(byIsRowDismissed).doesNotContain(true)
}
@Test
fun filteredEntrySet_noRepliedMessages() =
- testScope.runTest {
+ testComponent.runTest {
val filteredSet by
collectLastValue(underTest.filteredNotifSet(showRepliedMessages = false))
assertThat(filteredSet)
@@ -127,7 +136,7 @@
@Test
fun filteredEntrySet_noPulsing_notifsNotFullyHidden() =
- testScope.runTest {
+ testComponent.runTest {
val filteredSet by collectLastValue(underTest.filteredNotifSet(showPulsing = false))
notificationsKeyguardInteractor.setNotificationsFullyHidden(false)
assertThat(filteredSet).comparingElementsUsing(byIsPulsing).doesNotContain(true)
@@ -135,46 +144,65 @@
@Test
fun filteredEntrySet_noPulsing_notifsFullyHidden() =
- testScope.runTest {
+ testComponent.runTest {
val filteredSet by collectLastValue(underTest.filteredNotifSet(showPulsing = false))
notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
assertThat(filteredSet).comparingElementsUsing(byIsPulsing).contains(true)
}
}
-@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
class AlwaysOnDisplayNotificationIconsInteractorTest : SysuiTestCase() {
- private val kosmos = testKosmos()
- private val testScope = kosmos.testScope
- private val underTest =
- AlwaysOnDisplayNotificationIconsInteractor(
- kosmos.testDispatcher,
- kosmos.deviceEntryInteractor,
- kosmos.notificationIconsInteractor,
- )
+ private val bubbles: Bubbles = mock()
+
+ @Component(
+ modules =
+ [
+ SysUITestModule::class,
+ BiometricsDomainLayerModule::class,
+ UserDomainLayerModule::class,
+ ]
+ )
+ @SysUISingleton
+ interface TestComponent : SysUITestComponent<AlwaysOnDisplayNotificationIconsInteractor> {
+
+ val activeNotificationListRepository: ActiveNotificationListRepository
+ val deviceEntryRepository: FakeDeviceEntryRepository
+ val notificationsKeyguardInteractor: NotificationsKeyguardInteractor
+
+ @Component.Factory
+ interface Factory {
+ fun create(@BindsInstance test: SysuiTestCase, mocks: TestMocksModule): TestComponent
+ }
+ }
+
+ private val testComponent: TestComponent =
+ DaggerAlwaysOnDisplayNotificationIconsInteractorTest_TestComponent.factory()
+ .create(test = this, mocks = TestMocksModule(bubbles = Optional.of(bubbles)))
@Before
fun setup() {
- kosmos.activeNotificationListRepository.activeNotifications.value =
- ActiveNotificationsStore.Builder()
- .apply { testIcons.forEach(::addIndividualNotif) }
- .build()
+ testComponent.apply {
+ activeNotificationListRepository.activeNotifications.value =
+ ActiveNotificationsStore.Builder()
+ .apply { testIcons.forEach(::addIndividualNotif) }
+ .build()
+ }
}
@Test
fun filteredEntrySet_noExpandedBubbles() =
- testScope.runTest {
- whenever(kosmos.bubbles.isBubbleExpanded(eq("notif1"))).thenReturn(true)
+ testComponent.runTest {
+ whenever(bubbles.isBubbleExpanded(eq("notif1"))).thenReturn(true)
val filteredSet by collectLastValue(underTest.aodNotifs)
assertThat(filteredSet).comparingElementsUsing(byKey).doesNotContain("notif1")
}
@Test
fun filteredEntrySet_noAmbient() =
- testScope.runTest {
+ testComponent.runTest {
val filteredSet by collectLastValue(underTest.aodNotifs)
assertThat(filteredSet).comparingElementsUsing(byIsAmbient).doesNotContain(true)
assertThat(filteredSet)
@@ -184,14 +212,14 @@
@Test
fun filteredEntrySet_noDismissed() =
- testScope.runTest {
+ testComponent.runTest {
val filteredSet by collectLastValue(underTest.aodNotifs)
assertThat(filteredSet).comparingElementsUsing(byIsRowDismissed).doesNotContain(true)
}
@Test
fun filteredEntrySet_noRepliedMessages() =
- testScope.runTest {
+ testComponent.runTest {
val filteredSet by collectLastValue(underTest.aodNotifs)
assertThat(filteredSet)
.comparingElementsUsing(byIsLastMessageFromReply)
@@ -200,37 +228,37 @@
@Test
fun filteredEntrySet_showPulsing_notifsNotFullyHidden_bypassDisabled() =
- testScope.runTest {
+ testComponent.runTest {
val filteredSet by collectLastValue(underTest.aodNotifs)
- kosmos.fakeDeviceEntryRepository.setBypassEnabled(false)
- kosmos.notificationsKeyguardInteractor.setNotificationsFullyHidden(false)
+ deviceEntryRepository.setBypassEnabled(false)
+ notificationsKeyguardInteractor.setNotificationsFullyHidden(false)
assertThat(filteredSet).comparingElementsUsing(byIsPulsing).contains(true)
}
@Test
fun filteredEntrySet_showPulsing_notifsFullyHidden_bypassDisabled() =
- testScope.runTest {
+ testComponent.runTest {
val filteredSet by collectLastValue(underTest.aodNotifs)
- kosmos.fakeDeviceEntryRepository.setBypassEnabled(false)
- kosmos.notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
+ deviceEntryRepository.setBypassEnabled(false)
+ notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
assertThat(filteredSet).comparingElementsUsing(byIsPulsing).contains(true)
}
@Test
fun filteredEntrySet_noPulsing_notifsNotFullyHidden_bypassEnabled() =
- testScope.runTest {
+ testComponent.runTest {
val filteredSet by collectLastValue(underTest.aodNotifs)
- kosmos.fakeDeviceEntryRepository.setBypassEnabled(true)
- kosmos.notificationsKeyguardInteractor.setNotificationsFullyHidden(false)
+ deviceEntryRepository.setBypassEnabled(true)
+ notificationsKeyguardInteractor.setNotificationsFullyHidden(false)
assertThat(filteredSet).comparingElementsUsing(byIsPulsing).doesNotContain(true)
}
@Test
fun filteredEntrySet_showPulsing_notifsFullyHidden_bypassEnabled() =
- testScope.runTest {
+ testComponent.runTest {
val filteredSet by collectLastValue(underTest.aodNotifs)
- kosmos.fakeDeviceEntryRepository.setBypassEnabled(true)
- kosmos.notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
+ deviceEntryRepository.setBypassEnabled(true)
+ notificationsKeyguardInteractor.setNotificationsFullyHidden(true)
assertThat(filteredSet).comparingElementsUsing(byIsPulsing).contains(true)
}
}
@@ -238,19 +266,32 @@
@SmallTest
@RunWith(AndroidJUnit4::class)
class StatusBarNotificationIconsInteractorTest : SysuiTestCase() {
- private val kosmos = testKosmos()
- private val testScope = kosmos.testScope
- private val underTest =
- StatusBarNotificationIconsInteractor(
- kosmos.testDispatcher,
- kosmos.notificationIconsInteractor,
- kosmos.notificationListenerSettingsRepository,
- )
+
+ private val bubbles: Bubbles = mock()
+
+ @Component(modules = [SysUITestModule::class])
+ @SysUISingleton
+ interface TestComponent : SysUITestComponent<StatusBarNotificationIconsInteractor> {
+
+ val activeNotificationListRepository: ActiveNotificationListRepository
+ val headsUpIconsInteractor: HeadsUpNotificationIconInteractor
+ val notificationsKeyguardInteractor: NotificationsKeyguardInteractor
+ val notificationListenerSettingsRepository: NotificationListenerSettingsRepository
+
+ @Component.Factory
+ interface Factory {
+ fun create(@BindsInstance test: SysuiTestCase, mocks: TestMocksModule): TestComponent
+ }
+ }
+
+ val testComponent: TestComponent =
+ DaggerStatusBarNotificationIconsInteractorTest_TestComponent.factory()
+ .create(test = this, mocks = TestMocksModule(bubbles = Optional.of(bubbles)))
@Before
fun setup() {
- testScope.apply {
- kosmos.activeNotificationListRepository.activeNotifications.value =
+ testComponent.apply {
+ activeNotificationListRepository.activeNotifications.value =
ActiveNotificationsStore.Builder()
.apply { testIcons.forEach(::addIndividualNotif) }
.build()
@@ -259,15 +300,15 @@
@Test
fun filteredEntrySet_noExpandedBubbles() =
- testScope.runTest {
- whenever(kosmos.bubbles.isBubbleExpanded(eq("notif1"))).thenReturn(true)
+ testComponent.runTest {
+ whenever(bubbles.isBubbleExpanded(eq("notif1"))).thenReturn(true)
val filteredSet by collectLastValue(underTest.statusBarNotifs)
assertThat(filteredSet).comparingElementsUsing(byKey).doesNotContain("notif1")
}
@Test
fun filteredEntrySet_noAmbient() =
- testScope.runTest {
+ testComponent.runTest {
val filteredSet by collectLastValue(underTest.statusBarNotifs)
assertThat(filteredSet).comparingElementsUsing(byIsAmbient).doesNotContain(true)
assertThat(filteredSet)
@@ -277,30 +318,30 @@
@Test
fun filteredEntrySet_noLowPriority_whenDontShowSilentIcons() =
- testScope.runTest {
+ testComponent.runTest {
val filteredSet by collectLastValue(underTest.statusBarNotifs)
- kosmos.notificationListenerSettingsRepository.showSilentStatusIcons.value = false
+ notificationListenerSettingsRepository.showSilentStatusIcons.value = false
assertThat(filteredSet).comparingElementsUsing(byIsSilent).doesNotContain(true)
}
@Test
fun filteredEntrySet_showLowPriority_whenShowSilentIcons() =
- testScope.runTest {
+ testComponent.runTest {
val filteredSet by collectLastValue(underTest.statusBarNotifs)
- kosmos.notificationListenerSettingsRepository.showSilentStatusIcons.value = true
+ notificationListenerSettingsRepository.showSilentStatusIcons.value = true
assertThat(filteredSet).comparingElementsUsing(byIsSilent).contains(true)
}
@Test
fun filteredEntrySet_noDismissed() =
- testScope.runTest {
+ testComponent.runTest {
val filteredSet by collectLastValue(underTest.statusBarNotifs)
assertThat(filteredSet).comparingElementsUsing(byIsRowDismissed).doesNotContain(true)
}
@Test
fun filteredEntrySet_noRepliedMessages() =
- testScope.runTest {
+ testComponent.runTest {
val filteredSet by collectLastValue(underTest.statusBarNotifs)
assertThat(filteredSet)
.comparingElementsUsing(byIsLastMessageFromReply)
@@ -309,9 +350,9 @@
@Test
fun filteredEntrySet_includesIsolatedIcon() =
- testScope.runTest {
+ testComponent.runTest {
val filteredSet by collectLastValue(underTest.statusBarNotifs)
- kosmos.headsUpNotificationIconInteractor.setIsolatedIconNotificationKey("notif5")
+ headsUpIconsInteractor.setIsolatedIconNotificationKey("notif5")
assertThat(filteredSet).comparingElementsUsing(byKey).contains("notif5")
}
}
diff --git a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt
index 1f4e80e..894e02e 100644
--- a/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt
+++ b/packages/SystemUI/tests/src/com/android/systemui/statusbar/notification/icon/ui/viewmodel/NotificationIconContainerAlwaysOnDisplayViewModelTest.kt
@@ -16,81 +16,111 @@
package com.android.systemui.statusbar.notification.icon.ui.viewmodel
-import android.content.res.mainResources
import android.platform.test.annotations.DisableFlags
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.SmallTest
import com.android.systemui.Flags.FLAG_KEYGUARD_WM_STATE_REFACTOR
import com.android.systemui.Flags.FLAG_NEW_AOD_TRANSITION
+import com.android.systemui.SysUITestComponent
+import com.android.systemui.SysUITestModule
import com.android.systemui.SysuiTestCase
-import com.android.systemui.coroutines.collectLastValue
+import com.android.systemui.TestMocksModule
+import com.android.systemui.biometrics.domain.BiometricsDomainLayerModule
+import com.android.systemui.collectLastValue
+import com.android.systemui.dagger.SysUISingleton
+import com.android.systemui.flags.FakeFeatureFlagsClassicModule
import com.android.systemui.flags.Flags
-import com.android.systemui.flags.fakeFeatureFlagsClassic
-import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
-import com.android.systemui.keyguard.data.repository.fakeKeyguardTransitionRepository
-import com.android.systemui.keyguard.domain.interactor.keyguardInteractor
-import com.android.systemui.keyguard.domain.interactor.keyguardTransitionInteractor
+import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
+import com.android.systemui.keyguard.data.repository.FakeKeyguardTransitionRepository
import com.android.systemui.keyguard.shared.model.DozeStateModel
import com.android.systemui.keyguard.shared.model.DozeTransitionModel
import com.android.systemui.keyguard.shared.model.KeyguardState
import com.android.systemui.keyguard.shared.model.TransitionState
import com.android.systemui.keyguard.shared.model.TransitionStep
-import com.android.systemui.kosmos.testDispatcher
-import com.android.systemui.kosmos.testScope
-import com.android.systemui.power.data.repository.fakePowerRepository
+import com.android.systemui.power.data.repository.FakePowerRepository
import com.android.systemui.power.shared.model.WakeSleepReason
import com.android.systemui.power.shared.model.WakefulnessState
-import com.android.systemui.shade.domain.interactor.shadeInteractor
-import com.android.systemui.statusbar.notification.icon.domain.interactor.alwaysOnDisplayNotificationIconsInteractor
-import com.android.systemui.statusbar.phone.dozeParameters
-import com.android.systemui.testKosmos
+import com.android.systemui.runCurrent
+import com.android.systemui.runTest
+import com.android.systemui.statusbar.phone.DozeParameters
+import com.android.systemui.statusbar.phone.ScreenOffAnimationController
+import com.android.systemui.statusbar.policy.data.repository.FakeDeviceProvisioningRepository
+import com.android.systemui.user.domain.UserDomainLayerModule
+import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.whenever
import com.google.common.truth.Truth.assertThat
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-import kotlinx.coroutines.test.runCurrent
-import kotlinx.coroutines.test.runTest
+import dagger.BindsInstance
+import dagger.Component
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
-@OptIn(ExperimentalCoroutinesApi::class)
@SmallTest
@RunWith(AndroidJUnit4::class)
class NotificationIconContainerAlwaysOnDisplayViewModelTest : SysuiTestCase() {
- private val kosmos =
- testKosmos().apply {
- fakeFeatureFlagsClassic.apply { set(Flags.FULL_SCREEN_USER_SWITCHER, value = false) }
- }
- val underTest =
- NotificationIconContainerAlwaysOnDisplayViewModel(
- kosmos.testDispatcher,
- kosmos.alwaysOnDisplayNotificationIconsInteractor,
- kosmos.keyguardInteractor,
- kosmos.keyguardTransitionInteractor,
- kosmos.mainResources,
- kosmos.shadeInteractor,
- )
- val testScope = kosmos.testScope
- val keyguardRepository = kosmos.fakeKeyguardRepository
- val keyguardTransitionRepository = kosmos.fakeKeyguardTransitionRepository
- val powerRepository = kosmos.fakePowerRepository
+ @SysUISingleton
+ @Component(
+ modules =
+ [
+ SysUITestModule::class,
+ BiometricsDomainLayerModule::class,
+ UserDomainLayerModule::class,
+ ]
+ )
+ interface TestComponent :
+ SysUITestComponent<NotificationIconContainerAlwaysOnDisplayViewModel> {
+
+ val deviceProvisioningRepository: FakeDeviceProvisioningRepository
+ val keyguardRepository: FakeKeyguardRepository
+ val keyguardTransitionRepository: FakeKeyguardTransitionRepository
+ val powerRepository: FakePowerRepository
+
+ @Component.Factory
+ interface Factory {
+ fun create(
+ @BindsInstance test: SysuiTestCase,
+ mocks: TestMocksModule,
+ featureFlags: FakeFeatureFlagsClassicModule,
+ ): TestComponent
+ }
+ }
+
+ private val dozeParams: DozeParameters = mock()
+ private val screenOffAnimController: ScreenOffAnimationController = mock()
+
+ private val testComponent: TestComponent =
+ DaggerNotificationIconContainerAlwaysOnDisplayViewModelTest_TestComponent.factory()
+ .create(
+ test = this,
+ featureFlags =
+ FakeFeatureFlagsClassicModule {
+ set(Flags.FULL_SCREEN_USER_SWITCHER, value = false)
+ },
+ mocks =
+ TestMocksModule(
+ dozeParameters = dozeParams,
+ screenOffAnimationController = screenOffAnimController,
+ ),
+ )
@Before
fun setup() {
- keyguardRepository.setKeyguardShowing(true)
- keyguardRepository.setKeyguardOccluded(false)
- kosmos.fakePowerRepository.updateWakefulness(
- rawState = WakefulnessState.AWAKE,
- lastWakeReason = WakeSleepReason.OTHER,
- lastSleepReason = WakeSleepReason.OTHER,
- )
+ testComponent.apply {
+ keyguardRepository.setKeyguardShowing(true)
+ keyguardRepository.setKeyguardOccluded(false)
+ powerRepository.updateWakefulness(
+ rawState = WakefulnessState.AWAKE,
+ lastWakeReason = WakeSleepReason.OTHER,
+ lastSleepReason = WakeSleepReason.OTHER,
+ )
+ }
mSetFlagsRule.enableFlags(FLAG_NEW_AOD_TRANSITION)
}
@Test
fun animationsEnabled_isFalse_whenDeviceAsleepAndNotPulsing() =
- testScope.runTest {
+ testComponent.runTest {
powerRepository.updateWakefulness(
rawState = WakefulnessState.ASLEEP,
lastWakeReason = WakeSleepReason.POWER_BUTTON,
@@ -113,7 +143,7 @@
@Test
fun animationsEnabled_isTrue_whenDeviceAsleepAndPulsing() =
- testScope.runTest {
+ testComponent.runTest {
powerRepository.updateWakefulness(
rawState = WakefulnessState.ASLEEP,
lastWakeReason = WakeSleepReason.POWER_BUTTON,
@@ -136,7 +166,7 @@
@Test
fun animationsEnabled_isFalse_whenStartingToSleepAndNotControlScreenOff() =
- testScope.runTest {
+ testComponent.runTest {
powerRepository.updateWakefulness(
rawState = WakefulnessState.STARTING_TO_SLEEP,
lastWakeReason = WakeSleepReason.POWER_BUTTON,
@@ -149,7 +179,7 @@
transitionState = TransitionState.STARTED,
)
)
- whenever(kosmos.dozeParameters.shouldControlScreenOff()).thenReturn(false)
+ whenever(dozeParams.shouldControlScreenOff()).thenReturn(false)
val animationsEnabled by collectLastValue(underTest.areContainerChangesAnimated)
runCurrent()
assertThat(animationsEnabled).isFalse()
@@ -157,7 +187,7 @@
@Test
fun animationsEnabled_isTrue_whenStartingToSleepAndControlScreenOff() =
- testScope.runTest {
+ testComponent.runTest {
val animationsEnabled by collectLastValue(underTest.areContainerChangesAnimated)
assertThat(animationsEnabled).isTrue()
@@ -173,13 +203,13 @@
transitionState = TransitionState.STARTED,
)
)
- whenever(kosmos.dozeParameters.shouldControlScreenOff()).thenReturn(true)
+ whenever(dozeParams.shouldControlScreenOff()).thenReturn(true)
assertThat(animationsEnabled).isTrue()
}
@Test
fun animationsEnabled_isTrue_whenNotAsleep() =
- testScope.runTest {
+ testComponent.runTest {
powerRepository.updateWakefulness(
rawState = WakefulnessState.AWAKE,
lastWakeReason = WakeSleepReason.POWER_BUTTON,
@@ -198,7 +228,7 @@
@Test
@DisableFlags(FLAG_KEYGUARD_WM_STATE_REFACTOR)
fun animationsEnabled_isTrue_whenKeyguardIsShowing() =
- testScope.runTest {
+ testComponent.runTest {
keyguardTransitionRepository.sendTransitionStep(
TransitionStep(
transitionState = TransitionState.STARTED,
@@ -227,7 +257,7 @@
@Test
fun tintAlpha_isZero_whenNotOnAodOrDozing() =
- testScope.runTest {
+ testComponent.runTest {
val tintAlpha by collectLastValue(underTest.tintAlpha)
runCurrent()
keyguardTransitionRepository.sendTransitionSteps(
@@ -241,7 +271,7 @@
@Test
fun tintAlpha_isOne_whenOnAod() =
- testScope.runTest {
+ testComponent.runTest {
val tintAlpha by collectLastValue(underTest.tintAlpha)
runCurrent()
keyguardTransitionRepository.sendTransitionSteps(
@@ -255,7 +285,7 @@
@Test
fun tintAlpha_isOne_whenDozing() =
- testScope.runTest {
+ testComponent.runTest {
val tintAlpha by collectLastValue(underTest.tintAlpha)
runCurrent()
keyguardTransitionRepository.sendTransitionSteps(
@@ -268,7 +298,7 @@
@Test
fun tintAlpha_isOne_whenTransitionFromAodToDoze() =
- testScope.runTest {
+ testComponent.runTest {
keyguardTransitionRepository.sendTransitionSteps(
from = KeyguardState.GONE,
to = KeyguardState.AOD,
@@ -302,7 +332,7 @@
@Test
fun tintAlpha_isFraction_midTransitionToAod() =
- testScope.runTest {
+ testComponent.runTest {
val tintAlpha by collectLastValue(underTest.tintAlpha)
runCurrent()
@@ -331,7 +361,7 @@
@Test
fun iconAnimationsEnabled_whenOnLockScreen() =
- testScope.runTest {
+ testComponent.runTest {
val iconAnimationsEnabled by collectLastValue(underTest.areIconAnimationsEnabled)
runCurrent()
@@ -346,7 +376,7 @@
@Test
fun iconAnimationsDisabled_whenOnAod() =
- testScope.runTest {
+ testComponent.runTest {
val iconAnimationsEnabled by collectLastValue(underTest.areIconAnimationsEnabled)
runCurrent()
@@ -361,7 +391,7 @@
@Test
fun iconAnimationsDisabled_whenDozing() =
- testScope.runTest {
+ testComponent.runTest {
val iconAnimationsEnabled by collectLastValue(underTest.areIconAnimationsEnabled)
runCurrent()
diff --git a/packages/SystemUI/tests/utils/src/android/app/admin/AlarmManagerKosmos.kt b/packages/SystemUI/tests/utils/src/android/app/admin/AlarmManagerKosmos.kt
deleted file mode 100644
index a7b5873..0000000
--- a/packages/SystemUI/tests/utils/src/android/app/admin/AlarmManagerKosmos.kt
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Copyright (C) 2024 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 android.app.admin
-
-import android.app.AlarmManager
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.util.mockito.mock
-
-var Kosmos.alarmManager by Kosmos.Fixture { mock<AlarmManager>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/internal/widget/LockPatternUtilsKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/internal/widget/LockPatternUtilsKosmos.kt
index b511270..d9ea5e9 100644
--- a/packages/SystemUI/tests/utils/src/com/android/internal/widget/LockPatternUtilsKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/internal/widget/LockPatternUtilsKosmos.kt
@@ -16,14 +16,7 @@
package com.android.internal.widget
-import android.app.admin.devicePolicyManager
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.util.mockito.mock
-import com.android.systemui.util.mockito.whenever
-var Kosmos.lockPatternUtils by
- Kosmos.Fixture {
- mock<LockPatternUtils>().apply {
- whenever(this.devicePolicyManager).thenReturn(this@Fixture.devicePolicyManager)
- }
- }
+var Kosmos.lockPatternUtils by Kosmos.Fixture { mock<LockPatternUtils>() }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
index 87143ef..5bae6ec 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/data/repository/FakeKeyguardRepository.kt
@@ -135,9 +135,6 @@
private var isShowKeyguardWhenReenabled: Boolean = false
- private val _canIgnoreAuthAndReturnToGone = MutableStateFlow(false)
- override val canIgnoreAuthAndReturnToGone = _canIgnoreAuthAndReturnToGone.asStateFlow()
-
override fun setQuickSettingsVisible(isVisible: Boolean) {
_isQuickSettingsVisible.value = isVisible
}
@@ -281,10 +278,6 @@
override fun isShowKeyguardWhenReenabled(): Boolean {
return isShowKeyguardWhenReenabled
}
-
- override fun setCanIgnoreAuthAndReturnToGone(canWake: Boolean) {
- _canIgnoreAuthAndReturnToGone.value = canWake
- }
}
@Module
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorKosmos.kt
index ef789d1..ae138c8 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromAodTransitionInteractorKosmos.kt
@@ -37,6 +37,5 @@
powerInteractor = powerInteractor,
keyguardOcclusionInteractor = keyguardOcclusionInteractor,
deviceEntryRepository = deviceEntryRepository,
- wakeToGoneInteractor = keyguardWakeDirectlyToGoneInteractor,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorKosmos.kt
index 446652c..e7e007f 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromDozingTransitionInteractorKosmos.kt
@@ -39,6 +39,5 @@
powerInteractor = powerInteractor,
keyguardOcclusionInteractor = keyguardOcclusionInteractor,
deviceEntryRepository = deviceEntryRepository,
- wakeToGoneInteractor = keyguardWakeDirectlyToGoneInteractor,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorKosmos.kt
index 6c3de44..a9be06d 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/FromDreamingTransitionInteractorKosmos.kt
@@ -16,16 +16,13 @@
package com.android.systemui.keyguard.domain.interactor
-import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
import com.android.systemui.kosmos.testDispatcher
import com.android.systemui.power.domain.interactor.powerInteractor
import com.android.systemui.statusbar.domain.interactor.keyguardOcclusionInteractor
-import kotlinx.coroutines.ExperimentalCoroutinesApi
-@OptIn(ExperimentalCoroutinesApi::class)
var Kosmos.fromDreamingTransitionInteractor by
Kosmos.Fixture {
FromDreamingTransitionInteractor(
@@ -39,6 +36,5 @@
glanceableHubTransitions = glanceableHubTransitions,
powerInteractor = powerInteractor,
keyguardOcclusionInteractor = keyguardOcclusionInteractor,
- deviceEntryInteractor = deviceEntryInteractor,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorKosmos.kt
index 4328ca1..406b5cb 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardBlueprintInteractorKosmos.kt
@@ -16,11 +16,9 @@
package com.android.systemui.keyguard.domain.interactor
-import android.content.applicationContext
import com.android.systemui.biometrics.domain.interactor.fingerprintPropertyInteractor
import com.android.systemui.common.ui.domain.interactor.configurationInteractor
import com.android.systemui.keyguard.data.repository.keyguardBlueprintRepository
-import com.android.systemui.keyguard.data.repository.keyguardClockSection
import com.android.systemui.keyguard.data.repository.keyguardSmartspaceSection
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.kosmos.applicationCoroutineScope
@@ -31,12 +29,9 @@
KeyguardBlueprintInteractor(
keyguardBlueprintRepository = keyguardBlueprintRepository,
applicationScope = applicationCoroutineScope,
- context = applicationContext,
shadeInteractor = shadeInteractor,
- clockInteractor = keyguardClockInteractor,
configurationInteractor = configurationInteractor,
fingerprintPropertyInteractor = fingerprintPropertyInteractor,
- clockSection = keyguardClockSection,
smartspaceSection = keyguardSmartspaceSection,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractorKosmos.kt
deleted file mode 100644
index 63e168d..0000000
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/KeyguardWakeDirectlyToGoneInteractorKosmos.kt
+++ /dev/null
@@ -1,45 +0,0 @@
-/*
- * Copyright (C) 2024 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.systemui.keyguard.domain.interactor
-
-import android.app.admin.alarmManager
-import android.content.mockedContext
-import com.android.internal.widget.lockPatternUtils
-import com.android.systemui.keyguard.data.repository.fakeKeyguardRepository
-import com.android.systemui.kosmos.Kosmos
-import com.android.systemui.kosmos.applicationCoroutineScope
-import com.android.systemui.power.domain.interactor.powerInteractor
-import com.android.systemui.user.domain.interactor.selectedUserInteractor
-import com.android.systemui.util.settings.fakeSettings
-import com.android.systemui.util.time.systemClock
-
-val Kosmos.keyguardWakeDirectlyToGoneInteractor by
- Kosmos.Fixture {
- KeyguardWakeDirectlyToGoneInteractor(
- applicationCoroutineScope,
- mockedContext,
- fakeKeyguardRepository,
- systemClock,
- alarmManager,
- keyguardTransitionInteractor,
- powerInteractor,
- fakeSettings,
- lockPatternUtils,
- fakeSettings,
- selectedUserInteractor,
- )
- }
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorKosmos.kt
index 8bb2fce..bd9c0be 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/keyguard/domain/interactor/WindowManagerLockscreenVisibilityInteractorKosmos.kt
@@ -17,7 +17,6 @@
package com.android.systemui.keyguard.domain.interactor
import com.android.systemui.deviceentry.domain.interactor.deviceEntryInteractor
-import com.android.systemui.keyguard.data.repository.keyguardTransitionRepository
import com.android.systemui.kosmos.Kosmos
import com.android.systemui.scene.domain.interactor.sceneInteractor
import com.android.systemui.statusbar.notification.domain.interactor.notificationLaunchAnimationInteractor
@@ -26,7 +25,6 @@
Kosmos.Fixture {
WindowManagerLockscreenVisibilityInteractor(
keyguardInteractor = keyguardInteractor,
- transitionRepository = keyguardTransitionRepository,
transitionInteractor = keyguardTransitionInteractor,
surfaceBehindInteractor = keyguardSurfaceBehindInteractor,
fromLockscreenInteractor = fromLockscreenTransitionInteractor,
@@ -35,6 +33,5 @@
notificationLaunchAnimationInteractor = notificationLaunchAnimationInteractor,
sceneInteractor = { sceneInteractor },
deviceEntryInteractor = { deviceEntryInteractor },
- wakeToGoneInteractor = keyguardWakeDirectlyToGoneInteractor,
)
}
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
index b9918f1..4660337 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/data/repository/FakeShadeRepository.kt
@@ -18,7 +18,6 @@
package com.android.systemui.shade.data.repository
import com.android.systemui.dagger.SysUISingleton
-import com.android.systemui.shade.shared.model.ShadeMode
import dagger.Binds
import dagger.Module
import javax.inject.Inject
@@ -30,53 +29,65 @@
@SysUISingleton
class FakeShadeRepository @Inject constructor() : ShadeRepository {
private val _qsExpansion = MutableStateFlow(0f)
- @Deprecated("Use ShadeInteractor.qsExpansion instead") override val qsExpansion = _qsExpansion
+
+ @Deprecated("Use ShadeInteractor.qsExpansion instead")
+ override val qsExpansion = _qsExpansion.asStateFlow()
private val _udfpsTransitionToFullShadeProgress = MutableStateFlow(0f)
- override val udfpsTransitionToFullShadeProgress = _udfpsTransitionToFullShadeProgress
+ override val udfpsTransitionToFullShadeProgress =
+ _udfpsTransitionToFullShadeProgress.asStateFlow()
private val _currentFling: MutableStateFlow<FlingInfo?> = MutableStateFlow(null)
- override val currentFling: StateFlow<FlingInfo?> = _currentFling
+ override val currentFling: StateFlow<FlingInfo?> = _currentFling.asStateFlow()
private val _lockscreenShadeExpansion = MutableStateFlow(0f)
- override val lockscreenShadeExpansion = _lockscreenShadeExpansion
+ override val lockscreenShadeExpansion = _lockscreenShadeExpansion.asStateFlow()
private val _legacyShadeExpansion = MutableStateFlow(0f)
+
@Deprecated("Use ShadeInteractor instead")
- override val legacyShadeExpansion = _legacyShadeExpansion
+ override val legacyShadeExpansion = _legacyShadeExpansion.asStateFlow()
private val _legacyShadeTracking = MutableStateFlow(false)
+
@Deprecated("Use ShadeInteractor instead")
- override val legacyShadeTracking = _legacyShadeTracking
+ override val legacyShadeTracking = _legacyShadeTracking.asStateFlow()
private val _legacyQsTracking = MutableStateFlow(false)
- @Deprecated("Use ShadeInteractor instead") override val legacyQsTracking = _legacyQsTracking
+
+ @Deprecated("Use ShadeInteractor instead")
+ override val legacyQsTracking = _legacyQsTracking.asStateFlow()
private val _legacyExpandedOrAwaitingInputTransfer = MutableStateFlow(false)
+
@Deprecated("Use ShadeInteractor instead")
- override val legacyExpandedOrAwaitingInputTransfer = _legacyExpandedOrAwaitingInputTransfer
+ override val legacyExpandedOrAwaitingInputTransfer =
+ _legacyExpandedOrAwaitingInputTransfer.asStateFlow()
private val _legacyIsQsExpanded = MutableStateFlow(false)
- @Deprecated("Use ShadeInteractor instead") override val legacyIsQsExpanded = _legacyIsQsExpanded
+
+ @Deprecated("Use ShadeInteractor instead")
+ override val legacyIsQsExpanded = _legacyIsQsExpanded.asStateFlow()
@Deprecated("Use ShadeInteractor.isUserInteractingWithShade instead")
override val legacyLockscreenShadeTracking = MutableStateFlow(false)
- private val _shadeMode = MutableStateFlow<ShadeMode>(ShadeMode.Single)
- override val shadeMode: StateFlow<ShadeMode> = _shadeMode.asStateFlow()
-
private var _isDualShadeAlignedToBottom = false
override val isDualShadeAlignedToBottom
get() = _isDualShadeAlignedToBottom
+ private var _isShadeLayoutWide = MutableStateFlow(false)
+ override val isShadeLayoutWide: StateFlow<Boolean> = _isShadeLayoutWide.asStateFlow()
+
@Deprecated("Use ShadeInteractor instead")
override fun setLegacyIsQsExpanded(legacyIsQsExpanded: Boolean) {
_legacyIsQsExpanded.value = legacyIsQsExpanded
}
private val _legacyExpandImmediate = MutableStateFlow(false)
+
@Deprecated("Use ShadeInteractor instead")
- override val legacyExpandImmediate = _legacyExpandImmediate
+ override val legacyExpandImmediate = _legacyExpandImmediate.asStateFlow()
@Deprecated("Use ShadeInteractor instead")
override fun setLegacyExpandImmediate(legacyExpandImmediate: Boolean) {
@@ -106,6 +117,7 @@
}
private val _legacyQsFullscreen = MutableStateFlow(false)
+
@Deprecated("Use ShadeInteractor instead") override val legacyQsFullscreen = _legacyQsFullscreen
@Deprecated("Use ShadeInteractor instead")
@@ -114,6 +126,7 @@
}
private val _legacyIsClosing = MutableStateFlow(false)
+
@Deprecated("Use ShadeInteractor instead") override val legacyIsClosing = _legacyIsClosing
@Deprecated("Use ShadeInteractor instead")
@@ -142,13 +155,13 @@
_legacyShadeExpansion.value = expandedFraction
}
- override fun setShadeMode(mode: ShadeMode) {
- _shadeMode.value = mode
- }
-
fun setDualShadeAlignedToBottom(isAlignedToBottom: Boolean) {
_isDualShadeAlignedToBottom = isAlignedToBottom
}
+
+ override fun setShadeLayoutWide(isShadeLayoutWide: Boolean) {
+ _isShadeLayoutWide.value = isShadeLayoutWide
+ }
}
@Module
diff --git a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeInteractorKosmos.kt b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeInteractorKosmos.kt
index a00d2f4..bfd6614 100644
--- a/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeInteractorKosmos.kt
+++ b/packages/SystemUI/tests/utils/src/com/android/systemui/shade/domain/interactor/ShadeInteractorKosmos.kt
@@ -45,7 +45,6 @@
scope = applicationCoroutineScope,
sceneInteractor = sceneInteractor,
sharedNotificationContainerInteractor = sharedNotificationContainerInteractor,
- shadeRepository = shadeRepository,
)
}
val Kosmos.shadeInteractorLegacyImpl by
diff --git a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
index b061065..3706dcc 100644
--- a/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
+++ b/services/accessibility/java/com/android/server/accessibility/AccessibilityUserState.java
@@ -234,6 +234,8 @@
mAccessibilityShortcutKeyTargets.clear();
mAccessibilityButtonTargets.clear();
mAccessibilityGestureTargets.clear();
+ mAccessibilityQsTargets.clear();
+ mA11yTilesInQsPanel.clear();
mTargetAssignedToAccessibilityButton = null;
mIsTouchExplorationEnabled = false;
mServiceHandlesDoubleTap = false;
diff --git a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
index 2e9a4dc..a10039f 100644
--- a/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
+++ b/services/autofill/java/com/android/server/autofill/ui/AutoFillUI.java
@@ -462,7 +462,9 @@
@Override
public void onShown() {
- mCallback.onShown(UI_TYPE_DIALOG, response.getDatasets().size());
+ if (mCallback != null) {
+ mCallback.onShown(UI_TYPE_DIALOG, response.getDatasets().size());
+ }
}
@Override
@@ -511,7 +513,9 @@
@Override
public void startIntentSender(IntentSender intentSender) {
- mCallback.startIntentSenderAndFinishSession(intentSender);
+ if (mCallback != null) {
+ mCallback.startIntentSenderAndFinishSession(intentSender);
+ }
}
private void log(int type) {
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 25fb729..cc476a3 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -72,6 +72,7 @@
import static android.content.pm.PackageManager.MATCH_UNINSTALLED_PACKAGES;
import static android.content.pm.PackageManager.PERMISSION_GRANTED;
import static android.content.pm.PackageManager.SIGNATURE_NO_MATCH;
+import static android.crashrecovery.flags.Flags.refactorCrashrecovery;
import static android.net.ConnectivityManager.BLOCKED_REASON_NONE;
import static android.os.FactoryTest.FACTORY_TEST_OFF;
import static android.os.IServiceManager.DUMP_FLAG_PRIORITY_CRITICAL;
@@ -2322,7 +2323,9 @@
} else if (phase == PHASE_ACTIVITY_MANAGER_READY) {
mService.startBroadcastObservers();
} else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
- mService.mPackageWatchdog.onPackagesReady();
+ if (!refactorCrashrecovery()) {
+ mService.mPackageWatchdog.onPackagesReady();
+ }
mService.scheduleHomeTimeout();
}
}
diff --git a/services/core/java/com/android/server/crashrecovery/CrashRecoveryModule.java b/services/core/java/com/android/server/crashrecovery/CrashRecoveryModule.java
new file mode 100644
index 0000000..317c91e
--- /dev/null
+++ b/services/core/java/com/android/server/crashrecovery/CrashRecoveryModule.java
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2024 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.server.crashrecovery;
+
+import android.content.Context;
+
+import com.android.server.PackageWatchdog;
+import com.android.server.RescueParty;
+import com.android.server.SystemService;
+
+
+/** This class encapsulate the lifecycle methods of CrashRecovery module. */
+public class CrashRecoveryModule {
+ private static final String TAG = "CrashRecoveryModule";
+
+ /** Lifecycle definition for CrashRecovery module. */
+ public static class Lifecycle extends SystemService {
+ private Context mSystemContext;
+ private PackageWatchdog mPackageWatchdog;
+
+ public Lifecycle(Context context) {
+ super(context);
+ mSystemContext = context;
+ mPackageWatchdog = PackageWatchdog.getInstance(context);
+ }
+
+ @Override
+ public void onStart() {
+ RescueParty.registerHealthObserver(mSystemContext);
+ mPackageWatchdog.noteBoot();
+ }
+
+ @Override
+ public void onBootPhase(int phase) {
+ if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
+ mPackageWatchdog.onPackagesReady();
+ }
+ }
+ }
+}
diff --git a/services/core/java/com/android/server/crashrecovery/TEST_MAPPING b/services/core/java/com/android/server/crashrecovery/TEST_MAPPING
index 4a66bac..615db34 100644
--- a/services/core/java/com/android/server/crashrecovery/TEST_MAPPING
+++ b/services/core/java/com/android/server/crashrecovery/TEST_MAPPING
@@ -7,6 +7,9 @@
"include-filter": "com.android.server.RescuePartyTest"
}
]
+ },
+ {
+ "name": "CrashRecoveryModuleTests"
}
]
}
\ No newline at end of file
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index b5c12ce..5e644d3 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -107,7 +107,6 @@
import static android.content.res.Configuration.ORIENTATION_UNDEFINED;
import static android.content.res.Configuration.UI_MODE_TYPE_DESK;
import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
-import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
import static android.os.Build.VERSION_CODES.HONEYCOMB;
import static android.os.Build.VERSION_CODES.O;
import static android.os.InputConstants.DEFAULT_DISPATCHING_TIMEOUT_MILLIS;
@@ -236,8 +235,6 @@
import static com.android.server.wm.IdentifierProto.HASH_CODE;
import static com.android.server.wm.IdentifierProto.TITLE;
import static com.android.server.wm.IdentifierProto.USER_ID;
-import static com.android.server.wm.LetterboxConfiguration.DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW;
-import static com.android.server.wm.LetterboxConfiguration.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO;
import static com.android.server.wm.StartingData.AFTER_TRANSACTION_COPY_TO_CLIENT;
import static com.android.server.wm.StartingData.AFTER_TRANSACTION_REMOVE_DIRECTLY;
import static com.android.server.wm.SurfaceAnimator.ANIMATION_TYPE_APP_TRANSITION;
@@ -477,9 +474,6 @@
// finished destroying itself.
private static final int DESTROY_TIMEOUT = 10 * 1000;
- // Rounding tolerance to be used in aspect ratio computations
- private static final float ASPECT_RATIO_ROUNDING_TOLERANCE = 0.005f;
-
final ActivityTaskManagerService mAtmService;
final ActivityCallerState mCallerState;
@NonNull
@@ -823,26 +817,6 @@
// naturally.
private boolean mInSizeCompatModeForBounds = false;
- // Whether the aspect ratio restrictions applied to the activity bounds in applyAspectRatio().
- private boolean mIsAspectRatioApplied = false;
-
- // Bounds populated in resolveFixedOrientationConfiguration when this activity is letterboxed
- // for fixed orientation. If not null, they are used as parent container in
- // resolveSizeCompatModeConfiguration and in a constructor of CompatDisplayInsets. If
- // letterboxed due to fixed orientation then aspect ratio restrictions are also respected.
- // This happens when an activity has fixed orientation which doesn't match orientation of the
- // parent because a display is ignoring orientation request or fixed to user rotation.
- // See WindowManagerService#getIgnoreOrientationRequest and
- // WindowManagerService#getFixedToUserRotation for more context.
- @Nullable
- private Rect mLetterboxBoundsForFixedOrientationAndAspectRatio;
-
- // Bounds populated in resolveAspectRatioRestriction when this activity is letterboxed for
- // aspect ratio. If not null, they are used as parent container in
- // resolveSizeCompatModeConfiguration and in a constructor of CompatDisplayInsets.
- @Nullable
- private Rect mLetterboxBoundsForAspectRatio;
-
// Whether the activity is eligible to be letterboxed for fixed orientation with respect to its
// requested orientation, even when it's letterbox for another reason (e.g., size compat mode)
// and therefore #isLetterboxedForFixedOrientationAndAspectRatio returns false.
@@ -8384,7 +8358,7 @@
* aspect ratio.
*/
boolean shouldCreateCompatDisplayInsets() {
- if (mLetterboxUiController.hasFullscreenOverride()) {
+ if (mAppCompatController.getAppCompatAspectRatioOverrides().hasFullscreenOverride()) {
// If the user has forced the applications aspect ratio to be fullscreen, don't use size
// compatibility mode in any situation. The user has been warned and therefore accepts
// the risk of the application misbehaving.
@@ -8473,10 +8447,9 @@
fullConfig.windowConfiguration.getRotation());
}
- final Rect letterboxedContainerBounds =
- mLetterboxBoundsForFixedOrientationAndAspectRatio != null
- ? mLetterboxBoundsForFixedOrientationAndAspectRatio
- : mLetterboxBoundsForAspectRatio;
+ final Rect letterboxedContainerBounds = mAppCompatController
+ .getAppCompatAspectRatioPolicy().getLetterboxedContainerBounds();
+
// The role of CompatDisplayInsets is like the override bounds.
mCompatDisplayInsets =
new CompatDisplayInsets(
@@ -8550,10 +8523,8 @@
newParentConfiguration = mTmpConfig;
}
- mIsAspectRatioApplied = false;
+ mAppCompatController.getAppCompatAspectRatioPolicy().reset();
mIsEligibleForFixedOrientationLetterbox = false;
- mLetterboxBoundsForFixedOrientationAndAspectRatio = null;
- mLetterboxBoundsForAspectRatio = null;
mResolveConfigHint.resolveTmpOverrides(mDisplayContent, newParentConfiguration,
isFixedRotationTransforming());
@@ -8586,8 +8557,11 @@
// If activity in fullscreen mode is letterboxed because of fixed orientation then bounds
// are already calculated in resolveFixedOrientationConfiguration.
// Don't apply aspect ratio if app is overridden to fullscreen by device user/manufacturer.
- if (Flags.immersiveAppRepositioning() && !isLetterboxedForFixedOrientationAndAspectRatio()
- && !mLetterboxUiController.hasFullscreenOverride()) {
+ if (Flags.immersiveAppRepositioning()
+ && !mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio()
+ && !mAppCompatController.getAppCompatAspectRatioOverrides()
+ .hasFullscreenOverride()) {
resolveAspectRatioRestriction(newParentConfiguration);
}
final CompatDisplayInsets compatDisplayInsets = getCompatDisplayInsets();
@@ -8607,8 +8581,12 @@
// are already calculated in resolveFixedOrientationConfiguration, or if in size compat
// mode, it should already be calculated in resolveSizeCompatModeConfiguration.
// Don't apply aspect ratio if app is overridden to fullscreen by device user/manufacturer.
- if (!Flags.immersiveAppRepositioning() && !isLetterboxedForFixedOrientationAndAspectRatio()
- && !mInSizeCompatModeForBounds && !mLetterboxUiController.hasFullscreenOverride()) {
+ if (!Flags.immersiveAppRepositioning()
+ && !mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio()
+ && !mInSizeCompatModeForBounds
+ && !mAppCompatController.getAppCompatAspectRatioOverrides()
+ .hasFullscreenOverride()) {
resolveAspectRatioRestriction(newParentConfiguration);
}
@@ -8625,14 +8603,16 @@
// Fixed orientation letterboxing is possible on both large screen devices
// with ignoreOrientationRequest enabled and on phones in split screen even with
// ignoreOrientationRequest disabled.
- && (mLetterboxBoundsForFixedOrientationAndAspectRatio != null
+ && (mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio()
// Limiting check for aspect ratio letterboxing to devices with enabled
// ignoreOrientationRequest. This avoids affecting phones where apps may
// not expect the change of smallestScreenWidthDp after rotation which is
// possible with this logic. Not having smallestScreenWidthDp completely
// accurate on phones shouldn't make the big difference and is expected
// to be already well-tested by apps.
- || (isIgnoreOrientationRequest && mIsAspectRatioApplied))) {
+ || (isIgnoreOrientationRequest
+ && mAppCompatController.getAppCompatAspectRatioPolicy().isAspectRatioApplied()))) {
// TODO(b/264034555): Use mDisplayContent to calculate smallestScreenWidthDp from all
// rotations and only re-calculate if parent bounds have non-orientation size change.
resolvedConfig.smallestScreenWidthDp =
@@ -8749,11 +8729,13 @@
// letterboxed for fixed orientation. Aspect ratio restrictions are also applied if
// present. But this doesn't return true when the activity is letterboxed only because
// of aspect ratio restrictions.
- if (isLetterboxedForFixedOrientationAndAspectRatio()) {
+ if (mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio()) {
return APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_FIXED_ORIENTATION;
}
// Letterbox for limited aspect ratio.
- if (isLetterboxedForAspectRatioOnly()) {
+ if (mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForAspectRatioOnly()) {
return APP_COMPAT_STATE_CHANGED__STATE__LETTERBOXED_FOR_ASPECT_RATIO;
}
@@ -8904,26 +8886,6 @@
}
/**
- * Whether this activity is letterboxed for fixed orientation. If letterboxed due to fixed
- * orientation then aspect ratio restrictions are also already respected.
- *
- * <p>This happens when an activity has fixed orientation which doesn't match orientation of the
- * parent because a display setting 'ignoreOrientationRequest' is set to true. See {@link
- * WindowManagerService#getIgnoreOrientationRequest} for more context.
- */
- boolean isLetterboxedForFixedOrientationAndAspectRatio() {
- return mLetterboxBoundsForFixedOrientationAndAspectRatio != null;
- }
-
- boolean isLetterboxedForAspectRatioOnly() {
- return mLetterboxBoundsForAspectRatio != null;
- }
-
- boolean isAspectRatioApplied() {
- return mIsAspectRatioApplied;
- }
-
- /**
* Whether this activity is eligible for letterbox eduction.
*
* <p>Conditions that need to be met:
@@ -8955,7 +8917,7 @@
* @param parentBounds are the new parent bounds passed down to the activity and should be used
* to compute the stable bounds.
* @param outStableBounds will store the stable bounds, which are the bounds with insets
- * applied, if orientation is not respected when insets are applied.
+ * applied, if orientation is not respected when insets are applied.g
* Stable bounds should be used to compute letterboxed bounds if
* orientation is not respected when insets are applied.
* @param outNonDecorBounds will store the non decor bounds, which are the bounds with non
@@ -9108,23 +9070,9 @@
final Rect prevResolvedBounds = new Rect(resolvedBounds);
resolvedBounds.set(containingBounds);
- final float letterboxAspectRatioOverride =
- mLetterboxUiController.getFixedOrientationLetterboxAspectRatio(newParentConfig);
-
- // Aspect ratio as suggested by the system. Apps requested mix/max aspect ratio will
- // be respected in #applyAspectRatio.
- final float desiredAspectRatio;
- if (isDefaultMultiWindowLetterboxAspectRatioDesired(newParentConfig)) {
- desiredAspectRatio = DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW;
- } else if (letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO) {
- desiredAspectRatio = letterboxAspectRatioOverride;
- } else {
- desiredAspectRatio = computeAspectRatio(parentBounds);
- }
-
- // Apply aspect ratio to resolved bounds
- mIsAspectRatioApplied = applyAspectRatio(resolvedBounds, containingBoundsWithInsets,
- containingBounds, desiredAspectRatio);
+ mAppCompatController.getAppCompatAspectRatioPolicy()
+ .applyDesiredAspectRatio(newParentConfig, parentBounds, resolvedBounds,
+ containingBoundsWithInsets, containingBounds);
if (compatDisplayInsets != null) {
compatDisplayInsets.getBoundsByRotation(mTmpBounds,
@@ -9152,21 +9100,8 @@
// for comparison with size compat app bounds in {@link resolveSizeCompatModeConfiguration}.
mResolveConfigHint.mTmpCompatInsets = compatDisplayInsets;
computeConfigByResolveHint(getResolvedOverrideConfiguration(), newParentConfig);
- mLetterboxBoundsForFixedOrientationAndAspectRatio = new Rect(resolvedBounds);
- }
-
- /**
- * Returns {@code true} if the default aspect ratio for a letterboxed app in multi-window mode
- * should be used.
- */
- private boolean isDefaultMultiWindowLetterboxAspectRatioDesired(
- @NonNull Configuration parentConfig) {
- if (mDisplayContent == null) {
- return false;
- }
- final int windowingMode = parentConfig.windowConfiguration.getWindowingMode();
- return WindowConfiguration.inMultiWindowMode(windowingMode)
- && !mDisplayContent.getIgnoreOrientationRequest();
+ mAppCompatController.getAppCompatAspectRatioPolicy()
+ .setLetterboxBoundsForFixedOrientationAndAspectRatio(new Rect(resolvedBounds));
}
/**
@@ -9183,7 +9118,8 @@
// Use tmp bounds to calculate aspect ratio so we can know whether the activity should use
// restricted size (resolved bounds may be the requested override bounds).
mTmpBounds.setEmpty();
- mIsAspectRatioApplied = applyAspectRatio(mTmpBounds, parentAppBounds, parentBounds);
+ mAppCompatController.getAppCompatAspectRatioPolicy()
+ .applyAspectRatioForLetterbox(mTmpBounds, parentAppBounds, parentBounds);
// If the out bounds is not empty, it means the activity cannot fill parent's app bounds,
// then they should be aligned later in #updateResolvedBoundsPosition()
if (!mTmpBounds.isEmpty()) {
@@ -9194,7 +9130,8 @@
// restrict, the bounds should be the requested override bounds.
mResolveConfigHint.mTmpOverrideDisplayInfo = getFixedRotationTransformDisplayInfo();
computeConfigByResolveHint(resolvedConfig, newParentConfiguration);
- mLetterboxBoundsForAspectRatio = new Rect(resolvedBounds);
+ mAppCompatController.getAppCompatAspectRatioPolicy()
+ .setLetterboxBoundsForAspectRatio(new Rect(resolvedBounds));
}
}
@@ -9212,7 +9149,10 @@
// activity will be displayed within them even if it is in size compat mode. They should be
// saved here before resolved bounds are overridden below.
final boolean useResolvedBounds = Flags.immersiveAppRepositioning()
- ? isAspectRatioApplied() : isLetterboxedForFixedOrientationAndAspectRatio();
+ ? mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isAspectRatioApplied()
+ : mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio();
final Rect containerBounds = useResolvedBounds
? new Rect(resolvedBounds)
: newParentConfiguration.windowConfiguration.getBounds();
@@ -9256,8 +9196,9 @@
resolvedBounds.set(containingBounds);
// The size of floating task is fixed (only swap), so the aspect ratio is already correct.
if (!compatDisplayInsets.mIsFloating) {
- mIsAspectRatioApplied =
- applyAspectRatio(resolvedBounds, containingAppBounds, containingBounds);
+ mAppCompatController.getAppCompatAspectRatioPolicy()
+ .applyAspectRatioForLetterbox(resolvedBounds, containingAppBounds,
+ containingBounds);
}
// Use resolvedBounds to compute other override configurations such as appBounds. The bounds
@@ -9661,125 +9602,6 @@
return mPauseConfigurationDispatchCount > 0;
}
- private boolean applyAspectRatio(Rect outBounds, Rect containingAppBounds,
- Rect containingBounds) {
- return applyAspectRatio(outBounds, containingAppBounds, containingBounds,
- 0 /* desiredAspectRatio */);
- }
-
- /**
- * Applies aspect ratio restrictions to outBounds. If no restrictions, then no change is
- * made to outBounds.
- *
- * @return {@code true} if aspect ratio restrictions were applied.
- */
- // TODO(b/36505427): Consider moving this method and similar ones to ConfigurationContainer.
- private boolean applyAspectRatio(Rect outBounds, Rect containingAppBounds,
- Rect containingBounds, float desiredAspectRatio) {
- final float maxAspectRatio = getMaxAspectRatio();
- final Task rootTask = getRootTask();
- final float minAspectRatio = getMinAspectRatio();
- final TaskFragment organizedTf = getOrganizedTaskFragment();
- float aspectRatioToApply = desiredAspectRatio;
- if (task == null || rootTask == null
- || (maxAspectRatio < 1 && minAspectRatio < 1 && aspectRatioToApply < 1)
- // Don't set aspect ratio if we are in VR mode.
- || isInVrUiMode(getConfiguration())
- // TODO(b/232898850): Always respect aspect ratio requests.
- // Don't set aspect ratio for activity in ActivityEmbedding split.
- || (organizedTf != null && !organizedTf.fillsParent())) {
- return false;
- }
-
- final int containingAppWidth = containingAppBounds.width();
- final int containingAppHeight = containingAppBounds.height();
- final float containingRatio = computeAspectRatio(containingAppBounds);
-
- if (aspectRatioToApply < 1) {
- aspectRatioToApply = containingRatio;
- }
-
- if (maxAspectRatio >= 1 && aspectRatioToApply > maxAspectRatio) {
- aspectRatioToApply = maxAspectRatio;
- } else if (minAspectRatio >= 1 && aspectRatioToApply < minAspectRatio) {
- aspectRatioToApply = minAspectRatio;
- }
-
- int activityWidth = containingAppWidth;
- int activityHeight = containingAppHeight;
-
- if (containingRatio - aspectRatioToApply > ASPECT_RATIO_ROUNDING_TOLERANCE) {
- if (containingAppWidth < containingAppHeight) {
- // Width is the shorter side, so we use that to figure-out what the max. height
- // should be given the aspect ratio.
- activityHeight = (int) ((activityWidth * aspectRatioToApply) + 0.5f);
- } else {
- // Height is the shorter side, so we use that to figure-out what the max. width
- // should be given the aspect ratio.
- activityWidth = (int) ((activityHeight * aspectRatioToApply) + 0.5f);
- }
- } else if (aspectRatioToApply - containingRatio > ASPECT_RATIO_ROUNDING_TOLERANCE) {
- boolean adjustWidth;
- switch (getRequestedConfigurationOrientation()) {
- case ORIENTATION_LANDSCAPE:
- // Width should be the longer side for this landscape app, so we use the width
- // to figure-out what the max. height should be given the aspect ratio.
- adjustWidth = false;
- break;
- case ORIENTATION_PORTRAIT:
- // Height should be the longer side for this portrait app, so we use the height
- // to figure-out what the max. width should be given the aspect ratio.
- adjustWidth = true;
- break;
- default:
- // This app doesn't have a preferred orientation, so we keep the length of the
- // longer side, and use it to figure-out the length of the shorter side.
- if (containingAppWidth < containingAppHeight) {
- // Width is the shorter side, so we use the height to figure-out what the
- // max. width should be given the aspect ratio.
- adjustWidth = true;
- } else {
- // Height is the shorter side, so we use the width to figure-out what the
- // max. height should be given the aspect ratio.
- adjustWidth = false;
- }
- break;
- }
- if (adjustWidth) {
- activityWidth = (int) ((activityHeight / aspectRatioToApply) + 0.5f);
- } else {
- activityHeight = (int) ((activityWidth / aspectRatioToApply) + 0.5f);
- }
- }
-
- if (containingAppWidth <= activityWidth && containingAppHeight <= activityHeight) {
- // The display matches or is less than the activity aspect ratio, so nothing else to do.
- return false;
- }
-
- // Compute configuration based on max or min supported width and height.
- // Also account for the insets (e.g. display cutouts, navigation bar), which will be
- // clipped away later in {@link Task#computeConfigResourceOverrides()}, i.e., the out
- // bounds are the app bounds restricted by aspect ratio + clippable insets. Otherwise,
- // the app bounds would end up too small. To achieve this we will also add clippable insets
- // when the corresponding dimension fully fills the parent
-
- int right = activityWidth + containingAppBounds.left;
- int left = containingAppBounds.left;
- if (right >= containingAppBounds.right) {
- right = containingBounds.right;
- left = containingBounds.left;
- }
- int bottom = activityHeight + containingAppBounds.top;
- int top = containingAppBounds.top;
- if (bottom >= containingAppBounds.bottom) {
- bottom = containingBounds.bottom;
- top = containingBounds.top;
- }
- outBounds.set(left, top, right, bottom);
- return true;
- }
-
/**
* Returns the min aspect ratio of this activity.
*/
@@ -9788,10 +9610,7 @@
}
float getMaxAspectRatio() {
- if (mAppCompatController.getTransparentPolicy().isRunning()) {
- return mAppCompatController.getTransparentPolicy().getInheritedMaxAspectRatio();
- }
- return info.getMaxAspectRatio();
+ return mAppCompatController.getAppCompatAspectRatioPolicy().getMaxAspectRatio();
}
/**
@@ -9802,18 +9621,6 @@
}
/**
- * Returns the aspect ratio of the given {@code rect}.
- */
- static float computeAspectRatio(Rect rect) {
- final int width = rect.width();
- final int height = rect.height();
- if (width == 0 || height == 0) {
- return 0;
- }
- return Math.max(width, height) / (float) Math.min(width, height);
- }
-
- /**
* @return {@code true} if this activity was reparented to another display but
* {@link #ensureActivityConfiguration} is not called.
*/
@@ -10067,8 +9874,8 @@
*/
private boolean onlyVrUiModeChanged(int changes, Configuration lastReportedConfig) {
final Configuration currentConfig = getConfiguration();
- return changes == CONFIG_UI_MODE && (isInVrUiMode(currentConfig)
- != isInVrUiMode(lastReportedConfig));
+ return changes == CONFIG_UI_MODE && (AppCompatUtils.isInVrUiMode(currentConfig)
+ != AppCompatUtils.isInVrUiMode(lastReportedConfig));
}
/**
@@ -10440,10 +10247,6 @@
return r;
}
- private static boolean isInVrUiMode(Configuration config) {
- return (config.uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET;
- }
-
private static boolean isInDeskUiMode(Configuration config) {
return (config.uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_DESK;
}
@@ -10678,7 +10481,8 @@
mAppCompatController.getAppCompatAspectRatioOverrides()
.shouldEnableUserAspectRatioSettings());
proto.write(IS_USER_FULLSCREEN_OVERRIDE_ENABLED,
- mLetterboxUiController.isUserFullscreenOverrideEnabled());
+ mAppCompatController.getAppCompatAspectRatioOverrides()
+ .isUserFullscreenOverrideEnabled());
}
@Override
diff --git a/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java b/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java
index 5e6ef4c..cf008e7 100644
--- a/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java
+++ b/services/core/java/com/android/server/wm/AppCompatAspectRatioOverrides.java
@@ -32,7 +32,6 @@
import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE;
import static android.view.WindowManager.PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE;
-import static com.android.server.wm.ActivityRecord.computeAspectRatio;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_ATM;
import static com.android.server.wm.ActivityTaskManagerDebugConfig.TAG_WITH_CLASS_NAME;
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_POSITION_MULTIPLIER_CENTER;
@@ -174,6 +173,11 @@
&& mActivityRecord.mDisplayContent.getIgnoreOrientationRequest();
}
+ boolean hasFullscreenOverride() {
+ // `mUserAspectRatio` is always initialized first in `shouldApplyUserFullscreenOverride()`.
+ return shouldApplyUserFullscreenOverride() || isSystemOverrideToFullscreenEnabled();
+ }
+
float getUserMinAspectRatio() {
switch (mUserAspectRatioState.mUserAspectRatio) {
case USER_MIN_ASPECT_RATIO_DISPLAY_SIZE:
@@ -211,7 +215,7 @@
bounds.inset(/* dx */ 0, /* dy */ dividerSize / 2);
bounds.bottom = bounds.centerY();
}
- return computeAspectRatio(bounds);
+ return AppCompatUtils.computeAspectRatio(bounds);
}
float getFixedOrientationLetterboxAspectRatio(@NonNull Configuration parentConfiguration) {
@@ -228,7 +232,7 @@
return mActivityRecord.info.getMinAspectRatio();
}
final Rect bounds = new Rect(displayArea.getWindowConfiguration().getAppBounds());
- return computeAspectRatio(bounds);
+ return AppCompatUtils.computeAspectRatio(bounds);
}
private boolean shouldUseSplitScreenAspectRatio(@NonNull Configuration parentConfiguration) {
diff --git a/services/core/java/com/android/server/wm/AppCompatAspectRatioPolicy.java b/services/core/java/com/android/server/wm/AppCompatAspectRatioPolicy.java
index db7f745..a7d2ecc 100644
--- a/services/core/java/com/android/server/wm/AppCompatAspectRatioPolicy.java
+++ b/services/core/java/com/android/server/wm/AppCompatAspectRatioPolicy.java
@@ -23,33 +23,87 @@
import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_PORTRAIT_ONLY;
import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_SMALL;
import static android.content.pm.ActivityInfo.OVERRIDE_MIN_ASPECT_RATIO_TO_ALIGN_WITH_SPLIT_SCREEN;
+import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
+import static com.android.server.wm.LetterboxConfiguration.DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW;
+import static com.android.server.wm.LetterboxConfiguration.MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO;
+
import android.annotation.NonNull;
+import android.annotation.Nullable;
+import android.app.WindowConfiguration;
import android.content.pm.ActivityInfo;
+import android.content.res.Configuration;
+import android.graphics.Rect;
/**
* Encapsulate app compat policy logic related to aspect ratio.
*/
class AppCompatAspectRatioPolicy {
+ // Rounding tolerance to be used in aspect ratio computations
+ private static final float ASPECT_RATIO_ROUNDING_TOLERANCE = 0.005f;
+
@NonNull
private final ActivityRecord mActivityRecord;
@NonNull
private final TransparentPolicy mTransparentPolicy;
@NonNull
- private final AppCompatOrientationPolicy mAppCompatOrientationPolicy;
- @NonNull
private final AppCompatOverrides mAppCompatOverrides;
+ @NonNull
+ private final AppCompatAspectRatioState mAppCompatAspectRatioState;
AppCompatAspectRatioPolicy(@NonNull ActivityRecord activityRecord,
@NonNull TransparentPolicy transparentPolicy,
- @NonNull AppCompatOrientationPolicy orientationPolicy,
@NonNull AppCompatOverrides appCompatOverrides) {
mActivityRecord = activityRecord;
mTransparentPolicy = transparentPolicy;
- mAppCompatOrientationPolicy = orientationPolicy;
mAppCompatOverrides = appCompatOverrides;
+ mAppCompatAspectRatioState = new AppCompatAspectRatioState();
+ }
+
+ /**
+ * Starts the evaluation of app compat aspect ratio when a new configuration needs to be
+ * resolved.
+ */
+ void reset() {
+ mAppCompatAspectRatioState.reset();
+ }
+
+ float getDesiredAspectRatio(@NonNull Configuration newParentConfig,
+ @NonNull Rect parentBounds) {
+ final float letterboxAspectRatioOverride =
+ mAppCompatOverrides.getAppCompatAspectRatioOverrides()
+ .getFixedOrientationLetterboxAspectRatio(newParentConfig);
+ // Aspect ratio as suggested by the system. Apps requested mix/max aspect ratio will
+ // be respected in #applyAspectRatio.
+ if (isDefaultMultiWindowLetterboxAspectRatioDesired(newParentConfig)) {
+ return DEFAULT_LETTERBOX_ASPECT_RATIO_FOR_MULTI_WINDOW;
+ } else if (letterboxAspectRatioOverride > MIN_FIXED_ORIENTATION_LETTERBOX_ASPECT_RATIO) {
+ return letterboxAspectRatioOverride;
+ }
+ return AppCompatUtils.computeAspectRatio(parentBounds);
+ }
+
+ void applyDesiredAspectRatio(@NonNull Configuration newParentConfig, @NonNull Rect parentBounds,
+ @NonNull Rect resolvedBounds, @NonNull Rect containingBoundsWithInsets,
+ @NonNull Rect containingBounds) {
+ final float desiredAspectRatio = getDesiredAspectRatio(newParentConfig, parentBounds);
+ mAppCompatAspectRatioState.mIsAspectRatioApplied = applyAspectRatio(resolvedBounds,
+ containingBoundsWithInsets, containingBounds, desiredAspectRatio);
+ }
+
+ void applyAspectRatioForLetterbox(Rect outBounds, Rect containingAppBounds,
+ Rect containingBounds) {
+ mAppCompatAspectRatioState.mIsAspectRatioApplied = applyAspectRatio(outBounds,
+ containingAppBounds, containingBounds, 0 /* desiredAspectRatio */);
+ }
+
+ /**
+ * @return {@code true} when an app compat aspect ratio has been applied.
+ */
+ boolean isAspectRatioApplied() {
+ return mAppCompatAspectRatioState.mIsAspectRatioApplied;
}
/**
@@ -109,10 +163,217 @@
return info.getMinAspectRatio();
}
+ float getMaxAspectRatio() {
+ if (mTransparentPolicy.isRunning()) {
+ return mTransparentPolicy.getInheritedMaxAspectRatio();
+ }
+ return mActivityRecord.info.getMaxAspectRatio();
+ }
+
+ @Nullable
+ Rect getLetterboxedContainerBounds() {
+ return mAppCompatAspectRatioState.getLetterboxedContainerBounds();
+ }
+
+ /**
+ * Whether this activity is letterboxed for fixed orientation. If letterboxed due to fixed
+ * orientation then aspect ratio restrictions are also already respected.
+ *
+ * <p>This happens when an activity has fixed orientation which doesn't match orientation of the
+ * parent because a display setting 'ignoreOrientationRequest' is set to true. See {@link
+ * WindowManagerService#getIgnoreOrientationRequest} for more context.
+ */
+ boolean isLetterboxedForFixedOrientationAndAspectRatio() {
+ return mAppCompatAspectRatioState.isLetterboxedForFixedOrientationAndAspectRatio();
+ }
+
+ boolean isLetterboxedForAspectRatioOnly() {
+ return mAppCompatAspectRatioState.isLetterboxedForAspectRatioOnly();
+ }
+
+ void setLetterboxBoundsForFixedOrientationAndAspectRatio(@NonNull Rect bounds) {
+ mAppCompatAspectRatioState.mLetterboxBoundsForFixedOrientationAndAspectRatio = bounds;
+ }
+
+ void setLetterboxBoundsForAspectRatio(@NonNull Rect bounds) {
+ mAppCompatAspectRatioState.mLetterboxBoundsForAspectRatio = bounds;
+ }
+
private boolean isParentFullscreenPortrait() {
final WindowContainer<?> parent = mActivityRecord.getParent();
return parent != null
&& parent.getConfiguration().orientation == ORIENTATION_PORTRAIT
&& parent.getWindowConfiguration().getWindowingMode() == WINDOWING_MODE_FULLSCREEN;
}
+
+ /**
+ * Applies aspect ratio restrictions to outBounds. If no restrictions, then no change is
+ * made to outBounds.
+ *
+ * @return {@code true} if aspect ratio restrictions were applied.
+ */
+ private boolean applyAspectRatio(Rect outBounds, Rect containingAppBounds,
+ Rect containingBounds, float desiredAspectRatio) {
+ final float maxAspectRatio = getMaxAspectRatio();
+ final Task rootTask = mActivityRecord.getRootTask();
+ final Task task = mActivityRecord.getTask();
+ final float minAspectRatio = getMinAspectRatio();
+ final TaskFragment organizedTf = mActivityRecord.getOrganizedTaskFragment();
+ float aspectRatioToApply = desiredAspectRatio;
+ if (task == null || rootTask == null
+ || (maxAspectRatio < 1 && minAspectRatio < 1 && aspectRatioToApply < 1)
+ // Don't set aspect ratio if we are in VR mode.
+ || AppCompatUtils.isInVrUiMode(mActivityRecord.getConfiguration())
+ // TODO(b/232898850): Always respect aspect ratio requests.
+ // Don't set aspect ratio for activity in ActivityEmbedding split.
+ || (organizedTf != null && !organizedTf.fillsParent())) {
+ return false;
+ }
+
+ final int containingAppWidth = containingAppBounds.width();
+ final int containingAppHeight = containingAppBounds.height();
+ final float containingRatio = AppCompatUtils.computeAspectRatio(containingAppBounds);
+
+ if (aspectRatioToApply < 1) {
+ aspectRatioToApply = containingRatio;
+ }
+
+ if (maxAspectRatio >= 1 && aspectRatioToApply > maxAspectRatio) {
+ aspectRatioToApply = maxAspectRatio;
+ } else if (minAspectRatio >= 1 && aspectRatioToApply < minAspectRatio) {
+ aspectRatioToApply = minAspectRatio;
+ }
+
+ int activityWidth = containingAppWidth;
+ int activityHeight = containingAppHeight;
+
+ if (containingRatio - aspectRatioToApply > ASPECT_RATIO_ROUNDING_TOLERANCE) {
+ if (containingAppWidth < containingAppHeight) {
+ // Width is the shorter side, so we use that to figure-out what the max. height
+ // should be given the aspect ratio.
+ activityHeight = (int) ((activityWidth * aspectRatioToApply) + 0.5f);
+ } else {
+ // Height is the shorter side, so we use that to figure-out what the max. width
+ // should be given the aspect ratio.
+ activityWidth = (int) ((activityHeight * aspectRatioToApply) + 0.5f);
+ }
+ } else if (aspectRatioToApply - containingRatio > ASPECT_RATIO_ROUNDING_TOLERANCE) {
+ boolean adjustWidth;
+ switch (mActivityRecord.getRequestedConfigurationOrientation()) {
+ case ORIENTATION_LANDSCAPE:
+ // Width should be the longer side for this landscape app, so we use the width
+ // to figure-out what the max. height should be given the aspect ratio.
+ adjustWidth = false;
+ break;
+ case ORIENTATION_PORTRAIT:
+ // Height should be the longer side for this portrait app, so we use the height
+ // to figure-out what the max. width should be given the aspect ratio.
+ adjustWidth = true;
+ break;
+ default:
+ // This app doesn't have a preferred orientation, so we keep the length of the
+ // longer side, and use it to figure-out the length of the shorter side.
+ if (containingAppWidth < containingAppHeight) {
+ // Width is the shorter side, so we use the height to figure-out what the
+ // max. width should be given the aspect ratio.
+ adjustWidth = true;
+ } else {
+ // Height is the shorter side, so we use the width to figure-out what the
+ // max. height should be given the aspect ratio.
+ adjustWidth = false;
+ }
+ break;
+ }
+ if (adjustWidth) {
+ activityWidth = (int) ((activityHeight / aspectRatioToApply) + 0.5f);
+ } else {
+ activityHeight = (int) ((activityWidth / aspectRatioToApply) + 0.5f);
+ }
+ }
+
+ if (containingAppWidth <= activityWidth && containingAppHeight <= activityHeight) {
+ // The display matches or is less than the activity aspect ratio, so nothing else to do.
+ return false;
+ }
+
+ // Compute configuration based on max or min supported width and height.
+ // Also account for the insets (e.g. display cutouts, navigation bar), which will be
+ // clipped away later in {@link Task#computeConfigResourceOverrides()}, i.e., the out
+ // bounds are the app bounds restricted by aspect ratio + clippable insets. Otherwise,
+ // the app bounds would end up too small. To achieve this we will also add clippable insets
+ // when the corresponding dimension fully fills the parent
+
+ int right = activityWidth + containingAppBounds.left;
+ int left = containingAppBounds.left;
+ if (right >= containingAppBounds.right) {
+ right = containingBounds.right;
+ left = containingBounds.left;
+ }
+ int bottom = activityHeight + containingAppBounds.top;
+ int top = containingAppBounds.top;
+ if (bottom >= containingAppBounds.bottom) {
+ bottom = containingBounds.bottom;
+ top = containingBounds.top;
+ }
+ outBounds.set(left, top, right, bottom);
+ return true;
+ }
+
+ /**
+ * Returns {@code true} if the default aspect ratio for a letterboxed app in multi-window mode
+ * should be used.
+ */
+ private boolean isDefaultMultiWindowLetterboxAspectRatioDesired(
+ @NonNull Configuration parentConfig) {
+ final DisplayContent dc = mActivityRecord.mDisplayContent;
+ if (dc == null) {
+ return false;
+ }
+ final int windowingMode = parentConfig.windowConfiguration.getWindowingMode();
+ return WindowConfiguration.inMultiWindowMode(windowingMode)
+ && !dc.getIgnoreOrientationRequest();
+ }
+
+ private static class AppCompatAspectRatioState {
+ // Whether the aspect ratio restrictions applied to the activity bounds
+ // in applyAspectRatio().
+ private boolean mIsAspectRatioApplied = false;
+
+ // Bounds populated in resolveAspectRatioRestriction when this activity is letterboxed for
+ // aspect ratio. If not null, they are used as parent container in
+ // resolveSizeCompatModeConfiguration and in a constructor of CompatDisplayInsets.
+ @Nullable
+ private Rect mLetterboxBoundsForAspectRatio;
+ // Bounds populated in resolveFixedOrientationConfiguration when this activity is
+ // letterboxed for fixed orientation. If not null, they are used as parent container in
+ // resolveSizeCompatModeConfiguration and in a constructor of CompatDisplayInsets. If
+ // letterboxed due to fixed orientation then aspect ratio restrictions are also respected.
+ // This happens when an activity has fixed orientation which doesn't match orientation of
+ // the parent because a display is ignoring orientation request or fixed to user rotation.
+ // See WindowManagerService#getIgnoreOrientationRequest and
+ // WindowManagerService#getFixedToUserRotation for more context.
+ @Nullable
+ private Rect mLetterboxBoundsForFixedOrientationAndAspectRatio;
+
+ @Nullable
+ Rect getLetterboxedContainerBounds() {
+ return mLetterboxBoundsForFixedOrientationAndAspectRatio != null
+ ? mLetterboxBoundsForFixedOrientationAndAspectRatio
+ : mLetterboxBoundsForAspectRatio;
+ }
+
+ void reset() {
+ mIsAspectRatioApplied = false;
+ mLetterboxBoundsForFixedOrientationAndAspectRatio = null;
+ mLetterboxBoundsForAspectRatio = null;
+ }
+
+ boolean isLetterboxedForFixedOrientationAndAspectRatio() {
+ return mLetterboxBoundsForFixedOrientationAndAspectRatio != null;
+ }
+
+ boolean isLetterboxedForAspectRatioOnly() {
+ return mLetterboxBoundsForAspectRatio != null;
+ }
+ }
}
diff --git a/services/core/java/com/android/server/wm/AppCompatController.java b/services/core/java/com/android/server/wm/AppCompatController.java
index acd1d5a..3eed96d 100644
--- a/services/core/java/com/android/server/wm/AppCompatController.java
+++ b/services/core/java/com/android/server/wm/AppCompatController.java
@@ -49,7 +49,7 @@
wmService.mLetterboxConfiguration, optPropBuilder);
mOrientationPolicy = new AppCompatOrientationPolicy(activityRecord, mAppCompatOverrides);
mAppCompatAspectRatioPolicy = new AppCompatAspectRatioPolicy(activityRecord,
- mTransparentPolicy, mOrientationPolicy, mAppCompatOverrides);
+ mTransparentPolicy, mAppCompatOverrides);
}
@NonNull
diff --git a/services/core/java/com/android/server/wm/AppCompatOrientationOverrides.java b/services/core/java/com/android/server/wm/AppCompatOrientationOverrides.java
index 155e246..9bf8011 100644
--- a/services/core/java/com/android/server/wm/AppCompatOrientationOverrides.java
+++ b/services/core/java/com/android/server/wm/AppCompatOrientationOverrides.java
@@ -50,7 +50,6 @@
private final ActivityRecord mActivityRecord;
@NonNull
private final AppCompatCameraOverrides mAppCompatCameraOverrides;
-
@NonNull
private final OptPropFactory.OptProp mIgnoreRequestedOrientationOptProp;
@NonNull
@@ -109,7 +108,8 @@
mOrientationOverridesState.updateOrientationRequestLoopState();
return mOrientationOverridesState.shouldIgnoreRequestInLoop()
- && !mActivityRecord.isLetterboxedForFixedOrientationAndAspectRatio();
+ && !mActivityRecord.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio();
}
/**
diff --git a/services/core/java/com/android/server/wm/AppCompatUtils.java b/services/core/java/com/android/server/wm/AppCompatUtils.java
index be51dd3b..1b30a20 100644
--- a/services/core/java/com/android/server/wm/AppCompatUtils.java
+++ b/services/core/java/com/android/server/wm/AppCompatUtils.java
@@ -16,7 +16,12 @@
package com.android.server.wm;
+import static android.content.res.Configuration.UI_MODE_TYPE_MASK;
+import static android.content.res.Configuration.UI_MODE_TYPE_VR_HEADSET;
+
import android.annotation.NonNull;
+import android.content.res.Configuration;
+import android.graphics.Rect;
import java.util.function.BooleanSupplier;
@@ -48,4 +53,24 @@
}
};
}
+
+ /**
+ * Returns the aspect ratio of the given {@code rect}.
+ */
+ static float computeAspectRatio(Rect rect) {
+ final int width = rect.width();
+ final int height = rect.height();
+ if (width == 0 || height == 0) {
+ return 0;
+ }
+ return Math.max(width, height) / (float) Math.min(width, height);
+ }
+
+ /**
+ * @param config The current {@link Configuration}
+ * @return {@code true} if using a VR headset.
+ */
+ static boolean isInVrUiMode(Configuration config) {
+ return (config.uiMode & UI_MODE_TYPE_MASK) == UI_MODE_TYPE_VR_HEADSET;
+ }
}
diff --git a/services/core/java/com/android/server/wm/LetterboxUiController.java b/services/core/java/com/android/server/wm/LetterboxUiController.java
index 3925de8..235d6cd 100644
--- a/services/core/java/com/android/server/wm/LetterboxUiController.java
+++ b/services/core/java/com/android/server/wm/LetterboxUiController.java
@@ -472,51 +472,11 @@
return !isHorizontalThinLetterboxed();
}
- /**
- * Whether we should apply the user aspect ratio override to the min aspect ratio for the
- * current app.
- */
- boolean shouldApplyUserMinAspectRatioOverride() {
- return mActivityRecord.mAppCompatController.getAppCompatAspectRatioOverrides()
- .shouldApplyUserMinAspectRatioOverride();
- }
-
- boolean shouldApplyUserFullscreenOverride() {
- return mActivityRecord.mAppCompatController.getAppCompatAspectRatioOverrides()
- .shouldApplyUserFullscreenOverride();
- }
-
- boolean isUserFullscreenOverrideEnabled() {
- return mActivityRecord.mAppCompatController.getAppCompatAspectRatioOverrides()
- .isUserFullscreenOverrideEnabled();
- }
-
- boolean isSystemOverrideToFullscreenEnabled() {
- return mActivityRecord.mAppCompatController.getAppCompatAspectRatioOverrides()
- .isSystemOverrideToFullscreenEnabled();
- }
-
- boolean hasFullscreenOverride() {
- // `mUserAspectRatio` is always initialized first in `shouldApplyUserFullscreenOverride()`.
- return shouldApplyUserFullscreenOverride() || isSystemOverrideToFullscreenEnabled();
- }
-
- float getUserMinAspectRatio() {
- return mActivityRecord.mAppCompatController.getAppCompatAspectRatioOverrides()
- .getUserMinAspectRatio();
- }
-
boolean shouldOverrideMinAspectRatio() {
return mActivityRecord.mAppCompatController.getAppCompatAspectRatioOverrides()
.shouldOverrideMinAspectRatio();
}
- @VisibleForTesting
- int getUserMinAspectRatioOverrideCode() {
- return mActivityRecord.mAppCompatController.getAppCompatAspectRatioOverrides()
- .getUserMinAspectRatioOverrideCode();
- }
-
@LetterboxConfiguration.LetterboxVerticalReachabilityPosition
int getLetterboxPositionForVerticalReachability() {
final boolean isInFullScreenTabletopMode = isDisplayFullScreenAndSeparatingHinge();
@@ -937,7 +897,7 @@
pw.println(prefix + " letterboxReason=" + getLetterboxReasonString(mainWin));
pw.println(prefix + " activityAspectRatio="
- + mActivityRecord.computeAspectRatio(mActivityRecord.getBounds()));
+ + AppCompatUtils.computeAspectRatio(mActivityRecord.getBounds()));
boolean shouldShowLetterboxUi = shouldShowLetterboxUi(mainWin);
pw.println(prefix + "shouldShowLetterboxUi=" + shouldShowLetterboxUi);
@@ -996,13 +956,15 @@
if (mActivityRecord.inSizeCompatMode()) {
return "SIZE_COMPAT_MODE";
}
- if (mActivityRecord.isLetterboxedForFixedOrientationAndAspectRatio()) {
+ if (mActivityRecord.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio()) {
return "FIXED_ORIENTATION";
}
if (mainWin.isLetterboxedForDisplayCutout()) {
return "DISPLAY_CUTOUT";
}
- if (mActivityRecord.isLetterboxedForAspectRatioOnly()) {
+ if (mActivityRecord.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForAspectRatioOnly()) {
return "ASPECT_RATIO";
}
return "UNKNOWN_REASON";
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index 1d66192..74f8a068 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3406,9 +3406,11 @@
appCompatTaskInfo.topActivityLetterboxWidth = TaskInfo.PROPERTY_VALUE_UNSET;
appCompatTaskInfo.topActivityLetterboxHeight = TaskInfo.PROPERTY_VALUE_UNSET;
appCompatTaskInfo.isUserFullscreenOverrideEnabled = top != null
- && top.mLetterboxUiController.shouldApplyUserFullscreenOverride();
+ && top.mAppCompatController.getAppCompatAspectRatioOverrides()
+ .shouldApplyUserFullscreenOverride();
appCompatTaskInfo.isSystemFullscreenOverrideEnabled = top != null
- && top.mLetterboxUiController.isSystemOverrideToFullscreenEnabled();
+ && top.mAppCompatController.getAppCompatAspectRatioOverrides()
+ .isSystemOverrideToFullscreenEnabled();
appCompatTaskInfo.isFromLetterboxDoubleTap = top != null
&& top.mLetterboxUiController.isFromDoubleTap();
if (top != null) {
diff --git a/services/core/java/com/android/server/wm/WindowContainer.java b/services/core/java/com/android/server/wm/WindowContainer.java
index 1d02f1c..4da8bbf 100644
--- a/services/core/java/com/android/server/wm/WindowContainer.java
+++ b/services/core/java/com/android/server/wm/WindowContainer.java
@@ -117,6 +117,7 @@
import com.android.server.wm.SurfaceAnimator.AnimationType;
import com.android.server.wm.SurfaceAnimator.OnAnimationFinishedCallback;
import com.android.server.wm.utils.AlwaysTruePredicate;
+import com.android.window.flags.Flags;
import java.io.PrintWriter;
import java.lang.ref.WeakReference;
@@ -458,6 +459,9 @@
source.setFrame(provider.getArbitraryRectangle())
.updateSideHint(getBounds())
.setBoundingRects(provider.getBoundingRects());
+ if (Flags.enableCaptionCompatInsetForceConsumption()) {
+ source.setFlags(provider.getFlags());
+ }
mLocalInsetsSources.put(id, source);
mDisplayContent.getInsetsStateController().updateAboveInsetsState(true);
}
diff --git a/services/java/com/android/server/SystemServer.java b/services/java/com/android/server/SystemServer.java
index e5a1ebf..db4b171 100644
--- a/services/java/com/android/server/SystemServer.java
+++ b/services/java/com/android/server/SystemServer.java
@@ -381,6 +381,9 @@
+ "OnDevicePersonalizationSystemService$Lifecycle";
private static final String UPDATABLE_DEVICE_CONFIG_SERVICE_CLASS =
"com.android.server.deviceconfig.DeviceConfigInit$Lifecycle";
+ private static final String CRASHRECOVERY_MODULE_LIFECYCLE_CLASS =
+ "com.android.server.crashrecovery.CrashRecoveryModule$Lifecycle";
+
/*
* Implementation class names and jar locations for services in
@@ -1196,15 +1199,18 @@
mSystemServiceManager.startService(RecoverySystemService.Lifecycle.class);
t.traceEnd();
- // Initialize RescueParty.
- RescueParty.registerHealthObserver(mSystemContext);
- if (!Flags.recoverabilityDetection()) {
- // Now that we have the bare essentials of the OS up and running, take
- // note that we just booted, which might send out a rescue party if
- // we're stuck in a runtime restart loop.
- PackageWatchdog.getInstance(mSystemContext).noteBoot();
+ if (!Flags.refactorCrashrecovery()) {
+ // Initialize RescueParty.
+ RescueParty.registerHealthObserver(mSystemContext);
+ if (!Flags.recoverabilityDetection()) {
+ // Now that we have the bare essentials of the OS up and running, take
+ // note that we just booted, which might send out a rescue party if
+ // we're stuck in a runtime restart loop.
+ PackageWatchdog.getInstance(mSystemContext).noteBoot();
+ }
}
+
// Manages LEDs and display backlight so we need it to bring up the display.
t.traceBegin("StartLightsService");
mSystemServiceManager.startService(LightsService.class);
@@ -2931,12 +2937,18 @@
mPackageManagerService.systemReady();
t.traceEnd();
- if (Flags.recoverabilityDetection()) {
- // Now that we have the essential services needed for mitigations, register the boot
- // with package watchdog.
- // Note that we just booted, which might send out a rescue party if we're stuck in a
- // runtime restart loop.
- PackageWatchdog.getInstance(mSystemContext).noteBoot();
+ if (Flags.refactorCrashrecovery()) {
+ t.traceBegin("StartCrashRecoveryModule");
+ mSystemServiceManager.startService(CRASHRECOVERY_MODULE_LIFECYCLE_CLASS);
+ t.traceEnd();
+ } else {
+ if (Flags.recoverabilityDetection()) {
+ // Now that we have the essential services needed for mitigations, register the boot
+ // with package watchdog.
+ // Note that we just booted, which might send out a rescue party if we're stuck in a
+ // runtime restart loop.
+ PackageWatchdog.getInstance(mSystemContext).noteBoot();
+ }
}
t.traceBegin("MakeDisplayManagerServiceReady");
diff --git a/services/tests/mockingservicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java b/services/tests/mockingservicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
index 396f4da..bf7e3a0 100644
--- a/services/tests/mockingservicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
+++ b/services/tests/mockingservicestests/src/com/android/server/backup/utils/TarBackupReaderTest.java
@@ -525,7 +525,7 @@
@Test
public void
- chooseRestorePolicy_flagOnNotRestoreAnyVersionVToURestoreAndInAllowlist_returnsIgnore()
+ chooseRestorePolicy_flagOnNotRestoreAnyVersionVToURestoreAndInAllowlist_returnsAccept()
throws Exception {
mSetFlagsRule.enableFlags(
@@ -540,7 +540,8 @@
FileMetadata info = new FileMetadata();
info.version = Build.VERSION_CODES.UPSIDE_DOWN_CAKE + 1;
- PackageInfo packageInfo = createNonRestoreAnyVersionUPackage();
+ PackageInfo packageInfo = createNonRestoreAnyVersionPackage(
+ Build.VERSION_CODES.UPSIDE_DOWN_CAKE);
PackageManagerStub.sPackageInfo = packageInfo;
doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
@@ -559,7 +560,7 @@
@Test
public void
- chooseRestorePolicy_flagOffNotRestoreAnyVersionVToURestoreAndInAllowlist_returnsAccept()
+ chooseRestorePolicy_flagOffNotRestoreAnyVersionVToURestoreAndInAllowlist_returnsIgnore()
throws Exception {
mSetFlagsRule.disableFlags(
@@ -574,7 +575,8 @@
FileMetadata info = new FileMetadata();
info.version = Build.VERSION_CODES.UPSIDE_DOWN_CAKE + 1;
- PackageInfo packageInfo = createNonRestoreAnyVersionUPackage();
+ PackageInfo packageInfo = createNonRestoreAnyVersionPackage(
+ Build.VERSION_CODES.UPSIDE_DOWN_CAKE);
PackageManagerStub.sPackageInfo = packageInfo;
doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
@@ -608,7 +610,8 @@
FileMetadata info = new FileMetadata();
info.version = Build.VERSION_CODES.UPSIDE_DOWN_CAKE + 1;
- PackageInfo packageInfo = createNonRestoreAnyVersionUPackage();
+ PackageInfo packageInfo = createNonRestoreAnyVersionPackage(
+ Build.VERSION_CODES.UPSIDE_DOWN_CAKE);
PackageManagerStub.sPackageInfo = packageInfo;
doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
@@ -716,6 +719,36 @@
LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER);
}
+ @Test
+ public void
+ chooseRestorePolicy_allowlistNotSetNotRestoreAnyVersionVersionMismatch_returnsIgnore()
+ throws Exception {
+ mSetFlagsRule.disableFlags(
+ Flags.FLAG_ENABLE_V_TO_U_RESTORE_FOR_SYSTEM_COMPONENTS_IN_ALLOWLIST);
+
+ TarBackupReader tarBackupReader = createTarBackupReader();
+
+ Signature[] signatures = new Signature[]{FAKE_SIGNATURE_1};
+ FileMetadata info = new FileMetadata();
+ info.version = Build.VERSION_CODES.UPSIDE_DOWN_CAKE + 2;
+
+ PackageInfo packageInfo = createNonRestoreAnyVersionPackage(
+ Build.VERSION_CODES.UPSIDE_DOWN_CAKE + 1);
+ PackageManagerStub.sPackageInfo = packageInfo;
+
+ doReturn(true).when(mMockPackageManagerInternal).isDataRestoreSafe(FAKE_SIGNATURE_1,
+ packageInfo.packageName);
+ RestorePolicy policy = tarBackupReader.chooseRestorePolicy(mPackageManagerStub,
+ false /* allowApks */, info, signatures, mMockPackageManagerInternal,
+ mUserId, mContext);
+
+ assertThat(policy).isEqualTo(RestorePolicy.IGNORE);
+ ArgumentCaptor<Bundle> bundleCaptor = ArgumentCaptor.forClass(Bundle.class);
+ verify(mBackupManagerMonitorMock).onEvent(bundleCaptor.capture());
+ assertThat(bundleCaptor.getValue().get(EXTRA_LOG_EVENT_ID)).isEqualTo(
+ LOG_EVENT_ID_VERSION_OF_BACKUP_OLDER);
+ }
+
private TarBackupReader createTarBackupReader() throws Exception {
InputStream inputStream = mContext.getResources().openRawResource(
R.raw.backup_telephony_no_password);
@@ -726,7 +759,7 @@
return tarBackupReader;
}
- private PackageInfo createNonRestoreAnyVersionUPackage(){
+ private PackageInfo createNonRestoreAnyVersionPackage(int versionCode) {
PackageInfo packageInfo = new PackageInfo();
packageInfo.packageName = "test";
packageInfo.applicationInfo = new ApplicationInfo();
@@ -740,7 +773,7 @@
SigningDetails.SignatureSchemeVersion.SIGNING_BLOCK_V3,
null,
null));
- packageInfo.versionCode = Build.VERSION_CODES.UPSIDE_DOWN_CAKE;
+ packageInfo.versionCode = versionCode;
return packageInfo;
}
}
diff --git a/services/tests/mockingservicestests/src/com/android/server/crashrecovery/Android.bp b/services/tests/mockingservicestests/src/com/android/server/crashrecovery/Android.bp
new file mode 100644
index 0000000..127d3e8
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/crashrecovery/Android.bp
@@ -0,0 +1,58 @@
+// Copyright (C) 2024 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 {
+ // See: http://go/android-license-faq
+ // A large-scale-change added 'default_applicable_licenses' to import
+ // all of the 'license_kinds' from "frameworks_base_license"
+ // to get the below license kinds:
+ // SPDX-license-identifier-Apache-2.0
+ default_applicable_licenses: ["frameworks_base_license"],
+ default_team: "trendy_team_mainline_modularization",
+}
+
+android_test {
+ name: "CrashRecoveryModuleTests",
+
+ srcs: [
+ "*.java",
+ ],
+
+ static_libs: [
+ "androidx.test.core",
+ "androidx.test.runner",
+ "mockito-target-extended-minus-junit4",
+ "services.core",
+ "truth",
+ "flag-junit",
+ ],
+
+ libs: [
+ "android.test.mock",
+ "android.test.base",
+ "android.test.runner",
+ ],
+
+ jni_libs: [
+ "libdexmakerjvmtiagent",
+ "libstaticjvmtiagent",
+ ],
+
+ certificate: "platform",
+ platform_apis: true,
+ test_suites: [
+ "device-tests",
+ "automotive-tests",
+ ],
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/crashrecovery/AndroidManifest.xml b/services/tests/mockingservicestests/src/com/android/server/crashrecovery/AndroidManifest.xml
new file mode 100644
index 0000000..067f116
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/crashrecovery/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 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.
+ -->
+
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+ package="com.android.server.crashrecovery">
+
+ <uses-sdk android:targetSdkVersion="35" />
+
+ <application android:testOnly="true"
+ android:debuggable="true">
+ <uses-library android:name="android.test.runner" />
+ </application>
+
+ <instrumentation
+ android:name="androidx.test.runner.AndroidJUnitRunner"
+ android:targetPackage="com.android.server.crashrecovery"
+ android:label="Frameworks crashrecovery module test" />
+</manifest>
diff --git a/services/tests/mockingservicestests/src/com/android/server/crashrecovery/AndroidTest.xml b/services/tests/mockingservicestests/src/com/android/server/crashrecovery/AndroidTest.xml
new file mode 100644
index 0000000..7b06ebe
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/crashrecovery/AndroidTest.xml
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+ ~ Copyright (C) 2024 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.
+ -->
+<configuration description="Runs Crashrecovery Module Tests.">
+ <option name="test-suite-tag" value="apct" />
+ <option name="test-suite-tag" value="apct-instrumentation" />
+
+ <target_preparer class="com.android.tradefed.targetprep.suite.SuiteApkInstaller">
+ <option name="cleanup-apks" value="true" />
+ <option name="install-arg" value="-t" />
+ <option name="test-file-name" value="CrashRecoveryModuleTests.apk" />
+ </target_preparer>
+
+ <option name="test-tag" value="CrashRecoveryModuleTests" />
+
+ <test class="com.android.tradefed.testtype.AndroidJUnitTest" >
+ <option name="package" value="com.android.server.crashrecovery" />
+ <option name="runner" value="androidx.test.runner.AndroidJUnitRunner" />
+ <option name="hidden-api-checks" value="false"/>
+ </test>
+</configuration>
diff --git a/services/tests/mockingservicestests/src/com/android/server/crashrecovery/CrashRecoveryModuleTest.java b/services/tests/mockingservicestests/src/com/android/server/crashrecovery/CrashRecoveryModuleTest.java
new file mode 100644
index 0000000..c481f84
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/crashrecovery/CrashRecoveryModuleTest.java
@@ -0,0 +1,103 @@
+/*
+ * Copyright (C) 2024 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.server.crashrecovery;
+
+import static com.android.server.SystemService.PHASE_ACTIVITY_MANAGER_READY;
+import static com.android.server.SystemService.PHASE_THIRD_PARTY_APPS_CAN_START;
+
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.never;
+import static org.mockito.Mockito.times;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import android.content.Context;
+import android.platform.test.flag.junit.SetFlagsRule;
+
+import androidx.test.core.app.ApplicationProvider;
+import androidx.test.runner.AndroidJUnit4;
+
+
+import com.android.dx.mockito.inline.extended.ExtendedMockito;
+import com.android.server.PackageWatchdog;
+import com.android.server.RescueParty;
+import com.android.server.crashrecovery.CrashRecoveryModule.Lifecycle;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.Mockito;
+import org.mockito.MockitoSession;
+import org.mockito.quality.Strictness;
+
+/**
+ * Test CrashRecoveryModule.
+ */
+@RunWith(AndroidJUnit4.class)
+public class CrashRecoveryModuleTest {
+
+ @Rule
+ public SetFlagsRule mSetFlagsRule;
+
+ private MockitoSession mSession;
+ private Lifecycle mLifecycle;
+
+ @Mock PackageWatchdog mPackageWatchdog;
+
+ @Before
+ public void setup() {
+ Context context = ApplicationProvider.getApplicationContext();
+ mSession = ExtendedMockito.mockitoSession()
+ .initMocks(this)
+ .strictness(Strictness.LENIENT)
+ .mockStatic(PackageWatchdog.class)
+ .mockStatic(RescueParty.class)
+ .startMocking();
+ when(PackageWatchdog.getInstance(context)).thenReturn(mPackageWatchdog);
+ ExtendedMockito.doNothing().when(() -> RescueParty.registerHealthObserver(context));
+ mLifecycle = new Lifecycle(context);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ mSession.finishMocking();
+ }
+
+ @Test
+ public void testLifecycleServiceStart() {
+ mLifecycle.onStart();
+
+ verify(mPackageWatchdog, times(1)).noteBoot();
+ ExtendedMockito.verify(() -> RescueParty.registerHealthObserver(any()),
+ Mockito.times(1));
+ }
+
+ @Test
+ public void testLifecycleServiceOnBootPhase() {
+ doNothing().when(mPackageWatchdog).onPackagesReady();
+
+ mLifecycle.onBootPhase(PHASE_ACTIVITY_MANAGER_READY);
+ verify(mPackageWatchdog, never()).onPackagesReady();
+
+ mLifecycle.onBootPhase(PHASE_THIRD_PARTY_APPS_CAN_START);
+ verify(mPackageWatchdog, times(1)).onPackagesReady();
+ }
+}
diff --git a/services/tests/mockingservicestests/src/com/android/server/crashrecovery/OWNERS b/services/tests/mockingservicestests/src/com/android/server/crashrecovery/OWNERS
new file mode 100644
index 0000000..8337fd2
--- /dev/null
+++ b/services/tests/mockingservicestests/src/com/android/server/crashrecovery/OWNERS
@@ -0,0 +1 @@
+include /services/core/java/com/android/server/crashrecovery/OWNERS
\ No newline at end of file
diff --git a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
index ca30551..62fa951 100644
--- a/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
+++ b/services/tests/servicestests/src/com/android/server/accessibility/AccessibilityUserStateTest.java
@@ -152,6 +152,7 @@
@Test
public void onSwitchToAnotherUser_userStateClearedNonDefaultValues() {
+ String componentNameString = COMPONENT_NAME.flattenToString();
mUserState.getBoundServicesLocked().add(mMockConnection);
mUserState.getBindingServicesLocked().add(COMPONENT_NAME);
mUserState.setLastSentClientStateLocked(
@@ -162,10 +163,13 @@
mUserState.setInteractiveUiTimeoutLocked(30);
mUserState.mEnabledServices.add(COMPONENT_NAME);
mUserState.mTouchExplorationGrantedServices.add(COMPONENT_NAME);
- mUserState.updateShortcutTargetsLocked(Set.of(COMPONENT_NAME.flattenToString()), HARDWARE);
- mUserState.updateShortcutTargetsLocked(Set.of(COMPONENT_NAME.flattenToString()), SOFTWARE);
- mUserState.updateShortcutTargetsLocked(Set.of(COMPONENT_NAME.flattenToString()), GESTURE);
- mUserState.setTargetAssignedToAccessibilityButton(COMPONENT_NAME.flattenToString());
+ mUserState.updateShortcutTargetsLocked(Set.of(componentNameString), HARDWARE);
+ mUserState.updateShortcutTargetsLocked(Set.of(componentNameString), SOFTWARE);
+ mUserState.updateShortcutTargetsLocked(Set.of(componentNameString), GESTURE);
+ mUserState.updateShortcutTargetsLocked(Set.of(componentNameString), QUICK_SETTINGS);
+ mUserState.updateA11yTilesInQsPanelLocked(
+ Set.of(AccessibilityShortcutController.COLOR_INVERSION_TILE_COMPONENT_NAME));
+ mUserState.setTargetAssignedToAccessibilityButton(componentNameString);
mUserState.setTouchExplorationEnabledLocked(true);
mUserState.setMagnificationSingleFingerTripleTapEnabledLocked(true);
mUserState.setMagnificationTwoFingerTripleTapEnabledLocked(true);
@@ -189,6 +193,8 @@
assertTrue(mUserState.getShortcutTargetsLocked(HARDWARE).isEmpty());
assertTrue(mUserState.getShortcutTargetsLocked(SOFTWARE).isEmpty());
assertTrue(mUserState.getShortcutTargetsLocked(GESTURE).isEmpty());
+ assertTrue(mUserState.getShortcutTargetsLocked(QUICK_SETTINGS).isEmpty());
+ assertTrue(mUserState.getA11yQsTilesInQsPanel().isEmpty());
assertNull(mUserState.getTargetAssignedToAccessibilityButton());
assertFalse(mUserState.isTouchExplorationEnabledLocked());
assertFalse(mUserState.isMagnificationSingleFingerTripleTapEnabledLocked());
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index eb8825c..b4505fa 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -684,7 +684,8 @@
// Asserts fixed orientation request is not ignored, and the orientation is changed.
assertNotEquals(activityCurOrientation, activity.getConfiguration().orientation);
- assertTrue(activity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(activity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
}
@Test
@@ -717,7 +718,8 @@
// Relaunching the app should still respect the orientation request.
assertEquals(ORIENTATION_PORTRAIT, activity.getConfiguration().orientation);
- assertTrue(activity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(activity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java b/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java
index 433b091..867f01f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java
+++ b/services/tests/wmtests/src/com/android/server/wm/AppCompatActivityRobot.java
@@ -143,8 +143,8 @@
}
void setLetterboxedForFixedOrientationAndAspectRatio(boolean enabled) {
- doReturn(enabled).when(mActivityStack.top())
- .isLetterboxedForFixedOrientationAndAspectRatio();
+ doReturn(enabled).when(mActivityStack.top().mAppCompatController
+ .getAppCompatAspectRatioPolicy()).isLetterboxedForFixedOrientationAndAspectRatio();
}
void enableTreatmentForTopActivity(boolean enabled) {
@@ -403,6 +403,7 @@
spyOn(activity);
spyOn(activity.mAppCompatController.getTransparentPolicy());
spyOn(activity.mAppCompatController.getAppCompatAspectRatioOverrides());
+ spyOn(activity.mAppCompatController.getAppCompatAspectRatioPolicy());
spyOn(activity.mLetterboxUiController);
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
index 83ad7b1..708d686 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DualDisplayAreaGroupPolicyTest.java
@@ -214,7 +214,8 @@
final Rect activityBounds = new Rect(mFirstActivity.getBounds());
// DAG is portrait (860x1200), so Task and Activity fill DAG.
- assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
+ assertThat(mFirstActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
assertThat(taskBounds).isEqualTo(dagBounds);
assertThat(activityBounds).isEqualTo(taskBounds);
@@ -238,7 +239,8 @@
new Rect(mFirstActivity.getConfiguration().windowConfiguration.getBounds());
// DAG is landscape (1200x860), no fixed orientation letterbox
- assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
+ assertThat(mFirstActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
assertThat(mFirstActivity.inSizeCompatMode()).isTrue();
assertThat(newDagBounds.width()).isEqualTo(dagBounds.height());
assertThat(newDagBounds.height()).isEqualTo(dagBounds.width());
@@ -262,11 +264,13 @@
mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);
prepareUnresizable(mFirstActivity, SCREEN_ORIENTATION_NOSENSOR);
- assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
+ assertThat(mFirstActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
rotateDisplay(mDisplay, ROTATION_90);
- assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
+ assertThat(mFirstActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
}
@@ -283,7 +287,8 @@
// DAG is portrait (860x1200), and activity is letterboxed for fixed orientation
// (860x[860x860/1200=616]). Task fills DAG.
- assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isTrue();
+ assertThat(mFirstActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio()).isTrue();
assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
assertThat(taskBounds).isEqualTo(dagBounds);
assertThat(activityBounds.width()).isEqualTo(dagBounds.width());
@@ -300,7 +305,8 @@
mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);
prepareUnresizable(mFirstActivity, SCREEN_ORIENTATION_NOSENSOR);
- assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
+ assertThat(mFirstActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
}
@Test
@@ -310,7 +316,8 @@
mDisplay.onLastFocusedTaskDisplayAreaChanged(mFirstTda);
prepareUnresizable(mFirstActivity, SCREEN_ORIENTATION_LOCKED);
- assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
+ assertThat(mFirstActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
}
@Test
@@ -329,7 +336,8 @@
final Rect newActivityBounds = new Rect(mFirstActivity.getBounds());
// DAG is landscape (1200x860), no fixed orientation letterbox
- assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
+ assertThat(mFirstActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
assertThat(mFirstActivity.inSizeCompatMode()).isTrue();
assertThat(newDagBounds.width()).isEqualTo(dagBounds.height());
assertThat(newDagBounds.height()).isEqualTo(dagBounds.width());
@@ -354,7 +362,8 @@
rotateDisplay(mDisplay, ROTATION_90);
- assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
+ assertThat(mFirstActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
}
@@ -522,7 +531,8 @@
assertThat(mDisplay.getLastOrientation()).isEqualTo(SCREEN_ORIENTATION_LANDSCAPE);
assertThat(mFirstRoot.getConfiguration().orientation).isEqualTo(ORIENTATION_PORTRAIT);
assertThat(mFirstActivity.getConfiguration().orientation).isEqualTo(ORIENTATION_PORTRAIT);
- assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
+ assertThat(mFirstActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
// Launch portrait on second DAG
@@ -534,13 +544,15 @@
assertThat(mDisplay.getLastOrientation()).isEqualTo(SCREEN_ORIENTATION_PORTRAIT);
assertThat(mSecondRoot.getConfiguration().orientation).isEqualTo(ORIENTATION_LANDSCAPE);
assertThat(mSecondActivity.getConfiguration().orientation).isEqualTo(ORIENTATION_LANDSCAPE);
- assertThat(mSecondActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
+ assertThat(mSecondActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio()).isFalse();
assertThat(mSecondActivity.inSizeCompatMode()).isFalse();
// First activity is letterboxed in portrait as requested.
assertThat(mFirstRoot.getConfiguration().orientation).isEqualTo(ORIENTATION_LANDSCAPE);
assertThat(mFirstActivity.getConfiguration().orientation).isEqualTo(ORIENTATION_PORTRAIT);
- assertThat(mFirstActivity.isLetterboxedForFixedOrientationAndAspectRatio()).isTrue();
+ assertThat(mFirstActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio()).isTrue();
assertThat(mFirstActivity.inSizeCompatMode()).isFalse();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
index 802f8d2..c42367e 100644
--- a/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/LetterboxUiControllerTest.java
@@ -293,6 +293,7 @@
mainWindow.mInvGlobalScale = 1f;
spyOn(resources);
spyOn(mActivity);
+ spyOn(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy());
if (taskbar != null) {
taskbar.setVisible(true);
@@ -301,7 +302,8 @@
doReturn(mLetterboxedPortraitTaskBounds).when(mActivity).getBounds();
doReturn(false).when(mActivity).isInLetterboxAnimation();
doReturn(true).when(mActivity).isVisible();
- doReturn(true).when(mActivity).isLetterboxedForFixedOrientationAndAspectRatio();
+ doReturn(true).when(mActivity.mAppCompatController
+ .getAppCompatAspectRatioPolicy()).isLetterboxedForFixedOrientationAndAspectRatio();
doReturn(insets).when(mainWindow).getInsetsState();
doReturn(attrs).when(mainWindow).getAttrs();
doReturn(true).when(mainWindow).isDrawn();
@@ -324,11 +326,11 @@
mockThatProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_FULLSCREEN_OVERRIDE,
/* value */ true);
- mActivity = setUpActivityWithComponent();
- mController = new LetterboxUiController(mWm, mActivity);
doReturn(false).when(mLetterboxConfiguration).isUserAppAspectRatioFullscreenEnabled();
+ mActivity = setUpActivityWithComponent();
- assertFalse(mController.shouldApplyUserFullscreenOverride());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides()
+ .shouldApplyUserFullscreenOverride());
}
@Test
@@ -339,9 +341,9 @@
/* value */ false);
mActivity = setUpActivityWithComponent();
- mController = new LetterboxUiController(mWm, mActivity);
- assertFalse(mController.shouldApplyUserFullscreenOverride());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides()
+ .shouldApplyUserFullscreenOverride());
}
@Test
@@ -351,16 +353,17 @@
mockThatProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE, /* value */ false);
mActivity = setUpActivityWithComponent();
- mController = new LetterboxUiController(mWm, mActivity);
- assertFalse(mController.shouldApplyUserFullscreenOverride());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides()
+ .shouldApplyUserFullscreenOverride());
}
@Test
public void testShouldApplyUserFullscreenOverride_returnsTrue() {
prepareActivityThatShouldApplyUserFullscreenOverride();
- assertTrue(mController.shouldApplyUserFullscreenOverride());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides()
+ .shouldApplyUserFullscreenOverride());
}
@Test
@@ -421,9 +424,9 @@
mockThatProperty(PROPERTY_COMPAT_ALLOW_USER_ASPECT_RATIO_OVERRIDE, /* value */ true);
mActivity = setUpActivityWithComponent();
- mController = new LetterboxUiController(mWm, mActivity);
- assertFalse(mController.shouldApplyUserMinAspectRatioOverride());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides()
+ .shouldApplyUserMinAspectRatioOverride());
}
@Test
@@ -431,21 +434,24 @@
prepareActivityThatShouldApplyUserMinAspectRatioOverride();
mDisplayContent.setIgnoreOrientationRequest(false);
- assertFalse(mController.shouldApplyUserMinAspectRatioOverride());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides()
+ .shouldApplyUserMinAspectRatioOverride());
}
@Test
public void testShouldApplyUserMinAspectRatioOverride_returnsTrue() {
prepareActivityThatShouldApplyUserMinAspectRatioOverride();
- assertTrue(mController.shouldApplyUserMinAspectRatioOverride());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides()
+ .shouldApplyUserMinAspectRatioOverride());
}
@Test
public void testShouldApplyUserMinAspectRatioOverride_noIgnoreOrientation_returnsFalse() {
prepareActivityForShouldApplyUserMinAspectRatioOverride(/* orientationRequest */ false);
- assertFalse(mController.shouldApplyUserMinAspectRatioOverride());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides()
+ .shouldApplyUserMinAspectRatioOverride());
}
private void prepareActivityForShouldApplyUserMinAspectRatioOverride(
@@ -591,9 +597,10 @@
@Test
@EnableCompatChanges({OVERRIDE_MIN_ASPECT_RATIO})
public void testshouldOverrideMinAspectRatio_overrideEnabled_returnsTrue() {
- mController = new LetterboxUiController(mWm, mActivity);
+ mActivity = setUpActivityWithComponent();
- assertTrue(mController.shouldOverrideMinAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides()
+ .shouldOverrideMinAspectRatio());
}
@Test
@@ -601,9 +608,10 @@
public void testshouldOverrideMinAspectRatio_propertyTrue_overrideEnabled_returnsTrue()
throws Exception {
mockThatProperty(PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE, /* value */ true);
- mController = new LetterboxUiController(mWm, mActivity);
+ mActivity = setUpActivityWithComponent();
- assertTrue(mController.shouldOverrideMinAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides()
+ .shouldOverrideMinAspectRatio());
}
@Test
@@ -611,17 +619,19 @@
public void testshouldOverrideMinAspectRatio_propertyTrue_overrideDisabled_returnsFalse()
throws Exception {
mockThatProperty(PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE, /* value */ true);
- mController = new LetterboxUiController(mWm, mActivity);
+ mActivity = setUpActivityWithComponent();
- assertFalse(mController.shouldOverrideMinAspectRatio());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides()
+ .shouldOverrideMinAspectRatio());
}
@Test
@DisableCompatChanges({OVERRIDE_MIN_ASPECT_RATIO})
public void testshouldOverrideMinAspectRatio_overrideDisabled_returnsFalse() {
- mController = new LetterboxUiController(mWm, mActivity);
+ mActivity = setUpActivityWithComponent();
- assertFalse(mController.shouldOverrideMinAspectRatio());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides()
+ .shouldOverrideMinAspectRatio());
}
@Test
@@ -631,9 +641,9 @@
mockThatProperty(PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE, /* value */ false);
mActivity = setUpActivityWithComponent();
- mController = new LetterboxUiController(mWm, mActivity);
- assertFalse(mController.shouldOverrideMinAspectRatio());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides()
+ .shouldOverrideMinAspectRatio());
}
@Test
@@ -641,9 +651,10 @@
public void testshouldOverrideMinAspectRatio_propertyFalse_noOverride_returnsFalse()
throws Exception {
mockThatProperty(PROPERTY_COMPAT_ALLOW_MIN_ASPECT_RATIO_OVERRIDE, /* value */ false);
- mController = new LetterboxUiController(mWm, mActivity);
+ mActivity = setUpActivityWithComponent();
- assertFalse(mController.shouldOverrideMinAspectRatio());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioOverrides()
+ .shouldOverrideMinAspectRatio());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
index 3078df0..d6d8339 100644
--- a/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/RootWindowContainerTests.java
@@ -428,7 +428,8 @@
final Rect bounds = new Rect(task.getBounds());
bounds.scale(0.5f);
task.setBounds(bounds);
- assertFalse(activity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(activity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertThat(task.autoRemoveRecents).isFalse();
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
index 0eb3edb..5fe8524 100644
--- a/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/SizeCompatTests.java
@@ -64,6 +64,7 @@
import static com.android.server.wm.ActivityRecord.State.RESTARTING_PROCESS;
import static com.android.server.wm.ActivityRecord.State.RESUMED;
import static com.android.server.wm.ActivityRecord.State.STOPPED;
+import static com.android.server.wm.AppCompatUtils.computeAspectRatio;
import static com.android.server.wm.DisplayContent.IME_TARGET_LAYERING;
import static com.android.server.wm.LetterboxConfiguration.LETTERBOX_POSITION_MULTIPLIER_CENTER;
import static com.android.server.wm.WindowContainer.POSITION_TOP;
@@ -1103,9 +1104,10 @@
RESIZE_MODE_UNRESIZEABLE, ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
// Simulate the user selecting the fullscreen user aspect ratio override
- spyOn(activity.mLetterboxUiController);
- doReturn(true).when(activity.mLetterboxUiController)
- .isSystemOverrideToFullscreenEnabled();
+ spyOn(activity.mAppCompatController.getAppCompatAspectRatioOverrides());
+ doReturn(true).when(
+ activity.mAppCompatController.getAppCompatAspectRatioOverrides())
+ .isSystemOverrideToFullscreenEnabled();
assertFalse(activity.shouldCreateCompatDisplayInsets());
}
@@ -1124,7 +1126,8 @@
prepareUnresizable(activity, /* maxAspect=*/ 1.5f, SCREEN_ORIENTATION_LANDSCAPE);
// Activity max bounds should not be sandboxed, even though it is letterboxed.
- assertTrue(activity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(activity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertThat(activity.getConfiguration().windowConfiguration.getMaxBounds())
.isEqualTo(activity.getDisplayArea().getBounds());
}
@@ -1165,7 +1168,8 @@
prepareUnresizable(activity, /* maxAspect=*/ 1.5f, SCREEN_ORIENTATION_LANDSCAPE);
// Activity max bounds should not be sandboxed, even though it is letterboxed.
- assertTrue(activity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(activity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertThat(activity.getConfiguration().windowConfiguration.getMaxBounds())
.isEqualTo(activity.getDisplayArea().getBounds());
}
@@ -1188,7 +1192,8 @@
prepareUnresizable(activity, /* maxAspect=*/ 1.5f, SCREEN_ORIENTATION_LANDSCAPE);
// Activity max bounds should not be sandboxed, even though it is letterboxed.
- assertTrue(activity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(activity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertThat(activity.getConfiguration().windowConfiguration.getMaxBounds())
.isEqualTo(activity.getDisplayArea().getBounds());
}
@@ -1637,7 +1642,8 @@
addWindowToActivity(mActivity);
// App should launch in fullscreen.
- assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(mActivity.inSizeCompatMode());
// Activity inherits max bounds from TaskDisplayArea.
@@ -1651,7 +1657,8 @@
assertTrue(rotatedDisplayBounds.width() < rotatedDisplayBounds.height());
// App should be in size compat.
- assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertScaled();
assertThat(mActivity.inSizeCompatMode()).isTrue();
assertActivityMaxBoundsSandboxed();
@@ -1763,7 +1770,8 @@
assertTrue(displayBounds.width() > displayBounds.height());
// App should launch in fixed orientation letterbox.
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(mActivity.inSizeCompatMode());
assertActivityMaxBoundsSandboxed();
@@ -1794,7 +1802,8 @@
assertTrue(displayBounds.width() > displayBounds.height());
// App should launch in fixed orientation letterbox.
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(mActivity.inSizeCompatMode());
// Activity bounds should respect minimum aspect ratio for activity.
@@ -1824,7 +1833,8 @@
assertTrue(displayBounds.width() > displayBounds.height());
// App should launch in fixed orientation letterbox.
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(mActivity.inSizeCompatMode());
// Activity bounds should respect maximum aspect ratio for activity.
@@ -1854,7 +1864,8 @@
assertTrue(displayBounds.width() > displayBounds.height());
// App should launch in fixed orientation letterbox.
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(mActivity.inSizeCompatMode());
// Activity bounds should respect aspect ratio override for fixed orientation letterbox.
@@ -1951,7 +1962,8 @@
assertTrue(displayBounds.width() > displayBounds.height());
// App should launch in fixed orientation letterbox.
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(mActivity.inSizeCompatMode());
// Letterbox logic should use config_letterboxDefaultMinAspectRatioForUnresizableApps over
@@ -1977,7 +1989,8 @@
// App should launch in fixed orientation letterbox.
// Activity bounds should be 700x1400 with the ratio as the display.
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFitted();
assertEquals(originalScreenWidthDp, mActivity.getConfiguration().smallestScreenWidthDp);
assertTrue(originalScreenWidthDp < originalScreenHeighthDp);
@@ -2019,7 +2032,8 @@
// App should launch in fixed orientation letterbox.
// Activity bounds should be 700x1400 with the ratio as the display.
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFitted();
assertEquals(originalScreenWidthDp, mActivity.getConfiguration().smallestScreenWidthDp);
assertTrue(originalScreenWidthDp < originalScreenHeighthDp);
@@ -2053,7 +2067,8 @@
final Rect activityBounds = new Rect(mActivity.getBounds());
// App should launch in fixed orientation letterbox.
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
// Checking that there is no size compat mode.
assertFitted();
@@ -2593,7 +2608,8 @@
final Rect activityBounds = new Rect(mActivity.getBounds());
// App should launch in fixed orientation letterbox.
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
// Checking that there is no size compat mode.
assertFitted();
@@ -2637,13 +2653,14 @@
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
// App should launch in fixed orientation letterbox.
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
// Checking that there is no size compat mode.
assertFitted();
// Check that the display aspect ratio is used by the app.
final float targetMinAspectRatio = 1f * displayHeight / displayWidth;
- assertEquals(targetMinAspectRatio, ActivityRecord
- .computeAspectRatio(mActivity.getBounds()), DELTA_ASPECT_RATIO_TOLERANCE);
+ assertEquals(targetMinAspectRatio, computeAspectRatio(mActivity.getBounds()),
+ DELTA_ASPECT_RATIO_TOLERANCE);
}
@Test
@@ -2672,13 +2689,14 @@
assertEquals(WINDOWING_MODE_MULTI_WINDOW, mActivity.getWindowingMode());
// App should launch in fixed orientation letterbox.
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
// Checking that there is no size compat mode.
assertFitted();
// Check that the display aspect ratio is used by the app.
final float targetMinAspectRatio = 1f * displayWidth / displayHeight;
- assertEquals(targetMinAspectRatio, ActivityRecord
- .computeAspectRatio(mActivity.getBounds()), DELTA_ASPECT_RATIO_TOLERANCE);
+ assertEquals(targetMinAspectRatio, computeAspectRatio(mActivity.getBounds()),
+ DELTA_ASPECT_RATIO_TOLERANCE);
}
@Test
@@ -2698,13 +2716,14 @@
prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);
// App should launch in fixed orientation letterbox.
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
// Checking that there is no size compat mode.
assertFitted();
// Check that the display aspect ratio is used by the app.
final float targetMinAspectRatio = 1f * displayHeight / displayWidth;
- assertEquals(targetMinAspectRatio, ActivityRecord
- .computeAspectRatio(mActivity.getBounds()), DELTA_ASPECT_RATIO_TOLERANCE);
+ assertEquals(targetMinAspectRatio, computeAspectRatio(mActivity.getBounds()),
+ DELTA_ASPECT_RATIO_TOLERANCE);
}
@Test
@@ -2724,13 +2743,14 @@
prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
// App should launch in fixed orientation letterbox.
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
// Checking that there is no size compat mode.
assertFitted();
// Check that the display aspect ratio is used by the app.
final float targetMinAspectRatio = 1f * displayWidth / displayHeight;
- assertEquals(targetMinAspectRatio, ActivityRecord
- .computeAspectRatio(mActivity.getBounds()), DELTA_ASPECT_RATIO_TOLERANCE);
+ assertEquals(targetMinAspectRatio, computeAspectRatio(mActivity.getBounds()),
+ DELTA_ASPECT_RATIO_TOLERANCE);
}
@Test
@@ -2753,7 +2773,8 @@
assertTrue(displayBounds.width() < displayBounds.height());
// App should be in size compat.
- assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertScaled();
assertEquals(activityBounds.width(), newActivityBounds.width());
assertEquals(activityBounds.height(), newActivityBounds.height());
@@ -2770,7 +2791,8 @@
prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);
// App should launch in fullscreen.
- assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(mActivity.inSizeCompatMode());
// Activity inherits max bounds from TaskDisplayArea.
assertMaxBoundsInheritDisplayAreaBounds();
@@ -2783,7 +2805,8 @@
assertTrue(rotatedDisplayBounds.width() > rotatedDisplayBounds.height());
// App should be in size compat.
- assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertScaled();
assertThat(mActivity.inSizeCompatMode()).isTrue();
assertActivityMaxBoundsSandboxed();
@@ -2804,7 +2827,8 @@
// Portrait fixed app without max aspect.
prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(mActivity.inSizeCompatMode());
// Launch another portrait fixed app.
@@ -2826,7 +2850,8 @@
// Task and display bounds should be equal while activity should be letterboxed and
// has 700x1400 bounds with the ratio as the display.
- assertTrue(newActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(newActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(newActivity.inSizeCompatMode());
// Activity max bounds are sandboxed due to size compat mode.
assertThat(newActivity.getConfiguration().windowConfiguration.getMaxBounds())
@@ -2847,7 +2872,8 @@
// Portrait fixed app without max aspect.
prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(mActivity.inSizeCompatMode());
mActivity.setRequestedOrientation(SCREEN_ORIENTATION_UNSPECIFIED);
@@ -2868,7 +2894,8 @@
// Portrait fixed app without max aspect.
prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(mActivity.inSizeCompatMode());
// Launch another portrait fixed app with max aspect ratio as 1.3.
@@ -2898,7 +2925,8 @@
assertActivityMaxBoundsSandboxed();
// Activity bounds should be (1400 / 1.3 = 1076)x1400 with the app requested ratio.
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(newActivity.inSizeCompatMode());
assertEquals(displayBounds.height(), newActivityBounds.height());
assertEquals((long) Math.rint(newActivityBounds.height()
@@ -2917,14 +2945,16 @@
prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);
clearInvocations(mActivity);
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(mActivity.inSizeCompatMode());
// Rotate display to portrait.
rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
// App should be in size compat.
- assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertScaled();
assertThat(mActivity.inSizeCompatMode()).isTrue();
// Activity max bounds are sandboxed due to size compat mode.
@@ -2935,7 +2965,8 @@
// App still in size compat, and the bounds don't change.
verify(mActivity, never()).clearSizeCompatMode();
- assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertScaled();
assertEquals(activityBounds, mActivity.getBounds());
// Activity max bounds are sandboxed due to size compat.
@@ -2953,7 +2984,8 @@
prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_PORTRAIT);
// In fixed orientation letterbox
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(mActivity.inSizeCompatMode());
assertActivityMaxBoundsSandboxed();
@@ -2961,7 +2993,8 @@
rotateDisplay(display, ROTATION_90);
// App should be in size compat.
- assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertScaled();
assertActivityMaxBoundsSandboxed();
@@ -2969,7 +3002,8 @@
rotateDisplay(display, ROTATION_180);
// In activity letterbox
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(mActivity.inSizeCompatMode());
assertActivityMaxBoundsSandboxed();
}
@@ -2987,7 +3021,8 @@
prepareUnresizable(mActivity, 0, SCREEN_ORIENTATION_LANDSCAPE);
// In fixed orientation letterbox
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(mActivity.inSizeCompatMode());
assertActivityMaxBoundsSandboxed();
@@ -2995,7 +3030,8 @@
rotateDisplay(display, ROTATION_90);
// App should be in size compat.
- assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertScaled();
assertActivityMaxBoundsSandboxed();
@@ -3003,7 +3039,8 @@
rotateDisplay(display, ROTATION_180);
// In fixed orientation letterbox
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(mActivity.inSizeCompatMode());
assertActivityMaxBoundsSandboxed();
}
@@ -3200,7 +3237,8 @@
assertEquals(ORIENTATION_PORTRAIT, mTask.getConfiguration().orientation);
assertEquals(ORIENTATION_LANDSCAPE, mActivity.getConfiguration().orientation);
assertFitted();
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertActivityMaxBoundsSandboxed();
// Letterbox should fill the gap between the split screen and the letterboxed activity.
@@ -3226,7 +3264,8 @@
// Resizable activity is not in size compat mode but in the letterbox for fixed orientation.
assertFitted();
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
}
@Test
@@ -3262,7 +3301,8 @@
assertEquals(ORIENTATION_PORTRAIT, mTask.getConfiguration().orientation);
assertEquals(ORIENTATION_PORTRAIT, mActivity.getConfiguration().orientation);
assertFitted();
- assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertActivityMaxBoundsSandboxed();
// Activity bounds fill split screen.
@@ -3897,7 +3937,8 @@
// orientation is not respected with insets as insets have been decoupled.
final Rect appBounds = activity.getWindowConfiguration().getAppBounds();
final Rect displayBounds = display.getBounds();
- assertFalse(activity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(activity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertNotNull(appBounds);
assertEquals(displayBounds.width(), appBounds.width());
assertEquals(displayBounds.height(), appBounds.height());
@@ -3928,7 +3969,8 @@
final Rect bounds = activity.getBounds();
// Activity should be letterboxed and should have portrait app bounds
- assertTrue(activity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(activity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertTrue(bounds.height() > bounds.width());
}
@@ -3962,7 +4004,8 @@
assertNotNull(activity.getCompatDisplayInsets());
// Activity is not letterboxed for fixed orientation because orientation is respected
// with insets, and should not be in size compat mode
- assertFalse(activity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(activity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(activity.inSizeCompatMode());
}
@@ -4386,7 +4429,8 @@
verifyLogAppCompatState(mActivity, APP_COMPAT_STATE_CHANGED__STATE__NOT_LETTERBOXED);
prepareUnresizable(mActivity, /* maxAspect= */ 2, SCREEN_ORIENTATION_PORTRAIT);
- assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(mActivity.inSizeCompatMode());
assertTrue(mActivity.areBoundsLetterboxed());
@@ -4402,7 +4446,8 @@
// ActivityRecord#resolveSizeCompatModeConfiguration because mCompatDisplayInsets aren't
// null but activity doesn't enter size compat mode. Checking that areBoundsLetterboxed()
// still returns true because of the aspect ratio restrictions.
- assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(mActivity.inSizeCompatMode());
assertTrue(mActivity.areBoundsLetterboxed());
verifyLogAppCompatState(mActivity,
@@ -4429,7 +4474,8 @@
prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertFalse(mActivity.inSizeCompatMode());
assertTrue(mActivity.areBoundsLetterboxed());
verifyLogAppCompatState(mActivity,
@@ -4447,7 +4493,8 @@
rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
- assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertTrue(mActivity.inSizeCompatMode());
assertTrue(mActivity.areBoundsLetterboxed());
verifyLogAppCompatState(mActivity,
@@ -4508,7 +4555,8 @@
prepareUnresizable(mActivity, SCREEN_ORIENTATION_LANDSCAPE);
assertFalse(mActivity.isEligibleForLetterboxEducation());
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
}
@Test
@@ -4566,7 +4614,8 @@
prepareUnresizable(mActivity, SCREEN_ORIENTATION_PORTRAIT);
assertTrue(mActivity.isEligibleForLetterboxEducation());
- assertTrue(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertTrue(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
}
@Test
@@ -4580,7 +4629,8 @@
rotateDisplay(mActivity.mDisplayContent, ROTATION_90);
assertTrue(mActivity.isEligibleForLetterboxEducation());
- assertFalse(mActivity.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(mActivity.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertTrue(mActivity.inSizeCompatMode());
}
@@ -4648,12 +4698,12 @@
.windowConfiguration.getAppBounds());
// Check that aspect ratio of app bounds is equal to the min aspect ratio.
- assertEquals(targetMinAspectRatio, ActivityRecord
- .computeAspectRatio(fixedOrientationAppBounds), DELTA_ASPECT_RATIO_TOLERANCE);
- assertEquals(targetMinAspectRatio, ActivityRecord
- .computeAspectRatio(minAspectRatioAppBounds), DELTA_ASPECT_RATIO_TOLERANCE);
- assertEquals(targetMinAspectRatio, ActivityRecord
- .computeAspectRatio(sizeCompatAppBounds), DELTA_ASPECT_RATIO_TOLERANCE);
+ assertEquals(targetMinAspectRatio,
+ computeAspectRatio(fixedOrientationAppBounds), DELTA_ASPECT_RATIO_TOLERANCE);
+ assertEquals(targetMinAspectRatio,
+ computeAspectRatio(minAspectRatioAppBounds), DELTA_ASPECT_RATIO_TOLERANCE);
+ assertEquals(targetMinAspectRatio,
+ computeAspectRatio(sizeCompatAppBounds), DELTA_ASPECT_RATIO_TOLERANCE);
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
index 35b6b70..47d34a6 100644
--- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentTest.java
@@ -759,20 +759,24 @@
// Assert fixed orientation request is ignored for activity in ActivityEmbedding split.
activity0.setRequestedOrientation(SCREEN_ORIENTATION_LANDSCAPE);
- assertFalse(activity0.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(activity0.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertEquals(SCREEN_ORIENTATION_UNSET, task.getOrientation());
activity1.setRequestedOrientation(SCREEN_ORIENTATION_PORTRAIT);
- assertFalse(activity1.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(activity1.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertEquals(SCREEN_ORIENTATION_UNSET, task.getOrientation());
// Also verify the behavior on device that ignore orientation request.
mDisplayContent.setIgnoreOrientationRequest(true);
task.onConfigurationChanged(task.getParent().getConfiguration());
- assertFalse(activity0.isLetterboxedForFixedOrientationAndAspectRatio());
- assertFalse(activity1.isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(activity0.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
+ assertFalse(activity1.mAppCompatController.getAppCompatAspectRatioPolicy()
+ .isLetterboxedForFixedOrientationAndAspectRatio());
assertEquals(SCREEN_ORIENTATION_UNSET, task.getOrientation());
tf0.setResumedActivity(activity0, "test");
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
index a94b586..45dbea2 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowContainerTests.java
@@ -22,6 +22,7 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_PORTRAIT;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSET;
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
+import static android.view.InsetsSource.FLAG_FORCE_CONSUMING;
import static android.view.WindowInsets.Type.systemOverlays;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
import static android.view.WindowManager.LayoutParams.TYPE_BASE_APPLICATION;
@@ -77,6 +78,7 @@
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ShellCallback;
+import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.view.IRemoteAnimationFinishedCallback;
import android.view.IRemoteAnimationRunner;
@@ -91,6 +93,8 @@
import androidx.test.filters.SmallTest;
+import com.android.window.flags.Flags;
+
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.ArgumentCaptor;
@@ -960,6 +964,25 @@
assertTrue(child.handlesOrientationChangeFromDescendant(orientation));
}
+ @Test
+ @EnableFlags(Flags.FLAG_ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION)
+ public void testAddLocalInsets_addsFlagsFromProvider() {
+ final Task rootTask = createTask(mDisplayContent);
+ final Task task = createTaskInRootTask(rootTask, 0 /* userId */);
+
+ final Binder owner = new Binder();
+ Rect insetsRect = new Rect(0, 200, 1080, 700);
+ final int flags = FLAG_FORCE_CONSUMING;
+ final InsetsFrameProvider provider =
+ new InsetsFrameProvider(owner, 1, WindowInsets.Type.captionBar())
+ .setArbitraryRectangle(insetsRect)
+ .setFlags(flags);
+ task.addLocalInsetsFrameProvider(provider, owner);
+
+ final int sourceFlags = task.mLocalInsetsSources.get(provider.getId()).getFlags();
+ assertEquals(flags, sourceFlags);
+ }
+
private static void addLocalInsets(WindowContainer wc) {
final Binder owner = new Binder();
Rect genericOverlayInsetsRect1 = new Rect(0, 200, 1080, 700);
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
index d3504cc..fb81a52 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowOrganizerTests.java
@@ -30,6 +30,7 @@
import static android.content.pm.ActivityInfo.SCREEN_ORIENTATION_UNSPECIFIED;
import static android.content.res.Configuration.SCREEN_HEIGHT_DP_UNDEFINED;
import static android.content.res.Configuration.SCREEN_WIDTH_DP_UNDEFINED;
+import static android.view.InsetsSource.FLAG_FORCE_CONSUMING;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION;
import static android.window.DisplayAreaOrganizer.FEATURE_VENDOR_FIRST;
@@ -75,10 +76,12 @@
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
+import android.platform.test.annotations.EnableFlags;
import android.platform.test.annotations.Presubmit;
import android.util.ArrayMap;
import android.util.Rational;
import android.view.Display;
+import android.view.InsetsSource;
import android.view.SurfaceControl;
import android.view.WindowInsets;
import android.window.ITaskFragmentOrganizer;
@@ -904,7 +907,8 @@
0 /* index */,
WindowInsets.Type.systemOverlays(),
new Rect(0, 0, 1080, 200),
- null /* boundingRects */);
+ null /* boundingRects */,
+ 0 /* flags */);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
assertThat(navigationBarInsetsReceiverTask.mLocalInsetsSources
@@ -930,7 +934,8 @@
0 /* index */,
WindowInsets.Type.systemOverlays(),
new Rect(0, 0, 1080, 200),
- boundingRects);
+ boundingRects,
+ 0 /* flags */);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
assertArrayEquals(boundingRects, navigationBarInsetsReceiverTask.mLocalInsetsSources
@@ -938,6 +943,30 @@
}
@Test
+ @EnableFlags(Flags.FLAG_ENABLE_CAPTION_COMPAT_INSET_FORCE_CONSUMPTION)
+ public void testAddInsetsSource_withFlags() {
+ final Task rootTask = createTask(mDisplayContent);
+
+ final Task insetsReceiverTask = createTaskInRootTask(rootTask, 0);
+ insetsReceiverTask.getConfiguration().windowConfiguration
+ .setBounds(new Rect(0, 200, 1080, 700));
+
+ final @InsetsSource.Flags int flags = FLAG_FORCE_CONSUMING;
+ final WindowContainerTransaction wct = new WindowContainerTransaction();
+ wct.addInsetsSource(
+ insetsReceiverTask.mRemoteToken.toWindowContainerToken(),
+ new Binder(),
+ 0 /* index */,
+ WindowInsets.Type.systemOverlays(),
+ new Rect(0, 0, 1080, 200),
+ null /* boundingRects */,
+ flags);
+ mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
+
+ assertEquals(flags, insetsReceiverTask.mLocalInsetsSources.valueAt(0).getFlags());
+ }
+
+ @Test
public void testRemoveInsetsSource() {
final Task rootTask = createTask(mDisplayContent);
@@ -952,7 +981,8 @@
0 /* index */,
WindowInsets.Type.systemOverlays(),
new Rect(0, 0, 1080, 200),
- null /* boundingRects */);
+ null /* boundingRects */,
+ 0 /* flags */);
mWm.mAtmService.mWindowOrganizerController.applyTransaction(wct);
final WindowContainerTransaction wct2 = new WindowContainerTransaction();