summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Antony Sargent <asargent@google.com> 2023-04-12 10:40:19 -0700
committer Antony Sargent <asargent@google.com> 2023-04-25 11:27:50 -0700
commit5db377ff53b84a2f55364bb4edfed8591a428463 (patch)
tree8977c2d060d9d9aed9a5cbb447633714af1c4cc8
parent0c71d0594f65fdd1af7b4b5f504e441e4bb398bb (diff)
Fix how we send flag changes to mDwpcHelper in relayoutWindow
We were accidentally conflating the exclusive OR bitmask of which flags have changed, and the flag values themselves. This was causing two problems: (1) if a flag like FLAG_SECURE is added early in an Activity lifecycle such as in onCreate, the first layout happens with the flag present and therefore it wouldn't be included in the exclusive OR bitmask value sent to DisplayWindowPolicyController (which was expecting the flag value itself). (2) If a flag happened to have been removed, it would end up in the exclusive OR bitmask and get passed to DisplayWindowPolicyController, which would think that flag is present, not removed. Fixes: 261991662 Test: atest WmTests:WindowManagerServiceTests Change-Id: I18c359665264e689fcecea6428e3b45dc6337983
-rw-r--r--services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java4
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java26
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java122
3 files changed, 142 insertions, 10 deletions
diff --git a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java
index 1fb97f97f421..2fb98690f661 100644
--- a/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java
+++ b/services/core/java/com/android/server/wm/DisplayWindowPolicyControllerHelper.java
@@ -114,7 +114,7 @@ class DisplayWindowPolicyControllerHelper {
* @see DisplayWindowPolicyController#keepActivityOnWindowFlagsChanged(ActivityInfo, int, int)
*/
boolean keepActivityOnWindowFlagsChanged(ActivityInfo aInfo, int flagChanges,
- int privateFlagChanges) {
+ int privateFlagChanges, int flagValues, int privateFlagValues) {
if (mDisplayWindowPolicyController == null) {
return true;
}
@@ -125,7 +125,7 @@ class DisplayWindowPolicyControllerHelper {
}
return mDisplayWindowPolicyController.keepActivityOnWindowFlagsChanged(
- aInfo, flagChanges, privateFlagChanges);
+ aInfo, flagValues, privateFlagValues);
}
/** Update the top activity and the uids of non-finishing activity */
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 40b8274d4e51..6edf871d6d8d 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -2290,14 +2290,24 @@ public class WindowManagerService extends IWindowManager.Stub
winAnimator.setColorSpaceAgnosticLocked((win.mAttrs.privateFlags
& WindowManager.LayoutParams.PRIVATE_FLAG_COLOR_SPACE_AGNOSTIC) != 0);
}
- if (win.mActivityRecord != null
- && !displayContent.mDwpcHelper.keepActivityOnWindowFlagsChanged(
- win.mActivityRecord.info, flagChanges, privateFlagChanges)) {
- mH.sendMessage(mH.obtainMessage(H.REPARENT_TASK_TO_DEFAULT_DISPLAY,
- win.mActivityRecord.getTask()));
- Slog.w(TAG_WM, "Activity " + win.mActivityRecord + " window flag changed,"
- + " can't remain on display " + displayContent.getDisplayId());
- return 0;
+ // See if the DisplayWindowPolicyController wants to keep the activity on the window
+ if (displayContent.mDwpcHelper.hasController()
+ && win.mActivityRecord != null && (!win.mRelayoutCalled || flagChanges != 0
+ || privateFlagChanges != 0)) {
+ int newOrChangedFlags = !win.mRelayoutCalled ? win.mAttrs.flags : flagChanges;
+ int newOrChangedPrivateFlags =
+ !win.mRelayoutCalled ? win.mAttrs.privateFlags : privateFlagChanges;
+
+ if (!displayContent.mDwpcHelper.keepActivityOnWindowFlagsChanged(
+ win.mActivityRecord.info, newOrChangedFlags, newOrChangedPrivateFlags,
+ win.mAttrs.flags,
+ win.mAttrs.privateFlags)) {
+ mH.sendMessage(mH.obtainMessage(H.REPARENT_TASK_TO_DEFAULT_DISPLAY,
+ win.mActivityRecord.getTask()));
+ Slog.w(TAG_WM, "Activity " + win.mActivityRecord + " window flag changed,"
+ + " can't remain on display " + displayContent.getDisplayId());
+ return 0;
+ }
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
index ba6b3b6c9378..58bf184994e4 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java
@@ -27,6 +27,7 @@ import static android.hardware.display.DisplayManager.VIRTUAL_DISPLAY_FLAG_TRUST
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.Display.FLAG_OWN_FOCUS;
import static android.view.WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;
+import static android.view.WindowManager.LayoutParams.FLAG_SECURE;
import static android.view.WindowManager.LayoutParams.INPUT_FEATURE_SPY;
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
import static android.view.WindowManager.LayoutParams.PRIVATE_FLAG_TRUSTED_OVERLAY;
@@ -65,6 +66,7 @@ import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
+import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.graphics.Point;
import android.graphics.Rect;
@@ -89,6 +91,7 @@ import android.view.SurfaceControl;
import android.view.View;
import android.view.WindowInsets;
import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams;
import android.window.ClientWindowFrames;
import android.window.ScreenCapture;
import android.window.WindowContainerToken;
@@ -101,6 +104,7 @@ import com.android.compatibility.common.util.AdoptShellPermissionsRule;
import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.ArgumentCaptor;
/**
* Build/Install/Run:
@@ -272,6 +276,124 @@ public class WindowManagerServiceTests extends WindowTestsBase {
}
@Test
+ public void testRelayout_firstLayout_dwpcHelperCalledWithCorrectFlags() {
+ // When doing the first layout, the initial flags should be reported as changed to
+ // keepActivityOnWindowFlagsChanged.
+ testRelayoutFlagChanges(
+ /*firstRelayout=*/ true,
+ /*startFlags=*/ FLAG_SECURE,
+ /*startPrivateFlags=*/ PRIVATE_FLAG_TRUSTED_OVERLAY,
+ /*newFlags=*/ FLAG_SECURE,
+ /*newPrivateFlags=*/ PRIVATE_FLAG_TRUSTED_OVERLAY,
+ /*expectedChangedFlags=*/ FLAG_SECURE,
+ /*expectedChangedPrivateFlags=*/ PRIVATE_FLAG_TRUSTED_OVERLAY,
+ /*expectedFlagsValue=*/ FLAG_SECURE,
+ /*expectedPrivateFlagsValue=*/ PRIVATE_FLAG_TRUSTED_OVERLAY);
+ }
+
+ @Test
+ public void testRelayout_secondLayoutFlagAdded_dwpcHelperCalledWithCorrectFlags() {
+ testRelayoutFlagChanges(
+ /*firstRelayout=*/ false,
+ /*startFlags=*/ 0,
+ /*startPrivateFlags=*/ 0,
+ /*newFlags=*/ FLAG_SECURE,
+ /*newPrivateFlags=*/ 0,
+ /*expectedChangedFlags=*/ FLAG_SECURE,
+ /*expectedChangedPrivateFlags=*/ 0,
+ /*expectedFlagsValue=*/ FLAG_SECURE,
+ /*expectedPrivateFlagsValue=*/ 0);
+ }
+
+ @Test
+ public void testRelayout_secondLayoutMultipleFlagsAddOne_dwpcHelperCalledWithCorrectFlags() {
+ testRelayoutFlagChanges(
+ /*firstRelayout=*/ false,
+ /*startFlags=*/ FLAG_NOT_FOCUSABLE,
+ /*startPrivateFlags=*/ 0,
+ /*newFlags=*/ FLAG_SECURE | FLAG_NOT_FOCUSABLE,
+ /*newPrivateFlags=*/ 0,
+ /*expectedChangedFlags=*/ FLAG_SECURE,
+ /*expectedChangedPrivateFlags=*/ 0,
+ /*expectedFlagsValue=*/ FLAG_SECURE | FLAG_NOT_FOCUSABLE,
+ /*expectedPrivateFlagsValue=*/ 0);
+ }
+
+ @Test
+ public void testRelayout_secondLayoutPrivateFlagAdded_dwpcHelperCalledWithCorrectFlags() {
+ testRelayoutFlagChanges(
+ /*firstRelayout=*/ false,
+ /*startFlags=*/ 0,
+ /*startPrivateFlags=*/ 0,
+ /*newFlags=*/ 0,
+ /*newPrivateFlags=*/ PRIVATE_FLAG_TRUSTED_OVERLAY,
+ /*expectedChangedFlags=*/ 0,
+ /*expectedChangedPrivateFlags=*/ PRIVATE_FLAG_TRUSTED_OVERLAY,
+ /*expectedFlagsValue=*/ 0,
+ /*expectedPrivateFlagsValue=*/ PRIVATE_FLAG_TRUSTED_OVERLAY);
+ }
+
+ @Test
+ public void testRelayout_secondLayoutFlagsRemoved_dwpcHelperCalledWithCorrectFlags() {
+ testRelayoutFlagChanges(
+ /*firstRelayout=*/ false,
+ /*startFlags=*/ FLAG_SECURE,
+ /*startPrivateFlags=*/ PRIVATE_FLAG_TRUSTED_OVERLAY,
+ /*newFlags=*/ 0,
+ /*newPrivateFlags=*/ 0,
+ /*expectedChangedFlags=*/ FLAG_SECURE,
+ /*expectedChangedPrivateFlags=*/ PRIVATE_FLAG_TRUSTED_OVERLAY,
+ /*expectedFlagsValue=*/ 0,
+ /*expectedPrivateFlagsValue=*/ 0);
+ }
+
+ // Helper method to test relayout of a window, either for the initial layout, or a subsequent
+ // one, and makes sure that the flags and private flags changes and final values are properly
+ // reported to mDwpcHelper.keepActivityOnWindowFlagsChanged.
+ private void testRelayoutFlagChanges(boolean firstRelayout, int startFlags,
+ int startPrivateFlags, int newFlags, int newPrivateFlags, int expectedChangedFlags,
+ int expectedChangedPrivateFlags, int expectedFlagsValue,
+ int expectedPrivateFlagsValue) {
+ final WindowState win = createWindow(null, TYPE_BASE_APPLICATION, "appWin");
+ win.mRelayoutCalled = !firstRelayout;
+ mWm.mWindowMap.put(win.mClient.asBinder(), win);
+ spyOn(mDisplayContent.mDwpcHelper);
+ when(mDisplayContent.mDwpcHelper.hasController()).thenReturn(true);
+
+ win.mAttrs.flags = startFlags;
+ win.mAttrs.privateFlags = startPrivateFlags;
+
+ LayoutParams newParams = new LayoutParams();
+ newParams.copyFrom(win.mAttrs);
+ newParams.flags = newFlags;
+ newParams.privateFlags = newPrivateFlags;
+
+ int seq = 1;
+ if (!firstRelayout) {
+ win.mRelayoutSeq = 1;
+ seq = 2;
+ }
+ mWm.relayoutWindow(win.mSession, win.mClient, newParams, 100, 200, View.VISIBLE, 0, seq,
+ 0, new ClientWindowFrames(), new MergedConfiguration(),
+ new SurfaceControl(), new InsetsState(), new InsetsSourceControl.Array(),
+ new Bundle());
+
+ ArgumentCaptor<Integer> changedFlags = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<Integer> changedPrivateFlags = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<Integer> flagsValue = ArgumentCaptor.forClass(Integer.class);
+ ArgumentCaptor<Integer> privateFlagsValue = ArgumentCaptor.forClass(Integer.class);
+
+ verify(mDisplayContent.mDwpcHelper).keepActivityOnWindowFlagsChanged(
+ any(ActivityInfo.class), changedFlags.capture(), changedPrivateFlags.capture(),
+ flagsValue.capture(), privateFlagsValue.capture());
+
+ assertThat(changedFlags.getValue()).isEqualTo(expectedChangedFlags);
+ assertThat(changedPrivateFlags.getValue()).isEqualTo(expectedChangedPrivateFlags);
+ assertThat(flagsValue.getValue()).isEqualTo(expectedFlagsValue);
+ assertThat(privateFlagsValue.getValue()).isEqualTo(expectedPrivateFlagsValue);
+ }
+
+ @Test
public void testMoveWindowTokenToDisplay_NullToken_DoNothing() {
mWm.moveWindowTokenToDisplay(null, mDisplayContent.getDisplayId());