Merge "Migrate WindowContext#onConfigurationChanged to ClientTransaction (2/n)" into main
This commit is contained in:
@@ -65,6 +65,7 @@ import android.app.servertransaction.PendingTransactionActions.StopInfo;
|
||||
import android.app.servertransaction.ResumeActivityItem;
|
||||
import android.app.servertransaction.TransactionExecutor;
|
||||
import android.app.servertransaction.TransactionExecutorHelper;
|
||||
import android.app.servertransaction.WindowTokenClientController;
|
||||
import android.bluetooth.BluetoothFrameworkInitializer;
|
||||
import android.companion.virtual.VirtualDeviceManager;
|
||||
import android.compat.annotation.UnsupportedAppUsage;
|
||||
@@ -6221,6 +6222,18 @@ public final class ActivityThread extends ClientTransactionHandler
|
||||
false /* clearPending */);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleWindowContextConfigurationChanged(@NonNull IBinder clientToken,
|
||||
@NonNull Configuration configuration, int displayId) {
|
||||
WindowTokenClientController.getInstance().onWindowContextConfigurationChanged(clientToken,
|
||||
configuration, displayId);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleWindowContextWindowRemoval(@NonNull IBinder clientToken) {
|
||||
WindowTokenClientController.getInstance().onWindowContextWindowRemoved(clientToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends windowing mode change callbacks to {@link Activity} if applicable.
|
||||
*
|
||||
|
||||
@@ -163,6 +163,13 @@ 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.WindowContext} window removal event. */
|
||||
public abstract void handleWindowContextWindowRemoval(@NonNull IBinder clientToken);
|
||||
|
||||
/** Deliver result from another activity. */
|
||||
public abstract void handleSendResult(
|
||||
@NonNull ActivityClientRecord r, List<ResultInfo> results, String reason);
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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.app.servertransaction;
|
||||
|
||||
import static android.view.Display.INVALID_DISPLAY;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ClientTransactionHandler;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcel;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* {@link android.window.WindowContext} configuration change message.
|
||||
* @hide
|
||||
*/
|
||||
public class WindowContextConfigurationChangeItem extends ClientTransactionItem {
|
||||
|
||||
@Nullable
|
||||
private IBinder mClientToken;
|
||||
@Nullable
|
||||
private Configuration mConfiguration;
|
||||
private int mDisplayId;
|
||||
|
||||
@Override
|
||||
public void execute(@NonNull ClientTransactionHandler client, @NonNull IBinder token,
|
||||
@NonNull PendingTransactionActions pendingActions) {
|
||||
client.handleWindowContextConfigurationChanged(mClientToken, mConfiguration, mDisplayId);
|
||||
}
|
||||
|
||||
// ObjectPoolItem implementation
|
||||
|
||||
private WindowContextConfigurationChangeItem() {}
|
||||
|
||||
/** Obtains an instance initialized with provided params. */
|
||||
public static WindowContextConfigurationChangeItem obtain(
|
||||
@NonNull IBinder clientToken, @NonNull Configuration config, int displayId) {
|
||||
WindowContextConfigurationChangeItem instance =
|
||||
ObjectPool.obtain(WindowContextConfigurationChangeItem.class);
|
||||
if (instance == null) {
|
||||
instance = new WindowContextConfigurationChangeItem();
|
||||
}
|
||||
instance.mClientToken = requireNonNull(clientToken);
|
||||
instance.mConfiguration = requireNonNull(config);
|
||||
instance.mDisplayId = displayId;
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recycle() {
|
||||
mClientToken = null;
|
||||
mConfiguration = null;
|
||||
mDisplayId = INVALID_DISPLAY;
|
||||
ObjectPool.recycle(this);
|
||||
}
|
||||
|
||||
// Parcelable implementation
|
||||
|
||||
/** Writes to Parcel. */
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeStrongBinder(mClientToken);
|
||||
dest.writeTypedObject(mConfiguration, flags);
|
||||
dest.writeInt(mDisplayId);
|
||||
}
|
||||
|
||||
/** Reads from Parcel. */
|
||||
private WindowContextConfigurationChangeItem(@NonNull Parcel in) {
|
||||
mClientToken = in.readStrongBinder();
|
||||
mConfiguration = in.readTypedObject(Configuration.CREATOR);
|
||||
mDisplayId = in.readInt();
|
||||
}
|
||||
|
||||
public static final @NonNull Creator<WindowContextConfigurationChangeItem> CREATOR =
|
||||
new Creator<>() {
|
||||
public WindowContextConfigurationChangeItem createFromParcel(Parcel in) {
|
||||
return new WindowContextConfigurationChangeItem(in);
|
||||
}
|
||||
|
||||
public WindowContextConfigurationChangeItem[] newArray(int size) {
|
||||
return new WindowContextConfigurationChangeItem[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final WindowContextConfigurationChangeItem other = (WindowContextConfigurationChangeItem) o;
|
||||
return Objects.equals(mClientToken, other.mClientToken)
|
||||
&& Objects.equals(mConfiguration, other.mConfiguration)
|
||||
&& mDisplayId == other.mDisplayId;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 17;
|
||||
result = 31 * result + Objects.hashCode(mClientToken);
|
||||
result = 31 * result + Objects.hashCode(mConfiguration);
|
||||
result = 31 * result + mDisplayId;
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WindowContextConfigurationChangeItem{clientToken=" + mClientToken
|
||||
+ ", config=" + mConfiguration
|
||||
+ ", displayId=" + mDisplayId
|
||||
+ "}";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,112 @@
|
||||
/*
|
||||
* 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.app.servertransaction;
|
||||
|
||||
import static java.util.Objects.requireNonNull;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.ClientTransactionHandler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcel;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* {@link android.window.WindowContext} window removal message.
|
||||
* @hide
|
||||
*/
|
||||
public class WindowContextWindowRemovalItem extends ClientTransactionItem {
|
||||
|
||||
@Nullable
|
||||
private IBinder mClientToken;
|
||||
|
||||
@Override
|
||||
public void execute(@NonNull ClientTransactionHandler client, @NonNull IBinder token,
|
||||
@NonNull PendingTransactionActions pendingActions) {
|
||||
client.handleWindowContextWindowRemoval(mClientToken);
|
||||
}
|
||||
|
||||
// ObjectPoolItem implementation
|
||||
|
||||
private WindowContextWindowRemovalItem() {}
|
||||
|
||||
/** Obtains an instance initialized with provided params. */
|
||||
public static WindowContextWindowRemovalItem obtain(@NonNull IBinder clientToken) {
|
||||
WindowContextWindowRemovalItem instance =
|
||||
ObjectPool.obtain(WindowContextWindowRemovalItem.class);
|
||||
if (instance == null) {
|
||||
instance = new WindowContextWindowRemovalItem();
|
||||
}
|
||||
instance.mClientToken = requireNonNull(clientToken);
|
||||
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void recycle() {
|
||||
mClientToken = null;
|
||||
ObjectPool.recycle(this);
|
||||
}
|
||||
|
||||
// Parcelable implementation
|
||||
|
||||
/** Writes to Parcel. */
|
||||
@Override
|
||||
public void writeToParcel(@NonNull Parcel dest, int flags) {
|
||||
dest.writeStrongBinder(mClientToken);
|
||||
}
|
||||
|
||||
/** Reads from Parcel. */
|
||||
private WindowContextWindowRemovalItem(@NonNull Parcel in) {
|
||||
mClientToken = in.readStrongBinder();
|
||||
}
|
||||
|
||||
public static final @NonNull Creator<WindowContextWindowRemovalItem> CREATOR = new Creator<>() {
|
||||
public WindowContextWindowRemovalItem createFromParcel(Parcel in) {
|
||||
return new WindowContextWindowRemovalItem(in);
|
||||
}
|
||||
|
||||
public WindowContextWindowRemovalItem[] newArray(int size) {
|
||||
return new WindowContextWindowRemovalItem[size];
|
||||
}
|
||||
};
|
||||
|
||||
@Override
|
||||
public boolean equals(@Nullable Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
final WindowContextWindowRemovalItem other = (WindowContextWindowRemovalItem) o;
|
||||
return Objects.equals(mClientToken, other.mClientToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int result = 17;
|
||||
result = 31 * result + Objects.hashCode(mClientToken);
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "WindowContextWindowRemovalItem{clientToken=" + mClientToken + "}";
|
||||
}
|
||||
}
|
||||
@@ -27,6 +27,7 @@ import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.Log;
|
||||
import android.view.IWindowManager;
|
||||
import android.window.WindowContext;
|
||||
import android.window.WindowTokenClient;
|
||||
@@ -41,6 +42,7 @@ import com.android.internal.annotations.VisibleForTesting;
|
||||
*/
|
||||
public class WindowTokenClientController {
|
||||
|
||||
private static final String TAG = WindowTokenClientController.class.getSimpleName();
|
||||
private static WindowTokenClientController sController;
|
||||
|
||||
private final Object mLock = new Object();
|
||||
@@ -61,7 +63,7 @@ public class WindowTokenClientController {
|
||||
|
||||
/** Overrides the {@link #getInstance()} for test only. */
|
||||
@VisibleForTesting
|
||||
public static void overrideInstance(@NonNull WindowTokenClientController controller) {
|
||||
public static void overrideForTesting(@NonNull WindowTokenClientController controller) {
|
||||
synchronized (WindowTokenClientController.class) {
|
||||
sController = controller;
|
||||
}
|
||||
@@ -90,7 +92,7 @@ public class WindowTokenClientController {
|
||||
if (configuration == null) {
|
||||
return false;
|
||||
}
|
||||
onWindowContainerTokenAttached(client, displayId, configuration);
|
||||
onWindowContextTokenAttached(client, displayId, configuration);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -116,7 +118,7 @@ public class WindowTokenClientController {
|
||||
if (configuration == null) {
|
||||
return false;
|
||||
}
|
||||
onWindowContainerTokenAttached(client, displayId, configuration);
|
||||
onWindowContextTokenAttached(client, displayId, configuration);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -153,7 +155,7 @@ public class WindowTokenClientController {
|
||||
}
|
||||
}
|
||||
|
||||
private void onWindowContainerTokenAttached(@NonNull WindowTokenClient client, int displayId,
|
||||
private void onWindowContextTokenAttached(@NonNull WindowTokenClient client, int displayId,
|
||||
@NonNull Configuration configuration) {
|
||||
synchronized (mLock) {
|
||||
mWindowTokenClientMap.put(client.asBinder(), client);
|
||||
@@ -161,4 +163,33 @@ public class WindowTokenClientController {
|
||||
client.onConfigurationChanged(configuration, displayId,
|
||||
false /* shouldReportConfigChange */);
|
||||
}
|
||||
|
||||
/** Called when receives {@link WindowContextConfigurationChangeItem}. */
|
||||
public void onWindowContextConfigurationChanged(@NonNull IBinder clientToken,
|
||||
@NonNull Configuration configuration, int displayId) {
|
||||
final WindowTokenClient windowTokenClient = getWindowTokenClient(clientToken);
|
||||
if (windowTokenClient != null) {
|
||||
windowTokenClient.onConfigurationChanged(configuration, displayId);
|
||||
}
|
||||
}
|
||||
|
||||
/** Called when receives {@link WindowContextWindowRemovalItem}. */
|
||||
public void onWindowContextWindowRemoved(@NonNull IBinder clientToken) {
|
||||
final WindowTokenClient windowTokenClient = getWindowTokenClient(clientToken);
|
||||
if (windowTokenClient != null) {
|
||||
windowTokenClient.onWindowTokenRemoved();
|
||||
}
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private WindowTokenClient getWindowTokenClient(@NonNull IBinder clientToken) {
|
||||
final WindowTokenClient windowTokenClient;
|
||||
synchronized (mLock) {
|
||||
windowTokenClient = mWindowTokenClientMap.get(clientToken);
|
||||
}
|
||||
if (windowTokenClient == null) {
|
||||
Log.w(TAG, "Can't find attached WindowTokenClient for " + clientToken);
|
||||
}
|
||||
return windowTokenClient;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ import android.util.ArraySet;
|
||||
import android.util.Log;
|
||||
import android.view.inputmethod.InputMethodManager;
|
||||
|
||||
import com.android.internal.annotations.VisibleForTesting;
|
||||
import com.android.internal.util.FastPrintWriter;
|
||||
|
||||
import java.io.FileDescriptor;
|
||||
@@ -184,6 +185,15 @@ public final class WindowManagerGlobal {
|
||||
}
|
||||
}
|
||||
|
||||
/** Overrides the {@link #getWindowManagerService()} for test only. */
|
||||
@VisibleForTesting
|
||||
public static void overrideWindowManagerServiceForTesting(
|
||||
@NonNull IWindowManager windowManager) {
|
||||
synchronized (WindowManagerGlobal.class) {
|
||||
sWindowManagerService = windowManager;
|
||||
}
|
||||
}
|
||||
|
||||
@UnsupportedAppUsage
|
||||
public static IWindowSession getWindowSession() {
|
||||
synchronized (WindowManagerGlobal.class) {
|
||||
|
||||
@@ -20,7 +20,6 @@ import static android.window.ConfigurationHelper.isDifferentDisplay;
|
||||
import static android.window.ConfigurationHelper.shouldUpdateResources;
|
||||
|
||||
import android.annotation.AnyThread;
|
||||
import android.annotation.BinderThread;
|
||||
import android.annotation.MainThread;
|
||||
import android.annotation.NonNull;
|
||||
import android.app.ActivityThread;
|
||||
@@ -97,9 +96,10 @@ public class WindowTokenClient extends IWindowToken.Stub {
|
||||
* @param newConfig the updated {@link Configuration}
|
||||
* @param newDisplayId the updated {@link android.view.Display} ID
|
||||
*/
|
||||
@BinderThread
|
||||
@AnyThread
|
||||
@Override
|
||||
public void onConfigurationChanged(Configuration newConfig, int newDisplayId) {
|
||||
// TODO(b/290876897): No need to post on mHandler after migrating to ClientTransaction
|
||||
mHandler.post(PooledLambda.obtainRunnable(this::onConfigurationChanged, newConfig,
|
||||
newDisplayId, true /* shouldReportConfigChange */).recycleOnUse());
|
||||
}
|
||||
@@ -188,9 +188,10 @@ public class WindowTokenClient extends IWindowToken.Stub {
|
||||
}
|
||||
}
|
||||
|
||||
@BinderThread
|
||||
@AnyThread
|
||||
@Override
|
||||
public void onWindowTokenRemoved() {
|
||||
// TODO(b/290876897): No need to post on mHandler after migrating to ClientTransaction
|
||||
mHandler.post(PooledLambda.obtainRunnable(
|
||||
WindowTokenClient::onWindowTokenRemovedInner, this).recycleOnUse());
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ import static android.content.Intent.ACTION_EDIT;
|
||||
import static android.content.Intent.ACTION_VIEW;
|
||||
import static android.content.res.Configuration.ORIENTATION_LANDSCAPE;
|
||||
import static android.content.res.Configuration.ORIENTATION_PORTRAIT;
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
import static android.view.Display.INVALID_DISPLAY;
|
||||
|
||||
import static com.google.common.truth.Truth.assertThat;
|
||||
@@ -29,6 +30,8 @@ import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotEquals;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Activity;
|
||||
@@ -46,6 +49,7 @@ import android.app.servertransaction.ConfigurationChangeItem;
|
||||
import android.app.servertransaction.NewIntentItem;
|
||||
import android.app.servertransaction.ResumeActivityItem;
|
||||
import android.app.servertransaction.StopActivityItem;
|
||||
import android.app.servertransaction.WindowTokenClientController;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.res.CompatibilityInfo;
|
||||
@@ -70,6 +74,7 @@ import androidx.test.runner.AndroidJUnit4;
|
||||
import com.android.internal.content.ReferrerIntent;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -83,7 +88,7 @@ import java.util.function.Consumer;
|
||||
/**
|
||||
* Test for verifying {@link android.app.ActivityThread} class.
|
||||
* Build/Install/Run:
|
||||
* atest FrameworksCoreTests:android.app.activity.ActivityThreadTest
|
||||
* atest FrameworksCoreTests:ActivityThreadTest
|
||||
*/
|
||||
@RunWith(AndroidJUnit4.class)
|
||||
@MediumTest
|
||||
@@ -100,14 +105,24 @@ public class ActivityThreadTest {
|
||||
new ActivityTestRule<>(TestActivity.class, true /* initialTouchMode */,
|
||||
false /* launchActivity */);
|
||||
|
||||
private WindowTokenClientController mOriginalWindowTokenClientController;
|
||||
|
||||
private ArrayList<VirtualDisplay> mCreatedVirtualDisplays;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
// Keep track of the original controller, so that it can be used to restore in tearDown()
|
||||
// when there is override in some test cases.
|
||||
mOriginalWindowTokenClientController = WindowTokenClientController.getInstance();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
if (mCreatedVirtualDisplays != null) {
|
||||
mCreatedVirtualDisplays.forEach(VirtualDisplay::release);
|
||||
mCreatedVirtualDisplays = null;
|
||||
}
|
||||
WindowTokenClientController.overrideForTesting(mOriginalWindowTokenClientController);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -730,6 +745,39 @@ public class ActivityThreadTest {
|
||||
assertFalse(activity.enterPipSkipped());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleWindowContextConfigurationChanged() {
|
||||
final Activity activity = mActivityTestRule.launchActivity(new Intent());
|
||||
final ActivityThread activityThread = activity.getActivityThread();
|
||||
final WindowTokenClientController windowTokenClientController =
|
||||
mock(WindowTokenClientController.class);
|
||||
WindowTokenClientController.overrideForTesting(windowTokenClientController);
|
||||
final IBinder clientToken = mock(IBinder.class);
|
||||
final Configuration configuration = new Configuration();
|
||||
|
||||
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> activityThread
|
||||
.handleWindowContextConfigurationChanged(
|
||||
clientToken, configuration, DEFAULT_DISPLAY));
|
||||
|
||||
verify(windowTokenClientController).onWindowContextConfigurationChanged(
|
||||
clientToken, configuration, DEFAULT_DISPLAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHandleWindowContextWindowRemoval() {
|
||||
final Activity activity = mActivityTestRule.launchActivity(new Intent());
|
||||
final ActivityThread activityThread = activity.getActivityThread();
|
||||
final WindowTokenClientController windowTokenClientController =
|
||||
mock(WindowTokenClientController.class);
|
||||
WindowTokenClientController.overrideForTesting(windowTokenClientController);
|
||||
final IBinder clientToken = mock(IBinder.class);
|
||||
|
||||
InstrumentationRegistry.getInstrumentation().runOnMainSync(() -> activityThread
|
||||
.handleWindowContextWindowRemoval(clientToken));
|
||||
|
||||
verify(windowTokenClientController).onWindowContextWindowRemoved(clientToken);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calls {@link ActivityThread#handleActivityConfigurationChanged(ActivityClientRecord,
|
||||
* Configuration, int)} to try to push activity configuration to the activity for the given
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* 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.app.servertransaction;
|
||||
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.ClientTransactionHandler;
|
||||
import android.content.res.Configuration;
|
||||
import android.os.IBinder;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
/**
|
||||
* Tests for {@link WindowContextConfigurationChangeItem}.
|
||||
*
|
||||
* Build/Install/Run:
|
||||
* atest FrameworksCoreTests:WindowContextConfigurationChangeItemTest
|
||||
*/
|
||||
public class WindowContextConfigurationChangeItemTest {
|
||||
|
||||
@Mock
|
||||
private ClientTransactionHandler mHandler;
|
||||
@Mock
|
||||
private IBinder mToken;
|
||||
@Mock
|
||||
private PendingTransactionActions mPendingActions;
|
||||
@Mock
|
||||
private IBinder mClientToken;
|
||||
// Can't mock final class.
|
||||
private final Configuration mConfiguration = new Configuration();
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecute() {
|
||||
final WindowContextConfigurationChangeItem item = WindowContextConfigurationChangeItem
|
||||
.obtain(mClientToken, mConfiguration, DEFAULT_DISPLAY);
|
||||
item.execute(mHandler, mToken, mPendingActions);
|
||||
|
||||
verify(mHandler).handleWindowContextConfigurationChanged(mClientToken, mConfiguration,
|
||||
DEFAULT_DISPLAY);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* 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.app.servertransaction;
|
||||
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import android.app.ClientTransactionHandler;
|
||||
import android.os.IBinder;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
/**
|
||||
* Tests for {@link WindowContextWindowRemovalItem}.
|
||||
*
|
||||
* Build/Install/Run:
|
||||
* atest FrameworksCoreTests:WindowContextWindowRemovalItemTest
|
||||
*/
|
||||
public class WindowContextWindowRemovalItemTest {
|
||||
|
||||
@Mock
|
||||
private ClientTransactionHandler mHandler;
|
||||
@Mock
|
||||
private IBinder mToken;
|
||||
@Mock
|
||||
private PendingTransactionActions mPendingActions;
|
||||
@Mock
|
||||
private IBinder mClientToken;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExecute() {
|
||||
final WindowContextWindowRemovalItem item = WindowContextWindowRemovalItem.obtain(
|
||||
mClientToken);
|
||||
item.execute(mHandler, mToken, mPendingActions);
|
||||
|
||||
verify(mHandler).handleWindowContextWindowRemoval(mClientToken);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* 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.app.servertransaction;
|
||||
|
||||
import static android.view.Display.DEFAULT_DISPLAY;
|
||||
import static android.view.WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY;
|
||||
|
||||
import static org.mockito.ArgumentMatchers.any;
|
||||
import static org.mockito.ArgumentMatchers.anyBoolean;
|
||||
import static org.mockito.ArgumentMatchers.anyInt;
|
||||
import static org.mockito.Mockito.doReturn;
|
||||
import static org.mockito.Mockito.never;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.verify;
|
||||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import android.content.res.Configuration;
|
||||
import android.os.IBinder;
|
||||
import android.os.RemoteException;
|
||||
import android.platform.test.annotations.Presubmit;
|
||||
import android.view.IWindowManager;
|
||||
import android.view.WindowManagerGlobal;
|
||||
import android.window.WindowTokenClient;
|
||||
|
||||
import androidx.test.filters.SmallTest;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.MockitoAnnotations;
|
||||
|
||||
/**
|
||||
* Tests for {@link WindowTokenClientController}.
|
||||
*
|
||||
* Build/Install/Run:
|
||||
* atest FrameworksCoreTests:WindowTokenClientControllerTest
|
||||
*/
|
||||
@SmallTest
|
||||
@Presubmit
|
||||
public class WindowTokenClientControllerTest {
|
||||
|
||||
@Mock
|
||||
private IWindowManager mWindowManagerService;
|
||||
@Mock
|
||||
private WindowTokenClient mWindowTokenClient;
|
||||
@Mock
|
||||
private IBinder mClientToken;
|
||||
@Mock
|
||||
private IBinder mWindowToken;
|
||||
// Can't mock final class.
|
||||
private final Configuration mConfiguration = new Configuration();
|
||||
|
||||
private IWindowManager mOriginalWindowManagerService;
|
||||
|
||||
private WindowTokenClientController mController;
|
||||
|
||||
@Before
|
||||
public void setup() {
|
||||
MockitoAnnotations.initMocks(this);
|
||||
mOriginalWindowManagerService = WindowManagerGlobal.getWindowManagerService();
|
||||
WindowManagerGlobal.overrideWindowManagerServiceForTesting(mWindowManagerService);
|
||||
doReturn(mClientToken).when(mWindowTokenClient).asBinder();
|
||||
mController = spy(WindowTokenClientController.getInstance());
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
WindowManagerGlobal.overrideWindowManagerServiceForTesting(mOriginalWindowManagerService);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttachToDisplayArea() throws RemoteException {
|
||||
doReturn(null).when(mWindowManagerService).attachWindowContextToDisplayArea(
|
||||
any(), anyInt(), anyInt(), any());
|
||||
|
||||
assertFalse(mController.attachToDisplayArea(mWindowTokenClient, TYPE_APPLICATION_OVERLAY,
|
||||
DEFAULT_DISPLAY, null /* options */));
|
||||
verify(mWindowManagerService).attachWindowContextToDisplayArea(mWindowTokenClient,
|
||||
TYPE_APPLICATION_OVERLAY, DEFAULT_DISPLAY, null /* options */);
|
||||
verify(mWindowTokenClient, never()).onConfigurationChanged(any(), anyInt(), anyBoolean());
|
||||
|
||||
doReturn(mConfiguration).when(mWindowManagerService).attachWindowContextToDisplayArea(
|
||||
any(), anyInt(), anyInt(), any());
|
||||
|
||||
assertTrue(mController.attachToDisplayArea(mWindowTokenClient, TYPE_APPLICATION_OVERLAY,
|
||||
DEFAULT_DISPLAY, null /* options */));
|
||||
verify(mWindowTokenClient).onConfigurationChanged(mConfiguration, DEFAULT_DISPLAY,
|
||||
false /* shouldReportConfigChange */);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttachToDisplayArea_detachIfNeeded() throws RemoteException {
|
||||
mController.detachIfNeeded(mWindowTokenClient);
|
||||
|
||||
verify(mWindowManagerService, never()).detachWindowContextFromWindowContainer(any());
|
||||
|
||||
doReturn(null).when(mWindowManagerService).attachWindowContextToDisplayArea(
|
||||
any(), anyInt(), anyInt(), any());
|
||||
mController.attachToDisplayArea(mWindowTokenClient, TYPE_APPLICATION_OVERLAY,
|
||||
DEFAULT_DISPLAY, null /* options */);
|
||||
mController.detachIfNeeded(mWindowTokenClient);
|
||||
|
||||
verify(mWindowManagerService, never()).detachWindowContextFromWindowContainer(any());
|
||||
|
||||
doReturn(mConfiguration).when(mWindowManagerService).attachWindowContextToDisplayArea(
|
||||
any(), anyInt(), anyInt(), any());
|
||||
mController.attachToDisplayArea(mWindowTokenClient, TYPE_APPLICATION_OVERLAY,
|
||||
DEFAULT_DISPLAY, null /* options */);
|
||||
mController.detachIfNeeded(mWindowTokenClient);
|
||||
|
||||
verify(mWindowManagerService).detachWindowContextFromWindowContainer(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttachToDisplayContent() throws RemoteException {
|
||||
doReturn(null).when(mWindowManagerService).attachToDisplayContent(
|
||||
any(), anyInt());
|
||||
|
||||
assertFalse(mController.attachToDisplayContent(mWindowTokenClient, DEFAULT_DISPLAY));
|
||||
verify(mWindowManagerService).attachToDisplayContent(mWindowTokenClient, DEFAULT_DISPLAY);
|
||||
verify(mWindowTokenClient, never()).onConfigurationChanged(any(), anyInt(), anyBoolean());
|
||||
|
||||
doReturn(mConfiguration).when(mWindowManagerService).attachToDisplayContent(
|
||||
any(), anyInt());
|
||||
|
||||
assertTrue(mController.attachToDisplayContent(mWindowTokenClient, DEFAULT_DISPLAY));
|
||||
verify(mWindowTokenClient).onConfigurationChanged(mConfiguration, DEFAULT_DISPLAY,
|
||||
false /* shouldReportConfigChange */);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttachToDisplayContent_detachIfNeeded() throws RemoteException {
|
||||
mController.detachIfNeeded(mWindowTokenClient);
|
||||
|
||||
verify(mWindowManagerService, never()).detachWindowContextFromWindowContainer(any());
|
||||
|
||||
doReturn(null).when(mWindowManagerService).attachToDisplayContent(
|
||||
any(), anyInt());
|
||||
mController.attachToDisplayContent(mWindowTokenClient, DEFAULT_DISPLAY);
|
||||
mController.detachIfNeeded(mWindowTokenClient);
|
||||
|
||||
verify(mWindowManagerService, never()).detachWindowContextFromWindowContainer(any());
|
||||
|
||||
doReturn(mConfiguration).when(mWindowManagerService).attachToDisplayContent(
|
||||
any(), anyInt());
|
||||
mController.attachToDisplayContent(mWindowTokenClient, DEFAULT_DISPLAY);
|
||||
mController.detachIfNeeded(mWindowTokenClient);
|
||||
|
||||
verify(mWindowManagerService).detachWindowContextFromWindowContainer(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttachToWindowToken() throws RemoteException {
|
||||
mController.attachToWindowToken(mWindowTokenClient, mWindowToken);
|
||||
|
||||
verify(mWindowManagerService).attachWindowContextToWindowToken(mWindowTokenClient,
|
||||
mWindowToken);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAttachToWindowToken_detachIfNeeded() throws RemoteException {
|
||||
mController.detachIfNeeded(mWindowTokenClient);
|
||||
|
||||
verify(mWindowManagerService, never()).detachWindowContextFromWindowContainer(any());
|
||||
|
||||
mController.attachToWindowToken(mWindowTokenClient, mWindowToken);
|
||||
mController.detachIfNeeded(mWindowTokenClient);
|
||||
|
||||
verify(mWindowManagerService).detachWindowContextFromWindowContainer(any());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnWindowContextConfigurationChanged() {
|
||||
mController.onWindowContextConfigurationChanged(
|
||||
mClientToken, mConfiguration, DEFAULT_DISPLAY);
|
||||
|
||||
verify(mWindowTokenClient, never()).onConfigurationChanged(any(), anyInt());
|
||||
|
||||
mController.attachToWindowToken(mWindowTokenClient, mWindowToken);
|
||||
|
||||
mController.onWindowContextConfigurationChanged(
|
||||
mClientToken, mConfiguration, DEFAULT_DISPLAY);
|
||||
|
||||
verify(mWindowTokenClient).onConfigurationChanged(mConfiguration, DEFAULT_DISPLAY);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOnWindowContextWindowRemoved() {
|
||||
mController.onWindowContextWindowRemoved(mClientToken);
|
||||
|
||||
verify(mWindowTokenClient, never()).onWindowTokenRemoved();
|
||||
|
||||
mController.attachToWindowToken(mWindowTokenClient, mWindowToken);
|
||||
|
||||
mController.onWindowContextWindowRemoved(mClientToken);
|
||||
|
||||
verify(mWindowTokenClient).onWindowTokenRemoved();
|
||||
}
|
||||
}
|
||||
@@ -71,14 +71,14 @@ public class WindowContextControllerTest {
|
||||
mController = new WindowContextController(mMockToken);
|
||||
doNothing().when(mMockToken).onConfigurationChanged(any(), anyInt(), anyBoolean());
|
||||
mOriginalController = WindowTokenClientController.getInstance();
|
||||
WindowTokenClientController.overrideInstance(mWindowTokenClientController);
|
||||
WindowTokenClientController.overrideForTesting(mWindowTokenClientController);
|
||||
doReturn(true).when(mWindowTokenClientController).attachToDisplayArea(
|
||||
eq(mMockToken), anyInt(), anyInt(), any());
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() {
|
||||
WindowTokenClientController.overrideInstance(mOriginalController);
|
||||
WindowTokenClientController.overrideForTesting(mOriginalController);
|
||||
}
|
||||
|
||||
@Test(expected = IllegalStateException.class)
|
||||
|
||||
Reference in New Issue
Block a user