summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/app/WindowContext.java32
-rw-r--r--core/java/android/content/Context.java54
-rw-r--r--core/java/android/view/IWindowManager.aidl2
-rw-r--r--core/tests/coretests/AndroidManifest.xml3
-rw-r--r--core/tests/coretests/src/android/app/WindowContextTest.java152
-rw-r--r--services/core/java/com/android/server/inputmethod/InputMethodMenuController.java8
-rw-r--r--services/core/java/com/android/server/wm/WindowManagerService.java15
-rw-r--r--services/core/java/com/android/server/wm/WindowToken.java104
-rw-r--r--services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java24
9 files changed, 226 insertions, 168 deletions
diff --git a/core/java/android/app/WindowContext.java b/core/java/android/app/WindowContext.java
index 14ed414da9d0..cbe2995f2467 100644
--- a/core/java/android/app/WindowContext.java
+++ b/core/java/android/app/WindowContext.java
@@ -15,8 +15,7 @@
*/
package android.app;
-import static android.view.WindowManagerGlobal.ADD_OKAY;
-import static android.view.WindowManagerGlobal.ADD_TOO_MANY_TOKENS;
+import static android.view.WindowManagerImpl.createWindowContextWindowManager;
import android.annotation.NonNull;
import android.annotation.Nullable;
@@ -28,8 +27,8 @@ import android.os.IBinder;
import android.os.RemoteException;
import android.view.Display;
import android.view.IWindowManager;
+import android.view.WindowManager;
import android.view.WindowManagerGlobal;
-import android.view.WindowManagerImpl;
import com.android.internal.annotations.VisibleForTesting;
@@ -46,10 +45,10 @@ import java.lang.ref.Reference;
*/
@UiContext
public class WindowContext extends ContextWrapper {
- private final WindowManagerImpl mWindowManager;
+ private final WindowManager mWindowManager;
private final IWindowManager mWms;
private final WindowTokenClient mToken;
- private boolean mOwnsToken;
+ private boolean mListenerRegistered;
/**
* Default constructor. Will generate a {@link WindowTokenClient} and attach this context to
@@ -86,25 +85,14 @@ public class WindowContext extends ContextWrapper {
mToken.attachContext(this);
- mWindowManager = new WindowManagerImpl(this);
- mWindowManager.setDefaultToken(mToken);
+ mWindowManager = createWindowContextWindowManager(this);
- int result;
try {
- // Register the token with WindowManager. This will also call back with the current
- // config back to the client.
- result = mWms.addWindowTokenWithOptions(
- mToken, type, getDisplayId(), options, getPackageName());
+ mListenerRegistered = mWms.registerWindowContextListener(mToken, type, getDisplayId(),
+ options);
} catch (RemoteException e) {
- mOwnsToken = false;
throw e.rethrowFromSystemServer();
}
- if (result == ADD_TOO_MANY_TOKENS) {
- throw new UnsupportedOperationException("createWindowContext failed! Too many unused "
- + "window contexts. Please see Context#createWindowContext documentation for "
- + "detail.");
- }
- mOwnsToken = result == ADD_OKAY;
Reference.reachabilityFence(this);
}
@@ -131,10 +119,10 @@ public class WindowContext extends ContextWrapper {
/** Used for test to invoke because we can't invoke finalize directly. */
@VisibleForTesting
public void release() {
- if (mOwnsToken) {
+ if (mListenerRegistered) {
+ mListenerRegistered = false;
try {
- mWms.removeWindowToken(mToken, getDisplayId());
- mOwnsToken = false;
+ mWms.unregisterWindowContextListener(mToken);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
diff --git a/core/java/android/content/Context.java b/core/java/android/content/Context.java
index 987de3fca6b1..5d28216756ae 100644
--- a/core/java/android/content/Context.java
+++ b/core/java/android/content/Context.java
@@ -75,6 +75,7 @@ import android.view.Display;
import android.view.DisplayAdjustments;
import android.view.View;
import android.view.ViewDebug;
+import android.view.ViewGroup.LayoutParams;
import android.view.WindowManager;
import android.view.WindowManager.LayoutParams.WindowType;
import android.view.autofill.AutofillManager.AutofillClient;
@@ -6110,18 +6111,19 @@ public abstract class Context {
*
* // WindowManager.LayoutParams initialization
* ...
+ * // The types used in addView and createWindowContext must match.
* mParams.type = TYPE_APPLICATION_OVERLAY;
* ...
*
- * mWindowContext.getSystemService(WindowManager.class).addView(overlayView, mParams);
+ * windowContext.getSystemService(WindowManager.class).addView(overlayView, mParams);
* </pre>
*
* <p>
- * This context's configuration and resources are adjusted to a display area where the windows
- * with provided type will be added. <b>Note that all windows associated with the same context
- * will have an affinity and can only be moved together between different displays or areas on a
- * display.</b> If there is a need to add different window types, or non-associated windows,
- * separate Contexts should be used.
+ * This context's configuration and resources are adjusted to an area of the display where
+ * the windows with provided type will be added. <b>Note that all windows associated with the
+ * same context will have an affinity and can only be moved together between different displays
+ * or areas on a display.</b> If there is a need to add different window types, or
+ * non-associated windows, separate Contexts should be used.
* </p>
* <p>
* Creating a window context is an expensive operation. Misuse of this API may lead to a huge
@@ -6129,7 +6131,43 @@ public abstract class Context {
* An approach is to create one window context with specific window type and display and
* use it everywhere it's needed.
* </p>
+ * <p>
+ * After {@link Build.VERSION_CODES#S}, window context provides the capability to receive
+ * configuration changes for existing token by overriding the
+ * {@link android.view.WindowManager.LayoutParams#token token} of the
+ * {@link android.view.WindowManager.LayoutParams} passed in
+ * {@link WindowManager#addView(View, LayoutParams)}. This is useful when an application needs
+ * to attach its window to an existing activity for window token sharing use-case.
+ * </p>
+ * <p>
+ * Note that the window context in {@link Build.VERSION_CODES#R} didn't have this
+ * capability. This is a no-op for the window context in {@link Build.VERSION_CODES#R}.
+ * </p>
+ * Below is sample code to <b>attach an existing token to a window context:</b>
+ * <pre class="prettyprint">
+ * final DisplayManager dm = anyContext.getSystemService(DisplayManager.class);
+ * final Display primaryDisplay = dm.getDisplay(DEFAULT_DISPLAY);
+ * final Context windowContext = anyContext.createWindowContext(primaryDisplay,
+ * TYPE_APPLICATION, null);
+ *
+ * // Get an existing token.
+ * final IBinder existingToken = activity.getWindow().getAttributes().token;
+ *
+ * // The types used in addView() and createWindowContext() must match.
+ * final WindowManager.LayoutParams params = new WindowManager.LayoutParams(TYPE_APPLICATION);
+ * params.token = existingToken;
*
+ * // After WindowManager#addView(), the server side will extract the provided token from
+ * // LayoutParams#token (existingToken in the sample code), and switch to propagate
+ * // configuration changes from the node associated with the provided token.
+ * windowContext.getSystemService(WindowManager.class).addView(overlayView, mParams);
+ * </pre>
+ * <p>
+ * Note that using {@link android.app.Application} or {@link android.app.Service} context for
+ * UI-related queries may result in layout or continuity issues on devices with variable screen
+ * sizes (e.g. foldables) or in multi-window modes, since these non-UI contexts may not reflect
+ * the {@link Configuration} changes for the visual container.
+ * </p>
* @param type Window type in {@link WindowManager.LayoutParams}
* @param options A bundle used to pass window-related options
* @return A {@link Context} that can be used to create
@@ -6141,9 +6179,7 @@ public abstract class Context {
* @see #LAYOUT_INFLATER_SERVICE
* @see #WALLPAPER_SERVICE
* @throws UnsupportedOperationException if this {@link Context} does not attach to a display,
- * such as {@link android.app.Application Application} or {@link android.app.Service Service},
- * or the current number of window contexts without adding any view by
- * {@link WindowManager#addView} <b>exceeds five</b>.
+ * such as {@link android.app.Application Application} or {@link android.app.Service Service}.
*/
@UiContext
@NonNull
diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl
index 784341153d69..ae8afca9b5c5 100644
--- a/core/java/android/view/IWindowManager.aidl
+++ b/core/java/android/view/IWindowManager.aidl
@@ -117,7 +117,7 @@ interface IWindowManager
// These can only be called when holding the MANAGE_APP_TOKENS permission.
void setEventDispatching(boolean enabled);
- /** @return {@code true} if this binder is a registered window token. */
+ /** Returns {@code true} if this binder is a registered window token. */
boolean isWindowToken(in IBinder binder);
/**
* Adds window token for a given type.
diff --git a/core/tests/coretests/AndroidManifest.xml b/core/tests/coretests/AndroidManifest.xml
index bb826deb4eff..f31233b29cd0 100644
--- a/core/tests/coretests/AndroidManifest.xml
+++ b/core/tests/coretests/AndroidManifest.xml
@@ -147,6 +147,9 @@
<!-- WindowMetricsTest permissions -->
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" />
+ <!-- WindowContextTest permissions -->
+ <uses-permission android:name="android.permission.MANAGE_APP_TOKENS" />
+
<!-- Allow use of PendingIntent.getIntent() -->
<uses-permission android:name="android.permission.GET_INTENT_SENDER_INTENT" />
diff --git a/core/tests/coretests/src/android/app/WindowContextTest.java b/core/tests/coretests/src/android/app/WindowContextTest.java
index dcf5e025f82b..da7304efbd3d 100644
--- a/core/tests/coretests/src/android/app/WindowContextTest.java
+++ b/core/tests/coretests/src/android/app/WindowContextTest.java
@@ -18,29 +18,38 @@ package android.app;
import static android.view.Display.DEFAULT_DISPLAY;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
+import static android.view.WindowManager.LayoutParams.TYPE_INPUT_METHOD;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import android.content.Context;
+import android.content.Intent;
import android.hardware.display.DisplayManager;
+import android.os.Binder;
import android.os.IBinder;
import android.platform.test.annotations.Presubmit;
import android.view.Display;
import android.view.IWindowManager;
import android.view.View;
import android.view.WindowManager;
+import android.view.WindowManager.LayoutParams.WindowType;
import android.view.WindowManagerGlobal;
import android.view.WindowManagerImpl;
import androidx.test.filters.SmallTest;
import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.rule.ActivityTestRule;
import androidx.test.runner.AndroidJUnit4;
+import org.junit.Rule;
import org.junit.Test;
import org.junit.runner.RunWith;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.TimeUnit;
+
/**
* Tests for {@link WindowContext}
*
@@ -54,41 +63,156 @@ import org.junit.runner.RunWith;
@SmallTest
@Presubmit
public class WindowContextTest {
+ @Rule
+ public ActivityTestRule<EmptyActivity> mActivityRule =
+ new ActivityTestRule<>(EmptyActivity.class, false /* initialTouchMode */,
+ false /* launchActivity */);
+
private final Instrumentation mInstrumentation = InstrumentationRegistry.getInstrumentation();
private final WindowContext mWindowContext = createWindowContext();
+ private final IWindowManager mWms = WindowManagerGlobal.getWindowManagerService();
@Test
- public void testWindowContextRelease_doRemoveWindowToken() throws Throwable {
+ public void testCreateWindowContextWindowManagerAttachClientToken() {
+ final WindowManager windowContextWm = WindowManagerImpl
+ .createWindowContextWindowManager(mWindowContext);
+ final WindowManager.LayoutParams params =
+ new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
+ mInstrumentation.runOnMainSync(() -> {
+ final View view = new View(mWindowContext);
+ windowContextWm.addView(view, params);
+ });
+
+ assertEquals(mWindowContext.getWindowContextToken(), params.mWindowContextToken);
+ }
+
+ /**
+ * Test the {@link WindowContext} life cycle behavior to add a new window token:
+ * <ul>
+ * <li>The window token is created before adding the first view.</li>
+ * <li>The window token is registered after adding the first view.</li>
+ * <li>The window token is removed after {@link WindowContext}'s release.</li>
+ * </ul>
+ */
+ @Test
+ public void testCreateWindowContextNewTokenFromClient() throws Throwable {
final IBinder token = mWindowContext.getWindowContextToken();
- final IWindowManager wms = WindowManagerGlobal.getWindowManagerService();
- assertTrue("Token must be registered to WMS", wms.isWindowToken(token));
+ // Test that the window token is not created yet.
+ assertFalse("Token must not be registered until adding the first window",
+ mWms.isWindowToken(token));
+
+ final WindowManager.LayoutParams params =
+ new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
+ final View testView = new View(mWindowContext);
+
+ final CountDownLatch latch = new CountDownLatch(1);
+ testView.addOnAttachStateChangeListener(new View.OnAttachStateChangeListener() {
+ @Override
+ public void onViewAttachedToWindow(View v) {
+ latch.countDown();
+ }
+
+ @Override
+ public void onViewDetachedFromWindow(View v) {}
+ });
+
+ mInstrumentation.runOnMainSync(() -> {
+ mWindowContext.getSystemService(WindowManager.class).addView(testView, params);
+
+ assertEquals(token, params.mWindowContextToken);
+ });
+
+
+ assertTrue(latch.await(4, TimeUnit.SECONDS));
+
+
+ // Verify that the window token of the window context is created after first addView().
+ assertTrue("Token must exist after adding the first view.",
+ mWms.isWindowToken(token));
mWindowContext.release();
- assertFalse("Token must be unregistered to WMS", wms.isWindowToken(token));
+ // After the window context's release, the window token is also removed.
+ assertFalse("Token must be removed after release.", mWms.isWindowToken(token));
}
+ /**
+ * Verifies the behavior when window context attaches an {@link Activity} by override
+ * {@link WindowManager.LayoutParams#token}.
+ *
+ * The window context token should be overridden to
+ * {@link android.view.WindowManager.LayoutParams} and the {@link Activity}'s token must
+ * not be removed regardless of the release of window context.
+ */
@Test
- public void testCreateWindowContextWindowManagerAttachClientToken() {
- final WindowManager windowContextWm = WindowManagerImpl
- .createWindowContextWindowManager(mWindowContext);
+ public void testCreateWindowContext_AttachActivity_TokenNotRemovedAfterRelease()
+ throws Throwable {
+ mActivityRule.launchActivity(new Intent());
+ final Activity activity = mActivityRule.getActivity();
+ final WindowManager.LayoutParams params = activity.getWindow().getAttributes();
+
+ final WindowContext windowContext = createWindowContext(params.type);
+ final IBinder token = windowContext.getWindowContextToken();
+
+ final View testView = new View(windowContext);
+
+ mInstrumentation.runOnMainSync(() -> {
+ windowContext.getSystemService(WindowManager.class).addView(testView, params);
+
+ assertEquals(token, params.mWindowContextToken);
+ });
+ windowContext.release();
+
+ // Even if the window context is released, the activity should still exist.
+ assertTrue("Token must exist even if the window context is released.",
+ mWms.isWindowToken(activity.getActivityToken()));
+ }
+
+ /**
+ * Verifies the behavior when window context attaches an existing token by override
+ * {@link WindowManager.LayoutParams#token}.
+ *
+ * The window context token should be overridden to
+ * {@link android.view.WindowManager.LayoutParams} and the {@link Activity}'s token must not be
+ * removed regardless of release of window context.
+ */
+ @Test
+ public void testCreateWindowContext_AttachWindowToken_TokenNotRemovedAfterRelease()
+ throws Throwable {
+ final WindowContext windowContext = createWindowContext(TYPE_INPUT_METHOD);
+ final IBinder token = windowContext.getWindowContextToken();
+
+ final IBinder existingToken = new Binder();
+ mWms.addWindowToken(existingToken, TYPE_INPUT_METHOD, windowContext.getDisplayId());
+
final WindowManager.LayoutParams params =
- new WindowManager.LayoutParams(TYPE_APPLICATION_OVERLAY);
+ new WindowManager.LayoutParams(TYPE_INPUT_METHOD);
+ params.token = existingToken;
+ final View testView = new View(windowContext);
+
mInstrumentation.runOnMainSync(() -> {
- final View view = new View(mWindowContext);
- windowContextWm.addView(view, params);
+ windowContext.getSystemService(WindowManager.class).addView(testView, params);
+
+ assertEquals(token, params.mWindowContextToken);
});
+ windowContext.release();
- assertEquals(mWindowContext.getWindowContextToken(), params.mWindowContextToken);
+ // Even if the window context is released, the existing token should still exist.
+ assertTrue("Token must exist even if the window context is released.",
+ mWms.isWindowToken(existingToken));
+
+ mWms.removeWindowToken(existingToken, DEFAULT_DISPLAY);
}
private WindowContext createWindowContext() {
+ return createWindowContext(TYPE_APPLICATION_OVERLAY);
+ }
+
+ private WindowContext createWindowContext(@WindowType int type) {
final Context instContext = mInstrumentation.getTargetContext();
final Display display = instContext.getSystemService(DisplayManager.class)
.getDisplay(DEFAULT_DISPLAY);
- final Context context = instContext.createDisplayContext(display);
- return new WindowContext(context, TYPE_APPLICATION_OVERLAY,
- null /* options */);
+ return (WindowContext) instContext.createWindowContext(display, type, null /* options */);
}
}
diff --git a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
index 02a36dc74d68..f646d5d22263 100644
--- a/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
+++ b/services/core/java/com/android/server/inputmethod/InputMethodMenuController.java
@@ -220,7 +220,8 @@ public class InputMethodMenuController {
*/
@VisibleForTesting
public Context getSettingsContext(int displayId) {
- if (mSettingsContext == null) {
+ // TODO(b/178462039): Cover the case when IME is moved to another ImeContainer.
+ if (mSettingsContext == null || mSettingsContext.getDisplayId() != displayId) {
final Context systemUiContext = ActivityThread.currentActivityThread()
.createSystemUiContext(displayId);
final Context windowContext = systemUiContext.createWindowContext(
@@ -229,11 +230,6 @@ public class InputMethodMenuController {
windowContext, com.android.internal.R.style.Theme_DeviceDefault_Settings);
mSwitchingDialogToken = mSettingsContext.getWindowContextToken();
}
- // TODO(b/159767464): register the listener to another display again if window token is not
- // yet created.
- if (mSettingsContext.getDisplayId() != displayId) {
- mWindowManagerInternal.moveWindowTokenToDisplay(mSwitchingDialogToken, displayId);
- }
return mSettingsContext;
}
diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java
index 673c6a5fb470..6319c80dc9bd 100644
--- a/services/core/java/com/android/server/wm/WindowManagerService.java
+++ b/services/core/java/com/android/server/wm/WindowManagerService.java
@@ -770,7 +770,8 @@ public class WindowManagerService extends IWindowManager.Stub
final AnrController mAnrController;
private final ScreenshotHashController mScreenshotHashController;
- private final WindowContextListenerController mWindowContextListenerController =
+ @VisibleForTesting
+ final WindowContextListenerController mWindowContextListenerController =
new WindowContextListenerController();
@VisibleForTesting
@@ -2794,6 +2795,17 @@ public class WindowManagerService extends IWindowManager.Stub
return WindowManagerGlobal.ADD_OKAY;
}
+ /**
+ * Registers a listener for a {@link android.app.WindowContext} to subscribe to configuration
+ * changes of a {@link DisplayArea}.
+ *
+ * @param clientToken the window context's token
+ * @param type Window type of the window context
+ * @param displayId The display associated with the window context
+ * @param options A bundle used to pass window-related options and choose the right DisplayArea
+ *
+ * @return {@code true} if the listener was registered successfully.
+ */
@Override
public boolean registerWindowContextListener(IBinder clientToken, int type, int displayId,
Bundle options) {
@@ -2849,6 +2861,7 @@ public class WindowManagerService extends IWindowManager.Stub
}
}
+ /** Returns {@code true} if this binder is a registered window token. */
@Override
public boolean isWindowToken(IBinder binder) {
synchronized (mGlobalLock) {
diff --git a/services/core/java/com/android/server/wm/WindowToken.java b/services/core/java/com/android/server/wm/WindowToken.java
index 8a512bc8834b..cd18311d7d54 100644
--- a/services/core/java/com/android/server/wm/WindowToken.java
+++ b/services/core/java/com/android/server/wm/WindowToken.java
@@ -17,7 +17,6 @@
package com.android.server.wm;
import static android.os.Process.INVALID_UID;
-import static android.view.Display.INVALID_DISPLAY;
import static android.view.WindowManager.LayoutParams.FLAG_SHOW_WALLPAPER;
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_STARTING;
import static android.view.WindowManager.LayoutParams.TYPE_DOCK_DIVIDER;
@@ -26,7 +25,6 @@ import static android.view.WindowManager.LayoutParams.TYPE_NAVIGATION_BAR;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_ADD_REMOVE;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_FOCUS;
import static com.android.internal.protolog.ProtoLogGroup.WM_DEBUG_WINDOW_MOVEMENT;
-import static com.android.internal.protolog.ProtoLogGroup.WM_ERROR;
import static com.android.server.wm.WindowContainer.AnimationFlags.CHILDREN;
import static com.android.server.wm.WindowContainer.AnimationFlags.PARENTS;
import static com.android.server.wm.WindowContainer.AnimationFlags.TRANSITION;
@@ -41,7 +39,6 @@ import static com.android.server.wm.WindowTokenProto.WINDOW_CONTAINER;
import android.annotation.CallSuper;
import android.annotation.Nullable;
-import android.app.IWindowToken;
import android.app.servertransaction.FixedRotationAdjustmentsItem;
import android.content.res.Configuration;
import android.graphics.Rect;
@@ -58,7 +55,6 @@ import android.view.InsetsState;
import android.view.SurfaceControl;
import android.view.WindowManager;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.protolog.common.ProtoLog;
import com.android.server.policy.WindowManagerPolicy;
@@ -112,17 +108,10 @@ class WindowToken extends WindowContainer<WindowState> {
private FixedRotationTransformState mFixedRotationTransformState;
- private Configuration mLastReportedConfig;
- private int mLastReportedDisplay = INVALID_DISPLAY;
-
/**
* When set to {@code true}, this window token is created from {@link android.app.WindowContext}
*/
- @VisibleForTesting
- final boolean mFromClientToken;
-
- private DeathRecipient mDeathRecipient;
- private boolean mBinderDied = false;
+ private final boolean mFromClientToken;
private final int mOwnerUid;
@@ -188,30 +177,6 @@ class WindowToken extends WindowContainer<WindowState> {
}
}
- private class DeathRecipient implements IBinder.DeathRecipient {
- private boolean mHasUnlinkToDeath = false;
-
- @Override
- public void binderDied() {
- synchronized (mWmService.mGlobalLock) {
- mBinderDied = true;
- removeImmediately();
- }
- }
-
- void linkToDeath() throws RemoteException {
- token.linkToDeath(DeathRecipient.this, 0);
- }
-
- void unlinkToDeath() {
- if (mHasUnlinkToDeath) {
- return;
- }
- token.unlinkToDeath(DeathRecipient.this, 0);
- mHasUnlinkToDeath = true;
- }
- }
-
/**
* Compares two child window of this token and returns -1 if the first is lesser than the
* second in terms of z-order and 1 otherwise.
@@ -266,17 +231,6 @@ class WindowToken extends WindowContainer<WindowState> {
if (dc != null) {
dc.addWindowToken(token, this);
}
- if (shouldReportToClient()) {
- try {
- mDeathRecipient = new DeathRecipient();
- mDeathRecipient.linkToDeath();
- } catch (RemoteException e) {
- Slog.e(TAG, "Unable to add window token with type " + windowType + " on "
- + "display " + dc.getDisplayId(), e);
- mDeathRecipient = null;
- return;
- }
- }
}
void removeAllWindowsIfPossible() {
@@ -414,22 +368,6 @@ class WindowToken extends WindowContainer<WindowState> {
// Needs to occur after the token is removed from the display above to avoid attempt at
// duplicate removal of this window container from it's parent.
super.removeImmediately();
-
- reportWindowTokenRemovedToClient();
- }
-
- // TODO(b/159767464): Remove after we migrate to listener approach.
- private void reportWindowTokenRemovedToClient() {
- if (!shouldReportToClient()) {
- return;
- }
- mDeathRecipient.unlinkToDeath();
- IWindowToken windowTokenClient = IWindowToken.Stub.asInterface(token);
- try {
- windowTokenClient.onWindowTokenRemoved();
- } catch (RemoteException e) {
- ProtoLog.w(WM_ERROR, "Could not report token removal to the window token client.");
- }
}
@Override
@@ -441,51 +379,11 @@ class WindowToken extends WindowContainer<WindowState> {
// to another display before the window behind
// it is ready.
super.onDisplayChanged(dc);
- reportConfigToWindowTokenClient();
}
@Override
public void onConfigurationChanged(Configuration newParentConfig) {
super.onConfigurationChanged(newParentConfig);
- reportConfigToWindowTokenClient();
- }
-
- void reportConfigToWindowTokenClient() {
- if (!shouldReportToClient()) {
- return;
- }
- if (mLastReportedConfig == null) {
- mLastReportedConfig = new Configuration();
- }
- final Configuration config = getConfiguration();
- final int displayId = getDisplayContent().getDisplayId();
- if (config.diff(mLastReportedConfig) == 0 && displayId == mLastReportedDisplay) {
- // No changes since last reported time.
- return;
- }
-
- mLastReportedConfig.setTo(config);
- mLastReportedDisplay = displayId;
-
- IWindowToken windowTokenClient = IWindowToken.Stub.asInterface(token);
- try {
- windowTokenClient.onConfigurationChanged(config, displayId);
- } catch (RemoteException e) {
- ProtoLog.w(WM_ERROR,
- "Could not report config changes to the window token client.");
- }
- }
-
- /**
- * @return {@code true} if this {@link WindowToken} is not an {@link ActivityRecord} and
- * registered from client side.
- */
- private boolean shouldReportToClient() {
- // Only report to client for WindowToken because Activities are updated through ATM
- // callbacks.
- return asActivityRecord() == null
- // Report to {@link android.view.WindowTokenClient} if this token was registered from it.
- && mFromClientToken && !mBinderDied;
}
@Override
diff --git a/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java
index f75c98f39323..78074d6e1492 100644
--- a/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java
+++ b/services/tests/wmtests/src/com/android/server/wm/InputMethodMenuControllerTest.java
@@ -17,6 +17,7 @@
package com.android.server.wm;
import static android.view.Display.DEFAULT_DISPLAY;
+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.doReturn;
@@ -26,7 +27,6 @@ import static com.google.common.truth.Truth.assertThat;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
@@ -70,13 +70,15 @@ public class InputMethodMenuControllerTest extends WindowTestsBase {
spyOn(wms);
doAnswer(invocation -> {
Object[] args = invocation.getArguments();
- final IBinder token = (IBinder) args[0];
- final int windowType = (int) args[1];
- new WindowToken(mWm, token, windowType, true /* persistOnEmpty */,
- mDefaultDisplay, true /* ownerCanManageAppTokens */, 1000 /* ownerUid */,
- false /* roundedCornerOverlay */, true /* fromClientToken */);
- return WindowManagerGlobal.ADD_OKAY;
- }).when(wms).addWindowTokenWithOptions(any(), anyInt(), anyInt(), any(), anyString());
+ IBinder clientToken = (IBinder) args[0];
+ int displayId = (int) args[2];
+ DisplayContent dc = mWm.mRoot.getDisplayContent(displayId);
+ mWm.mWindowContextListenerController.registerWindowContainerListener(clientToken,
+ dc.getImeContainer(), 1000 /* ownerUid */, TYPE_INPUT_METHOD_DIALOG,
+ null /* options */);
+ return true;
+ }).when(wms).registerWindowContextListener(any(), eq(TYPE_INPUT_METHOD_DIALOG),
+ anyInt(), any());
mSecondaryDisplay = new TestDisplayContent.Builder(mAtm, 1000, 1000).build();
@@ -95,14 +97,12 @@ public class InputMethodMenuControllerTest extends WindowTestsBase {
assertImeSwitchContextMetricsValidity(contextOnDefaultDisplay, mDefaultDisplay);
- // Obtain the context again and check they are the same instance and match the display
- // metrics of the secondary display.
+ // Obtain the context again and check if the window metrics match the IME container bounds
+ // of the secondary display.
final Context contextOnSecondaryDisplay = mController.getSettingsContext(
mSecondaryDisplay.getDisplayId());
assertImeSwitchContextMetricsValidity(contextOnSecondaryDisplay, mSecondaryDisplay);
- assertThat(contextOnDefaultDisplay.getWindowContextToken())
- .isEqualTo(contextOnSecondaryDisplay.getWindowContextToken());
}
private void assertImeSwitchContextMetricsValidity(Context context, DisplayContent dc) {