Loading core/java/android/app/ActivityThread.java +12 −0 Original line number Diff line number Diff line Loading @@ -3841,6 +3841,18 @@ public final class ActivityThread extends ClientTransactionHandler return activityRecord != null ? activityRecord.activity : null; } /** * Returns the most recent created activity that's still running. */ @Nullable public Activity getLastCreatedActivity() { if (mActivities.isEmpty()) { return null; } return mActivities.valueAt(mActivities.size() - 1).activity; } @Override public ActivityClientRecord getActivityClient(IBinder token) { return mActivities.get(token); Loading libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java +26 −1 Original line number Diff line number Diff line Loading @@ -148,8 +148,12 @@ class BackupHelper { final TaskFragmentInfo info = mTaskFragmentInfos.valueAt(i); mPresenter.deleteTaskFragment(wct, info.getFragmentToken()); } mPresenter.setSavedState(new Bundle()); removeSavedState(); } private void removeSavedState() { mPresenter.setSavedState(new Bundle()); mParcelableTaskContainerDataList.clear(); mTaskFragmentInfos.clear(); mTaskFragmentParentInfos.clear(); Loading @@ -169,6 +173,19 @@ class BackupHelper { return false; } if (mTaskFragmentParentInfos.size() == 0) { // No Task left in the WM hierarchy, remove the states and no need to restore. if (DEBUG) Log.d(TAG, "Remove save states due to no task to restore."); removeSavedState(); return false; } final ArrayList<Integer> taskIdsInSystem = new ArrayList<>(); for (int i = mTaskFragmentParentInfos.size() - 1; i >= 0; --i) { final TaskFragmentParentInfo parentInfo = mTaskFragmentParentInfos.valueAt(i); taskIdsInSystem.add(parentInfo.getTaskId()); } if (DEBUG) Log.d(TAG, "Rebuilding TaskContainers."); final ArrayMap<String, EmbeddingRule> embeddingRuleMap = new ArrayMap<>(); for (EmbeddingRule rule : rules) { Loading @@ -190,6 +207,14 @@ class BackupHelper { } mParcelableTaskContainerDataList.remove(parcelableTaskContainerData); if (!taskIdsInSystem.contains(parcelableTaskContainerData.mTaskId)) { if (DEBUG) { Log.d(TAG, "Rebuilding TaskContainer abort! Not existed. Task#" + parcelableTaskContainerData.mTaskId); } continue; } final TaskContainer taskContainer = new TaskContainer(parcelableTaskContainerData, mController, mTaskFragmentInfos); if (DEBUG) Log.d(TAG, "Created TaskContainer " + taskContainer); Loading libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +57 −27 Original line number Diff line number Diff line Loading @@ -239,6 +239,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen mActivityStartMonitor = new ActivityStartMonitor(); instrumentation.addMonitor(mActivityStartMonitor); foldingFeatureProducer.addDataChangedCallback(new FoldingFeatureListener()); synchronized (mLock) { // Abort the restoration if any and the application already has running activities. abortRebuildingTaskContainersIfNeeded(null /* launchingActivity */); } } private class FoldingFeatureListener Loading Loading @@ -285,6 +290,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return; } if (abortRebuildingTaskContainersIfNeeded(null /* launchingActivity */)) { return; } try { final TransactionRecord transactionRecord = mTransactionManager.startNewTransaction(); Loading Loading @@ -2883,31 +2892,28 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } } private final class LifecycleCallbacks extends EmptyLifecycleCallbacksAdapter { @GuardedBy("mLock") private boolean abortRebuildingTaskContainersIfNeeded(@Nullable Activity launchingActivity) { if (mPresenter == null || !mPresenter.isWaitingToRebuildTaskContainers()) { return false; } @Override public void onActivityPreCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) { if (activity.isChild()) { // Skip Activity that is child of another Activity (ActivityGroup) because it's // window will just be a child of the parent Activity window. return; final ActivityThread activityThread = ActivityThread.currentActivityThread(); if (activityThread == null) { return false; } synchronized (mLock) { if (mPresenter.isWaitingToRebuildTaskContainers()) { Log.w(TAG, "Rebuilding aborted, clean up and restart"); final Activity lastCreatedActivity = activityThread.getLastCreatedActivity(); final Activity activity = launchingActivity != null ? launchingActivity : lastCreatedActivity; if (activity == null) { return false; } Log.w(TAG, "Rebuilding aborted, clean up."); // Retrieve the Task intent. final int taskId = getTaskId(activity); Intent taskIntent = null; final ActivityManager am = activity.getSystemService(ActivityManager.class); final List<ActivityManager.AppTask> appTasks = am.getAppTasks(); for (ActivityManager.AppTask appTask : appTasks) { if (appTask.getTaskInfo().taskId == taskId) { taskIntent = appTask.getTaskInfo().baseIntent.cloneFilter(); break; } } // Clean up and abort the restoration // TODO(b/369488857): also to remove the non-organized activities in the Task? Loading @@ -2917,10 +2923,34 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen mPresenter.abortTaskContainerRebuilding(wct); transactionRecord.apply(false /* shouldApplyIndependently */); // Start the Task root activity. if (taskIntent != null) { activity.startActivity(taskIntent); // Start the Task root activity if the task is now empty. ActivityManager.RecentTaskInfo taskInfo = null; final ActivityManager am = activity.getSystemService(ActivityManager.class); final List<ActivityManager.AppTask> appTasks = am.getAppTasks(); for (ActivityManager.AppTask appTask : appTasks) { if (appTask.getTaskInfo().taskId == taskId) { taskInfo = appTask.getTaskInfo(); break; } } if (taskInfo != null && !taskInfo.isRunning) { activity.startActivity(taskInfo.baseIntent.cloneFilter()); } return true; } private final class LifecycleCallbacks extends EmptyLifecycleCallbacksAdapter { @Override public void onActivityPreCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) { if (activity.isChild()) { // Skip Activity that is child of another Activity (ActivityGroup) because it's // window will just be a child of the parent Activity window. return; } synchronized (mLock) { if (abortRebuildingTaskContainersIfNeeded(activity)) { return; } Loading Loading
core/java/android/app/ActivityThread.java +12 −0 Original line number Diff line number Diff line Loading @@ -3841,6 +3841,18 @@ public final class ActivityThread extends ClientTransactionHandler return activityRecord != null ? activityRecord.activity : null; } /** * Returns the most recent created activity that's still running. */ @Nullable public Activity getLastCreatedActivity() { if (mActivities.isEmpty()) { return null; } return mActivities.valueAt(mActivities.size() - 1).activity; } @Override public ActivityClientRecord getActivityClient(IBinder token) { return mActivities.get(token); Loading
libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/BackupHelper.java +26 −1 Original line number Diff line number Diff line Loading @@ -148,8 +148,12 @@ class BackupHelper { final TaskFragmentInfo info = mTaskFragmentInfos.valueAt(i); mPresenter.deleteTaskFragment(wct, info.getFragmentToken()); } mPresenter.setSavedState(new Bundle()); removeSavedState(); } private void removeSavedState() { mPresenter.setSavedState(new Bundle()); mParcelableTaskContainerDataList.clear(); mTaskFragmentInfos.clear(); mTaskFragmentParentInfos.clear(); Loading @@ -169,6 +173,19 @@ class BackupHelper { return false; } if (mTaskFragmentParentInfos.size() == 0) { // No Task left in the WM hierarchy, remove the states and no need to restore. if (DEBUG) Log.d(TAG, "Remove save states due to no task to restore."); removeSavedState(); return false; } final ArrayList<Integer> taskIdsInSystem = new ArrayList<>(); for (int i = mTaskFragmentParentInfos.size() - 1; i >= 0; --i) { final TaskFragmentParentInfo parentInfo = mTaskFragmentParentInfos.valueAt(i); taskIdsInSystem.add(parentInfo.getTaskId()); } if (DEBUG) Log.d(TAG, "Rebuilding TaskContainers."); final ArrayMap<String, EmbeddingRule> embeddingRuleMap = new ArrayMap<>(); for (EmbeddingRule rule : rules) { Loading @@ -190,6 +207,14 @@ class BackupHelper { } mParcelableTaskContainerDataList.remove(parcelableTaskContainerData); if (!taskIdsInSystem.contains(parcelableTaskContainerData.mTaskId)) { if (DEBUG) { Log.d(TAG, "Rebuilding TaskContainer abort! Not existed. Task#" + parcelableTaskContainerData.mTaskId); } continue; } final TaskContainer taskContainer = new TaskContainer(parcelableTaskContainerData, mController, mTaskFragmentInfos); if (DEBUG) Log.d(TAG, "Created TaskContainer " + taskContainer); Loading
libs/WindowManager/Jetpack/src/androidx/window/extensions/embedding/SplitController.java +57 −27 Original line number Diff line number Diff line Loading @@ -239,6 +239,11 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen mActivityStartMonitor = new ActivityStartMonitor(); instrumentation.addMonitor(mActivityStartMonitor); foldingFeatureProducer.addDataChangedCallback(new FoldingFeatureListener()); synchronized (mLock) { // Abort the restoration if any and the application already has running activities. abortRebuildingTaskContainersIfNeeded(null /* launchingActivity */); } } private class FoldingFeatureListener Loading Loading @@ -285,6 +290,10 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen return; } if (abortRebuildingTaskContainersIfNeeded(null /* launchingActivity */)) { return; } try { final TransactionRecord transactionRecord = mTransactionManager.startNewTransaction(); Loading Loading @@ -2883,31 +2892,28 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen } } private final class LifecycleCallbacks extends EmptyLifecycleCallbacksAdapter { @GuardedBy("mLock") private boolean abortRebuildingTaskContainersIfNeeded(@Nullable Activity launchingActivity) { if (mPresenter == null || !mPresenter.isWaitingToRebuildTaskContainers()) { return false; } @Override public void onActivityPreCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) { if (activity.isChild()) { // Skip Activity that is child of another Activity (ActivityGroup) because it's // window will just be a child of the parent Activity window. return; final ActivityThread activityThread = ActivityThread.currentActivityThread(); if (activityThread == null) { return false; } synchronized (mLock) { if (mPresenter.isWaitingToRebuildTaskContainers()) { Log.w(TAG, "Rebuilding aborted, clean up and restart"); final Activity lastCreatedActivity = activityThread.getLastCreatedActivity(); final Activity activity = launchingActivity != null ? launchingActivity : lastCreatedActivity; if (activity == null) { return false; } Log.w(TAG, "Rebuilding aborted, clean up."); // Retrieve the Task intent. final int taskId = getTaskId(activity); Intent taskIntent = null; final ActivityManager am = activity.getSystemService(ActivityManager.class); final List<ActivityManager.AppTask> appTasks = am.getAppTasks(); for (ActivityManager.AppTask appTask : appTasks) { if (appTask.getTaskInfo().taskId == taskId) { taskIntent = appTask.getTaskInfo().baseIntent.cloneFilter(); break; } } // Clean up and abort the restoration // TODO(b/369488857): also to remove the non-organized activities in the Task? Loading @@ -2917,10 +2923,34 @@ public class SplitController implements JetpackTaskFragmentOrganizer.TaskFragmen mPresenter.abortTaskContainerRebuilding(wct); transactionRecord.apply(false /* shouldApplyIndependently */); // Start the Task root activity. if (taskIntent != null) { activity.startActivity(taskIntent); // Start the Task root activity if the task is now empty. ActivityManager.RecentTaskInfo taskInfo = null; final ActivityManager am = activity.getSystemService(ActivityManager.class); final List<ActivityManager.AppTask> appTasks = am.getAppTasks(); for (ActivityManager.AppTask appTask : appTasks) { if (appTask.getTaskInfo().taskId == taskId) { taskInfo = appTask.getTaskInfo(); break; } } if (taskInfo != null && !taskInfo.isRunning) { activity.startActivity(taskInfo.baseIntent.cloneFilter()); } return true; } private final class LifecycleCallbacks extends EmptyLifecycleCallbacksAdapter { @Override public void onActivityPreCreated(@NonNull Activity activity, @Nullable Bundle savedInstanceState) { if (activity.isChild()) { // Skip Activity that is child of another Activity (ActivityGroup) because it's // window will just be a child of the parent Activity window. return; } synchronized (mLock) { if (abortRebuildingTaskContainersIfNeeded(activity)) { return; } Loading