diff options
| author | 2023-07-20 12:48:21 +0800 | |
|---|---|---|
| committer | 2023-07-31 16:26:05 +0800 | |
| commit | 7ef648e6a353bbae7aab5119f3b7474a36094fac (patch) | |
| tree | 3b5fe8349a899c9bfef7b840fd3e93af9622f48a | |
| parent | 6603c87997c2b7bdffd7a134413b7c560f3d0576 (diff) | |
Migrate WindowContext#onConfigurationChanged to ClientTransaction (7/n)
1. Introdce WindowContextInfo to store info that we want to pass for
WindowContext.
2. Update #attachToWindowToken to be consistent with
#attachToDisplayArea that it also return the current WindowContext
config.
Before, when #attachToWindowToken, the server side will trigger an
onConfigurationChanged to the WindowContext. Now, this will be done in
the client side by post to the main thread so it doesn't change the
client side behavior.
Bug: 290876897
Test: atest FrameworksCoreTests:WindowTokenClientControllerTest
Change-Id: I7655ac454a941a795d519351de4741778c514d82
16 files changed, 315 insertions, 121 deletions
diff --git a/core/java/android/app/ActivityThread.java b/core/java/android/app/ActivityThread.java index 58c25489431a..a09d7dcfa08d 100644 --- a/core/java/android/app/ActivityThread.java +++ b/core/java/android/app/ActivityThread.java @@ -203,6 +203,7 @@ import android.webkit.WebView; import android.window.SizeConfigurationBuckets; import android.window.SplashScreen; import android.window.SplashScreenView; +import android.window.WindowContextInfo; import android.window.WindowProviderService; import android.window.WindowTokenClientController; @@ -6248,10 +6249,9 @@ public final class ActivityThread extends ClientTransactionHandler } @Override - public void handleWindowContextConfigurationChanged(@NonNull IBinder clientToken, - @NonNull Configuration configuration, int displayId) { - WindowTokenClientController.getInstance().onWindowContextConfigurationChanged(clientToken, - configuration, displayId); + public void handleWindowContextInfoChanged(@NonNull IBinder clientToken, + @NonNull WindowContextInfo info) { + WindowTokenClientController.getInstance().onWindowContextInfoChanged(clientToken, info); } @Override diff --git a/core/java/android/app/ClientTransactionHandler.java b/core/java/android/app/ClientTransactionHandler.java index f7a43f42f2ef..6753cb884ea7 100644 --- a/core/java/android/app/ClientTransactionHandler.java +++ b/core/java/android/app/ClientTransactionHandler.java @@ -28,6 +28,7 @@ import android.os.IBinder; import android.util.MergedConfiguration; import android.view.SurfaceControl; import android.window.SplashScreenView.SplashScreenViewParcelable; +import android.window.WindowContextInfo; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.content.ReferrerIntent; @@ -163,9 +164,9 @@ public abstract class ClientTransactionHandler { public abstract void handleActivityConfigurationChanged(@NonNull ActivityClientRecord r, Configuration overrideConfig, int displayId); - /** Deliver {@link android.window.WindowContext} configuration change. */ - public abstract void handleWindowContextConfigurationChanged(@NonNull IBinder clientToken, - @NonNull Configuration configuration, int displayId); + /** Deliver {@link android.window.WindowContextInfo} change. */ + public abstract void handleWindowContextInfoChanged(@NonNull IBinder clientToken, + @NonNull WindowContextInfo info); /** Deliver {@link android.window.WindowContext} window removal event. */ public abstract void handleWindowContextWindowRemoval(@NonNull IBinder clientToken); diff --git a/core/java/android/app/servertransaction/WindowContextConfigurationChangeItem.java b/core/java/android/app/servertransaction/WindowContextInfoChangeItem.java index 3ac642fd4664..74721d555081 100644 --- a/core/java/android/app/servertransaction/WindowContextConfigurationChangeItem.java +++ b/core/java/android/app/servertransaction/WindowContextInfoChangeItem.java @@ -16,8 +16,6 @@ package android.app.servertransaction; -import static android.view.Display.INVALID_DISPLAY; - import static java.util.Objects.requireNonNull; import android.annotation.NonNull; @@ -26,6 +24,7 @@ import android.app.ClientTransactionHandler; import android.content.res.Configuration; import android.os.IBinder; import android.os.Parcel; +import android.window.WindowContextInfo; import java.util.Objects; @@ -33,35 +32,33 @@ import java.util.Objects; * {@link android.window.WindowContext} configuration change message. * @hide */ -public class WindowContextConfigurationChangeItem extends ClientTransactionItem { +public class WindowContextInfoChangeItem extends ClientTransactionItem { @Nullable private IBinder mClientToken; @Nullable - private Configuration mConfiguration; - private int mDisplayId; + private WindowContextInfo mInfo; @Override public void execute(@NonNull ClientTransactionHandler client, @NonNull IBinder token, @NonNull PendingTransactionActions pendingActions) { - client.handleWindowContextConfigurationChanged(mClientToken, mConfiguration, mDisplayId); + client.handleWindowContextInfoChanged(mClientToken, mInfo); } // ObjectPoolItem implementation - private WindowContextConfigurationChangeItem() {} + private WindowContextInfoChangeItem() {} /** Obtains an instance initialized with provided params. */ - public static WindowContextConfigurationChangeItem obtain( + public static WindowContextInfoChangeItem obtain( @NonNull IBinder clientToken, @NonNull Configuration config, int displayId) { - WindowContextConfigurationChangeItem instance = - ObjectPool.obtain(WindowContextConfigurationChangeItem.class); + WindowContextInfoChangeItem instance = + ObjectPool.obtain(WindowContextInfoChangeItem.class); if (instance == null) { - instance = new WindowContextConfigurationChangeItem(); + instance = new WindowContextInfoChangeItem(); } instance.mClientToken = requireNonNull(clientToken); - instance.mConfiguration = requireNonNull(config); - instance.mDisplayId = displayId; + instance.mInfo = new WindowContextInfo(config, displayId); return instance; } @@ -69,8 +66,7 @@ public class WindowContextConfigurationChangeItem extends ClientTransactionItem @Override public void recycle() { mClientToken = null; - mConfiguration = null; - mDisplayId = INVALID_DISPLAY; + mInfo = null; ObjectPool.recycle(this); } @@ -80,25 +76,23 @@ public class WindowContextConfigurationChangeItem extends ClientTransactionItem @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeStrongBinder(mClientToken); - dest.writeTypedObject(mConfiguration, flags); - dest.writeInt(mDisplayId); + dest.writeTypedObject(mInfo, flags); } /** Reads from Parcel. */ - private WindowContextConfigurationChangeItem(@NonNull Parcel in) { + private WindowContextInfoChangeItem(@NonNull Parcel in) { mClientToken = in.readStrongBinder(); - mConfiguration = in.readTypedObject(Configuration.CREATOR); - mDisplayId = in.readInt(); + mInfo = in.readTypedObject(WindowContextInfo.CREATOR); } - public static final @NonNull Creator<WindowContextConfigurationChangeItem> CREATOR = + public static final @NonNull Creator<WindowContextInfoChangeItem> CREATOR = new Creator<>() { - public WindowContextConfigurationChangeItem createFromParcel(Parcel in) { - return new WindowContextConfigurationChangeItem(in); + public WindowContextInfoChangeItem createFromParcel(Parcel in) { + return new WindowContextInfoChangeItem(in); } - public WindowContextConfigurationChangeItem[] newArray(int size) { - return new WindowContextConfigurationChangeItem[size]; + public WindowContextInfoChangeItem[] newArray(int size) { + return new WindowContextInfoChangeItem[size]; } }; @@ -110,26 +104,23 @@ public class WindowContextConfigurationChangeItem extends ClientTransactionItem if (o == null || getClass() != o.getClass()) { return false; } - final WindowContextConfigurationChangeItem other = (WindowContextConfigurationChangeItem) o; + final WindowContextInfoChangeItem other = (WindowContextInfoChangeItem) o; return Objects.equals(mClientToken, other.mClientToken) - && Objects.equals(mConfiguration, other.mConfiguration) - && mDisplayId == other.mDisplayId; + && Objects.equals(mInfo, other.mInfo); } @Override public int hashCode() { int result = 17; result = 31 * result + Objects.hashCode(mClientToken); - result = 31 * result + Objects.hashCode(mConfiguration); - result = 31 * result + mDisplayId; + result = 31 * result + Objects.hashCode(mInfo); return result; } @Override public String toString() { - return "WindowContextConfigurationChangeItem{clientToken=" + mClientToken - + ", config=" + mConfiguration - + ", displayId=" + mDisplayId + return "WindowContextInfoChangeItem{clientToken=" + mClientToken + + ", info=" + mInfo + "}"; } } diff --git a/core/java/android/view/IWindowManager.aidl b/core/java/android/view/IWindowManager.aidl index c1474ebad227..d3b7a5be47ba 100644 --- a/core/java/android/view/IWindowManager.aidl +++ b/core/java/android/view/IWindowManager.aidl @@ -71,6 +71,7 @@ import android.window.AddToSurfaceSyncGroupResult; import android.window.ISurfaceSyncGroupCompletedListener; import android.window.ITaskFpsCallback; import android.window.ScreenCapture; +import android.window.WindowContextInfo; /** * System private interface to the window manager. @@ -858,10 +859,10 @@ interface IWindowManager * @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 the DisplayArea's {@link android.app.res.Configuration} if the WindowContext is - * attached to the DisplayArea successfully. {@code null}, otherwise. + * @return the {@link WindowContextInfo} of the DisplayArea if the WindowContext is attached to + * the DisplayArea successfully. {@code null}, otherwise. */ - @nullable Configuration attachWindowContextToDisplayArea(in IApplicationThread appThread, + @nullable WindowContextInfo attachWindowContextToDisplayArea(in IApplicationThread appThread, IBinder clientToken, int type, int displayId, in @nullable Bundle options); /** @@ -879,13 +880,15 @@ interface IWindowManager * the WindowContext's token} * @param token the WindowToken to attach * + * @return the {@link WindowContextInfo} of the WindowToken if the WindowContext is attached to + * the WindowToken successfully. {@code null}, otherwise. * @throws IllegalArgumentException if the {@code clientToken} have not been attached to * the server or the WindowContext's type doesn't match WindowToken {@code token}'s type. * * @see #attachWindowContextToDisplayArea(IBinder, int, int, Bundle) */ - void attachWindowContextToWindowToken(in IApplicationThread appThread, IBinder clientToken, - IBinder token); + @nullable WindowContextInfo attachWindowContextToWindowToken(in IApplicationThread appThread, + IBinder clientToken, IBinder token); /** * Attaches a {@code clientToken} to associate with DisplayContent. @@ -899,11 +902,11 @@ interface IWindowManager * the WindowContext's token} * @param displayId The display associated with the window context * - * @return the DisplayContent's {@link android.app.res.Configuration} if the Context is - * attached to the DisplayContent successfully. {@code null}, otherwise. + * @return the {@link WindowContextInfo} of the DisplayContent if the WindowContext is attached + * to the DisplayContent successfully. {@code null}, otherwise. * @throws android.view.WindowManager.InvalidDisplayException if the display ID is invalid */ - @nullable Configuration attachWindowContextToDisplayContent(in IApplicationThread appThread, + @nullable WindowContextInfo attachWindowContextToDisplayContent(in IApplicationThread appThread, IBinder clientToken, int displayId); /** diff --git a/core/java/android/window/WindowContextController.java b/core/java/android/window/WindowContextController.java index 36eef5375391..c9ac245bc36f 100644 --- a/core/java/android/window/WindowContextController.java +++ b/core/java/android/window/WindowContextController.java @@ -137,12 +137,14 @@ public class WindowContextController { * @see WindowProviderService#attachToWindowToken(IBinder)) * @see IWindowManager#attachWindowContextToWindowToken */ - public void attachToWindowToken(IBinder windowToken) { + public void attachToWindowToken(@NonNull IBinder windowToken) { if (mAttachedToDisplayArea != AttachStatus.STATUS_ATTACHED) { throw new IllegalStateException("The Window Context should have been attached" + " to a DisplayArea. AttachToDisplayArea:" + mAttachedToDisplayArea); } - getWindowTokenClientController().attachToWindowToken(mToken, windowToken); + if (!getWindowTokenClientController().attachToWindowToken(mToken, windowToken)) { + Log.e(TAG, "attachToWindowToken fail"); + } } /** Detaches the window context from the node it's currently associated with. */ diff --git a/core/java/android/window/WindowContextInfo.aidl b/core/java/android/window/WindowContextInfo.aidl new file mode 100644 index 000000000000..360431cf6daa --- /dev/null +++ b/core/java/android/window/WindowContextInfo.aidl @@ -0,0 +1,20 @@ +/* + * Copyright 2023 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.window; + +/** @hide */ +parcelable WindowContextInfo;
\ No newline at end of file diff --git a/core/java/android/window/WindowContextInfo.java b/core/java/android/window/WindowContextInfo.java new file mode 100644 index 000000000000..3c21cd44b10a --- /dev/null +++ b/core/java/android/window/WindowContextInfo.java @@ -0,0 +1,117 @@ +/* + * Copyright (C) 2023 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.window; + +import static java.util.Objects.requireNonNull; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.content.res.Configuration; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; + +/** + * Stores information about a particular window that a {@link WindowContext} is attached to. + * @hide + */ +public class WindowContextInfo implements Parcelable { + + /** + * Configuration of the window. + */ + @NonNull + private final Configuration mConfiguration; + + /** + * The display id that the window is attached to. + */ + private final int mDisplayId; + + public WindowContextInfo(@NonNull Configuration configuration, int displayId) { + mConfiguration = requireNonNull(configuration); + mDisplayId = displayId; + } + + @NonNull + public Configuration getConfiguration() { + return mConfiguration; + } + + public int getDisplayId() { + return mDisplayId; + } + + // Parcelable implementation + + /** Writes to Parcel. */ + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeTypedObject(mConfiguration, flags); + dest.writeInt(mDisplayId); + } + + /** Reads from Parcel. */ + private WindowContextInfo(@NonNull Parcel in) { + mConfiguration = in.readTypedObject(Configuration.CREATOR); + mDisplayId = in.readInt(); + } + + public static final @NonNull Creator<WindowContextInfo> CREATOR = new Creator<>() { + public WindowContextInfo createFromParcel(Parcel in) { + return new WindowContextInfo(in); + } + + public WindowContextInfo[] newArray(int size) { + return new WindowContextInfo[size]; + } + }; + + @Override + public int describeContents() { + return 0; + } + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final WindowContextInfo other = (WindowContextInfo) o; + return Objects.equals(mConfiguration, other.mConfiguration) + && mDisplayId == other.mDisplayId; + } + + @Override + public int hashCode() { + int result = 17; + result = 31 * result + Objects.hashCode(mConfiguration); + result = 31 * result + mDisplayId; + return result; + } + + @Override + public String toString() { + return "WindowContextInfo{config=" + mConfiguration + + ", displayId=" + mDisplayId + + "}"; + } +} diff --git a/core/java/android/window/WindowTokenClient.java b/core/java/android/window/WindowTokenClient.java index 74585638df6f..6a32529f31c7 100644 --- a/core/java/android/window/WindowTokenClient.java +++ b/core/java/android/window/WindowTokenClient.java @@ -99,6 +99,13 @@ public class WindowTokenClient extends IWindowToken.Stub { @Override public void onConfigurationChanged(Configuration newConfig, int newDisplayId) { // TODO(b/290876897): No need to post on mHandler after migrating to ClientTransaction + postOnConfigurationChanged(newConfig, newDisplayId); + } + + /** + * Posts an {@link #onConfigurationChanged} to the main thread. + */ + public void postOnConfigurationChanged(@NonNull Configuration newConfig, int newDisplayId) { mHandler.post(PooledLambda.obtainRunnable(this::onConfigurationChanged, newConfig, newDisplayId, true /* shouldReportConfigChange */).recycleOnUse()); } @@ -162,7 +169,6 @@ public class WindowTokenClient extends IWindowToken.Stub { windowContext.dispatchConfigurationChanged(newConfig); } - if (shouldReportConfigChange && diff != 0 && context instanceof WindowProviderService) { final WindowProviderService windowProviderService = (WindowProviderService) context; diff --git a/core/java/android/window/WindowTokenClientController.java b/core/java/android/window/WindowTokenClientController.java index 14b9df65aa69..7a84123c91e1 100644 --- a/core/java/android/window/WindowTokenClientController.java +++ b/core/java/android/window/WindowTokenClientController.java @@ -22,10 +22,9 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.app.ActivityThread; import android.app.IApplicationThread; -import android.app.servertransaction.WindowContextConfigurationChangeItem; +import android.app.servertransaction.WindowContextInfoChangeItem; import android.app.servertransaction.WindowContextWindowRemovalItem; import android.content.Context; -import android.content.res.Configuration; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; @@ -94,17 +93,17 @@ public class WindowTokenClientController { */ public boolean attachToDisplayArea(@NonNull WindowTokenClient client, @WindowType int type, int displayId, @Nullable Bundle options) { - final Configuration configuration; + final WindowContextInfo info; try { - configuration = getWindowManagerService().attachWindowContextToDisplayArea( + info = getWindowManagerService().attachWindowContextToDisplayArea( mAppThread, client, type, displayId, options); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } - if (configuration == null) { + if (info == null) { return false; } - onWindowContextTokenAttached(client, displayId, configuration); + onWindowContextTokenAttached(client, info, false /* shouldReportConfigChange */); return true; } @@ -121,16 +120,16 @@ public class WindowTokenClientController { if (wms == null) { return false; } - final Configuration configuration; + final WindowContextInfo info; try { - configuration = wms.attachWindowContextToDisplayContent(mAppThread, client, displayId); + info = wms.attachWindowContextToDisplayContent(mAppThread, client, displayId); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } - if (configuration == null) { + if (info == null) { return false; } - onWindowContextTokenAttached(client, displayId, configuration); + onWindowContextTokenAttached(client, info, false /* shouldReportConfigChange */); return true; } @@ -139,19 +138,23 @@ public class WindowTokenClientController { * * @param client The {@link WindowTokenClient} to attach. * @param windowToken the window token to associated with + * @return {@code true} if attaching successfully. */ - public void attachToWindowToken(@NonNull WindowTokenClient client, + public boolean attachToWindowToken(@NonNull WindowTokenClient client, @NonNull IBinder windowToken) { + final WindowContextInfo info; try { - getWindowManagerService().attachWindowContextToWindowToken( + info = getWindowManagerService().attachWindowContextToWindowToken( mAppThread, client, windowToken); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } - // We don't report configuration change for now. - synchronized (mLock) { - mWindowTokenClientMap.put(client.asBinder(), client); + if (info == null) { + return false; } + // We currently report configuration for WindowToken after attached. + onWindowContextTokenAttached(client, info, true /* shouldReportConfigChange */); + return true; } /** Detaches a {@link WindowTokenClient} from associated WindowContainer if there's one. */ @@ -168,21 +171,30 @@ public class WindowTokenClientController { } } - private void onWindowContextTokenAttached(@NonNull WindowTokenClient client, int displayId, - @NonNull Configuration configuration) { + private void onWindowContextTokenAttached(@NonNull WindowTokenClient client, + @NonNull WindowContextInfo info, boolean shouldReportConfigChange) { synchronized (mLock) { mWindowTokenClientMap.put(client.asBinder(), client); } - client.onConfigurationChanged(configuration, displayId, - false /* shouldReportConfigChange */); + if (shouldReportConfigChange) { + // Should trigger an #onConfigurationChanged callback to the WindowContext. Post the + // dispatch in the next loop to prevent the callback from being dispatched before + // #onCreate or WindowContext creation.. + client.postOnConfigurationChanged(info.getConfiguration(), info.getDisplayId()); + } else { + // Apply the config change directly in case users get stale values after WindowContext + // creation. + client.onConfigurationChanged(info.getConfiguration(), info.getDisplayId(), + false /* shouldReportConfigChange */); + } } - /** Called when receives {@link WindowContextConfigurationChangeItem}. */ - public void onWindowContextConfigurationChanged(@NonNull IBinder clientToken, - @NonNull Configuration configuration, int displayId) { + /** Called when receives {@link WindowContextInfoChangeItem}. */ + public void onWindowContextInfoChanged(@NonNull IBinder clientToken, + @NonNull WindowContextInfo info) { final WindowTokenClient windowTokenClient = getWindowTokenClient(clientToken); if (windowTokenClient != null) { - windowTokenClient.onConfigurationChanged(configuration, displayId); + windowTokenClient.onConfigurationChanged(info.getConfiguration(), info.getDisplayId()); } } diff --git a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java index 8da6d74de36d..c904d96b6091 100644 --- a/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java +++ b/core/tests/coretests/src/android/app/activity/ActivityThreadTest.java @@ -64,6 +64,7 @@ import android.util.DisplayMetrics; import android.util.MergedConfiguration; import android.view.Display; import android.view.View; +import android.window.WindowContextInfo; import android.window.WindowTokenClientController; import androidx.test.filters.MediumTest; @@ -753,13 +754,12 @@ public class ActivityThreadTest { WindowTokenClientController.overrideForTesting(windowTokenClientController); final IBinder clientToken = mock(IBinder.class); final Configuration configuration = new Configuration(); + final WindowContextInfo info = new WindowContextInfo(configuration, DEFAULT_DISPLAY); InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> activityThread - .handleWindowContextConfigurationChanged( - clientToken, configuration, DEFAULT_DISPLAY)); + .handleWindowContextInfoChanged(clientToken, info)); - verify(windowTokenClientController).onWindowContextConfigurationChanged( - clientToken, configuration, DEFAULT_DISPLAY); + verify(windowTokenClientController).onWindowContextInfoChanged(clientToken, info); } @Test diff --git a/core/tests/coretests/src/android/app/servertransaction/WindowContextConfigurationChangeItemTest.java b/core/tests/coretests/src/android/app/servertransaction/WindowContextInfoChangeItemTest.java index 7811e1a58c22..37a517e87c74 100644 --- a/core/tests/coretests/src/android/app/servertransaction/WindowContextConfigurationChangeItemTest.java +++ b/core/tests/coretests/src/android/app/servertransaction/WindowContextInfoChangeItemTest.java @@ -23,6 +23,7 @@ import static org.mockito.Mockito.verify; import android.app.ClientTransactionHandler; import android.content.res.Configuration; import android.os.IBinder; +import android.window.WindowContextInfo; import org.junit.Before; import org.junit.Test; @@ -30,12 +31,12 @@ import org.mockito.Mock; import org.mockito.MockitoAnnotations; /** - * Tests for {@link WindowContextConfigurationChangeItem}. + * Tests for {@link WindowContextInfoChangeItem}. * * Build/Install/Run: - * atest FrameworksCoreTests:WindowContextConfigurationChangeItemTest + * atest FrameworksCoreTests:WindowContextInfoChangeItemTest */ -public class WindowContextConfigurationChangeItemTest { +public class WindowContextInfoChangeItemTest { @Mock private ClientTransactionHandler mHandler; @@ -55,11 +56,11 @@ public class WindowContextConfigurationChangeItemTest { @Test public void testExecute() { - final WindowContextConfigurationChangeItem item = WindowContextConfigurationChangeItem + final WindowContextInfoChangeItem item = WindowContextInfoChangeItem .obtain(mClientToken, mConfiguration, DEFAULT_DISPLAY); item.execute(mHandler, mToken, mPendingActions); - verify(mHandler).handleWindowContextConfigurationChanged(mClientToken, mConfiguration, - DEFAULT_DISPLAY); + verify(mHandler).handleWindowContextInfoChanged(mClientToken, + new WindowContextInfo(mConfiguration, DEFAULT_DISPLAY)); } } diff --git a/core/tests/coretests/src/android/window/WindowTokenClientControllerTest.java b/core/tests/coretests/src/android/window/WindowTokenClientControllerTest.java index c4f7b3b5cd59..7bd6f05d3775 100644 --- a/core/tests/coretests/src/android/window/WindowTokenClientControllerTest.java +++ b/core/tests/coretests/src/android/window/WindowTokenClientControllerTest.java @@ -64,6 +64,7 @@ public class WindowTokenClientControllerTest { // Can't mock final class. private final Configuration mConfiguration = new Configuration(); + private WindowContextInfo mWindowContextInfo; private WindowTokenClientController mController; @Before @@ -72,6 +73,7 @@ public class WindowTokenClientControllerTest { doReturn(mClientToken).when(mWindowTokenClient).asBinder(); mController = spy(WindowTokenClientController.createInstanceForTesting()); doReturn(mWindowManagerService).when(mController).getWindowManagerService(); + mWindowContextInfo = new WindowContextInfo(mConfiguration, DEFAULT_DISPLAY); } @Test @@ -86,7 +88,7 @@ public class WindowTokenClientControllerTest { TYPE_APPLICATION_OVERLAY, DEFAULT_DISPLAY, null /* options */); verify(mWindowTokenClient, never()).onConfigurationChanged(any(), anyInt(), anyBoolean()); - doReturn(mConfiguration).when(mWindowManagerService).attachWindowContextToDisplayArea( + doReturn(mWindowContextInfo).when(mWindowManagerService).attachWindowContextToDisplayArea( any(), any(), anyInt(), anyInt(), any()); assertTrue(mController.attachToDisplayArea(mWindowTokenClient, TYPE_APPLICATION_OVERLAY, @@ -109,7 +111,7 @@ public class WindowTokenClientControllerTest { verify(mWindowManagerService, never()).detachWindowContext(any()); - doReturn(mConfiguration).when(mWindowManagerService).attachWindowContextToDisplayArea( + doReturn(mWindowContextInfo).when(mWindowManagerService).attachWindowContextToDisplayArea( any(), any(), anyInt(), anyInt(), any()); mController.attachToDisplayArea(mWindowTokenClient, TYPE_APPLICATION_OVERLAY, DEFAULT_DISPLAY, null /* options */); @@ -129,8 +131,8 @@ public class WindowTokenClientControllerTest { DEFAULT_DISPLAY); verify(mWindowTokenClient, never()).onConfigurationChanged(any(), anyInt(), anyBoolean()); - doReturn(mConfiguration).when(mWindowManagerService).attachWindowContextToDisplayContent( - any(), any(), anyInt()); + doReturn(mWindowContextInfo).when(mWindowManagerService) + .attachWindowContextToDisplayContent(any(), any(), anyInt()); assertTrue(mController.attachToDisplayContent(mWindowTokenClient, DEFAULT_DISPLAY)); verify(mWindowTokenClient).onConfigurationChanged(mConfiguration, DEFAULT_DISPLAY, @@ -150,8 +152,8 @@ public class WindowTokenClientControllerTest { verify(mWindowManagerService, never()).detachWindowContext(any()); - doReturn(mConfiguration).when(mWindowManagerService).attachWindowContextToDisplayContent( - any(), any(), anyInt()); + doReturn(mWindowContextInfo).when(mWindowManagerService) + .attachWindowContextToDisplayContent(any(), any(), anyInt()); mController.attachToDisplayContent(mWindowTokenClient, DEFAULT_DISPLAY); mController.detachIfNeeded(mWindowTokenClient); @@ -160,11 +162,20 @@ public class WindowTokenClientControllerTest { @Test public void testAttachToWindowToken() throws RemoteException { - mController.attachToWindowToken(mWindowTokenClient, mWindowToken); + doReturn(null).when(mWindowManagerService).attachWindowContextToWindowToken( + any(), any(), any()); + assertFalse(mController.attachToWindowToken(mWindowTokenClient, mWindowToken)); verify(mWindowManagerService).attachWindowContextToWindowToken( ActivityThread.currentActivityThread().getApplicationThread(), mWindowTokenClient, mWindowToken); + verify(mWindowTokenClient, never()).onConfigurationChanged(any(), anyInt(), anyBoolean()); + + doReturn(mWindowContextInfo).when(mWindowManagerService) + .attachWindowContextToWindowToken(any(), any(), any()); + + assertTrue(mController.attachToWindowToken(mWindowTokenClient, mWindowToken)); + verify(mWindowTokenClient).postOnConfigurationChanged(mConfiguration, DEFAULT_DISPLAY); } @Test @@ -173,6 +184,15 @@ public class WindowTokenClientControllerTest { verify(mWindowManagerService, never()).detachWindowContext(any()); + doReturn(null).when(mWindowManagerService).attachWindowContextToWindowToken( + any(), any(), any()); + mController.attachToWindowToken(mWindowTokenClient, mWindowToken); + mController.detachIfNeeded(mWindowTokenClient); + + verify(mWindowManagerService, never()).detachWindowContext(any()); + + doReturn(mWindowContextInfo).when(mWindowManagerService).attachWindowContextToWindowToken( + any(), any(), any()); mController.attachToWindowToken(mWindowTokenClient, mWindowToken); mController.detachIfNeeded(mWindowTokenClient); @@ -180,28 +200,43 @@ public class WindowTokenClientControllerTest { } @Test - public void testOnWindowContextConfigurationChanged() { - mController.onWindowContextConfigurationChanged( - mClientToken, mConfiguration, DEFAULT_DISPLAY); + public void testOnWindowContextInfoChanged() throws RemoteException { + doReturn(mWindowContextInfo).when(mWindowManagerService) + .attachWindowContextToWindowToken(any(), any(), any()); + + // No invoke if not attached. + mController.onWindowContextInfoChanged(mClientToken, mWindowContextInfo); verify(mWindowTokenClient, never()).onConfigurationChanged(any(), anyInt()); - mController.attachToWindowToken(mWindowTokenClient, mWindowToken); + // Invoke postOnConfigurationChanged when attached + assertTrue(mController.attachToWindowToken(mWindowTokenClient, mWindowToken)); - mController.onWindowContextConfigurationChanged( - mClientToken, mConfiguration, DEFAULT_DISPLAY); + verify(mWindowTokenClient).postOnConfigurationChanged(mConfiguration, DEFAULT_DISPLAY); - verify(mWindowTokenClient).onConfigurationChanged(mConfiguration, DEFAULT_DISPLAY); + // Invoke onConfigurationChanged when onWindowContextInfoChanged + mController.onWindowContextInfoChanged( + mClientToken, new WindowContextInfo(mConfiguration, DEFAULT_DISPLAY + 1)); + + verify(mWindowTokenClient).onConfigurationChanged(mConfiguration, DEFAULT_DISPLAY + 1); } @Test - public void testOnWindowContextWindowRemoved() { + public void testOnWindowContextWindowRemoved() throws RemoteException { + doReturn(mWindowContextInfo).when(mWindowManagerService) + .attachWindowContextToWindowToken(any(), any(), any()); + + // No invoke if not attached. mController.onWindowContextWindowRemoved(mClientToken); verify(mWindowTokenClient, never()).onWindowTokenRemoved(); + // No invoke if not onWindowTokenRemoved. mController.attachToWindowToken(mWindowTokenClient, mWindowToken); + verify(mWindowTokenClient, never()).onWindowTokenRemoved(); + + // Invoke onWindowTokenRemoved when onWindowContextWindowRemoved mController.onWindowContextWindowRemoved(mClientToken); verify(mWindowTokenClient).onWindowTokenRemoved(); diff --git a/services/core/java/com/android/server/wm/WindowContextListenerController.java b/services/core/java/com/android/server/wm/WindowContextListenerController.java index 26aab07695ca..726ae5c61d56 100644 --- a/services/core/java/com/android/server/wm/WindowContextListenerController.java +++ b/services/core/java/com/android/server/wm/WindowContextListenerController.java @@ -76,7 +76,7 @@ class WindowContextListenerController { @NonNull IBinder clientToken, @NonNull WindowContainer<?> container, @WindowType int type, @Nullable Bundle options) { registerWindowContainerListener(wpc, clientToken, container, type, options, - true /* shouDispatchConfigWhenRegistering */); + true /* shouldDispatchConfigWhenRegistering */); } /** @@ -91,19 +91,19 @@ class WindowContextListenerController { * @param container the {@link WindowContainer} which the listener is going to listen to. * @param type the window type * @param options a bundle used to pass window-related options. - * @param shouDispatchConfigWhenRegistering {@code true} to indicate the current + * @param shouldDispatchConfigWhenRegistering {@code true} to indicate the current * {@code container}'s config will dispatch to the client side when * registering the {@link WindowContextListenerImpl} */ void registerWindowContainerListener(@NonNull WindowProcessController wpc, @NonNull IBinder clientToken, @NonNull WindowContainer<?> container, @WindowType int type, @Nullable Bundle options, - boolean shouDispatchConfigWhenRegistering) { + boolean shouldDispatchConfigWhenRegistering) { WindowContextListenerImpl listener = mListeners.get(clientToken); if (listener == null) { listener = new WindowContextListenerImpl(wpc, clientToken, container, type, options); - listener.register(shouDispatchConfigWhenRegistering); + listener.register(shouldDispatchConfigWhenRegistering); } else { updateContainerForWindowContextListener(clientToken, container); } diff --git a/services/core/java/com/android/server/wm/WindowManagerService.java b/services/core/java/com/android/server/wm/WindowManagerService.java index 210378f79af1..261d6bc489b6 100644 --- a/services/core/java/com/android/server/wm/WindowManagerService.java +++ b/services/core/java/com/android/server/wm/WindowManagerService.java @@ -305,6 +305,7 @@ import android.window.ITaskFpsCallback; import android.window.ScreenCapture; import android.window.TaskSnapshot; import android.window.WindowContainerToken; +import android.window.WindowContextInfo; import com.android.internal.R; import com.android.internal.annotations.VisibleForTesting; @@ -2737,7 +2738,7 @@ public class WindowManagerService extends IWindowManager.Stub @Nullable @Override - public Configuration attachWindowContextToDisplayArea(@NonNull IApplicationThread appThread, + public WindowContextInfo attachWindowContextToDisplayArea(@NonNull IApplicationThread appThread, @NonNull IBinder clientToken, @LayoutParams.WindowType int type, int displayId, @Nullable Bundle options) { Objects.requireNonNull(appThread); @@ -2766,8 +2767,8 @@ public class WindowManagerService extends IWindowManager.Stub final DisplayArea<?> da = dc.findAreaForWindowType(type, options, callerCanManageAppTokens, false /* roundedCornerOverlay */); mWindowContextListenerController.registerWindowContainerListener(wpc, clientToken, - da, type, options, false /* shouDispatchConfigWhenRegistering */); - return da.getConfiguration(); + da, type, options, false /* shouldDispatchConfigWhenRegistering */); + return new WindowContextInfo(da.getConfiguration(), displayId); } } finally { Binder.restoreCallingIdentity(origId); @@ -2776,8 +2777,8 @@ public class WindowManagerService extends IWindowManager.Stub @Nullable @Override - public Configuration attachWindowContextToDisplayContent(@NonNull IApplicationThread appThread, - @NonNull IBinder clientToken, int displayId) { + public WindowContextInfo attachWindowContextToDisplayContent( + @NonNull IApplicationThread appThread, @NonNull IBinder clientToken, int displayId) { Objects.requireNonNull(appThread); Objects.requireNonNull(clientToken); final int callingPid = Binder.getCallingPid(); @@ -2809,16 +2810,17 @@ public class WindowManagerService extends IWindowManager.Stub mWindowContextListenerController.registerWindowContainerListener(wpc, clientToken, dc, INVALID_WINDOW_TYPE, null /* options */, - false /* shouDispatchConfigWhenRegistering */); - return dc.getConfiguration(); + false /* shouldDispatchConfigWhenRegistering */); + return new WindowContextInfo(dc.getConfiguration(), displayId); } } finally { Binder.restoreCallingIdentity(origId); } } + @Nullable @Override - public void attachWindowContextToWindowToken(@NonNull IApplicationThread appThread, + public WindowContextInfo attachWindowContextToWindowToken(@NonNull IApplicationThread appThread, @NonNull IBinder clientToken, @NonNull IBinder token) { Objects.requireNonNull(appThread); Objects.requireNonNull(clientToken); @@ -2834,13 +2836,13 @@ public class WindowManagerService extends IWindowManager.Stub if (wpc == null) { ProtoLog.w(WM_ERROR, "attachWindowContextToWindowToken: calling from" + " non-existing process pid=%d uid=%d", callingPid, callingUid); - return; + return null; } final WindowToken windowToken = mRoot.getWindowToken(token); if (windowToken == null) { ProtoLog.w(WM_ERROR, "Then token:%s is invalid. It might be " + "removed", token); - return; + return null; } final int type = mWindowContextListenerController.getWindowType(clientToken); if (type == INVALID_WINDOW_TYPE) { @@ -2854,10 +2856,13 @@ public class WindowManagerService extends IWindowManager.Stub } if (!mWindowContextListenerController.assertCallerCanModifyListener(clientToken, callerCanManageAppTokens, callingUid)) { - return; + return null; } mWindowContextListenerController.registerWindowContainerListener(wpc, clientToken, - windowToken, windowToken.windowType, windowToken.mOptions); + windowToken, windowToken.windowType, windowToken.mOptions, + false /* shouldDispatchConfigWhenRegistering */); + return new WindowContextInfo(windowToken.getConfiguration(), + windowToken.getDisplayContent().getDisplayId()); } } finally { Binder.restoreCallingIdentity(origId); diff --git a/services/tests/wmtests/src/com/android/server/wm/InputMethodDialogWindowContextTest.java b/services/tests/wmtests/src/com/android/server/wm/InputMethodDialogWindowContextTest.java index 1180ebdcaecb..c3db241f28ae 100644 --- a/services/tests/wmtests/src/com/android/server/wm/InputMethodDialogWindowContextTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/InputMethodDialogWindowContextTest.java @@ -47,6 +47,7 @@ import android.view.Display; import android.view.IWindowManager; import android.view.WindowManager; import android.view.WindowManagerGlobal; +import android.window.WindowContextInfo; import android.window.WindowTokenClient; import com.android.server.inputmethod.InputMethodDialogWindowContext; @@ -99,7 +100,7 @@ public class InputMethodDialogWindowContextTest extends WindowTestsBase { final WindowProcessController wpc = mAtm.getProcessController(appThread); mWm.mWindowContextListenerController.registerWindowContainerListener(wpc, clientToken, dc.getImeContainer(), TYPE_INPUT_METHOD_DIALOG, null /* options */); - return dc.getImeContainer().getConfiguration(); + return new WindowContextInfo(dc.getImeContainer().getConfiguration(), displayId); }).when(mIWindowManager).attachWindowContextToDisplayArea(any(), any(), eq(TYPE_INPUT_METHOD_DIALOG), anyInt(), any()); mDisplayManagerGlobal = DisplayManagerGlobal.getInstance(); 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 325176fbe7a8..55fda0521e01 100644 --- a/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java +++ b/services/tests/wmtests/src/com/android/server/wm/WindowManagerServiceTests.java @@ -468,7 +468,7 @@ public class WindowManagerServiceTests extends WindowTestsBase { mWm.attachWindowContextToWindowToken(mAppThread, new Binder(), windowToken.token); verify(mWm.mWindowContextListenerController, never()).registerWindowContainerListener( - any(), any(), any(), anyInt(), any()); + any(), any(), any(), anyInt(), any(), anyBoolean()); } @Test @@ -484,9 +484,9 @@ public class WindowManagerServiceTests extends WindowTestsBase { final IBinder clientToken = new Binder(); mWm.attachWindowContextToWindowToken(mAppThread, clientToken, windowToken.token); final WindowProcessController wpc = mAtm.getProcessController(mAppThread); - verify(mWm.mWindowContextListenerController).registerWindowContainerListener(eq(wpc), - eq(clientToken), eq(windowToken), eq(TYPE_INPUT_METHOD), - eq(windowToken.mOptions)); + verify(mWm.mWindowContextListenerController).registerWindowContainerListener(wpc, + clientToken, windowToken, TYPE_INPUT_METHOD, windowToken.mOptions, + false /* shouldDispatchConfigWhenRegistering */); } @Test @@ -514,7 +514,7 @@ public class WindowManagerServiceTests extends WindowTestsBase { new InsetsSourceControl.Array(), new Rect(), new float[1]); verify(mWm.mWindowContextListenerController, never()).registerWindowContainerListener(any(), - any(), any(), anyInt(), any()); + any(), any(), anyInt(), any(), anyBoolean()); } @Test |