Loading libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +8 −1 Original line number Original line Diff line number Diff line Loading @@ -1121,8 +1121,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } } // Update the latest taskFragmentInfo and perform necessary clean-up // Update the latest taskFragmentInfo and perform necessary clean-up container.setInfo(wct, taskFragmentInfo); // Clear pending first, so that the #setInfo will evaluate for clean-up container.clearPendingAppearedActivities(); container.clearPendingAppearedActivities(); container.setInfo(wct, taskFragmentInfo); if (container.isEmpty()) { if (container.isEmpty()) { mTransactionManager.getCurrentTransactionRecord() mTransactionManager.getCurrentTransactionRecord() .setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE); .setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE); Loading Loading @@ -3205,6 +3206,12 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen // If the TF is an existing one, this Intent will not be kept as a pending // If the TF is an existing one, this Intent will not be kept as a pending // appeared Intent. // appeared Intent. mCurrentPendingAppearedIntent = intent; mCurrentPendingAppearedIntent = intent; } else if (launchedInTaskFragment.isEmpty() && launchedInTaskFragment.getPendingAppearedIntent() == null) { // When this Intent is added to an empty TaskFragment, make sure to wait for // this Intent launch before consider cleanup. launchedInTaskFragment.setPendingAppearedIntent(intent); mCurrentPendingAppearedIntent = intent; } } } else { } else { transactionRecord.abort(); transactionRecord.abort(); Loading libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java +8 −0 Original line number Original line Diff line number Diff line Loading @@ -499,6 +499,10 @@ class TaskFragmentContainer { return; return; } } mPendingAppearedIntent = null; mPendingAppearedIntent = null; if (mPendingAppearedActivities.isEmpty() && mAppearEmptyTimeout != null) { // Nothing to wait. Can be cleanup now. mAppearEmptyTimeout.run(); } } } boolean hasActivity(@NonNull IBinder activityToken) { boolean hasActivity(@NonNull IBinder activityToken) { Loading Loading @@ -548,6 +552,10 @@ class TaskFragmentContainer { if (mPendingAppearedIntent != null || !mPendingAppearedActivities.isEmpty()) { if (mPendingAppearedIntent != null || !mPendingAppearedActivities.isEmpty()) { mAppearEmptyTimeout = () -> { mAppearEmptyTimeout = () -> { synchronized (mController.mLock) { synchronized (mController.mLock) { if (mAppearEmptyTimeout == null) { // The timeout has already been executed. return; } Log.w(SplitController.TAG, Log.w(SplitController.TAG, "Fail to wait for activity start in TaskFragment=" + this); "Fail to wait for activity start in TaskFragment=" + this); mAppearEmptyTimeout = null; mAppearEmptyTimeout = null; Loading libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java +34 −2 Original line number Original line Diff line number Diff line Loading @@ -412,7 +412,7 @@ public class SplitControllerTest { assertEquals(intent, container.getPendingAppearedIntent()); assertEquals(intent, container.getPendingAppearedIntent()); // On success, do not clear the pending Intent. // On success, do not clear the pending Intent. monitor.onStartActivityResult(START_SUCCESS, new Bundle()); monitor.onStartActivityResult(START_SUCCESS, options0); assertNull(monitor.mCurrentPendingAppearedIntent); assertNull(monitor.mCurrentPendingAppearedIntent); assertEquals(intent, container.getPendingAppearedIntent()); assertEquals(intent, container.getPendingAppearedIntent()); Loading @@ -425,11 +425,43 @@ public class SplitControllerTest { assertNull(monitor.mCurrentPendingAppearedIntent); assertNull(monitor.mCurrentPendingAppearedIntent); // On failure of a non-tracking Intent, do not clear the pending Intent. // On failure of a non-tracking Intent, do not clear the pending Intent. monitor.onStartActivityResult(START_DELIVERED_TO_TOP, new Bundle()); monitor.onStartActivityResult(START_DELIVERED_TO_TOP, options1); assertEquals(intent, container.getPendingAppearedIntent()); assertEquals(intent, container.getPendingAppearedIntent()); } } @Test public void testOnStartActivity_emptyExistingTaskFragment_setPendingAppearedIntent() { final SplitController.ActivityStartMonitor monitor = mSplitController.getActivityStartMonitor(); final Intent intent = new Intent(); final Bundle options0 = new Bundle(); setupSplitRule(mActivity, intent, false /* clearTop */); // On creating a new split pair, keep track of the pending Intent. monitor.onStartActivity(mActivity, intent, options0); final IBinder tfToken = options0.getBinder(KEY_LAUNCH_TASK_FRAGMENT_TOKEN); final TaskFragmentContainer container = mSplitController.getContainer(tfToken); assertEquals(intent, monitor.mCurrentPendingAppearedIntent); assertNotNull(container); assertEquals(intent, container.getPendingAppearedIntent()); // On failure of a tracking Intent, clear the pending Intent. monitor.onStartActivityResult(START_DELIVERED_TO_TOP, options0); assertNull(container.getPendingAppearedIntent()); // On launching another activity into the existing empty container, keep track of the // pending Intent. final Bundle option1 = new Bundle(); monitor.onStartActivity(mActivity, intent, option1); assertEquals(tfToken, option1.getBinder(KEY_LAUNCH_TASK_FRAGMENT_TOKEN)); assertEquals(intent, monitor.mCurrentPendingAppearedIntent); assertEquals(intent, container.getPendingAppearedIntent()); } @Test @Test public void testOnActivityCreated() { public void testOnActivityCreated() { mSplitController.onActivityCreated(mTransaction, mActivity); mSplitController.onActivityCreated(mTransaction, mActivity); Loading Loading
libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +8 −1 Original line number Original line Diff line number Diff line Loading @@ -1121,8 +1121,9 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } } // Update the latest taskFragmentInfo and perform necessary clean-up // Update the latest taskFragmentInfo and perform necessary clean-up container.setInfo(wct, taskFragmentInfo); // Clear pending first, so that the #setInfo will evaluate for clean-up container.clearPendingAppearedActivities(); container.clearPendingAppearedActivities(); container.setInfo(wct, taskFragmentInfo); if (container.isEmpty()) { if (container.isEmpty()) { mTransactionManager.getCurrentTransactionRecord() mTransactionManager.getCurrentTransactionRecord() .setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE); .setOriginType(TASK_FRAGMENT_TRANSIT_CLOSE); Loading Loading @@ -3205,6 +3206,12 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen // If the TF is an existing one, this Intent will not be kept as a pending // If the TF is an existing one, this Intent will not be kept as a pending // appeared Intent. // appeared Intent. mCurrentPendingAppearedIntent = intent; mCurrentPendingAppearedIntent = intent; } else if (launchedInTaskFragment.isEmpty() && launchedInTaskFragment.getPendingAppearedIntent() == null) { // When this Intent is added to an empty TaskFragment, make sure to wait for // this Intent launch before consider cleanup. launchedInTaskFragment.setPendingAppearedIntent(intent); mCurrentPendingAppearedIntent = intent; } } } else { } else { transactionRecord.abort(); transactionRecord.abort(); Loading
libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/TaskFragmentContainer.java +8 −0 Original line number Original line Diff line number Diff line Loading @@ -499,6 +499,10 @@ class TaskFragmentContainer { return; return; } } mPendingAppearedIntent = null; mPendingAppearedIntent = null; if (mPendingAppearedActivities.isEmpty() && mAppearEmptyTimeout != null) { // Nothing to wait. Can be cleanup now. mAppearEmptyTimeout.run(); } } } boolean hasActivity(@NonNull IBinder activityToken) { boolean hasActivity(@NonNull IBinder activityToken) { Loading Loading @@ -548,6 +552,10 @@ class TaskFragmentContainer { if (mPendingAppearedIntent != null || !mPendingAppearedActivities.isEmpty()) { if (mPendingAppearedIntent != null || !mPendingAppearedActivities.isEmpty()) { mAppearEmptyTimeout = () -> { mAppearEmptyTimeout = () -> { synchronized (mController.mLock) { synchronized (mController.mLock) { if (mAppearEmptyTimeout == null) { // The timeout has already been executed. return; } Log.w(SplitController.TAG, Log.w(SplitController.TAG, "Fail to wait for activity start in TaskFragment=" + this); "Fail to wait for activity start in TaskFragment=" + this); mAppearEmptyTimeout = null; mAppearEmptyTimeout = null; Loading
libs/WindowManager/Jetpack/tests/unittest/src/androidx/window/extensions/embedding/SplitControllerTest.java +34 −2 Original line number Original line Diff line number Diff line Loading @@ -412,7 +412,7 @@ public class SplitControllerTest { assertEquals(intent, container.getPendingAppearedIntent()); assertEquals(intent, container.getPendingAppearedIntent()); // On success, do not clear the pending Intent. // On success, do not clear the pending Intent. monitor.onStartActivityResult(START_SUCCESS, new Bundle()); monitor.onStartActivityResult(START_SUCCESS, options0); assertNull(monitor.mCurrentPendingAppearedIntent); assertNull(monitor.mCurrentPendingAppearedIntent); assertEquals(intent, container.getPendingAppearedIntent()); assertEquals(intent, container.getPendingAppearedIntent()); Loading @@ -425,11 +425,43 @@ public class SplitControllerTest { assertNull(monitor.mCurrentPendingAppearedIntent); assertNull(monitor.mCurrentPendingAppearedIntent); // On failure of a non-tracking Intent, do not clear the pending Intent. // On failure of a non-tracking Intent, do not clear the pending Intent. monitor.onStartActivityResult(START_DELIVERED_TO_TOP, new Bundle()); monitor.onStartActivityResult(START_DELIVERED_TO_TOP, options1); assertEquals(intent, container.getPendingAppearedIntent()); assertEquals(intent, container.getPendingAppearedIntent()); } } @Test public void testOnStartActivity_emptyExistingTaskFragment_setPendingAppearedIntent() { final SplitController.ActivityStartMonitor monitor = mSplitController.getActivityStartMonitor(); final Intent intent = new Intent(); final Bundle options0 = new Bundle(); setupSplitRule(mActivity, intent, false /* clearTop */); // On creating a new split pair, keep track of the pending Intent. monitor.onStartActivity(mActivity, intent, options0); final IBinder tfToken = options0.getBinder(KEY_LAUNCH_TASK_FRAGMENT_TOKEN); final TaskFragmentContainer container = mSplitController.getContainer(tfToken); assertEquals(intent, monitor.mCurrentPendingAppearedIntent); assertNotNull(container); assertEquals(intent, container.getPendingAppearedIntent()); // On failure of a tracking Intent, clear the pending Intent. monitor.onStartActivityResult(START_DELIVERED_TO_TOP, options0); assertNull(container.getPendingAppearedIntent()); // On launching another activity into the existing empty container, keep track of the // pending Intent. final Bundle option1 = new Bundle(); monitor.onStartActivity(mActivity, intent, option1); assertEquals(tfToken, option1.getBinder(KEY_LAUNCH_TASK_FRAGMENT_TOKEN)); assertEquals(intent, monitor.mCurrentPendingAppearedIntent); assertEquals(intent, container.getPendingAppearedIntent()); } @Test @Test public void testOnActivityCreated() { public void testOnActivityCreated() { mSplitController.onActivityCreated(mTransaction, mActivity); mSplitController.onActivityCreated(mTransaction, mActivity); Loading