Purge Nonexistent User Jobs on Boot

In the case that a user has been removed but their jobs still exist on
disk, the JobSchedulerService will remove all jobs not associated with
current users on boot.
Exposed UserManagerService#getUserIds() via UserManagerInternal for
quick user id retrieval.

Fixes: 38261977
Test: manual

Change-Id: Id4b3c0a4142b4818fcd875eef18ea03f3c45ca40
Signed-off-by: Michael Wachenschwanz <mwachens@google.com>
This commit is contained in:
Michael Wachenschwanz
2017-05-15 13:53:09 -07:00
parent 7e08c7ec17
commit 3f2b6552ec
4 changed files with 43 additions and 0 deletions

View File

@@ -167,4 +167,12 @@ public abstract class UserManagerInternal {
* Remove user's running state
*/
public abstract void removeUserState(int userId);
/**
* Returns an array of user ids. This array is cached in UserManagerService and passed as a
* reference, so do not modify the returned array.
*
* @return the array of user ids.
*/
public abstract int[] getUserIds();
}

View File

@@ -63,6 +63,7 @@ import android.os.ServiceManager;
import android.os.ShellCallback;
import android.os.SystemClock;
import android.os.UserHandle;
import android.os.UserManagerInternal;
import android.provider.Settings;
import android.util.KeyValueListParser;
import android.util.Slog;
@@ -751,6 +752,13 @@ public final class JobSchedulerService extends com.android.server.SystemService
}
}
private void cancelJobsForNonExistentUsers() {
UserManagerInternal umi = LocalServices.getService(UserManagerInternal.class);
synchronized (mLock) {
mJobs.removeJobsOfNonUsers(umi.getUserIds());
}
}
void cancelJobsForPackageAndUid(String pkgName, int uid) {
synchronized (mLock) {
final List<JobStatus> jobsForUid = mJobs.getJobsByUid(uid);
@@ -941,6 +949,8 @@ public final class JobSchedulerService extends com.android.server.SystemService
} catch (RemoteException e) {
// ignored; both services live in system_server
}
// Remove any jobs that are not associated with any of the current users.
cancelJobsForNonExistentUsers();
} else if (phase == PHASE_THIRD_PARTY_APPS_CAN_START) {
synchronized (mLock) {
// Let's go!

View File

@@ -35,6 +35,7 @@ import android.util.SparseArray;
import android.util.Xml;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.ArrayUtils;
import com.android.internal.util.FastXmlSerializer;
import com.android.server.IoThread;
import com.android.server.job.controllers.JobStatus;
@@ -171,6 +172,14 @@ public class JobStore {
return removed;
}
/**
* Remove the jobs of users not specified in the whitelist.
* @param whitelist Array of User IDs whose jobs are not to be removed.
*/
public void removeJobsOfNonUsers(int[] whitelist) {
mJobSet.removeJobsOfNonUsers(whitelist);
}
@VisibleForTesting
public void clear() {
mJobSet.clear();
@@ -839,6 +848,17 @@ public class JobStore {
return didRemove;
}
// Remove the jobs all users not specified by the whitelist of user ids
public void removeJobsOfNonUsers(int[] whitelist) {
for (int jobIndex = mJobs.size() - 1; jobIndex >= 0; jobIndex--) {
int jobUserId = UserHandle.getUserId(mJobs.keyAt(jobIndex));
// check if job's user id is not in the whitelist
if (!ArrayUtils.contains(whitelist, jobUserId)) {
mJobs.removeAt(jobIndex);
}
}
}
public boolean contains(JobStatus job) {
final int uid = job.getUid();
ArraySet<JobStatus> jobs = mJobs.get(uid);

View File

@@ -3683,6 +3683,11 @@ public class UserManagerService extends IUserManager.Stub {
}
}
@Override
public int[] getUserIds() {
return UserManagerService.this.getUserIds();
}
@Override
public boolean isUserUnlockingOrUnlocked(int userId) {
synchronized (mUserStates) {