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

Commit 515d4060 authored by Amith Yamasani's avatar Amith Yamasani
Browse files

Delay cleaning user tasks until user is removed

Fixes #24301208 No recent apps shows when switching
between users.

Instead of cleaning up when stopping a user, we
should remove tasks when removing a user, since
recents tasks should be persisted across reboots.
Reboots are similar to stopping and starting users.

Change-Id: I9a250792077cca5f18ae1a10bc36f7b97e8ea867
parent dfc9ce54
Loading
Loading
Loading
Loading
+9 −0
Original line number Original line Diff line number Diff line
@@ -55,4 +55,13 @@ public abstract class ActivityManagerInternal {
     * @param userId ID of the user or {@link android.os.UserHandle#USER_ALL}
     * @param userId ID of the user or {@link android.os.UserHandle#USER_ALL}
     */
     */
    public abstract ComponentName getHomeActivityForUser(int userId);
    public abstract ComponentName getHomeActivityForUser(int userId);

    /**
     * Called when a user has been deleted. This can happen during normal device usage
     * or just at startup, when partially removed users are purged. Any state persisted by the
     * ActivityManager should be purged now.
     *
     * @param userId The user being cleaned up.
     */
    public abstract void onUserRemoved(int userId);
}
}
+13 −4
Original line number Original line Diff line number Diff line
@@ -11893,7 +11893,8 @@ public final class ActivityManagerService extends ActivityManagerNative
            updateCurrentProfileIdsLocked();
            updateCurrentProfileIdsLocked();
            mRecentTasks.clear();
            mRecentTasks.clear();
            mRecentTasks.addAll(mTaskPersister.restoreTasksLocked());
            mRecentTasks.addAll(mTaskPersister.restoreTasksLocked(
                    getUserManagerLocked().getUserIds()));
            mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
            mRecentTasks.cleanupLocked(UserHandle.USER_ALL);
            mTaskPersister.startPersisting();
            mTaskPersister.startPersisting();
@@ -20644,9 +20645,6 @@ public final class ActivityManagerService extends ActivityManagerNative
                // Kill all the processes for the user.
                // Kill all the processes for the user.
                forceStopUserLocked(userId, "finish user");
                forceStopUserLocked(userId, "finish user");
            }
            }
            // Explicitly remove the old information in mRecentTasks.
            mRecentTasks.removeTasksForUserLocked(userId);
        }
        }
        for (int i=0; i<callbacks.size(); i++) {
        for (int i=0; i<callbacks.size(); i++) {
@@ -20665,6 +20663,10 @@ public final class ActivityManagerService extends ActivityManagerNative
        }
        }
    }
    }
    void onUserRemovedLocked(int userId) {
        mRecentTasks.removeTasksForUserLocked(userId);
    }
    @Override
    @Override
    public UserInfo getCurrentUser() {
    public UserInfo getCurrentUser() {
        if ((checkCallingPermission(INTERACT_ACROSS_USERS)
        if ((checkCallingPermission(INTERACT_ACROSS_USERS)
@@ -20949,6 +20951,13 @@ public final class ActivityManagerService extends ActivityManagerNative
                return homeActivity == null ? null : homeActivity.realActivity;
                return homeActivity == null ? null : homeActivity.realActivity;
            }
            }
        }
        }
        @Override
        public void onUserRemoved(int userId) {
            synchronized (ActivityManagerService.this) {
                ActivityManagerService.this.onUserRemovedLocked(userId);
            }
        }
    }
    }
    private final class SleepTokenImpl extends SleepToken {
    private final class SleepTokenImpl extends SleepToken {
+8 −4
Original line number Original line Diff line number Diff line
@@ -35,6 +35,7 @@ import android.util.SparseArray;
import android.util.Xml;
import android.util.Xml;
import android.os.Process;
import android.os.Process;


import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
import com.android.internal.util.XmlUtils;


@@ -330,7 +331,7 @@ public class TaskPersister {
        return null;
        return null;
    }
    }


    ArrayList<TaskRecord> restoreTasksLocked() {
    ArrayList<TaskRecord> restoreTasksLocked(final int [] validUserIds) {
        final ArrayList<TaskRecord> tasks = new ArrayList<TaskRecord>();
        final ArrayList<TaskRecord> tasks = new ArrayList<TaskRecord>();
        ArraySet<Integer> recoveredTaskIds = new ArraySet<Integer>();
        ArraySet<Integer> recoveredTaskIds = new ArraySet<Integer>();


@@ -362,15 +363,18 @@ public class TaskPersister {
                            if (DEBUG) Slog.d(TAG, "restoreTasksLocked: restored task=" +
                            if (DEBUG) Slog.d(TAG, "restoreTasksLocked: restored task=" +
                                    task);
                                    task);
                            if (task != null) {
                            if (task != null) {
                                task.isPersistable = true;
                                // XXX Don't add to write queue... there is no reason to write
                                // XXX Don't add to write queue... there is no reason to write
                                // out the stuff we just read, if we don't write it we will
                                // out the stuff we just read, if we don't write it we will
                                // read the same thing again.
                                // read the same thing again.
                                //mWriteQueue.add(new TaskWriteQueueItem(task));
                                //mWriteQueue.add(new TaskWriteQueueItem(task));
                                tasks.add(task);
                                final int taskId = task.taskId;
                                final int taskId = task.taskId;
                                recoveredTaskIds.add(taskId);
                                mStackSupervisor.setNextTaskId(taskId);
                                mStackSupervisor.setNextTaskId(taskId);
                                // Check if it's a valid user id. Don't add tasks for removed users.
                                if (ArrayUtils.contains(validUserIds, task.userId)) {
                                    task.isPersistable = true;
                                    tasks.add(task);
                                    recoveredTaskIds.add(taskId);
                                }
                            } else {
                            } else {
                                Slog.e(TAG, "Unable to restore taskFile=" + taskFile + ": " +
                                Slog.e(TAG, "Unable to restore taskFile=" + taskFile + ": " +
                                        fileToString(taskFile));
                                        fileToString(taskFile));
+20 −9
Original line number Original line Diff line number Diff line
@@ -20,6 +20,7 @@ import android.accounts.Account;
import android.annotation.NonNull;
import android.annotation.NonNull;
import android.app.Activity;
import android.app.Activity;
import android.app.ActivityManager;
import android.app.ActivityManager;
import android.app.ActivityManagerInternal;
import android.app.ActivityManagerNative;
import android.app.ActivityManagerNative;
import android.app.IStopUserCallback;
import android.app.IStopUserCallback;
import android.app.admin.DevicePolicyManager;
import android.app.admin.DevicePolicyManager;
@@ -64,7 +65,7 @@ import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.app.IAppOpsService;
import com.android.internal.app.IAppOpsService;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.FastXmlSerializer;
import com.android.internal.util.XmlUtils;
import com.android.internal.util.XmlUtils;
import com.android.server.accounts.AccountManagerService;
import com.android.server.LocalServices;


import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserException;
@@ -242,13 +243,15 @@ public class UserManagerService extends IUserManager.Stub {
            synchronized (mPackagesLock) {
            synchronized (mPackagesLock) {
                // Prune out any partially created/partially removed users.
                // Prune out any partially created/partially removed users.
                ArrayList<UserInfo> partials = new ArrayList<UserInfo>();
                ArrayList<UserInfo> partials = new ArrayList<UserInfo>();
                for (int i = 0; i < mUsers.size(); i++) {
                final int userSize = mUsers.size();
                for (int i = 0; i < userSize; i++) {
                    UserInfo ui = mUsers.valueAt(i);
                    UserInfo ui = mUsers.valueAt(i);
                    if ((ui.partial || ui.guestToRemove) && i != 0) {
                    if ((ui.partial || ui.guestToRemove) && i != 0) {
                        partials.add(ui);
                        partials.add(ui);
                    }
                    }
                }
                }
                for (int i = 0; i < partials.size(); i++) {
                final int partialsSize = partials.size();
                for (int i = 0; i < partialsSize; i++) {
                    UserInfo ui = partials.get(i);
                    UserInfo ui = partials.get(i);
                    Slog.w(LOG_TAG, "Removing partially created user " + ui.id
                    Slog.w(LOG_TAG, "Removing partially created user " + ui.id
                            + " (name=" + ui.name + ")");
                            + " (name=" + ui.name + ")");
@@ -272,7 +275,8 @@ public class UserManagerService extends IUserManager.Stub {
    public UserInfo getPrimaryUser() {
    public UserInfo getPrimaryUser() {
        checkManageUsersPermission("query users");
        checkManageUsersPermission("query users");
        synchronized (mPackagesLock) {
        synchronized (mPackagesLock) {
            for (int i = 0; i < mUsers.size(); i++) {
            final int userSize = mUsers.size();
            for (int i = 0; i < userSize; i++) {
                UserInfo ui = mUsers.valueAt(i);
                UserInfo ui = mUsers.valueAt(i);
                if (ui.isPrimary()) {
                if (ui.isPrimary()) {
                    return ui;
                    return ui;
@@ -287,7 +291,8 @@ public class UserManagerService extends IUserManager.Stub {
        checkManageUsersPermission("query users");
        checkManageUsersPermission("query users");
        synchronized (mPackagesLock) {
        synchronized (mPackagesLock) {
            ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
            ArrayList<UserInfo> users = new ArrayList<UserInfo>(mUsers.size());
            for (int i = 0; i < mUsers.size(); i++) {
            final int userSize = mUsers.size();
            for (int i = 0; i < userSize; i++) {
                UserInfo ui = mUsers.valueAt(i);
                UserInfo ui = mUsers.valueAt(i);
                if (ui.partial) {
                if (ui.partial) {
                    continue;
                    continue;
@@ -323,7 +328,8 @@ public class UserManagerService extends IUserManager.Stub {
            // Probably a dying user
            // Probably a dying user
            return users;
            return users;
        }
        }
        for (int i = 0; i < mUsers.size(); i++) {
        final int userSize = mUsers.size();
        for (int i = 0; i < userSize; i++) {
            UserInfo profile = mUsers.valueAt(i);
            UserInfo profile = mUsers.valueAt(i);
            if (!isProfileOf(user, profile)) {
            if (!isProfileOf(user, profile)) {
                continue;
                continue;
@@ -978,7 +984,8 @@ public class UserManagerService extends IUserManager.Stub {
            serializer.startTag(null, TAG_GUEST_RESTRICTIONS);
            serializer.startTag(null, TAG_GUEST_RESTRICTIONS);
            writeRestrictionsLocked(serializer, mGuestRestrictions);
            writeRestrictionsLocked(serializer, mGuestRestrictions);
            serializer.endTag(null, TAG_GUEST_RESTRICTIONS);
            serializer.endTag(null, TAG_GUEST_RESTRICTIONS);
            for (int i = 0; i < mUsers.size(); i++) {
            final int userSize = mUsers.size();
            for (int i = 0; i < userSize; i++) {
                UserInfo user = mUsers.valueAt(i);
                UserInfo user = mUsers.valueAt(i);
                serializer.startTag(null, TAG_USER);
                serializer.startTag(null, TAG_USER);
                serializer.attribute(null, ATTR_ID, Integer.toString(user.id));
                serializer.attribute(null, ATTR_ID, Integer.toString(user.id));
@@ -1555,6 +1562,9 @@ public class UserManagerService extends IUserManager.Stub {
                            }
                            }
                            new Thread() {
                            new Thread() {
                                public void run() {
                                public void run() {
                                    // Clean up any ActivityManager state
                                    LocalServices.getService(ActivityManagerInternal.class)
                                            .onUserRemoved(userHandle);
                                    synchronized (mInstallLock) {
                                    synchronized (mInstallLock) {
                                        synchronized (mPackagesLock) {
                                        synchronized (mPackagesLock) {
                                            removeUserStateLocked(userHandle);
                                            removeUserStateLocked(userHandle);
@@ -1919,14 +1929,15 @@ public class UserManagerService extends IUserManager.Stub {
     */
     */
    private void updateUserIdsLocked() {
    private void updateUserIdsLocked() {
        int num = 0;
        int num = 0;
        for (int i = 0; i < mUsers.size(); i++) {
        final int userSize = mUsers.size();
        for (int i = 0; i < userSize; i++) {
            if (!mUsers.valueAt(i).partial) {
            if (!mUsers.valueAt(i).partial) {
                num++;
                num++;
            }
            }
        }
        }
        final int[] newUsers = new int[num];
        final int[] newUsers = new int[num];
        int n = 0;
        int n = 0;
        for (int i = 0; i < mUsers.size(); i++) {
        for (int i = 0; i < userSize; i++) {
            if (!mUsers.valueAt(i).partial) {
            if (!mUsers.valueAt(i).partial) {
                newUsers[n++] = mUsers.keyAt(i);
                newUsers[n++] = mUsers.keyAt(i);
            }
            }