Loading core/java/android/window/WindowContext.java +5 −22 Original line number Diff line number Diff line Loading @@ -27,10 +27,7 @@ import android.content.ContextWrapper; import android.content.res.Configuration; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.view.IWindowManager; import android.view.WindowManager; import android.view.WindowManagerGlobal; import com.android.internal.annotations.VisibleForTesting; Loading @@ -48,13 +45,11 @@ import java.lang.ref.Reference; @UiContext public class WindowContext extends ContextWrapper { private final WindowManager mWindowManager; private final IWindowManager mWms; private final @NonNull IBinder mToken; private final @WindowManager.LayoutParams.WindowType int mType; private final @Nullable Bundle mOptions; private boolean mListenerRegistered; private final ComponentCallbacksController mCallbacksController = new ComponentCallbacksController(); private final WindowContextController mController; /** * Default constructor. Will generate a {@link WindowTokenClient} and attach this context to Loading @@ -69,9 +64,9 @@ public class WindowContext extends ContextWrapper { mType = type; mOptions = options; mWms = WindowManagerGlobal.getWindowManagerService(); mToken = getWindowContextToken(); mWindowManager = createWindowContextWindowManager(this); IBinder token = getWindowContextToken(); mController = new WindowContextController(token); Reference.reachabilityFence(this); } Loading @@ -81,12 +76,7 @@ public class WindowContext extends ContextWrapper { * to receive configuration changes of the associated {@link WindowManager} node. */ public void registerWithServer() { try { mListenerRegistered = mWms.registerWindowContextListener(mToken, mType, getDisplayId(), mOptions); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } mController.registerListener(mType, getDisplayId(), mOptions); } @Override Loading @@ -106,14 +96,7 @@ public class WindowContext extends ContextWrapper { /** Used for test to invoke because we can't invoke finalize directly. */ @VisibleForTesting public void release() { if (mListenerRegistered) { mListenerRegistered = false; try { mWms.unregisterWindowContextListener(mToken); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } mController.unregisterListenerIfNeeded(); destroy(); } Loading core/java/android/window/WindowContextController.java 0 → 100644 +96 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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 android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.view.IWindowManager; import android.view.WindowManager.LayoutParams.WindowType; import android.view.WindowManagerGlobal; import com.android.internal.annotations.VisibleForTesting; /** * The controller to manage {@link WindowContext} listener, such as registering and unregistering * the listener. * * @hide */ public class WindowContextController { private final IWindowManager mWms; @VisibleForTesting public boolean mListenerRegistered; @NonNull private final IBinder mToken; /** * Window Context Controller constructor * * @param token The token to register to the window context listener. It is usually from * {@link Context#getWindowContextToken()}. */ public WindowContextController(@NonNull IBinder token) { mToken = token; mWms = WindowManagerGlobal.getWindowManagerService(); } /** Used for test only. DO NOT USE it in production code. */ @VisibleForTesting public WindowContextController(@NonNull IBinder token, IWindowManager mockWms) { mToken = token; mWms = mockWms; } /** * Registers the {@code mToken} to the window context listener. * * @param type The window type of the {@link WindowContext} * @param displayId The {@link Context#getDisplayId() ID of display} to associate with * @param options The window context launched option */ public void registerListener(@WindowType int type, int displayId, @Nullable Bundle options) { if (mListenerRegistered) { throw new UnsupportedOperationException("A Window Context can only register a listener" + " once."); } try { mListenerRegistered = mWms.registerWindowContextListener(mToken, type, displayId, options); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Unregisters the window context listener associated with the {@code mToken} if it has been * registered. */ public void unregisterListenerIfNeeded() { if (mListenerRegistered) { try { mWms.unregisterWindowContextListener(mToken); mListenerRegistered = false; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } } core/tests/coretests/src/android/window/WindowContextControllerTest.java 0 → 100644 +93 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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 android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.os.Binder; import android.platform.test.annotations.Presubmit; import android.view.IWindowManager; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; /** * Tests for {@link WindowContextController} * * <p>Build/Install/Run: * atest FrameworksCoreTests:WindowContextControllerTest * * <p>This test class is a part of Window Manager Service tests and specified in * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. */ @RunWith(AndroidJUnit4.class) @SmallTest @Presubmit public class WindowContextControllerTest { private WindowContextController mController; private IWindowManager mMockWms; @Before public void setUp() throws Exception { mMockWms = mock(IWindowManager.class); mController = new WindowContextController(new Binder(), mMockWms); doReturn(true).when(mMockWms).registerWindowContextListener( any(), anyInt(), anyInt(), any()); } @Test(expected = UnsupportedOperationException.class) public void testRegisterListenerTwiceThrowException() { mController.registerListener(TYPE_APPLICATION_OVERLAY, DEFAULT_DISPLAY, null /* options */); mController.registerListener(TYPE_APPLICATION_OVERLAY, DEFAULT_DISPLAY, null /* options */); } @Test public void testUnregisterListenerIfNeeded_NotRegisteredYet_DoNothing() throws Exception { mController.unregisterListenerIfNeeded(); verify(mMockWms, never()).registerWindowContextListener(any(), anyInt(), anyInt(), any()); } @Test public void testRegisterAndUnRegisterListener() { mController.registerListener(TYPE_APPLICATION_OVERLAY, DEFAULT_DISPLAY, null /* options */); assertThat(mController.mListenerRegistered).isTrue(); mController.unregisterListenerIfNeeded(); assertThat(mController.mListenerRegistered).isFalse(); } } tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java +2 −1 Original line number Diff line number Diff line Loading @@ -61,7 +61,8 @@ public final class FrameworksTestsFilter extends SelectTest { "android.view.PendingInsetsControllerTest", "android.window.WindowContextTest", "android.window.WindowMetricsHelperTest", "android.app.activity.ActivityThreadTest" "android.app.activity.ActivityThreadTest", "android.window.WindowContextControllerTest" }; public FrameworksTestsFilter(Bundle testArgs) { Loading Loading
core/java/android/window/WindowContext.java +5 −22 Original line number Diff line number Diff line Loading @@ -27,10 +27,7 @@ import android.content.ContextWrapper; import android.content.res.Configuration; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.view.IWindowManager; import android.view.WindowManager; import android.view.WindowManagerGlobal; import com.android.internal.annotations.VisibleForTesting; Loading @@ -48,13 +45,11 @@ import java.lang.ref.Reference; @UiContext public class WindowContext extends ContextWrapper { private final WindowManager mWindowManager; private final IWindowManager mWms; private final @NonNull IBinder mToken; private final @WindowManager.LayoutParams.WindowType int mType; private final @Nullable Bundle mOptions; private boolean mListenerRegistered; private final ComponentCallbacksController mCallbacksController = new ComponentCallbacksController(); private final WindowContextController mController; /** * Default constructor. Will generate a {@link WindowTokenClient} and attach this context to Loading @@ -69,9 +64,9 @@ public class WindowContext extends ContextWrapper { mType = type; mOptions = options; mWms = WindowManagerGlobal.getWindowManagerService(); mToken = getWindowContextToken(); mWindowManager = createWindowContextWindowManager(this); IBinder token = getWindowContextToken(); mController = new WindowContextController(token); Reference.reachabilityFence(this); } Loading @@ -81,12 +76,7 @@ public class WindowContext extends ContextWrapper { * to receive configuration changes of the associated {@link WindowManager} node. */ public void registerWithServer() { try { mListenerRegistered = mWms.registerWindowContextListener(mToken, mType, getDisplayId(), mOptions); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } mController.registerListener(mType, getDisplayId(), mOptions); } @Override Loading @@ -106,14 +96,7 @@ public class WindowContext extends ContextWrapper { /** Used for test to invoke because we can't invoke finalize directly. */ @VisibleForTesting public void release() { if (mListenerRegistered) { mListenerRegistered = false; try { mWms.unregisterWindowContextListener(mToken); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } mController.unregisterListenerIfNeeded(); destroy(); } Loading
core/java/android/window/WindowContextController.java 0 → 100644 +96 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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 android.annotation.NonNull; import android.annotation.Nullable; import android.content.Context; import android.os.Bundle; import android.os.IBinder; import android.os.RemoteException; import android.view.IWindowManager; import android.view.WindowManager.LayoutParams.WindowType; import android.view.WindowManagerGlobal; import com.android.internal.annotations.VisibleForTesting; /** * The controller to manage {@link WindowContext} listener, such as registering and unregistering * the listener. * * @hide */ public class WindowContextController { private final IWindowManager mWms; @VisibleForTesting public boolean mListenerRegistered; @NonNull private final IBinder mToken; /** * Window Context Controller constructor * * @param token The token to register to the window context listener. It is usually from * {@link Context#getWindowContextToken()}. */ public WindowContextController(@NonNull IBinder token) { mToken = token; mWms = WindowManagerGlobal.getWindowManagerService(); } /** Used for test only. DO NOT USE it in production code. */ @VisibleForTesting public WindowContextController(@NonNull IBinder token, IWindowManager mockWms) { mToken = token; mWms = mockWms; } /** * Registers the {@code mToken} to the window context listener. * * @param type The window type of the {@link WindowContext} * @param displayId The {@link Context#getDisplayId() ID of display} to associate with * @param options The window context launched option */ public void registerListener(@WindowType int type, int displayId, @Nullable Bundle options) { if (mListenerRegistered) { throw new UnsupportedOperationException("A Window Context can only register a listener" + " once."); } try { mListenerRegistered = mWms.registerWindowContextListener(mToken, type, displayId, options); } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } /** * Unregisters the window context listener associated with the {@code mToken} if it has been * registered. */ public void unregisterListenerIfNeeded() { if (mListenerRegistered) { try { mWms.unregisterWindowContextListener(mToken); mListenerRegistered = false; } catch (RemoteException e) { throw e.rethrowFromSystemServer(); } } } }
core/tests/coretests/src/android/window/WindowContextControllerTest.java 0 → 100644 +93 −0 Original line number Diff line number Diff line /* * Copyright (C) 2021 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 android.view.Display.DEFAULT_DISPLAY; import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY; import static com.google.common.truth.Truth.assertThat; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import android.os.Binder; import android.platform.test.annotations.Presubmit; import android.view.IWindowManager; import androidx.test.filters.SmallTest; import androidx.test.runner.AndroidJUnit4; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; /** * Tests for {@link WindowContextController} * * <p>Build/Install/Run: * atest FrameworksCoreTests:WindowContextControllerTest * * <p>This test class is a part of Window Manager Service tests and specified in * {@link com.android.server.wm.test.filters.FrameworksTestsFilter}. */ @RunWith(AndroidJUnit4.class) @SmallTest @Presubmit public class WindowContextControllerTest { private WindowContextController mController; private IWindowManager mMockWms; @Before public void setUp() throws Exception { mMockWms = mock(IWindowManager.class); mController = new WindowContextController(new Binder(), mMockWms); doReturn(true).when(mMockWms).registerWindowContextListener( any(), anyInt(), anyInt(), any()); } @Test(expected = UnsupportedOperationException.class) public void testRegisterListenerTwiceThrowException() { mController.registerListener(TYPE_APPLICATION_OVERLAY, DEFAULT_DISPLAY, null /* options */); mController.registerListener(TYPE_APPLICATION_OVERLAY, DEFAULT_DISPLAY, null /* options */); } @Test public void testUnregisterListenerIfNeeded_NotRegisteredYet_DoNothing() throws Exception { mController.unregisterListenerIfNeeded(); verify(mMockWms, never()).registerWindowContextListener(any(), anyInt(), anyInt(), any()); } @Test public void testRegisterAndUnRegisterListener() { mController.registerListener(TYPE_APPLICATION_OVERLAY, DEFAULT_DISPLAY, null /* options */); assertThat(mController.mListenerRegistered).isTrue(); mController.unregisterListenerIfNeeded(); assertThat(mController.mListenerRegistered).isFalse(); } }
tests/utils/testutils/java/com/android/server/wm/test/filters/FrameworksTestsFilter.java +2 −1 Original line number Diff line number Diff line Loading @@ -61,7 +61,8 @@ public final class FrameworksTestsFilter extends SelectTest { "android.view.PendingInsetsControllerTest", "android.window.WindowContextTest", "android.window.WindowMetricsHelperTest", "android.app.activity.ActivityThreadTest" "android.app.activity.ActivityThreadTest", "android.window.WindowContextControllerTest" }; public FrameworksTestsFilter(Bundle testArgs) { Loading