Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 520e9396 authored by Riddle Hsu's avatar Riddle Hsu Committed by Automerger Merge Worker
Browse files

Merge "Give fg apps a chance to handle stop before killing its process" into udc-dev am: d2f60406

parents 6ce456a1 d2f60406
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -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);
+71 −7
Original line number Diff line number Diff line
@@ -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;
@@ -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) {
@@ -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;
@@ -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++) {
@@ -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.
@@ -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) {
+1 −3
Original line number Diff line number Diff line
@@ -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;
            }
        }
+2 −5
Original line number Diff line number Diff line
@@ -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");
        }
@@ -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);
+24 −0
Original line number Diff line number Diff line
@@ -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;

@@ -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...
@@ -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