diff --git a/services/core/java/com/android/server/wm/TaskFragment.java b/services/core/java/com/android/server/wm/TaskFragment.java index 3411104dbff05..b53062745d68c 100644 --- a/services/core/java/com/android/server/wm/TaskFragment.java +++ b/services/core/java/com/android/server/wm/TaskFragment.java @@ -242,7 +242,7 @@ class TaskFragment extends WindowContainer { /** Client assigned unique token for this TaskFragment if this is created by an organizer. */ @Nullable - private IBinder mFragmentToken; + private final IBinder mFragmentToken; /** * Whether to delay the last activity of TaskFragment being immediately removed while finishing. @@ -2383,10 +2383,18 @@ class TaskFragment extends WindowContainer { void removeImmediately() { mIsRemovalRequested = false; resetAdjacentTaskFragment(); + cleanUp(); super.removeImmediately(); sendTaskFragmentVanished(); } + /** Called on remove to cleanup. */ + private void cleanUp() { + if (mIsEmbedded) { + mAtmService.mWindowOrganizerController.cleanUpEmbeddedTaskFragment(this); + } + } + @Override Dimmer getDimmer() { // If the window is in an embedded TaskFragment, we want to dim at the TaskFragment. diff --git a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java index 19f921deab4c2..bdec49e2ec409 100644 --- a/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java +++ b/services/core/java/com/android/server/wm/TaskFragmentOrganizerController.java @@ -140,7 +140,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr mLastSentTaskFragmentInfos.put(tf, info); tf.mTaskFragmentAppearedSent = true; } catch (RemoteException e) { - Slog.e(TAG, "Exception sending onTaskFragmentAppeared callback", e); + Slog.d(TAG, "Exception sending onTaskFragmentAppeared callback", e); } onTaskFragmentParentInfoChanged(organizer, tf); } @@ -150,7 +150,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr try { organizer.onTaskFragmentVanished(tf.getTaskFragmentInfo()); } catch (RemoteException e) { - Slog.e(TAG, "Exception sending onTaskFragmentVanished callback", e); + Slog.d(TAG, "Exception sending onTaskFragmentVanished callback", e); } tf.mTaskFragmentAppearedSent = false; mLastSentTaskFragmentInfos.remove(tf); @@ -175,7 +175,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr organizer.onTaskFragmentInfoChanged(tf.getTaskFragmentInfo()); mLastSentTaskFragmentInfos.put(tf, info); } catch (RemoteException e) { - Slog.e(TAG, "Exception sending onTaskFragmentInfoChanged callback", e); + Slog.d(TAG, "Exception sending onTaskFragmentInfoChanged callback", e); } } @@ -198,7 +198,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr organizer.onTaskFragmentParentInfoChanged(tf.getFragmentToken(), parentConfig); mLastSentTaskFragmentParentConfigs.put(tf, new Configuration(parentConfig)); } catch (RemoteException e) { - Slog.e(TAG, "Exception sending onTaskFragmentParentInfoChanged callback", e); + Slog.d(TAG, "Exception sending onTaskFragmentParentInfoChanged callback", e); } } @@ -210,7 +210,7 @@ public class TaskFragmentOrganizerController extends ITaskFragmentOrganizerContr try { organizer.onTaskFragmentError(errorCallbackToken, exceptionBundle); } catch (RemoteException e) { - Slog.e(TAG, "Exception sending onTaskFragmentError callback", e); + Slog.d(TAG, "Exception sending onTaskFragmentError callback", e); } } } diff --git a/services/core/java/com/android/server/wm/WindowOrganizerController.java b/services/core/java/com/android/server/wm/WindowOrganizerController.java index 81344ac311080..d862012942353 100644 --- a/services/core/java/com/android/server/wm/WindowOrganizerController.java +++ b/services/core/java/com/android/server/wm/WindowOrganizerController.java @@ -1470,6 +1470,10 @@ class WindowOrganizerController extends IWindowOrganizerController.Stub return mLaunchTaskFragments.get(tfToken); } + void cleanUpEmbeddedTaskFragment(TaskFragment taskFragment) { + mLaunchTaskFragments.remove(taskFragment.getFragmentToken()); + } + static class CallerInfo { final int mPid; final int mUid; diff --git a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java index 0debdfa3bd1a4..c6158662d110c 100644 --- a/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java +++ b/services/tests/wmtests/src/com/android/server/wm/TaskFragmentOrganizerControllerTest.java @@ -359,17 +359,11 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { public void testApplyTransaction_enforceHierarchyChange_createTaskFragment() throws RemoteException { mController.registerOrganizer(mIOrganizer); - final ActivityRecord activity = createActivityRecord(mDisplayContent); - final int uid = Binder.getCallingUid(); - activity.info.applicationInfo.uid = uid; - activity.getTask().effectiveUid = uid; + final ActivityRecord ownerActivity = createActivityRecord(mDisplayContent); final IBinder fragmentToken = new Binder(); - final TaskFragmentCreationParams params = new TaskFragmentCreationParams.Builder( - mOrganizerToken, fragmentToken, activity.token).build(); - mOrganizer.applyTransaction(mTransaction); // Allow organizer to create TaskFragment and start/reparent activity to TaskFragment. - mTransaction.createTaskFragment(params); + createTaskFragmentFromOrganizer(mTransaction, ownerActivity, fragmentToken); mTransaction.startActivityInTaskFragment( mFragmentToken, null /* callerToken */, new Intent(), null /* activityOptions */); mTransaction.reparentActivityToTaskFragment(mFragmentToken, mock(IBinder.class)); @@ -381,7 +375,7 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { final TaskFragment taskFragment = mAtm.mWindowOrganizerController .getTaskFragment(fragmentToken); assertNotNull(taskFragment); - assertEquals(activity.getTask(), taskFragment.getTask()); + assertEquals(ownerActivity.getTask(), taskFragment.getTask()); } @Test @@ -523,4 +517,43 @@ public class TaskFragmentOrganizerControllerTest extends WindowTestsBase { mController.dispatchPendingEvents(); verify(mOrganizer).onTaskFragmentInfoChanged(any()); } + + /** + * When an embedded {@link TaskFragment} is removed, we should clean up the reference in the + * {@link WindowOrganizerController}. + */ + @Test + public void testTaskFragmentRemoved_cleanUpEmbeddedTaskFragment() + throws RemoteException { + mController.registerOrganizer(mIOrganizer); + final ActivityRecord ownerActivity = createActivityRecord(mDisplayContent); + final IBinder fragmentToken = new Binder(); + createTaskFragmentFromOrganizer(mTransaction, ownerActivity, fragmentToken); + mAtm.getWindowOrganizerController().applyTransaction(mTransaction); + final TaskFragment taskFragment = mAtm.mWindowOrganizerController + .getTaskFragment(fragmentToken); + + assertNotNull(taskFragment); + + taskFragment.removeImmediately(); + + assertNull(mAtm.mWindowOrganizerController.getTaskFragment(fragmentToken)); + } + + /** + * Creates a {@link TaskFragment} with the {@link WindowContainerTransaction}. Calls + * {@link WindowOrganizerController#applyTransaction} to apply the transaction, + */ + private void createTaskFragmentFromOrganizer(WindowContainerTransaction wct, + ActivityRecord ownerActivity, IBinder fragmentToken) { + final int uid = Binder.getCallingUid(); + ownerActivity.info.applicationInfo.uid = uid; + ownerActivity.getTask().effectiveUid = uid; + final TaskFragmentCreationParams params = new TaskFragmentCreationParams.Builder( + mOrganizerToken, fragmentToken, ownerActivity.token).build(); + mOrganizer.applyTransaction(wct); + + // Allow organizer to create TaskFragment and start/reparent activity to TaskFragment. + wct.createTaskFragment(params); + } }