Merge "Introduce WindowContextController" into sc-dev

This commit is contained in:
Charles Chen
2021-03-24 09:42:51 +00:00
committed by Android (Google) Code Review
4 changed files with 196 additions and 23 deletions

View File

@@ -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;
@@ -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
@@ -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);
}
@@ -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
@@ -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();
}

View File

@@ -0,0 +1,96 @@
/*
* 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();
}
}
}
}

View File

@@ -0,0 +1,93 @@
/*
* 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();
}
}

View File

@@ -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) {