Loading services/core/java/com/android/server/wm/ActivityRecord.java +1 −0 Original line number Diff line number Diff line Loading @@ -3978,6 +3978,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A "Reported destroyed for activity that is not destroying: r=" + this); } mTaskSupervisor.killTaskProcessesOnDestroyedIfNeeded(task); if (isInRootTaskLocked()) { cleanUp(true /* cleanServices */, false /* setState */); removeFromHistory(reason); Loading services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +71 −7 Original line number Diff line number Diff line Loading @@ -190,12 +190,19 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { /** How long we wait until giving up on the activity telling us it released the top state. */ private static final int TOP_RESUMED_STATE_LOSS_TIMEOUT = 500; /** * The timeout to kill task processes if its activity didn't complete destruction in time * when there is a request to remove the task with killProcess=true. */ private static final int KILL_TASK_PROCESSES_TIMEOUT_MS = 1000; private static final int IDLE_TIMEOUT_MSG = FIRST_SUPERVISOR_TASK_MSG; private static final int IDLE_NOW_MSG = FIRST_SUPERVISOR_TASK_MSG + 1; private static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_TASK_MSG + 2; private static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_TASK_MSG + 3; private static final int LAUNCH_TIMEOUT_MSG = FIRST_SUPERVISOR_TASK_MSG + 4; private static final int PROCESS_STOPPING_AND_FINISHING_MSG = FIRST_SUPERVISOR_TASK_MSG + 5; private static final int KILL_TASK_PROCESSES_TIMEOUT_MSG = FIRST_SUPERVISOR_TASK_MSG + 6; private static final int LAUNCH_TASK_BEHIND_COMPLETE = FIRST_SUPERVISOR_TASK_MSG + 12; private static final int RESTART_ACTIVITY_PROCESS_TIMEOUT_MSG = FIRST_SUPERVISOR_TASK_MSG + 13; private static final int REPORT_MULTI_WINDOW_MODE_CHANGED_MSG = FIRST_SUPERVISOR_TASK_MSG + 14; Loading Loading @@ -1642,10 +1649,32 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { return; } task.mTransitionController.requestCloseTransitionIfNeeded(task); // Consume the stopping activities immediately so activity manager won't skip killing // the process because it is still foreground state, i.e. RESUMED -> PAUSING set from // removeActivities -> finishIfPossible. if (killProcess) { ArrayList<ActivityRecord> activities = null; for (int i = mStoppingActivities.size() - 1; i >= 0; i--) { final ActivityRecord r = mStoppingActivities.get(i); if (r.getTask() == task) { if (activities == null) { activities = new ArrayList<>(); } activities.add(r); mStoppingActivities.remove(i); } } if (activities != null) { // This can update to background state. for (int i = activities.size() - 1; i >= 0; i--) { activities.get(i).stopIfPossible(); } } } task.mInRemoveTask = true; try { task.removeActivities(reason, false /* excludingTaskOverlay */); cleanUpRemovedTaskLocked(task, killProcess, removeFromRecents); cleanUpRemovedTask(task, killProcess, removeFromRecents); mService.getLockTaskController().clearLockedTask(task); mService.getTaskChangeNotificationController().notifyTaskStackChanged(); if (task.isPersistable) { Loading Loading @@ -1825,11 +1854,13 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { } } void cleanUpRemovedTaskLocked(Task task, boolean killProcess, boolean removeFromRecents) { /** This method should only be called for leaf task. */ private void cleanUpRemovedTask(Task task, boolean killProcess, boolean removeFromRecents) { if (removeFromRecents) { mRecentTasks.remove(task); } ComponentName component = task.getBaseIntent().getComponent(); final Intent baseIntent = task.getBaseIntent(); final ComponentName component = baseIntent != null ? baseIntent.getComponent() : null; if (component == null) { Slog.w(TAG, "No component for base intent of task: " + task); return; Loading @@ -1837,16 +1868,38 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { // Find any running services associated with this app and stop if needed. final Message msg = PooledLambda.obtainMessage(ActivityManagerInternal::cleanUpServices, mService.mAmInternal, task.mUserId, component, new Intent(task.getBaseIntent())); mService.mAmInternal, task.mUserId, component, new Intent(baseIntent)); mService.mH.sendMessage(msg); if (!killProcess) { return; } // Give a chance for the client to handle Activity#onStop(). The timeout waits for // onDestroy because the client defers to report completion of stopped, the callback from // DestroyActivityItem may be called first. final ActivityRecord top = task.getTopMostActivity(); if (top != null && top.finishing && !top.mAppStopped && top.lastVisibleTime > 0 && !task.mKillProcessesOnDestroyed) { task.mKillProcessesOnDestroyed = true; mHandler.sendMessageDelayed( mHandler.obtainMessage(KILL_TASK_PROCESSES_TIMEOUT_MSG, task), KILL_TASK_PROCESSES_TIMEOUT_MS); return; } killTaskProcessesIfPossible(task); } void killTaskProcessesOnDestroyedIfNeeded(Task task) { if (task == null || !task.mKillProcessesOnDestroyed) return; mHandler.removeMessages(KILL_TASK_PROCESSES_TIMEOUT_MSG, task); killTaskProcessesIfPossible(task); } // Determine if the process(es) for this task should be killed. final String pkg = component.getPackageName(); ArrayList<Object> procsToKill = new ArrayList<>(); /** Kills the processes in the task if it doesn't contain perceptible components. */ private void killTaskProcessesIfPossible(Task task) { task.mKillProcessesOnDestroyed = false; final String pkg = task.getBasePackageName(); ArrayList<Object> procsToKill = null; ArrayMap<String, SparseArray<WindowProcessController>> pmap = mService.mProcessNames.getMap(); for (int i = 0; i < pmap.size(); i++) { Loading Loading @@ -1878,10 +1931,14 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { return; } if (procsToKill == null) { procsToKill = new ArrayList<>(); } // Add process to kill list. procsToKill.add(proc); } } if (procsToKill == null) return; // Kill the running processes. Post on handle since we don't want to hold the service lock // while calling into AM. Loading Loading @@ -2677,6 +2734,13 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { processStoppingAndFinishingActivities(null /* launchedActivity */, false /* processPausingActivities */, "transit"); } break; case KILL_TASK_PROCESSES_TIMEOUT_MSG: { final Task task = (Task) msg.obj; if (task.mKillProcessesOnDestroyed) { Slog.i(TAG, "Destroy timeout of remove-task, attempt to kill " + task); killTaskProcessesIfPossible(task); } } break; case LAUNCH_TASK_BEHIND_COMPLETE: { final ActivityRecord r = ActivityRecord.forTokenLocked((IBinder) msg.obj); if (r != null) { Loading services/core/java/com/android/server/wm/LockTaskController.java +1 −3 Original line number Diff line number Diff line Loading @@ -1014,9 +1014,7 @@ public class LockTaskController { */ boolean isBaseOfLockedTask(String packageName) { for (int i = 0; i < mLockTaskModeTasks.size(); i++) { final Intent bi = mLockTaskModeTasks.get(i).getBaseIntent(); if (bi != null && packageName.equals(bi.getComponent() .getPackageName())) { if (packageName.equals(mLockTaskModeTasks.get(i).getBasePackageName())) { return true; } } Loading services/core/java/com/android/server/wm/RecentTasks.java +2 −5 Original line number Diff line number Diff line Loading @@ -682,10 +682,8 @@ class RecentTasks { void removeTasksByPackageName(String packageName, int userId) { for (int i = mTasks.size() - 1; i >= 0; --i) { final Task task = mTasks.get(i); final String taskPackageName = task.getBaseIntent().getComponent().getPackageName(); if (task.mUserId != userId) continue; if (!taskPackageName.equals(packageName)) continue; if (!task.getBasePackageName().equals(packageName)) continue; mSupervisor.removeTask(task, true, REMOVE_FROM_RECENTS, "remove-package-task"); } Loading Loading @@ -859,8 +857,7 @@ class RecentTasks { if (task.effectiveUid != callingUid) { continue; } Intent intent = task.getBaseIntent(); if (intent == null || !callingPackage.equals(intent.getComponent().getPackageName())) { if (!callingPackage.equals(task.getBasePackageName())) { continue; } AppTaskImpl taskImpl = new AppTaskImpl(mService, task.mTaskId, callingUid); Loading services/core/java/com/android/server/wm/Task.java +24 −0 Original line number Diff line number Diff line Loading @@ -374,6 +374,13 @@ class Task extends TaskFragment { * determining the order when restoring. */ long mLastTimeMoved; /** * If it is set, the processes belong to the task will be killed when one of its activity * reports that Activity#onDestroy is done and the task no longer contains perceptible * components. This should only be set on a leaf task. */ boolean mKillProcessesOnDestroyed; /** If original intent did not allow relinquishing task identity, save that information */ private boolean mNeverRelinquishIdentity = true; Loading Loading @@ -1325,6 +1332,20 @@ class Task extends TaskFragment { return (topTask != this && topTask != null) ? topTask.getBaseIntent() : null; } /** * Returns the package name which stands for this task. It is empty string if no activities * have been added to this task. */ @NonNull String getBasePackageName() { final Intent intent = getBaseIntent(); if (intent == null) { return ""; } final ComponentName componentName = intent.getComponent(); return componentName != null ? componentName.getPackageName() : ""; } /** Returns the first non-finishing activity from the bottom. */ ActivityRecord getRootActivity() { // TODO: Figure out why we historical ignore relinquish identity for this case... Loading Loading @@ -3679,6 +3700,9 @@ class Task extends TaskFragment { if (mSharedStartingData != null) { pw.println(prefix + "mSharedStartingData=" + mSharedStartingData); } if (mKillProcessesOnDestroyed) { pw.println(prefix + "mKillProcessesOnDestroyed=true"); } pw.print(prefix); pw.print("taskId=" + mTaskId); pw.println(" rootTaskId=" + getRootTaskId()); pw.print(prefix); pw.println("hasChildPipActivity=" + (mChildPipActivity != null)); Loading Loading
services/core/java/com/android/server/wm/ActivityRecord.java +1 −0 Original line number Diff line number Diff line Loading @@ -3978,6 +3978,7 @@ final class ActivityRecord extends WindowToken implements WindowManagerService.A "Reported destroyed for activity that is not destroying: r=" + this); } mTaskSupervisor.killTaskProcessesOnDestroyedIfNeeded(task); if (isInRootTaskLocked()) { cleanUp(true /* cleanServices */, false /* setState */); removeFromHistory(reason); Loading
services/core/java/com/android/server/wm/ActivityTaskSupervisor.java +71 −7 Original line number Diff line number Diff line Loading @@ -190,12 +190,19 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { /** How long we wait until giving up on the activity telling us it released the top state. */ private static final int TOP_RESUMED_STATE_LOSS_TIMEOUT = 500; /** * The timeout to kill task processes if its activity didn't complete destruction in time * when there is a request to remove the task with killProcess=true. */ private static final int KILL_TASK_PROCESSES_TIMEOUT_MS = 1000; private static final int IDLE_TIMEOUT_MSG = FIRST_SUPERVISOR_TASK_MSG; private static final int IDLE_NOW_MSG = FIRST_SUPERVISOR_TASK_MSG + 1; private static final int RESUME_TOP_ACTIVITY_MSG = FIRST_SUPERVISOR_TASK_MSG + 2; private static final int SLEEP_TIMEOUT_MSG = FIRST_SUPERVISOR_TASK_MSG + 3; private static final int LAUNCH_TIMEOUT_MSG = FIRST_SUPERVISOR_TASK_MSG + 4; private static final int PROCESS_STOPPING_AND_FINISHING_MSG = FIRST_SUPERVISOR_TASK_MSG + 5; private static final int KILL_TASK_PROCESSES_TIMEOUT_MSG = FIRST_SUPERVISOR_TASK_MSG + 6; private static final int LAUNCH_TASK_BEHIND_COMPLETE = FIRST_SUPERVISOR_TASK_MSG + 12; private static final int RESTART_ACTIVITY_PROCESS_TIMEOUT_MSG = FIRST_SUPERVISOR_TASK_MSG + 13; private static final int REPORT_MULTI_WINDOW_MODE_CHANGED_MSG = FIRST_SUPERVISOR_TASK_MSG + 14; Loading Loading @@ -1642,10 +1649,32 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { return; } task.mTransitionController.requestCloseTransitionIfNeeded(task); // Consume the stopping activities immediately so activity manager won't skip killing // the process because it is still foreground state, i.e. RESUMED -> PAUSING set from // removeActivities -> finishIfPossible. if (killProcess) { ArrayList<ActivityRecord> activities = null; for (int i = mStoppingActivities.size() - 1; i >= 0; i--) { final ActivityRecord r = mStoppingActivities.get(i); if (r.getTask() == task) { if (activities == null) { activities = new ArrayList<>(); } activities.add(r); mStoppingActivities.remove(i); } } if (activities != null) { // This can update to background state. for (int i = activities.size() - 1; i >= 0; i--) { activities.get(i).stopIfPossible(); } } } task.mInRemoveTask = true; try { task.removeActivities(reason, false /* excludingTaskOverlay */); cleanUpRemovedTaskLocked(task, killProcess, removeFromRecents); cleanUpRemovedTask(task, killProcess, removeFromRecents); mService.getLockTaskController().clearLockedTask(task); mService.getTaskChangeNotificationController().notifyTaskStackChanged(); if (task.isPersistable) { Loading Loading @@ -1825,11 +1854,13 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { } } void cleanUpRemovedTaskLocked(Task task, boolean killProcess, boolean removeFromRecents) { /** This method should only be called for leaf task. */ private void cleanUpRemovedTask(Task task, boolean killProcess, boolean removeFromRecents) { if (removeFromRecents) { mRecentTasks.remove(task); } ComponentName component = task.getBaseIntent().getComponent(); final Intent baseIntent = task.getBaseIntent(); final ComponentName component = baseIntent != null ? baseIntent.getComponent() : null; if (component == null) { Slog.w(TAG, "No component for base intent of task: " + task); return; Loading @@ -1837,16 +1868,38 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { // Find any running services associated with this app and stop if needed. final Message msg = PooledLambda.obtainMessage(ActivityManagerInternal::cleanUpServices, mService.mAmInternal, task.mUserId, component, new Intent(task.getBaseIntent())); mService.mAmInternal, task.mUserId, component, new Intent(baseIntent)); mService.mH.sendMessage(msg); if (!killProcess) { return; } // Give a chance for the client to handle Activity#onStop(). The timeout waits for // onDestroy because the client defers to report completion of stopped, the callback from // DestroyActivityItem may be called first. final ActivityRecord top = task.getTopMostActivity(); if (top != null && top.finishing && !top.mAppStopped && top.lastVisibleTime > 0 && !task.mKillProcessesOnDestroyed) { task.mKillProcessesOnDestroyed = true; mHandler.sendMessageDelayed( mHandler.obtainMessage(KILL_TASK_PROCESSES_TIMEOUT_MSG, task), KILL_TASK_PROCESSES_TIMEOUT_MS); return; } killTaskProcessesIfPossible(task); } void killTaskProcessesOnDestroyedIfNeeded(Task task) { if (task == null || !task.mKillProcessesOnDestroyed) return; mHandler.removeMessages(KILL_TASK_PROCESSES_TIMEOUT_MSG, task); killTaskProcessesIfPossible(task); } // Determine if the process(es) for this task should be killed. final String pkg = component.getPackageName(); ArrayList<Object> procsToKill = new ArrayList<>(); /** Kills the processes in the task if it doesn't contain perceptible components. */ private void killTaskProcessesIfPossible(Task task) { task.mKillProcessesOnDestroyed = false; final String pkg = task.getBasePackageName(); ArrayList<Object> procsToKill = null; ArrayMap<String, SparseArray<WindowProcessController>> pmap = mService.mProcessNames.getMap(); for (int i = 0; i < pmap.size(); i++) { Loading Loading @@ -1878,10 +1931,14 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { return; } if (procsToKill == null) { procsToKill = new ArrayList<>(); } // Add process to kill list. procsToKill.add(proc); } } if (procsToKill == null) return; // Kill the running processes. Post on handle since we don't want to hold the service lock // while calling into AM. Loading Loading @@ -2677,6 +2734,13 @@ public class ActivityTaskSupervisor implements RecentTasks.Callbacks { processStoppingAndFinishingActivities(null /* launchedActivity */, false /* processPausingActivities */, "transit"); } break; case KILL_TASK_PROCESSES_TIMEOUT_MSG: { final Task task = (Task) msg.obj; if (task.mKillProcessesOnDestroyed) { Slog.i(TAG, "Destroy timeout of remove-task, attempt to kill " + task); killTaskProcessesIfPossible(task); } } break; case LAUNCH_TASK_BEHIND_COMPLETE: { final ActivityRecord r = ActivityRecord.forTokenLocked((IBinder) msg.obj); if (r != null) { Loading
services/core/java/com/android/server/wm/LockTaskController.java +1 −3 Original line number Diff line number Diff line Loading @@ -1014,9 +1014,7 @@ public class LockTaskController { */ boolean isBaseOfLockedTask(String packageName) { for (int i = 0; i < mLockTaskModeTasks.size(); i++) { final Intent bi = mLockTaskModeTasks.get(i).getBaseIntent(); if (bi != null && packageName.equals(bi.getComponent() .getPackageName())) { if (packageName.equals(mLockTaskModeTasks.get(i).getBasePackageName())) { return true; } } Loading
services/core/java/com/android/server/wm/RecentTasks.java +2 −5 Original line number Diff line number Diff line Loading @@ -682,10 +682,8 @@ class RecentTasks { void removeTasksByPackageName(String packageName, int userId) { for (int i = mTasks.size() - 1; i >= 0; --i) { final Task task = mTasks.get(i); final String taskPackageName = task.getBaseIntent().getComponent().getPackageName(); if (task.mUserId != userId) continue; if (!taskPackageName.equals(packageName)) continue; if (!task.getBasePackageName().equals(packageName)) continue; mSupervisor.removeTask(task, true, REMOVE_FROM_RECENTS, "remove-package-task"); } Loading Loading @@ -859,8 +857,7 @@ class RecentTasks { if (task.effectiveUid != callingUid) { continue; } Intent intent = task.getBaseIntent(); if (intent == null || !callingPackage.equals(intent.getComponent().getPackageName())) { if (!callingPackage.equals(task.getBasePackageName())) { continue; } AppTaskImpl taskImpl = new AppTaskImpl(mService, task.mTaskId, callingUid); Loading
services/core/java/com/android/server/wm/Task.java +24 −0 Original line number Diff line number Diff line Loading @@ -374,6 +374,13 @@ class Task extends TaskFragment { * determining the order when restoring. */ long mLastTimeMoved; /** * If it is set, the processes belong to the task will be killed when one of its activity * reports that Activity#onDestroy is done and the task no longer contains perceptible * components. This should only be set on a leaf task. */ boolean mKillProcessesOnDestroyed; /** If original intent did not allow relinquishing task identity, save that information */ private boolean mNeverRelinquishIdentity = true; Loading Loading @@ -1325,6 +1332,20 @@ class Task extends TaskFragment { return (topTask != this && topTask != null) ? topTask.getBaseIntent() : null; } /** * Returns the package name which stands for this task. It is empty string if no activities * have been added to this task. */ @NonNull String getBasePackageName() { final Intent intent = getBaseIntent(); if (intent == null) { return ""; } final ComponentName componentName = intent.getComponent(); return componentName != null ? componentName.getPackageName() : ""; } /** Returns the first non-finishing activity from the bottom. */ ActivityRecord getRootActivity() { // TODO: Figure out why we historical ignore relinquish identity for this case... Loading Loading @@ -3679,6 +3700,9 @@ class Task extends TaskFragment { if (mSharedStartingData != null) { pw.println(prefix + "mSharedStartingData=" + mSharedStartingData); } if (mKillProcessesOnDestroyed) { pw.println(prefix + "mKillProcessesOnDestroyed=true"); } pw.print(prefix); pw.print("taskId=" + mTaskId); pw.println(" rootTaskId=" + getRootTaskId()); pw.print(prefix); pw.println("hasChildPipActivity=" + (mChildPipActivity != null)); Loading