Loading services/core/java/com/android/server/job/controllers/ContentObserverController.java +90 −59 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.job.controllers; import android.annotation.UserIdInt; import android.app.job.JobInfo; import android.content.Context; import android.database.ContentObserver; Loading @@ -23,6 +24,7 @@ import android.net.Uri; import android.os.Handler; import android.os.UserHandle; import android.util.Slog; import android.util.SparseArray; import android.util.TimeUtils; import android.util.ArrayMap; import android.util.ArraySet; Loading @@ -35,6 +37,7 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Objects; /** * Controller for monitoring changes to content URIs through a ContentObserver. Loading @@ -59,7 +62,11 @@ public class ContentObserverController extends StateController { private static volatile ContentObserverController sController; final private List<JobStatus> mTrackedTasks = new ArrayList<JobStatus>(); ArrayMap<JobInfo.TriggerContentUri, ObserverInstance> mObservers = new ArrayMap<>(); /** * Per-userid {@link JobInfo.TriggerContentUri} keyed ContentObserver cache. */ SparseArray<ArrayMap<JobInfo.TriggerContentUri, ObserverInstance>> mObservers = new SparseArray<>(); final Handler mHandler; public static ContentObserverController get(JobSchedulerService taskManagerService) { Loading Loading @@ -203,18 +210,21 @@ public class ContentObserverController extends StateController { final class ObserverInstance extends ContentObserver { final JobInfo.TriggerContentUri mUri; final @UserIdInt int mUserId; final ArraySet<JobInstance> mJobs = new ArraySet<>(); public ObserverInstance(Handler handler, JobInfo.TriggerContentUri uri) { public ObserverInstance(Handler handler, JobInfo.TriggerContentUri uri, @UserIdInt int userId) { super(handler); mUri = uri; mUserId = userId; } @Override public void onChange(boolean selfChange, Uri uri) { if (DEBUG) { Slog.i(TAG, "onChange(self=" + selfChange + ") for " + uri + " when mUri=" + mUri); + " when mUri=" + mUri + " mUserId=" + mUserId); } synchronized (mLock) { final int N = mJobs.size(); Loading Loading @@ -258,27 +268,38 @@ public class ContentObserverController extends StateController { boolean mTriggerPending; // This constructor must be called with the master job scheduler lock held. JobInstance(JobStatus jobStatus) { mJobStatus = jobStatus; mExecuteRunner = new TriggerRunnable(this); mTimeoutRunner = new TriggerRunnable(this); final JobInfo.TriggerContentUri[] uris = jobStatus.getJob().getTriggerContentUris(); final int sourceUserId = jobStatus.getSourceUserId(); ArrayMap<JobInfo.TriggerContentUri, ObserverInstance> observersOfUser = mObservers.get(sourceUserId); if (observersOfUser == null) { observersOfUser = new ArrayMap<>(); mObservers.put(sourceUserId, observersOfUser); } if (uris != null) { for (JobInfo.TriggerContentUri uri : uris) { ObserverInstance obs = mObservers.get(uri); ObserverInstance obs = observersOfUser.get(uri); if (obs == null) { obs = new ObserverInstance(mHandler, uri); mObservers.put(uri, obs); obs = new ObserverInstance(mHandler, uri, jobStatus.getSourceUserId()); observersOfUser.put(uri, obs); final boolean andDescendants = (uri.getFlags() & JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS) != 0; if (DEBUG) { Slog.v(TAG, "New observer " + obs + " for " + uri.getUri() + " andDescendants=" + andDescendants); + " andDescendants=" + andDescendants + " sourceUserId=" + sourceUserId); } mContext.getContentResolver().registerContentObserver( uri.getUri(), andDescendants, obs); obs, sourceUserId ); } else { if (DEBUG) { final boolean andDescendants = (uri.getFlags() & Loading Loading @@ -342,7 +363,11 @@ public class ContentObserverController extends StateController { Slog.i(TAG, "Unregistering observer " + obs + " for " + obs.mUri.getUri()); } mContext.getContentResolver().unregisterContentObserver(obs); mObservers.remove(obs.mUri); ArrayMap<JobInfo.TriggerContentUri, ObserverInstance> observerOfUser = mObservers.get(obs.mUserId); if (observerOfUser != null) { observerOfUser.remove(obs.mUri); } } } } Loading @@ -366,8 +391,13 @@ public class ContentObserverController extends StateController { int N = mObservers.size(); if (N > 0) { pw.println(" Observers:"); for (int i = 0; i < N; i++) { ObserverInstance obs = mObservers.valueAt(i); for (int userIdx = 0; userIdx < N; userIdx++) { final int userId = mObservers.keyAt(userIdx); ArrayMap<JobInfo.TriggerContentUri, ObserverInstance> observersOfUser = mObservers.get(userId); int numbOfObserversPerUser = observersOfUser.size(); for (int observerIdx = 0 ; observerIdx < numbOfObserversPerUser; observerIdx++) { ObserverInstance obs = observersOfUser.valueAt(observerIdx); int M = obs.mJobs.size(); boolean shouldDump = false; for (int j = 0; j < M; j++) { Loading @@ -381,7 +411,7 @@ public class ContentObserverController extends StateController { continue; } pw.print(" "); JobInfo.TriggerContentUri trigger = mObservers.keyAt(i); JobInfo.TriggerContentUri trigger = observersOfUser.keyAt(observerIdx); pw.print(trigger.getUri()); pw.print(" 0x"); pw.print(Integer.toHexString(trigger.getFlags())); Loading Loading @@ -426,3 +456,4 @@ public class ContentObserverController extends StateController { } } } } Loading
services/core/java/com/android/server/job/controllers/ContentObserverController.java +90 −59 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.job.controllers; import android.annotation.UserIdInt; import android.app.job.JobInfo; import android.content.Context; import android.database.ContentObserver; Loading @@ -23,6 +24,7 @@ import android.net.Uri; import android.os.Handler; import android.os.UserHandle; import android.util.Slog; import android.util.SparseArray; import android.util.TimeUtils; import android.util.ArrayMap; import android.util.ArraySet; Loading @@ -35,6 +37,7 @@ import java.io.PrintWriter; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Objects; /** * Controller for monitoring changes to content URIs through a ContentObserver. Loading @@ -59,7 +62,11 @@ public class ContentObserverController extends StateController { private static volatile ContentObserverController sController; final private List<JobStatus> mTrackedTasks = new ArrayList<JobStatus>(); ArrayMap<JobInfo.TriggerContentUri, ObserverInstance> mObservers = new ArrayMap<>(); /** * Per-userid {@link JobInfo.TriggerContentUri} keyed ContentObserver cache. */ SparseArray<ArrayMap<JobInfo.TriggerContentUri, ObserverInstance>> mObservers = new SparseArray<>(); final Handler mHandler; public static ContentObserverController get(JobSchedulerService taskManagerService) { Loading Loading @@ -203,18 +210,21 @@ public class ContentObserverController extends StateController { final class ObserverInstance extends ContentObserver { final JobInfo.TriggerContentUri mUri; final @UserIdInt int mUserId; final ArraySet<JobInstance> mJobs = new ArraySet<>(); public ObserverInstance(Handler handler, JobInfo.TriggerContentUri uri) { public ObserverInstance(Handler handler, JobInfo.TriggerContentUri uri, @UserIdInt int userId) { super(handler); mUri = uri; mUserId = userId; } @Override public void onChange(boolean selfChange, Uri uri) { if (DEBUG) { Slog.i(TAG, "onChange(self=" + selfChange + ") for " + uri + " when mUri=" + mUri); + " when mUri=" + mUri + " mUserId=" + mUserId); } synchronized (mLock) { final int N = mJobs.size(); Loading Loading @@ -258,27 +268,38 @@ public class ContentObserverController extends StateController { boolean mTriggerPending; // This constructor must be called with the master job scheduler lock held. JobInstance(JobStatus jobStatus) { mJobStatus = jobStatus; mExecuteRunner = new TriggerRunnable(this); mTimeoutRunner = new TriggerRunnable(this); final JobInfo.TriggerContentUri[] uris = jobStatus.getJob().getTriggerContentUris(); final int sourceUserId = jobStatus.getSourceUserId(); ArrayMap<JobInfo.TriggerContentUri, ObserverInstance> observersOfUser = mObservers.get(sourceUserId); if (observersOfUser == null) { observersOfUser = new ArrayMap<>(); mObservers.put(sourceUserId, observersOfUser); } if (uris != null) { for (JobInfo.TriggerContentUri uri : uris) { ObserverInstance obs = mObservers.get(uri); ObserverInstance obs = observersOfUser.get(uri); if (obs == null) { obs = new ObserverInstance(mHandler, uri); mObservers.put(uri, obs); obs = new ObserverInstance(mHandler, uri, jobStatus.getSourceUserId()); observersOfUser.put(uri, obs); final boolean andDescendants = (uri.getFlags() & JobInfo.TriggerContentUri.FLAG_NOTIFY_FOR_DESCENDANTS) != 0; if (DEBUG) { Slog.v(TAG, "New observer " + obs + " for " + uri.getUri() + " andDescendants=" + andDescendants); + " andDescendants=" + andDescendants + " sourceUserId=" + sourceUserId); } mContext.getContentResolver().registerContentObserver( uri.getUri(), andDescendants, obs); obs, sourceUserId ); } else { if (DEBUG) { final boolean andDescendants = (uri.getFlags() & Loading Loading @@ -342,7 +363,11 @@ public class ContentObserverController extends StateController { Slog.i(TAG, "Unregistering observer " + obs + " for " + obs.mUri.getUri()); } mContext.getContentResolver().unregisterContentObserver(obs); mObservers.remove(obs.mUri); ArrayMap<JobInfo.TriggerContentUri, ObserverInstance> observerOfUser = mObservers.get(obs.mUserId); if (observerOfUser != null) { observerOfUser.remove(obs.mUri); } } } } Loading @@ -366,8 +391,13 @@ public class ContentObserverController extends StateController { int N = mObservers.size(); if (N > 0) { pw.println(" Observers:"); for (int i = 0; i < N; i++) { ObserverInstance obs = mObservers.valueAt(i); for (int userIdx = 0; userIdx < N; userIdx++) { final int userId = mObservers.keyAt(userIdx); ArrayMap<JobInfo.TriggerContentUri, ObserverInstance> observersOfUser = mObservers.get(userId); int numbOfObserversPerUser = observersOfUser.size(); for (int observerIdx = 0 ; observerIdx < numbOfObserversPerUser; observerIdx++) { ObserverInstance obs = observersOfUser.valueAt(observerIdx); int M = obs.mJobs.size(); boolean shouldDump = false; for (int j = 0; j < M; j++) { Loading @@ -381,7 +411,7 @@ public class ContentObserverController extends StateController { continue; } pw.print(" "); JobInfo.TriggerContentUri trigger = mObservers.keyAt(i); JobInfo.TriggerContentUri trigger = observersOfUser.keyAt(observerIdx); pw.print(trigger.getUri()); pw.print(" 0x"); pw.print(Integer.toHexString(trigger.getFlags())); Loading Loading @@ -426,3 +456,4 @@ public class ContentObserverController extends StateController { } } } }