Synchronize window config updates (9/n)
Refactor to call scheduleTransaction through ClientLifecycleManager.
Bug: 260873529
Test: atest WmTests:ClientLifecycleManagerTests
Change-Id: I1ffc8e78b4a7c7c0363e385efbf404aff5f181a2
diff --git a/core/java/android/app/servertransaction/ActivityLifecycleItem.java b/core/java/android/app/servertransaction/ActivityLifecycleItem.java
index 06bff5d..48db18f 100644
--- a/core/java/android/app/servertransaction/ActivityLifecycleItem.java
+++ b/core/java/android/app/servertransaction/ActivityLifecycleItem.java
@@ -59,7 +59,7 @@
}
@Override
- boolean isActivityLifecycleItem() {
+ public boolean isActivityLifecycleItem() {
return true;
}
diff --git a/core/java/android/app/servertransaction/ClientTransactionItem.java b/core/java/android/app/servertransaction/ClientTransactionItem.java
index f94e22d..a8d61db 100644
--- a/core/java/android/app/servertransaction/ClientTransactionItem.java
+++ b/core/java/android/app/servertransaction/ClientTransactionItem.java
@@ -75,7 +75,7 @@
/**
* Whether this is a {@link ActivityLifecycleItem}.
*/
- boolean isActivityLifecycleItem() {
+ public boolean isActivityLifecycleItem() {
return false;
}
diff --git a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
index 443dcb4..2315a58 100644
--- a/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
+++ b/core/tests/coretests/src/android/app/servertransaction/TransactionExecutorTests.java
@@ -31,6 +31,7 @@
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.inOrder;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
@@ -59,6 +60,8 @@
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InOrder;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
import java.util.Arrays;
import java.util.Collections;
@@ -80,20 +83,32 @@
@Presubmit
public class TransactionExecutorTests {
+ @Mock
+ private ClientTransactionHandler mTransactionHandler;
+ @Mock
+ private ActivityLifecycleItem mActivityLifecycleItem;
+ @Mock
+ private IBinder mActivityToken;
+ @Mock
+ private Activity mActivity;
+
private TransactionExecutor mExecutor;
private TransactionExecutorHelper mExecutorHelper;
- private ClientTransactionHandler mTransactionHandler;
private ActivityClientRecord mClientRecord;
@Before
public void setUp() throws Exception {
- mTransactionHandler = mock(ClientTransactionHandler.class);
+ MockitoAnnotations.initMocks(this);
mClientRecord = new ActivityClientRecord();
when(mTransactionHandler.getActivityClient(any())).thenReturn(mClientRecord);
mExecutor = spy(new TransactionExecutor(mTransactionHandler));
mExecutorHelper = new TransactionExecutorHelper();
+
+ doReturn(true).when(mActivityLifecycleItem).isActivityLifecycleItem();
+ doReturn(mActivityToken).when(mActivityLifecycleItem).getActivityToken();
+ doReturn(mActivity).when(mTransactionHandler).getActivity(mActivityToken);
}
@Test
@@ -229,23 +244,21 @@
when(callback1.getPostExecutionState()).thenReturn(UNDEFINED);
ClientTransactionItem callback2 = mock(ClientTransactionItem.class);
when(callback2.getPostExecutionState()).thenReturn(UNDEFINED);
- ActivityLifecycleItem stateRequest = mock(ActivityLifecycleItem.class);
- IBinder token = mock(IBinder.class);
- when(stateRequest.getActivityToken()).thenReturn(token);
- when(mTransactionHandler.getActivity(token)).thenReturn(mock(Activity.class));
ClientTransaction transaction = ClientTransaction.obtain(null /* client */);
transaction.addCallback(callback1);
transaction.addCallback(callback2);
- transaction.setLifecycleStateRequest(stateRequest);
+ transaction.setLifecycleStateRequest(mActivityLifecycleItem);
transaction.preExecute(mTransactionHandler);
mExecutor.execute(transaction);
- InOrder inOrder = inOrder(mTransactionHandler, callback1, callback2, stateRequest);
+ InOrder inOrder = inOrder(mTransactionHandler, callback1, callback2,
+ mActivityLifecycleItem);
inOrder.verify(callback1).execute(eq(mTransactionHandler), any());
inOrder.verify(callback2).execute(eq(mTransactionHandler), any());
- inOrder.verify(stateRequest).execute(eq(mTransactionHandler), eq(mClientRecord), any());
+ inOrder.verify(mActivityLifecycleItem).execute(eq(mTransactionHandler), eq(mClientRecord),
+ any());
}
@Test
@@ -254,23 +267,21 @@
when(callback1.getPostExecutionState()).thenReturn(UNDEFINED);
ClientTransactionItem callback2 = mock(ClientTransactionItem.class);
when(callback2.getPostExecutionState()).thenReturn(UNDEFINED);
- ActivityLifecycleItem stateRequest = mock(ActivityLifecycleItem.class);
- IBinder token = mock(IBinder.class);
- when(stateRequest.getActivityToken()).thenReturn(token);
- when(mTransactionHandler.getActivity(token)).thenReturn(mock(Activity.class));
ClientTransaction transaction = ClientTransaction.obtain(null /* client */);
transaction.addTransactionItem(callback1);
transaction.addTransactionItem(callback2);
- transaction.addTransactionItem(stateRequest);
+ transaction.addTransactionItem(mActivityLifecycleItem);
transaction.preExecute(mTransactionHandler);
mExecutor.execute(transaction);
- InOrder inOrder = inOrder(mTransactionHandler, callback1, callback2, stateRequest);
+ InOrder inOrder = inOrder(mTransactionHandler, callback1, callback2,
+ mActivityLifecycleItem);
inOrder.verify(callback1).execute(eq(mTransactionHandler), any());
inOrder.verify(callback2).execute(eq(mTransactionHandler), any());
- inOrder.verify(stateRequest).execute(eq(mTransactionHandler), eq(mClientRecord), any());
+ inOrder.verify(mActivityLifecycleItem).execute(eq(mTransactionHandler), eq(mClientRecord),
+ any());
}
@Test
@@ -536,42 +547,36 @@
@Test
public void testActivityItemExecute() {
- final IBinder token = mock(IBinder.class);
final ClientTransaction transaction = ClientTransaction.obtain(null /* client */);
final ActivityTransactionItem activityItem = mock(ActivityTransactionItem.class);
when(activityItem.getPostExecutionState()).thenReturn(UNDEFINED);
- when(activityItem.getActivityToken()).thenReturn(token);
+ when(activityItem.getActivityToken()).thenReturn(mActivityToken);
transaction.addCallback(activityItem);
- final ActivityLifecycleItem stateRequest = mock(ActivityLifecycleItem.class);
- transaction.setLifecycleStateRequest(stateRequest);
- when(stateRequest.getActivityToken()).thenReturn(token);
- when(mTransactionHandler.getActivity(token)).thenReturn(mock(Activity.class));
+ transaction.setLifecycleStateRequest(mActivityLifecycleItem);
mExecutor.execute(transaction);
- final InOrder inOrder = inOrder(activityItem, stateRequest);
+ final InOrder inOrder = inOrder(activityItem, mActivityLifecycleItem);
inOrder.verify(activityItem).execute(eq(mTransactionHandler), eq(mClientRecord), any());
- inOrder.verify(stateRequest).execute(eq(mTransactionHandler), eq(mClientRecord), any());
+ inOrder.verify(mActivityLifecycleItem).execute(eq(mTransactionHandler), eq(mClientRecord),
+ any());
}
@Test
public void testExecuteTransactionItems_activityItemExecute() {
- final IBinder token = mock(IBinder.class);
final ClientTransaction transaction = ClientTransaction.obtain(null /* client */);
final ActivityTransactionItem activityItem = mock(ActivityTransactionItem.class);
when(activityItem.getPostExecutionState()).thenReturn(UNDEFINED);
- when(activityItem.getActivityToken()).thenReturn(token);
+ when(activityItem.getActivityToken()).thenReturn(mActivityToken);
transaction.addTransactionItem(activityItem);
- final ActivityLifecycleItem stateRequest = mock(ActivityLifecycleItem.class);
- transaction.addTransactionItem(stateRequest);
- when(stateRequest.getActivityToken()).thenReturn(token);
- when(mTransactionHandler.getActivity(token)).thenReturn(mock(Activity.class));
+ transaction.addTransactionItem(mActivityLifecycleItem);
mExecutor.execute(transaction);
- final InOrder inOrder = inOrder(activityItem, stateRequest);
+ final InOrder inOrder = inOrder(activityItem, mActivityLifecycleItem);
inOrder.verify(activityItem).execute(eq(mTransactionHandler), eq(mClientRecord), any());
- inOrder.verify(stateRequest).execute(eq(mTransactionHandler), eq(mClientRecord), any());
+ inOrder.verify(mActivityLifecycleItem).execute(eq(mTransactionHandler), eq(mClientRecord),
+ any());
}
private static int[] shuffledArray(int[] inputArray) {
diff --git a/services/core/java/com/android/server/wm/ActivityClientController.java b/services/core/java/com/android/server/wm/ActivityClientController.java
index 7b399c8..faccca8 100644
--- a/services/core/java/com/android/server/wm/ActivityClientController.java
+++ b/services/core/java/com/android/server/wm/ActivityClientController.java
@@ -70,7 +70,6 @@
import android.app.PictureInPictureParams;
import android.app.PictureInPictureUiState;
import android.app.compat.CompatChanges;
-import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.EnterPipRequestedItem;
import android.app.servertransaction.PipStateTransactionItem;
import android.compat.annotation.ChangeId;
@@ -1018,7 +1017,7 @@
}
try {
- mService.getLifecycleManager().scheduleTransaction(r.app.getThread(),
+ mService.getLifecycleManager().scheduleTransactionItem(r.app.getThread(),
EnterPipRequestedItem.obtain(r.token));
return true;
} catch (Exception e) {
@@ -1038,9 +1037,8 @@
}
try {
- final ClientTransaction transaction = ClientTransaction.obtain(r.app.getThread());
- transaction.addCallback(PipStateTransactionItem.obtain(r.token, pipState));
- mService.getLifecycleManager().scheduleTransaction(transaction);
+ mService.getLifecycleManager().scheduleTransactionItem(r.app.getThread(),
+ PipStateTransactionItem.obtain(r.token, pipState));
} catch (Exception e) {
Slog.w(TAG, "Failed to send pip state transaction item: "
+ r.intent.getComponent(), e);
diff --git a/services/core/java/com/android/server/wm/ActivityRecord.java b/services/core/java/com/android/server/wm/ActivityRecord.java
index eeeca10..1f905ea 100644
--- a/services/core/java/com/android/server/wm/ActivityRecord.java
+++ b/services/core/java/com/android/server/wm/ActivityRecord.java
@@ -277,7 +277,6 @@
import android.app.servertransaction.ActivityLifecycleItem;
import android.app.servertransaction.ActivityRelaunchItem;
import android.app.servertransaction.ActivityResultItem;
-import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.ClientTransactionItem;
import android.app.servertransaction.DestroyActivityItem;
import android.app.servertransaction.MoveToDisplayItem;
@@ -1449,7 +1448,7 @@
+ "display, activityRecord=%s, displayId=%d, config=%s", this, displayId,
config);
- mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(),
+ mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(),
MoveToDisplayItem.obtain(token, displayId, config));
} catch (RemoteException e) {
// If process died, whatever.
@@ -1466,7 +1465,7 @@
ProtoLog.v(WM_DEBUG_CONFIGURATION, "Sending new config to %s, "
+ "config: %s", this, config);
- mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(),
+ mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(),
ActivityConfigurationChangeItem.obtain(token, config));
} catch (RemoteException e) {
// If process died, whatever.
@@ -1487,7 +1486,7 @@
ProtoLog.v(WM_DEBUG_STATES, "Sending position change to %s, onTop: %b",
this, onTop);
- mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(),
+ mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(),
TopResumedActivityChangeItem.obtain(token, onTop));
} catch (RemoteException e) {
// If process died, whatever.
@@ -2744,7 +2743,7 @@
}
try {
mTransferringSplashScreenState = TRANSFER_SPLASH_SCREEN_ATTACH_TO_CLIENT;
- mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(),
+ mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(),
TransferSplashScreenViewStateItem.obtain(token, parcelable,
windowAnimationLeash));
scheduleTransferSplashScreenTimeout();
@@ -3908,7 +3907,7 @@
try {
if (DEBUG_SWITCH) Slog.i(TAG_SWITCH, "Destroying: " + this);
- mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(),
+ mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(),
DestroyActivityItem.obtain(token, finishing, configChangeFlags));
} catch (Exception e) {
// We can just ignore exceptions here... if the process has crashed, our death
@@ -4819,7 +4818,7 @@
try {
final ArrayList<ResultInfo> list = new ArrayList<>();
list.add(new ResultInfo(resultWho, requestCode, resultCode, data));
- mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(),
+ mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(),
ActivityResultItem.obtain(token, list));
return;
} catch (Exception e) {
@@ -4830,22 +4829,23 @@
// Schedule sending results now for Media Projection setup.
if (forceSendForMediaProjection && attachedToProcess() && isState(STARTED, PAUSING, PAUSED,
STOPPING, STOPPED)) {
- final ClientTransaction transaction = ClientTransaction.obtain(app.getThread());
// Build result to be returned immediately.
- transaction.addCallback(ActivityResultItem.obtain(
- token, List.of(new ResultInfo(resultWho, requestCode, resultCode, data))));
+ final ActivityResultItem activityResultItem = ActivityResultItem.obtain(
+ token, List.of(new ResultInfo(resultWho, requestCode, resultCode, data)));
// When the activity result is delivered, the activity will transition to RESUMED.
// Since the activity is only resumed so the result can be immediately delivered,
// return it to its original lifecycle state.
- ActivityLifecycleItem lifecycleItem = getLifecycleItemForCurrentStateForResult();
- if (lifecycleItem != null) {
- transaction.setLifecycleStateRequest(lifecycleItem);
- } else {
- Slog.w(TAG, "Unable to get the lifecycle item for state " + mState
- + " so couldn't immediately send result");
- }
+ final ActivityLifecycleItem lifecycleItem = getLifecycleItemForCurrentStateForResult();
try {
- mAtmService.getLifecycleManager().scheduleTransaction(transaction);
+ if (lifecycleItem != null) {
+ mAtmService.getLifecycleManager().scheduleTransactionAndLifecycleItems(
+ app.getThread(), activityResultItem, lifecycleItem);
+ } else {
+ Slog.w(TAG, "Unable to get the lifecycle item for state " + mState
+ + " so couldn't immediately send result");
+ mAtmService.getLifecycleManager().scheduleTransactionItem(
+ app.getThread(), activityResultItem);
+ }
} catch (RemoteException e) {
Slog.w(TAG, "Exception thrown sending result to " + this, e);
}
@@ -4925,7 +4925,7 @@
// Making sure the client state is RESUMED after transaction completed and doing
// so only if activity is currently RESUMED. Otherwise, client may have extra
// life-cycle calls to RESUMED (and PAUSED later).
- mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(),
+ mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(),
NewIntentItem.obtain(token, ar, mState == RESUMED));
unsent = false;
} catch (RemoteException e) {
@@ -6150,7 +6150,7 @@
EventLogTags.writeWmPauseActivity(mUserId, System.identityHashCode(this),
shortComponentName, "userLeaving=false", "make-active");
try {
- mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(),
+ mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(),
PauseActivityItem.obtain(token, finishing, false /* userLeaving */,
configChangeFlags, false /* dontReport */, mAutoEnteringPip));
} catch (Exception e) {
@@ -6163,7 +6163,7 @@
setState(STARTED, "makeActiveIfNeeded");
try {
- mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(),
+ mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(),
StartActivityItem.obtain(token, takeOptions()));
} catch (Exception e) {
Slog.w(TAG, "Exception thrown sending start: " + intent.getComponent(), e);
@@ -6461,7 +6461,7 @@
}
EventLogTags.writeWmStopActivity(
mUserId, System.identityHashCode(this), shortComponentName);
- mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(),
+ mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(),
StopActivityItem.obtain(token, configChangeFlags));
mAtmService.mH.postDelayed(mStopTimeoutRunnable, STOP_TIMEOUT);
@@ -9895,10 +9895,8 @@
} else {
lifecycleItem = PauseActivityItem.obtain(token);
}
- final ClientTransaction transaction = ClientTransaction.obtain(app.getThread());
- transaction.addCallback(callbackItem);
- transaction.setLifecycleStateRequest(lifecycleItem);
- mAtmService.getLifecycleManager().scheduleTransaction(transaction);
+ mAtmService.getLifecycleManager().scheduleTransactionAndLifecycleItems(
+ app.getThread(), callbackItem, lifecycleItem);
startRelaunching();
// Note: don't need to call pauseIfSleepingLocked() here, because the caller will only
// request resume if this activity is currently resumed, which implies we aren't
@@ -9990,7 +9988,7 @@
// The process will be killed until the activity reports stopped with saved state (see
// {@link ActivityTaskManagerService.activityStopped}).
try {
- mAtmService.getLifecycleManager().scheduleTransaction(app.getThread(),
+ mAtmService.getLifecycleManager().scheduleTransactionItem(app.getThread(),
StopActivityItem.obtain(token, 0 /* configChanges */));
} catch (RemoteException e) {
Slog.w(TAG, "Exception thrown during restart " + this, e);
diff --git a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
index e196d46..ce8d051 100644
--- a/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
+++ b/services/core/java/com/android/server/wm/ActivityTaskSupervisor.java
@@ -98,7 +98,6 @@
import android.app.TaskInfo;
import android.app.WaitResult;
import android.app.servertransaction.ActivityLifecycleItem;
-import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.LaunchActivityItem;
import android.app.servertransaction.PauseActivityItem;
import android.app.servertransaction.ResumeActivityItem;
@@ -928,14 +927,10 @@
}
// Create activity launch transaction.
- final ClientTransaction clientTransaction = ClientTransaction.obtain(
- proc.getThread());
-
final boolean isTransitionForward = r.isTransitionForward();
final IBinder fragmentToken = r.getTaskFragment().getFragmentToken();
-
final int deviceId = getDeviceIdForDisplayId(r.getDisplayId());
- clientTransaction.addCallback(LaunchActivityItem.obtain(r.token,
+ final LaunchActivityItem launchActivityItem = LaunchActivityItem.obtain(r.token,
r.intent, System.identityHashCode(r), r.info,
// TODO: Have this take the merged configuration instead of separate global
// and override configs.
@@ -945,7 +940,7 @@
proc.getReportedProcState(), r.getSavedState(), r.getPersistentSavedState(),
results, newIntents, r.takeOptions(), isTransitionForward,
proc.createProfilerInfoIfNeeded(), r.assistToken, activityClientController,
- r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken));
+ r.shareableActivityToken, r.getLaunchedFromBubble(), fragmentToken);
// Set desired final state.
final ActivityLifecycleItem lifecycleItem;
@@ -955,10 +950,10 @@
} else {
lifecycleItem = PauseActivityItem.obtain(r.token);
}
- clientTransaction.setLifecycleStateRequest(lifecycleItem);
// Schedule transaction.
- mService.getLifecycleManager().scheduleTransaction(clientTransaction);
+ mService.getLifecycleManager().scheduleTransactionAndLifecycleItems(
+ proc.getThread(), launchActivityItem, lifecycleItem);
if (procConfig.seq > mRootWindowContainer.getConfiguration().seq) {
// If the seq is increased, there should be something changed (e.g. registered
diff --git a/services/core/java/com/android/server/wm/ClientLifecycleManager.java b/services/core/java/com/android/server/wm/ClientLifecycleManager.java
index ef31837..28f656e 100644
--- a/services/core/java/com/android/server/wm/ClientLifecycleManager.java
+++ b/services/core/java/com/android/server/wm/ClientLifecycleManager.java
@@ -40,35 +40,51 @@
* @throws RemoteException
*
* @see ClientTransaction
+ * @deprecated use {@link #scheduleTransactionItem(IApplicationThread, ClientTransactionItem)}.
*/
+ @Deprecated
void scheduleTransaction(@NonNull ClientTransaction transaction) throws RemoteException {
final IApplicationThread client = transaction.getClient();
- transaction.schedule();
- if (!(client instanceof Binder)) {
- // If client is not an instance of Binder - it's a remote call and at this point it is
- // safe to recycle the object. All objects used for local calls will be recycled after
- // the transaction is executed on client in ActivityThread.
- transaction.recycle();
+ try {
+ transaction.schedule();
+ } finally {
+ if (!(client instanceof Binder)) {
+ // If client is not an instance of Binder - it's a remote call and at this point it
+ // is safe to recycle the object. All objects used for local calls will be recycled
+ // after the transaction is executed on client in ActivityThread.
+ transaction.recycle();
+ }
}
}
/**
* Schedules a single transaction item, either a callback or a lifecycle request, delivery to
* client application.
- * @param client Target client.
- * @param transactionItem A transaction item to deliver a message.
* @throws RemoteException
- *
* @see ClientTransactionItem
*/
- void scheduleTransaction(@NonNull IApplicationThread client,
+ void scheduleTransactionItem(@NonNull IApplicationThread client,
@NonNull ClientTransactionItem transactionItem) throws RemoteException {
final ClientTransaction clientTransaction = ClientTransaction.obtain(client);
- if (transactionItem instanceof ActivityLifecycleItem) {
+ if (transactionItem.isActivityLifecycleItem()) {
clientTransaction.setLifecycleStateRequest((ActivityLifecycleItem) transactionItem);
} else {
clientTransaction.addCallback(transactionItem);
}
scheduleTransaction(clientTransaction);
}
+
+ /**
+ * Schedules a single transaction item with a lifecycle request, delivery to client application.
+ * @throws RemoteException
+ * @see ClientTransactionItem
+ */
+ void scheduleTransactionAndLifecycleItems(@NonNull IApplicationThread client,
+ @NonNull ClientTransactionItem transactionItem,
+ @NonNull ActivityLifecycleItem lifecycleItem) throws RemoteException {
+ final ClientTransaction clientTransaction = ClientTransaction.obtain(client);
+ clientTransaction.addCallback(transactionItem);
+ clientTransaction.setLifecycleStateRequest(lifecycleItem);
+ scheduleTransaction(clientTransaction);
+ }
}
diff --git a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
index 534cdc2..e808dec 100644
--- a/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
+++ b/services/core/java/com/android/server/wm/DisplayRotationCompatPolicy.java
@@ -38,7 +38,6 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringRes;
-import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.RefreshCallbackItem;
import android.app.servertransaction.ResumeActivityItem;
import android.content.pm.ActivityInfo.ScreenOrientation;
@@ -226,13 +225,12 @@
ProtoLog.v(WM_DEBUG_STATES,
"Refreshing activity for camera compatibility treatment, "
+ "activityRecord=%s", activity);
- final ClientTransaction transaction = ClientTransaction.obtain(
- activity.app.getThread());
- transaction.addCallback(RefreshCallbackItem.obtain(activity.token,
- cycleThroughStop ? ON_STOP : ON_PAUSE));
- transaction.setLifecycleStateRequest(ResumeActivityItem.obtain(activity.token,
- /* isForward */ false, /* shouldSendCompatFakeFocus */ false));
- activity.mAtmService.getLifecycleManager().scheduleTransaction(transaction);
+ final RefreshCallbackItem refreshCallbackItem = RefreshCallbackItem.obtain(
+ activity.token, cycleThroughStop ? ON_STOP : ON_PAUSE);
+ final ResumeActivityItem resumeActivityItem = ResumeActivityItem.obtain(
+ activity.token, /* isForward */ false, /* shouldSendCompatFakeFocus */ false);
+ activity.mAtmService.getLifecycleManager().scheduleTransactionAndLifecycleItems(
+ activity.app.getThread(), refreshCallbackItem, resumeActivityItem);
mHandler.postDelayed(
() -> onActivityRefreshed(activity),
REFRESH_CALLBACK_TIMEOUT_MS);
diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java
index 197edc3..8bc461f 100644
--- a/services/core/java/com/android/server/wm/TaskFragment.java
+++ b/services/core/java/com/android/server/wm/TaskFragment.java
@@ -1793,7 +1793,7 @@
EventLogTags.writeWmPauseActivity(prev.mUserId, System.identityHashCode(prev),
prev.shortComponentName, "userLeaving=" + userLeaving, reason);
- mAtmService.getLifecycleManager().scheduleTransaction(prev.app.getThread(),
+ mAtmService.getLifecycleManager().scheduleTransactionItem(prev.app.getThread(),
PauseActivityItem.obtain(prev.token, prev.finishing, userLeaving,
prev.configChangeFlags, pauseImmediately, autoEnteringPip));
} catch (Exception e) {
diff --git a/services/core/java/com/android/server/wm/WindowProcessController.java b/services/core/java/com/android/server/wm/WindowProcessController.java
index a74a707..192d960 100644
--- a/services/core/java/com/android/server/wm/WindowProcessController.java
+++ b/services/core/java/com/android/server/wm/WindowProcessController.java
@@ -1666,7 +1666,7 @@
private void scheduleClientTransactionItem(@NonNull IApplicationThread thread,
@NonNull ClientTransactionItem transactionItem) {
try {
- mAtm.getLifecycleManager().scheduleTransaction(thread, transactionItem);
+ mAtm.getLifecycleManager().scheduleTransactionItem(thread, transactionItem);
} catch (Exception e) {
Slog.e(TAG_CONFIGURATION, "Failed to schedule ClientTransactionItem="
+ transactionItem + " owner=" + mOwner, e);
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
index 1776ba5..786432a 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityRecordTests.java
@@ -490,7 +490,7 @@
ensureActivityConfiguration(activity);
verify(mClientLifecycleManager, never())
- .scheduleTransaction(any(), isA(ActivityConfigurationChangeItem.class));
+ .scheduleTransactionItem(any(), isA(ActivityConfigurationChangeItem.class));
}
@Test
@@ -519,7 +519,7 @@
// The configuration change is still sent to the activity, even if it doesn't relaunch.
final ActivityConfigurationChangeItem expected =
ActivityConfigurationChangeItem.obtain(activity.token, newConfig);
- verify(mClientLifecycleManager).scheduleTransaction(
+ verify(mClientLifecycleManager).scheduleTransactionItem(
eq(activity.app.getThread()), eq(expected));
}
@@ -592,7 +592,7 @@
assertEquals(expectedOrientation, currentConfig.orientation);
final ActivityConfigurationChangeItem expected =
ActivityConfigurationChangeItem.obtain(activity.token, currentConfig);
- verify(mClientLifecycleManager).scheduleTransaction(activity.app.getThread(), expected);
+ verify(mClientLifecycleManager).scheduleTransactionItem(activity.app.getThread(), expected);
verify(displayRotation).onSetRequestedOrientation();
}
@@ -812,7 +812,8 @@
final ActivityConfigurationChangeItem expected =
ActivityConfigurationChangeItem.obtain(activity.token,
activity.getConfiguration());
- verify(mClientLifecycleManager).scheduleTransaction(activity.app.getThread(), expected);
+ verify(mClientLifecycleManager).scheduleTransactionItem(
+ activity.app.getThread(), expected);
} finally {
stack.getDisplayArea().removeChild(stack);
}
@@ -1785,7 +1786,7 @@
clearInvocations(mClientLifecycleManager);
activity.getTask().removeImmediately("test");
try {
- verify(mClientLifecycleManager).scheduleTransaction(any(),
+ verify(mClientLifecycleManager).scheduleTransactionItem(any(),
isA(DestroyActivityItem.class));
} catch (RemoteException ignored) {
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
index 3c027ff..d2c731c 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ActivityTaskManagerServiceTests.java
@@ -127,7 +127,7 @@
final ArgumentCaptor<ClientTransactionItem> clientTransactionItemCaptor =
ArgumentCaptor.forClass(ClientTransactionItem.class);
- verify(mockLifecycleManager).scheduleTransaction(any(),
+ verify(mockLifecycleManager).scheduleTransactionItem(any(),
clientTransactionItemCaptor.capture());
final ClientTransactionItem transactionItem = clientTransactionItemCaptor.getValue();
// Check that only an enter pip request item callback was scheduled.
@@ -144,7 +144,7 @@
mAtm.mActivityClientController.requestPictureInPictureMode(activity);
- verify(mClientLifecycleManager, never()).scheduleTransaction(any(), any());
+ verify(mClientLifecycleManager, never()).scheduleTransactionItem(any(), any());
}
@Test
@@ -156,7 +156,7 @@
mAtm.mActivityClientController.requestPictureInPictureMode(activity);
- verify(mClientLifecycleManager, never()).scheduleTransaction(any(), any());
+ verify(mClientLifecycleManager, never()).scheduleTransactionItem(any(), any());
}
@Test
diff --git a/services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java b/services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java
index a18dbaf..04aa981 100644
--- a/services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/ClientLifecycleManagerTests.java
@@ -16,18 +16,32 @@
package com.android.server.wm;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.mock;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.spy;
-import static com.android.dx.mockito.inline.extended.ExtendedMockito.times;
import static com.android.dx.mockito.inline.extended.ExtendedMockito.verify;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNull;
+import static org.mockito.ArgumentMatchers.any;
+import static org.mockito.Mockito.clearInvocations;
+import static org.mockito.Mockito.doNothing;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.never;
+
import android.app.IApplicationThread;
+import android.app.servertransaction.ActivityLifecycleItem;
import android.app.servertransaction.ClientTransaction;
+import android.app.servertransaction.ClientTransactionItem;
+import android.os.RemoteException;
import android.platform.test.annotations.Presubmit;
import androidx.test.filters.SmallTest;
+import org.junit.Before;
import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Captor;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
/**
* Build/Install/Run:
@@ -37,23 +51,77 @@
@Presubmit
public class ClientLifecycleManagerTests {
- @Test
- public void testScheduleAndRecycleBinderClientTransaction() throws Exception {
- ClientTransaction item = spy(ClientTransaction.obtain(mock(IApplicationThread.class)));
+ @Mock
+ private IApplicationThread mClient;
+ @Mock
+ private IApplicationThread.Stub mNonBinderClient;
+ @Mock
+ private ClientTransactionItem mTransactionItem;
+ @Mock
+ private ActivityLifecycleItem mLifecycleItem;
+ @Captor
+ private ArgumentCaptor<ClientTransaction> mTransactionCaptor;
- ClientLifecycleManager clientLifecycleManager = new ClientLifecycleManager();
- clientLifecycleManager.scheduleTransaction(item);
+ private ClientLifecycleManager mLifecycleManager;
- verify(item, times(1)).recycle();
+ @Before
+ public void setup() {
+ MockitoAnnotations.initMocks(this);
+
+ mLifecycleManager = spy(new ClientLifecycleManager());
+
+ doReturn(true).when(mLifecycleItem).isActivityLifecycleItem();
}
@Test
- public void testScheduleNoRecycleNonBinderClientTransaction() throws Exception {
- ClientTransaction item = spy(ClientTransaction.obtain(mock(IApplicationThread.Stub.class)));
+ public void testScheduleTransaction_recycleBinderClientTransaction() throws Exception {
+ final ClientTransaction item = spy(ClientTransaction.obtain(mClient));
- ClientLifecycleManager clientLifecycleManager = new ClientLifecycleManager();
- clientLifecycleManager.scheduleTransaction(item);
+ mLifecycleManager.scheduleTransaction(item);
- verify(item, times(0)).recycle();
+ verify(item).recycle();
+ }
+
+ @Test
+ public void testScheduleTransaction_notRecycleNonBinderClientTransaction() throws Exception {
+ final ClientTransaction item = spy(ClientTransaction.obtain(mNonBinderClient));
+
+ mLifecycleManager.scheduleTransaction(item);
+
+ verify(item, never()).recycle();
+ }
+
+ @Test
+ public void testScheduleTransactionItem() throws RemoteException {
+ doNothing().when(mLifecycleManager).scheduleTransaction(any());
+ mLifecycleManager.scheduleTransactionItem(mClient, mTransactionItem);
+
+ verify(mLifecycleManager).scheduleTransaction(mTransactionCaptor.capture());
+ ClientTransaction transaction = mTransactionCaptor.getValue();
+ assertEquals(1, transaction.getCallbacks().size());
+ assertEquals(mTransactionItem, transaction.getCallbacks().get(0));
+ assertNull(transaction.getLifecycleStateRequest());
+ assertNull(transaction.getTransactionItems());
+
+ clearInvocations(mLifecycleManager);
+ mLifecycleManager.scheduleTransactionItem(mClient, mLifecycleItem);
+
+ verify(mLifecycleManager).scheduleTransaction(mTransactionCaptor.capture());
+ transaction = mTransactionCaptor.getValue();
+ assertNull(transaction.getCallbacks());
+ assertEquals(mLifecycleItem, transaction.getLifecycleStateRequest());
+ }
+
+ @Test
+ public void testScheduleTransactionAndLifecycleItems() throws RemoteException {
+ doNothing().when(mLifecycleManager).scheduleTransaction(any());
+ mLifecycleManager.scheduleTransactionAndLifecycleItems(mClient, mTransactionItem,
+ mLifecycleItem);
+
+ verify(mLifecycleManager).scheduleTransaction(mTransactionCaptor.capture());
+ final ClientTransaction transaction = mTransactionCaptor.getValue();
+ assertEquals(1, transaction.getCallbacks().size());
+ assertEquals(mTransactionItem, transaction.getCallbacks().get(0));
+ assertEquals(mLifecycleItem, transaction.getLifecycleStateRequest());
}
}
diff --git a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java
index 2af6745..e7ac33f 100644
--- a/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/DisplayRotationCompatPolicyTests.java
@@ -43,12 +43,9 @@
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.ArgumentMatchers.anyLong;
import static org.mockito.ArgumentMatchers.anyString;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
-import static org.mockito.Mockito.verify;
-import android.app.servertransaction.ClientTransaction;
import android.app.servertransaction.RefreshCallbackItem;
import android.app.servertransaction.ResumeActivityItem;
import android.content.ComponentName;
@@ -529,8 +526,8 @@
public void testOnActivityConfigurationChanging_cycleThroughStopDisabledForApp()
throws Exception {
configureActivity(SCREEN_ORIENTATION_PORTRAIT);
- when(mActivity.mLetterboxUiController.shouldRefreshActivityViaPauseForCameraCompat())
- .thenReturn(true);
+ doReturn(true).when(mActivity.mLetterboxUiController)
+ .shouldRefreshActivityViaPauseForCameraCompat();
mCameraAvailabilityCallback.onCameraOpened(CAMERA_ID_1, TEST_PACKAGE_1);
callOnActivityConfigurationChanging(mActivity, /* isDisplayRotationChanging */ true);
@@ -571,14 +568,14 @@
verify(mActivity.mLetterboxUiController, times(refreshRequested ? 1 : 0))
.setIsRefreshAfterRotationRequested(true);
- final ClientTransaction transaction = ClientTransaction.obtain(mActivity.app.getThread());
- transaction.addCallback(RefreshCallbackItem.obtain(mActivity.token,
- cycleThroughStop ? ON_STOP : ON_PAUSE));
- transaction.setLifecycleStateRequest(ResumeActivityItem.obtain(mActivity.token,
- /* isForward */ false, /* shouldSendCompatFakeFocus */ false));
+ final RefreshCallbackItem refreshCallbackItem = RefreshCallbackItem.obtain(mActivity.token,
+ cycleThroughStop ? ON_STOP : ON_PAUSE);
+ final ResumeActivityItem resumeActivityItem = ResumeActivityItem.obtain(mActivity.token,
+ /* isForward */ false, /* shouldSendCompatFakeFocus */ false);
verify(mActivity.mAtmService.getLifecycleManager(), times(refreshRequested ? 1 : 0))
- .scheduleTransaction(eq(transaction));
+ .scheduleTransactionAndLifecycleItems(mActivity.app.getThread(),
+ refreshCallbackItem, resumeActivityItem);
}
private void assertNoForceRotationOrRefresh() throws Exception {
diff --git a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
index 46cff8b..e152feb 100644
--- a/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
+++ b/services/tests/wmtests/src/com/android/server/wm/WindowProcessControllerTests.java
@@ -306,7 +306,7 @@
@Test
public void testCachedStateConfigurationChange() throws RemoteException {
- doNothing().when(mClientLifecycleManager).scheduleTransaction(any(), any());
+ doNothing().when(mClientLifecycleManager).scheduleTransactionItem(any(), any());
final IApplicationThread thread = mWpc.getThread();
final Configuration newConfig = new Configuration(mWpc.getConfiguration());
newConfig.densityDpi += 100;
@@ -314,20 +314,20 @@
mWpc.setReportedProcState(ActivityManager.PROCESS_STATE_IMPORTANT_BACKGROUND);
clearInvocations(mClientLifecycleManager);
mWpc.onConfigurationChanged(newConfig);
- verify(mClientLifecycleManager).scheduleTransaction(eq(thread), any());
+ verify(mClientLifecycleManager).scheduleTransactionItem(eq(thread), any());
// Cached state won't send the change.
clearInvocations(mClientLifecycleManager);
mWpc.setReportedProcState(ActivityManager.PROCESS_STATE_CACHED_ACTIVITY);
newConfig.densityDpi += 100;
mWpc.onConfigurationChanged(newConfig);
- verify(mClientLifecycleManager, never()).scheduleTransaction(eq(thread), any());
+ verify(mClientLifecycleManager, never()).scheduleTransactionItem(eq(thread), any());
// Cached -> non-cached will send the previous deferred config immediately.
mWpc.setReportedProcState(ActivityManager.PROCESS_STATE_RECEIVER);
final ArgumentCaptor<ConfigurationChangeItem> captor =
ArgumentCaptor.forClass(ConfigurationChangeItem.class);
- verify(mClientLifecycleManager).scheduleTransaction(eq(thread), captor.capture());
+ verify(mClientLifecycleManager).scheduleTransactionItem(eq(thread), captor.capture());
final ClientTransactionHandler client = mock(ClientTransactionHandler.class);
captor.getValue().preExecute(client);
final ArgumentCaptor<Configuration> configCaptor =