[RESTRICT AUTOMERGE] Send WindowContext config only when Display is active
WMS may provide stale configuration value when secondary display is off. This CL makes WindowContext only receives Configuration updates if the display of associated WindowContainer is not suspended. Test: atest WindowContextListenerControllerTests Test: atest InputMethodMenuControllerTest Bug: 198965093 Change-Id: I3c2871823f1b104f89bb801f3bf5ecef01966bb3
This commit is contained in:
@@ -44,6 +44,8 @@ import static android.view.Display.FLAG_PRIVATE;
|
|||||||
import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
|
import static android.view.Display.FLAG_SHOULD_SHOW_SYSTEM_DECORATIONS;
|
||||||
import static android.view.Display.INVALID_DISPLAY;
|
import static android.view.Display.INVALID_DISPLAY;
|
||||||
import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
|
import static android.view.Display.REMOVE_MODE_DESTROY_CONTENT;
|
||||||
|
import static android.view.Display.STATE_UNKNOWN;
|
||||||
|
import static android.view.Display.isSuspendedState;
|
||||||
import static android.view.InsetsState.ITYPE_IME;
|
import static android.view.InsetsState.ITYPE_IME;
|
||||||
import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
|
import static android.view.InsetsState.ITYPE_LEFT_GESTURES;
|
||||||
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
|
import static android.view.InsetsState.ITYPE_NAVIGATION_BAR;
|
||||||
@@ -322,11 +324,6 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
|||||||
*/
|
*/
|
||||||
private Rect mLastMirroredDisplayAreaBounds = null;
|
private Rect mLastMirroredDisplayAreaBounds = null;
|
||||||
|
|
||||||
/**
|
|
||||||
* The last state of the display.
|
|
||||||
*/
|
|
||||||
private int mLastDisplayState;
|
|
||||||
|
|
||||||
// Contains all IME window containers. Note that the z-ordering of the IME windows will depend
|
// Contains all IME window containers. Note that the z-ordering of the IME windows will depend
|
||||||
// on the IME target. We mainly have this container grouping so we can keep track of all the IME
|
// on the IME target. We mainly have this container grouping so we can keep track of all the IME
|
||||||
// window containers together and move them in-sync if/when needed. We use a subclass of
|
// window containers together and move them in-sync if/when needed. We use a subclass of
|
||||||
@@ -5623,12 +5620,13 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
|||||||
void onDisplayChanged() {
|
void onDisplayChanged() {
|
||||||
mDisplay.getRealSize(mTmpDisplaySize);
|
mDisplay.getRealSize(mTmpDisplaySize);
|
||||||
setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
|
setBounds(0, 0, mTmpDisplaySize.x, mTmpDisplaySize.y);
|
||||||
|
final int lastDisplayState = mDisplayInfo.state;
|
||||||
updateDisplayInfo();
|
updateDisplayInfo();
|
||||||
|
|
||||||
// The window policy is responsible for stopping activities on the default display.
|
// The window policy is responsible for stopping activities on the default display.
|
||||||
final int displayId = mDisplay.getDisplayId();
|
final int displayId = mDisplay.getDisplayId();
|
||||||
|
final int displayState = mDisplayInfo.state;
|
||||||
if (displayId != DEFAULT_DISPLAY) {
|
if (displayId != DEFAULT_DISPLAY) {
|
||||||
final int displayState = mDisplay.getState();
|
|
||||||
if (displayState == Display.STATE_OFF) {
|
if (displayState == Display.STATE_OFF) {
|
||||||
mOffTokenAcquirer.acquire(mDisplayId);
|
mOffTokenAcquirer.acquire(mDisplayId);
|
||||||
} else if (displayState == Display.STATE_ON) {
|
} else if (displayState == Display.STATE_ON) {
|
||||||
@@ -5637,12 +5635,18 @@ class DisplayContent extends RootDisplayArea implements WindowManagerPolicy.Disp
|
|||||||
ProtoLog.v(WM_DEBUG_LAYER_MIRRORING,
|
ProtoLog.v(WM_DEBUG_LAYER_MIRRORING,
|
||||||
"Display %d state is now (%d), so update layer mirroring?",
|
"Display %d state is now (%d), so update layer mirroring?",
|
||||||
mDisplayId, displayState);
|
mDisplayId, displayState);
|
||||||
if (mLastDisplayState != displayState) {
|
if (lastDisplayState != displayState) {
|
||||||
// If state is on due to surface being added, then start layer mirroring.
|
// If state is on due to surface being added, then start layer mirroring.
|
||||||
// If state is off due to surface being removed, then stop layer mirroring.
|
// If state is off due to surface being removed, then stop layer mirroring.
|
||||||
updateMirroring();
|
updateMirroring();
|
||||||
}
|
}
|
||||||
mLastDisplayState = displayState;
|
}
|
||||||
|
// Dispatch pending Configuration to WindowContext if the associated display changes to
|
||||||
|
// un-suspended state from suspended.
|
||||||
|
if (isSuspendedState(lastDisplayState)
|
||||||
|
&& !isSuspendedState(displayState) && displayState != STATE_UNKNOWN) {
|
||||||
|
mWmService.mWindowContextListenerController
|
||||||
|
.dispatchPendingConfigurationIfNeeded(mDisplayId);
|
||||||
}
|
}
|
||||||
mWmService.requestTraversal();
|
mWmService.requestTraversal();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,9 @@
|
|||||||
package com.android.server.wm;
|
package com.android.server.wm;
|
||||||
|
|
||||||
import static android.view.Display.INVALID_DISPLAY;
|
import static android.view.Display.INVALID_DISPLAY;
|
||||||
|
import static android.view.Display.isSuspendedState;
|
||||||
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
|
import static android.view.WindowManager.LayoutParams.INVALID_WINDOW_TYPE;
|
||||||
|
import static android.window.WindowProviderService.isWindowProviderService;
|
||||||
|
|
||||||
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
|
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
|
||||||
import static com.android.internal.protolog.ProtoLogGroup.WM_ERROR;
|
import static com.android.internal.protolog.ProtoLogGroup.WM_ERROR;
|
||||||
@@ -80,7 +82,7 @@ class WindowContextListenerController {
|
|||||||
* @param options a bundle used to pass window-related options.
|
* @param options a bundle used to pass window-related options.
|
||||||
*/
|
*/
|
||||||
void registerWindowContainerListener(@NonNull IBinder clientToken,
|
void registerWindowContainerListener(@NonNull IBinder clientToken,
|
||||||
@NonNull WindowContainer container, int ownerUid, @WindowType int type,
|
@NonNull WindowContainer<?> container, int ownerUid, @WindowType int type,
|
||||||
@Nullable Bundle options) {
|
@Nullable Bundle options) {
|
||||||
WindowContextListenerImpl listener = mListeners.get(clientToken);
|
WindowContextListenerImpl listener = mListeners.get(clientToken);
|
||||||
if (listener == null) {
|
if (listener == null) {
|
||||||
@@ -103,6 +105,16 @@ class WindowContextListenerController {
|
|||||||
listener.unregister();
|
listener.unregister();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void dispatchPendingConfigurationIfNeeded(int displayId) {
|
||||||
|
for (int i = mListeners.size() - 1; i >= 0; --i) {
|
||||||
|
final WindowContextListenerImpl listener = mListeners.valueAt(i);
|
||||||
|
if (listener.getWindowContainer().getDisplayContent().getDisplayId() == displayId
|
||||||
|
&& listener.mHasPendingConfiguration) {
|
||||||
|
listener.reportConfigToWindowTokenClient();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Verifies if the caller is allowed to do the operation to the listener specified by
|
* Verifies if the caller is allowed to do the operation to the listener specified by
|
||||||
* {@code clientToken}.
|
* {@code clientToken}.
|
||||||
@@ -138,7 +150,7 @@ class WindowContextListenerController {
|
|||||||
return listener != null ? listener.mOptions : null;
|
return listener != null ? listener.mOptions : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Nullable WindowContainer getContainer(IBinder clientToken) {
|
@Nullable WindowContainer<?> getContainer(IBinder clientToken) {
|
||||||
final WindowContextListenerImpl listener = mListeners.get(clientToken);
|
final WindowContextListenerImpl listener = mListeners.get(clientToken);
|
||||||
return listener != null ? listener.mContainer : null;
|
return listener != null ? listener.mContainer : null;
|
||||||
}
|
}
|
||||||
@@ -163,7 +175,7 @@ class WindowContextListenerController {
|
|||||||
class WindowContextListenerImpl implements WindowContainerListener {
|
class WindowContextListenerImpl implements WindowContainerListener {
|
||||||
@NonNull private final IBinder mClientToken;
|
@NonNull private final IBinder mClientToken;
|
||||||
private final int mOwnerUid;
|
private final int mOwnerUid;
|
||||||
@NonNull private WindowContainer mContainer;
|
@NonNull private WindowContainer<?> mContainer;
|
||||||
/**
|
/**
|
||||||
* The options from {@link Context#createWindowContext(int, Bundle)}.
|
* The options from {@link Context#createWindowContext(int, Bundle)}.
|
||||||
* <p>It can be used for choosing the {@link DisplayArea} where the window context
|
* <p>It can be used for choosing the {@link DisplayArea} where the window context
|
||||||
@@ -177,7 +189,9 @@ class WindowContextListenerController {
|
|||||||
private int mLastReportedDisplay = INVALID_DISPLAY;
|
private int mLastReportedDisplay = INVALID_DISPLAY;
|
||||||
private Configuration mLastReportedConfig;
|
private Configuration mLastReportedConfig;
|
||||||
|
|
||||||
private WindowContextListenerImpl(IBinder clientToken, WindowContainer container,
|
private boolean mHasPendingConfiguration;
|
||||||
|
|
||||||
|
private WindowContextListenerImpl(IBinder clientToken, WindowContainer<?> container,
|
||||||
int ownerUid, @WindowType int type, @Nullable Bundle options) {
|
int ownerUid, @WindowType int type, @Nullable Bundle options) {
|
||||||
mClientToken = clientToken;
|
mClientToken = clientToken;
|
||||||
mContainer = Objects.requireNonNull(container);
|
mContainer = Objects.requireNonNull(container);
|
||||||
@@ -197,11 +211,11 @@ class WindowContextListenerController {
|
|||||||
|
|
||||||
/** TEST ONLY: returns the {@link WindowContainer} of the listener */
|
/** TEST ONLY: returns the {@link WindowContainer} of the listener */
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
WindowContainer getWindowContainer() {
|
WindowContainer<?> getWindowContainer() {
|
||||||
return mContainer;
|
return mContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void updateContainer(@NonNull WindowContainer newContainer) {
|
private void updateContainer(@NonNull WindowContainer<?> newContainer) {
|
||||||
Objects.requireNonNull(newContainer);
|
Objects.requireNonNull(newContainer);
|
||||||
|
|
||||||
if (mContainer.equals(newContainer)) {
|
if (mContainer.equals(newContainer)) {
|
||||||
@@ -246,12 +260,20 @@ class WindowContextListenerController {
|
|||||||
if (mDeathRecipient == null) {
|
if (mDeathRecipient == null) {
|
||||||
throw new IllegalStateException("Invalid client token: " + mClientToken);
|
throw new IllegalStateException("Invalid client token: " + mClientToken);
|
||||||
}
|
}
|
||||||
|
// If the display of window context associated window container is suspended, don't
|
||||||
if (mLastReportedConfig == null) {
|
// report the configuration update. Note that we still dispatch the configuration update
|
||||||
mLastReportedConfig = new Configuration();
|
// to WindowProviderService to make it compatible with Service#onConfigurationChanged.
|
||||||
|
// Service always receives #onConfigurationChanged callback regardless of display state.
|
||||||
|
if (!isWindowProviderService(mOptions)
|
||||||
|
&& isSuspendedState(mContainer.getDisplayContent().getDisplayInfo().state)) {
|
||||||
|
mHasPendingConfiguration = true;
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
final Configuration config = mContainer.getConfiguration();
|
final Configuration config = mContainer.getConfiguration();
|
||||||
final int displayId = mContainer.getDisplayContent().getDisplayId();
|
final int displayId = mContainer.getDisplayContent().getDisplayId();
|
||||||
|
if (mLastReportedConfig == null) {
|
||||||
|
mLastReportedConfig = new Configuration();
|
||||||
|
}
|
||||||
if (config.equals(mLastReportedConfig) && displayId == mLastReportedDisplay) {
|
if (config.equals(mLastReportedConfig) && displayId == mLastReportedDisplay) {
|
||||||
// No changes since last reported time.
|
// No changes since last reported time.
|
||||||
return;
|
return;
|
||||||
@@ -266,6 +288,7 @@ class WindowContextListenerController {
|
|||||||
} catch (RemoteException e) {
|
} catch (RemoteException e) {
|
||||||
ProtoLog.w(WM_ERROR, "Could not report config changes to the window token client.");
|
ProtoLog.w(WM_ERROR, "Could not report config changes to the window token client.");
|
||||||
}
|
}
|
||||||
|
mHasPendingConfiguration = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -283,7 +306,7 @@ class WindowContextListenerController {
|
|||||||
// If we cannot obtain the DisplayContent, the DisplayContent may also be removed.
|
// If we cannot obtain the DisplayContent, the DisplayContent may also be removed.
|
||||||
// We should proceed the removal process.
|
// We should proceed the removal process.
|
||||||
if (dc != null) {
|
if (dc != null) {
|
||||||
final DisplayArea da = dc.findAreaForToken(windowToken);
|
final DisplayArea<?> da = dc.findAreaForToken(windowToken);
|
||||||
updateContainer(da);
|
updateContainer(da);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,6 +17,7 @@
|
|||||||
package com.android.server.wm;
|
package com.android.server.wm;
|
||||||
|
|
||||||
import static android.view.Display.DEFAULT_DISPLAY;
|
import static android.view.Display.DEFAULT_DISPLAY;
|
||||||
|
import static android.view.Display.STATE_ON;
|
||||||
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
|
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
|
||||||
|
|
||||||
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.doAnswer;
|
||||||
@@ -70,7 +71,7 @@ public class InputMethodMenuControllerTest extends WindowTestsBase {
|
|||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() throws Exception {
|
public void setUp() throws Exception {
|
||||||
// Let the Display to be created with the DualDisplay policy.
|
// Let the Display be created with the DualDisplay policy.
|
||||||
final DisplayAreaPolicy.Provider policyProvider =
|
final DisplayAreaPolicy.Provider policyProvider =
|
||||||
new DualDisplayAreaGroupPolicyTest.DualDisplayTestPolicyProvider();
|
new DualDisplayAreaGroupPolicyTest.DualDisplayTestPolicyProvider();
|
||||||
Mockito.doReturn(policyProvider).when(mWm).getDisplayAreaPolicyProvider();
|
Mockito.doReturn(policyProvider).when(mWm).getDisplayAreaPolicyProvider();
|
||||||
@@ -78,6 +79,7 @@ public class InputMethodMenuControllerTest extends WindowTestsBase {
|
|||||||
mController = new InputMethodMenuController(mock(InputMethodManagerService.class));
|
mController = new InputMethodMenuController(mock(InputMethodManagerService.class));
|
||||||
mSecondaryDisplay = new DualDisplayAreaGroupPolicyTest.DualDisplayContent
|
mSecondaryDisplay = new DualDisplayAreaGroupPolicyTest.DualDisplayContent
|
||||||
.Builder(mAtm, 1000, 1000).build();
|
.Builder(mAtm, 1000, 1000).build();
|
||||||
|
mSecondaryDisplay.getDisplayInfo().state = STATE_ON;
|
||||||
|
|
||||||
// Mock addWindowTokenWithOptions to create a test window token.
|
// Mock addWindowTokenWithOptions to create a test window token.
|
||||||
mIWindowManager = WindowManagerGlobal.getWindowManagerService();
|
mIWindowManager = WindowManagerGlobal.getWindowManagerService();
|
||||||
|
|||||||
@@ -17,22 +17,35 @@
|
|||||||
package com.android.server.wm;
|
package com.android.server.wm;
|
||||||
|
|
||||||
import static android.view.Display.DEFAULT_DISPLAY;
|
import static android.view.Display.DEFAULT_DISPLAY;
|
||||||
|
import static android.view.Display.STATE_OFF;
|
||||||
|
import static android.view.Display.STATE_ON;
|
||||||
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY;
|
import static android.view.WindowManager.LayoutParams.TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY;
|
||||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
||||||
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
|
import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD_DIALOG;
|
||||||
|
import static android.window.WindowProvider.KEY_IS_WINDOW_PROVIDER_SERVICE;
|
||||||
|
|
||||||
|
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spyOn;
|
||||||
|
|
||||||
import static com.google.common.truth.Truth.assertThat;
|
import static com.google.common.truth.Truth.assertThat;
|
||||||
|
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.Assert.assertEquals;
|
||||||
import static org.junit.Assert.assertFalse;
|
import static org.junit.Assert.assertFalse;
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.Assert.assertTrue;
|
||||||
|
import static org.mockito.ArgumentMatchers.any;
|
||||||
|
import static org.mockito.ArgumentMatchers.anyInt;
|
||||||
|
import static org.mockito.Mockito.doReturn;
|
||||||
|
import static org.mockito.Mockito.never;
|
||||||
|
import static org.mockito.Mockito.verify;
|
||||||
|
|
||||||
import android.app.IWindowToken;
|
import android.app.IWindowToken;
|
||||||
import android.content.res.Configuration;
|
import android.content.res.Configuration;
|
||||||
import android.graphics.Rect;
|
import android.graphics.Rect;
|
||||||
import android.os.Binder;
|
import android.os.Binder;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
import android.platform.test.annotations.Presubmit;
|
import android.platform.test.annotations.Presubmit;
|
||||||
|
import android.view.Display;
|
||||||
|
import android.view.DisplayInfo;
|
||||||
|
|
||||||
import androidx.test.filters.SmallTest;
|
import androidx.test.filters.SmallTest;
|
||||||
|
|
||||||
@@ -55,12 +68,15 @@ public class WindowContextListenerControllerTests extends WindowTestsBase {
|
|||||||
private static final int ANOTHER_UID = 1000;
|
private static final int ANOTHER_UID = 1000;
|
||||||
|
|
||||||
private final IBinder mClientToken = new Binder();
|
private final IBinder mClientToken = new Binder();
|
||||||
private WindowContainer mContainer;
|
private WindowContainer<?> mContainer;
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mController = new WindowContextListenerController();
|
mController = new WindowContextListenerController();
|
||||||
mContainer = createTestWindowToken(TYPE_APPLICATION_OVERLAY, mDisplayContent);
|
mContainer = createTestWindowToken(TYPE_APPLICATION_OVERLAY, mDisplayContent);
|
||||||
|
// Make display on to verify configuration propagation.
|
||||||
|
mDefaultDisplay.getDisplayInfo().state = STATE_ON;
|
||||||
|
mDisplayContent.getDisplayInfo().state = STATE_ON;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@@ -76,7 +92,7 @@ public class WindowContextListenerControllerTests extends WindowTestsBase {
|
|||||||
|
|
||||||
assertEquals(2, mController.mListeners.size());
|
assertEquals(2, mController.mListeners.size());
|
||||||
|
|
||||||
final WindowContainer container = createTestWindowToken(TYPE_APPLICATION_OVERLAY,
|
final WindowContainer<?> container = createTestWindowToken(TYPE_APPLICATION_OVERLAY,
|
||||||
mDefaultDisplay);
|
mDefaultDisplay);
|
||||||
mController.registerWindowContainerListener(mClientToken, container, -1,
|
mController.registerWindowContainerListener(mClientToken, container, -1,
|
||||||
TYPE_APPLICATION_OVERLAY, null /* options */);
|
TYPE_APPLICATION_OVERLAY, null /* options */);
|
||||||
@@ -89,6 +105,7 @@ public class WindowContextListenerControllerTests extends WindowTestsBase {
|
|||||||
assertEquals(container, listener.getWindowContainer());
|
assertEquals(container, listener.getWindowContainer());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@UseTestDisplay
|
||||||
@Test
|
@Test
|
||||||
public void testRegisterWindowContextListenerClientConfigPropagation() {
|
public void testRegisterWindowContextListenerClientConfigPropagation() {
|
||||||
final TestWindowTokenClient clientToken = new TestWindowTokenClient();
|
final TestWindowTokenClient clientToken = new TestWindowTokenClient();
|
||||||
@@ -107,7 +124,7 @@ public class WindowContextListenerControllerTests extends WindowTestsBase {
|
|||||||
assertEquals(mDisplayContent.mDisplayId, clientToken.mDisplayId);
|
assertEquals(mDisplayContent.mDisplayId, clientToken.mDisplayId);
|
||||||
|
|
||||||
// Update the WindowContainer.
|
// Update the WindowContainer.
|
||||||
final WindowContainer container = createTestWindowToken(TYPE_APPLICATION_OVERLAY,
|
final WindowContainer<?> container = createTestWindowToken(TYPE_APPLICATION_OVERLAY,
|
||||||
mDefaultDisplay);
|
mDefaultDisplay);
|
||||||
final Configuration config2 = container.getConfiguration();
|
final Configuration config2 = container.getConfiguration();
|
||||||
final Rect bounds2 = new Rect(0, 0, 20, 20);
|
final Rect bounds2 = new Rect(0, 0, 20, 20);
|
||||||
@@ -174,7 +191,7 @@ public class WindowContextListenerControllerTests extends WindowTestsBase {
|
|||||||
.setDisplayContent(mDefaultDisplay)
|
.setDisplayContent(mDefaultDisplay)
|
||||||
.setFromClientToken(true)
|
.setFromClientToken(true)
|
||||||
.build();
|
.build();
|
||||||
final DisplayArea da = windowContextCreatedToken.getDisplayArea();
|
final DisplayArea<?> da = windowContextCreatedToken.getDisplayArea();
|
||||||
|
|
||||||
mController.registerWindowContainerListener(mClientToken, windowContextCreatedToken,
|
mController.registerWindowContainerListener(mClientToken, windowContextCreatedToken,
|
||||||
TEST_UID, TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, null /* options */);
|
TEST_UID, TYPE_ACCESSIBILITY_MAGNIFICATION_OVERLAY, null /* options */);
|
||||||
@@ -192,11 +209,12 @@ public class WindowContextListenerControllerTests extends WindowTestsBase {
|
|||||||
// Let the Display to be created with the DualDisplay policy.
|
// Let the Display to be created with the DualDisplay policy.
|
||||||
final DisplayAreaPolicy.Provider policyProvider =
|
final DisplayAreaPolicy.Provider policyProvider =
|
||||||
new DualDisplayAreaGroupPolicyTest.DualDisplayTestPolicyProvider();
|
new DualDisplayAreaGroupPolicyTest.DualDisplayTestPolicyProvider();
|
||||||
Mockito.doReturn(policyProvider).when(mWm).getDisplayAreaPolicyProvider();
|
doReturn(policyProvider).when(mWm).getDisplayAreaPolicyProvider();
|
||||||
// Create a DisplayContent with dual RootDisplayArea
|
// Create a DisplayContent with dual RootDisplayArea
|
||||||
DualDisplayAreaGroupPolicyTest.DualDisplayContent dualDisplayContent =
|
DualDisplayAreaGroupPolicyTest.DualDisplayContent dualDisplayContent =
|
||||||
new DualDisplayAreaGroupPolicyTest.DualDisplayContent
|
new DualDisplayAreaGroupPolicyTest.DualDisplayContent
|
||||||
.Builder(mAtm, 1000, 1000).build();
|
.Builder(mAtm, 1000, 1000).build();
|
||||||
|
dualDisplayContent.getDisplayInfo().state = STATE_ON;
|
||||||
final DisplayArea.Tokens imeContainer = dualDisplayContent.getImeContainer();
|
final DisplayArea.Tokens imeContainer = dualDisplayContent.getImeContainer();
|
||||||
// Put the ImeContainer to the first sub-RootDisplayArea
|
// Put the ImeContainer to the first sub-RootDisplayArea
|
||||||
dualDisplayContent.mFirstRoot.placeImeContainer(imeContainer);
|
dualDisplayContent.mFirstRoot.placeImeContainer(imeContainer);
|
||||||
@@ -222,7 +240,62 @@ public class WindowContextListenerControllerTests extends WindowTestsBase {
|
|||||||
assertThat(mController.getContainer(mClientToken)).isEqualTo(imeContainer);
|
assertThat(mController.getContainer(mClientToken)).isEqualTo(imeContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
private class TestWindowTokenClient extends IWindowToken.Stub {
|
@Test
|
||||||
|
public void testConfigUpdateForSuspendedWindowContext() {
|
||||||
|
final TestWindowTokenClient mockToken = new TestWindowTokenClient();
|
||||||
|
spyOn(mockToken);
|
||||||
|
|
||||||
|
mContainer.getDisplayContent().getDisplayInfo().state = STATE_OFF;
|
||||||
|
|
||||||
|
final Configuration config1 = mContainer.getConfiguration();
|
||||||
|
final Rect bounds1 = new Rect(0, 0, 10, 10);
|
||||||
|
config1.windowConfiguration.setBounds(bounds1);
|
||||||
|
config1.densityDpi = 100;
|
||||||
|
mContainer.onRequestedOverrideConfigurationChanged(config1);
|
||||||
|
|
||||||
|
mController.registerWindowContainerListener(mockToken, mContainer, -1,
|
||||||
|
TYPE_APPLICATION_OVERLAY, null /* options */);
|
||||||
|
|
||||||
|
verify(mockToken, never()).onConfigurationChanged(any(), anyInt());
|
||||||
|
|
||||||
|
// Turn on the display and verify if the client receive the callback
|
||||||
|
Display display = mContainer.getDisplayContent().getDisplay();
|
||||||
|
spyOn(display);
|
||||||
|
Mockito.doAnswer(invocation -> {
|
||||||
|
final DisplayInfo info = mContainer.getDisplayContent().getDisplayInfo();
|
||||||
|
info.state = STATE_ON;
|
||||||
|
((DisplayInfo) invocation.getArgument(0)).copyFrom(info);
|
||||||
|
return null;
|
||||||
|
}).when(display).getDisplayInfo(any(DisplayInfo.class));
|
||||||
|
|
||||||
|
mContainer.getDisplayContent().onDisplayChanged();
|
||||||
|
|
||||||
|
assertThat(mockToken.mConfiguration).isEqualTo(config1);
|
||||||
|
assertThat(mockToken.mDisplayId).isEqualTo(mContainer.getDisplayContent().getDisplayId());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testReportConfigUpdateForSuspendedWindowProviderService() {
|
||||||
|
final TestWindowTokenClient clientToken = new TestWindowTokenClient();
|
||||||
|
final Bundle options = new Bundle();
|
||||||
|
options.putBoolean(KEY_IS_WINDOW_PROVIDER_SERVICE, true);
|
||||||
|
|
||||||
|
mContainer.getDisplayContent().getDisplayInfo().state = STATE_OFF;
|
||||||
|
|
||||||
|
final Configuration config1 = mContainer.getConfiguration();
|
||||||
|
final Rect bounds1 = new Rect(0, 0, 10, 10);
|
||||||
|
config1.windowConfiguration.setBounds(bounds1);
|
||||||
|
config1.densityDpi = 100;
|
||||||
|
mContainer.onRequestedOverrideConfigurationChanged(config1);
|
||||||
|
|
||||||
|
mController.registerWindowContainerListener(clientToken, mContainer, -1,
|
||||||
|
TYPE_APPLICATION_OVERLAY, options);
|
||||||
|
|
||||||
|
assertThat(clientToken.mConfiguration).isEqualTo(config1);
|
||||||
|
assertThat(clientToken.mDisplayId).isEqualTo(mDisplayContent.mDisplayId);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class TestWindowTokenClient extends IWindowToken.Stub {
|
||||||
private Configuration mConfiguration;
|
private Configuration mConfiguration;
|
||||||
private int mDisplayId;
|
private int mDisplayId;
|
||||||
private boolean mRemoved;
|
private boolean mRemoved;
|
||||||
|
|||||||
Reference in New Issue
Block a user