Merge "More work on issue #26390151: Add new JobScheduler API..." into nyc-dev

This commit is contained in:
Dianne Hackborn
2016-04-06 19:38:49 +00:00
committed by Android (Google) Code Review
16 changed files with 180 additions and 66 deletions

View File

@@ -7885,6 +7885,7 @@ package android.content {
method public static boolean isSyncPending(android.accounts.Account, java.lang.String);
method public void notifyChange(android.net.Uri, android.database.ContentObserver);
method public void notifyChange(android.net.Uri, android.database.ContentObserver, boolean);
method public void notifyChange(android.net.Uri, android.database.ContentObserver, int);
method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public final android.os.ParcelFileDescriptor openFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
@@ -7915,6 +7916,8 @@ package android.content {
field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
field public static final java.lang.String SCHEME_CONTENT = "content";
field public static final java.lang.String SCHEME_FILE = "file";

View File

@@ -8183,6 +8183,7 @@ package android.content {
method public static boolean isSyncPending(android.accounts.Account, java.lang.String);
method public void notifyChange(android.net.Uri, android.database.ContentObserver);
method public void notifyChange(android.net.Uri, android.database.ContentObserver, boolean);
method public void notifyChange(android.net.Uri, android.database.ContentObserver, int);
method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public final android.os.ParcelFileDescriptor openFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
@@ -8213,6 +8214,8 @@ package android.content {
field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
field public static final java.lang.String SCHEME_CONTENT = "content";
field public static final java.lang.String SCHEME_FILE = "file";

View File

@@ -7890,6 +7890,7 @@ package android.content {
method public static boolean isSyncPending(android.accounts.Account, java.lang.String);
method public void notifyChange(android.net.Uri, android.database.ContentObserver);
method public void notifyChange(android.net.Uri, android.database.ContentObserver, boolean);
method public void notifyChange(android.net.Uri, android.database.ContentObserver, int);
method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
method public final android.content.res.AssetFileDescriptor openAssetFileDescriptor(android.net.Uri, java.lang.String, android.os.CancellationSignal) throws java.io.FileNotFoundException;
method public final android.os.ParcelFileDescriptor openFileDescriptor(android.net.Uri, java.lang.String) throws java.io.FileNotFoundException;
@@ -7920,6 +7921,8 @@ package android.content {
field public static final java.lang.String CURSOR_DIR_BASE_TYPE = "vnd.android.cursor.dir";
field public static final java.lang.String CURSOR_ITEM_BASE_TYPE = "vnd.android.cursor.item";
field public static final java.lang.String EXTRA_SIZE = "android.content.extra.SIZE";
field public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 2; // 0x2
field public static final int NOTIFY_SYNC_TO_NETWORK = 1; // 0x1
field public static final java.lang.String SCHEME_ANDROID_RESOURCE = "android.resource";
field public static final java.lang.String SCHEME_CONTENT = "content";
field public static final java.lang.String SCHEME_FILE = "file";

View File

@@ -17,6 +17,7 @@
package android.content;
import android.accounts.Account;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.RequiresPermission;
@@ -60,6 +61,8 @@ import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
@@ -289,6 +292,31 @@ public abstract class ContentResolver {
/** @hide */
public static final int SYNC_OBSERVER_TYPE_ALL = 0x7fffffff;
/** @hide */
@IntDef(flag = true,
value = {
NOTIFY_SYNC_TO_NETWORK,
NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS
})
@Retention(RetentionPolicy.SOURCE)
public @interface NotifyFlags {}
/**
* Flag for {@link #notifyChange(Uri, ContentObserver, int)}: attempt to sync the change
* to the network.
*/
public static final int NOTIFY_SYNC_TO_NETWORK = 1<<0;
/**
* Flag for {@link #notifyChange(Uri, ContentObserver, int)}: if set, this notification
* will be skipped if it is being delivered to the root URI of a ContentObserver that is
* using "notify for descendants." The purpose of this is to allow the provide to send
* a general notification of "something under X" changed that observers of that specific
* URI can receive, while also sending a specific URI under X. It would use this flag
* when sending the former, so that observers of "X and descendants" only see the latter.
*/
public static final int NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS = 1<<1;
// Always log queries which take 500ms+; shorter queries are
// sampled accordingly.
private static final boolean ENABLE_CONTENT_SAMPLE = false;
@@ -1676,7 +1704,7 @@ public abstract class ContentResolver {
* The observer that originated the change will only receive the notification if it
* has requested to receive self-change notifications by implementing
* {@link ContentObserver#deliverSelfNotifications()} to return true.
* @param syncToNetwork If true, attempt to sync the change to the network.
* @param syncToNetwork If true, same as {@link #NOTIFY_SYNC_TO_NETWORK}.
* @see #requestSync(android.accounts.Account, String, android.os.Bundle)
*/
public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer,
@@ -1689,6 +1717,32 @@ public abstract class ContentResolver {
ContentProvider.getUserIdFromUri(uri, UserHandle.myUserId()));
}
/**
* Notify registered observers that a row was updated.
* To register, call {@link #registerContentObserver(android.net.Uri, boolean, android.database.ContentObserver) registerContentObserver()}.
* By default, CursorAdapter objects will get this notification.
* If syncToNetwork is true, this will attempt to schedule a local sync using the sync
* adapter that's registered for the authority of the provided uri. No account will be
* passed to the sync adapter, so all matching accounts will be synchronized.
*
* @param uri The uri of the content that was changed.
* @param observer The observer that originated the change, may be <code>null</null>.
* The observer that originated the change will only receive the notification if it
* has requested to receive self-change notifications by implementing
* {@link ContentObserver#deliverSelfNotifications()} to return true.
* @param flags Additional flags: {@link #NOTIFY_SYNC_TO_NETWORK}.
* @see #requestSync(android.accounts.Account, String, android.os.Bundle)
*/
public void notifyChange(@NonNull Uri uri, @Nullable ContentObserver observer,
@NotifyFlags int flags) {
Preconditions.checkNotNull(uri, "uri");
notifyChange(
ContentProvider.getUriWithoutUserId(uri),
observer,
flags,
ContentProvider.getUserIdFromUri(uri, UserHandle.myUserId()));
}
/**
* Notify registered observers within the designated user(s) that a row was updated.
*
@@ -1699,7 +1753,24 @@ public abstract class ContentResolver {
try {
getContentService().notifyChange(
uri, observer == null ? null : observer.getContentObserver(),
observer != null && observer.deliverSelfNotifications(), syncToNetwork,
observer != null && observer.deliverSelfNotifications(),
syncToNetwork ? NOTIFY_SYNC_TO_NETWORK : 0,
userHandle);
} catch (RemoteException e) {
}
}
/**
* Notify registered observers within the designated user(s) that a row was updated.
*
* @hide
*/
public void notifyChange(Uri uri, ContentObserver observer, @NotifyFlags int flags,
@UserIdInt int userHandle) {
try {
getContentService().notifyChange(
uri, observer == null ? null : observer.getContentObserver(),
observer != null && observer.deliverSelfNotifications(), flags,
userHandle);
} catch (RemoteException e) {
}

View File

@@ -52,7 +52,7 @@ interface IContentService {
* USER_CURRENT are properly interpreted.
*/
void notifyChange(in Uri uri, IContentObserver observer,
boolean observerWantsSelfNotifications, boolean syncToNetwork,
boolean observerWantsSelfNotifications, int flags,
int userHandle);
void requestSync(in Account account, String authority, in Bundle extras);

View File

@@ -73,7 +73,8 @@ import java.util.List;
* {@hide}
*/
public final class ContentService extends IContentService.Stub {
private static final String TAG = "ContentService";
static final String TAG = "ContentService";
static final boolean DEBUG = false;
public static class Lifecycle extends SystemService {
private ContentService mContentService;
@@ -339,12 +340,10 @@ public final class ContentService extends IContentService.Stub {
*/
@Override
public void notifyChange(Uri uri, IContentObserver observer,
boolean observerWantsSelfNotifications, boolean syncToNetwork,
boolean observerWantsSelfNotifications, int flags,
int userHandle) {
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Notifying update of " + uri + " for user " + userHandle
+ " from observer " + observer + ", syncToNetwork " + syncToNetwork);
}
if (DEBUG) Slog.d(TAG, "Notifying update of " + uri + " for user " + userHandle
+ " from observer " + observer + ", flags " + Integer.toHexString(flags));
final int uid = Binder.getCallingUid();
final int pid = Binder.getCallingPid();
@@ -373,16 +372,15 @@ public final class ContentService extends IContentService.Stub {
ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
synchronized (mRootNode) {
mRootNode.collectObserversLocked(uri, 0, observer, observerWantsSelfNotifications,
userHandle, calls);
flags, userHandle, calls);
}
final int numCalls = calls.size();
for (int i=0; i<numCalls; i++) {
ObserverCall oc = calls.get(i);
try {
oc.mObserver.onChange(oc.mSelfChange, uri, userHandle);
if (Log.isLoggable(TAG, Log.VERBOSE)) {
Log.v(TAG, "Notified " + oc.mObserver + " of " + "update at " + uri);
}
if (DEBUG) Slog.d(TAG, "Notified " + oc.mObserver + " of " + "update at "
+ uri);
} catch (RemoteException ex) {
synchronized (mRootNode) {
Log.w(TAG, "Found dead observer, removing");
@@ -401,7 +399,7 @@ public final class ContentService extends IContentService.Stub {
}
}
}
if (syncToNetwork) {
if ((flags&ContentResolver.NOTIFY_SYNC_TO_NETWORK) != 0) {
SyncManager syncManager = getSyncManager();
if (syncManager != null) {
syncManager.scheduleLocalSync(null /* all accounts */, callingUserHandle, uid,
@@ -420,7 +418,8 @@ public final class ContentService extends IContentService.Stub {
public void notifyChange(Uri uri, IContentObserver observer,
boolean observerWantsSelfNotifications, boolean syncToNetwork) {
notifyChange(uri, observer, observerWantsSelfNotifications, syncToNetwork,
notifyChange(uri, observer, observerWantsSelfNotifications,
syncToNetwork ? ContentResolver.NOTIFY_SYNC_TO_NETWORK : 0,
UserHandle.getCallingUserId());
}
@@ -1064,14 +1063,14 @@ public final class ContentService extends IContentService.Stub {
for (int i = 0; i < packageCache.size();) {
final Pair<String, Uri> key = packageCache.keyAt(i);
if (key.second != null && key.second.toString().startsWith(uri.toString())) {
Slog.d(TAG, "Invalidating cache for key " + key);
if (DEBUG) Slog.d(TAG, "Invalidating cache for key " + key);
packageCache.removeAt(i);
} else {
i++;
}
}
} else {
Slog.d(TAG, "Invalidating cache for package " + providerPackageName);
if (DEBUG) Slog.d(TAG, "Invalidating cache for package " + providerPackageName);
packageCache.clear();
}
}
@@ -1310,8 +1309,8 @@ public final class ContentService extends IContentService.Stub {
}
private void collectMyObserversLocked(boolean leaf, IContentObserver observer,
boolean observerWantsSelfNotifications, int targetUserHandle,
ArrayList<ObserverCall> calls) {
boolean observerWantsSelfNotifications, int flags,
int targetUserHandle, ArrayList<ObserverCall> calls) {
int N = mObservers.size();
IBinder observerBinder = observer == null ? null : observer.asBinder();
for (int i = 0; i < N; i++) {
@@ -1329,9 +1328,29 @@ public final class ContentService extends IContentService.Stub {
|| entry.userHandle == UserHandle.USER_ALL
|| targetUserHandle == entry.userHandle) {
// Make sure the observer is interested in the notification
if (leaf || (!leaf && entry.notifyForDescendants)) {
calls.add(new ObserverCall(this, entry.observer, selfChange));
if (leaf) {
// If we are at the leaf: we always report, unless the sender has asked
// to skip observers that are notifying for descendants (since they will
// be sending another more specific URI for them).
if ((flags&ContentResolver.NOTIFY_SKIP_NOTIFY_FOR_DESCENDANTS) != 0
&& entry.notifyForDescendants) {
if (DEBUG) Slog.d(TAG, "Skipping " + entry.observer
+ ": skip notify for descendants");
continue;
}
} else {
// If we are not at the leaf: we report if the observer says it wants
// to be notified for all descendants.
if (!entry.notifyForDescendants) {
if (DEBUG) Slog.d(TAG, "Skipping " + entry.observer
+ ": not monitor descendants");
continue;
}
}
if (DEBUG) Slog.d(TAG, "Reporting to " + entry.observer + ": leaf=" + leaf
+ " flags=" + Integer.toHexString(flags)
+ " desc=" + entry.notifyForDescendants);
calls.add(new ObserverCall(this, entry.observer, selfChange));
}
}
}
@@ -1340,19 +1359,22 @@ public final class ContentService extends IContentService.Stub {
* targetUserHandle is either a hard user handle or is USER_ALL
*/
public void collectObserversLocked(Uri uri, int index, IContentObserver observer,
boolean observerWantsSelfNotifications, int targetUserHandle,
ArrayList<ObserverCall> calls) {
boolean observerWantsSelfNotifications, int flags,
int targetUserHandle, ArrayList<ObserverCall> calls) {
String segment = null;
int segmentCount = countUriSegments(uri);
if (index >= segmentCount) {
// This is the leaf node, notify all observers
if (DEBUG) Slog.d(TAG, "Collecting leaf observers @ #" + index + ", node " + mName);
collectMyObserversLocked(true, observer, observerWantsSelfNotifications,
targetUserHandle, calls);
flags, targetUserHandle, calls);
} else if (index < segmentCount){
segment = getUriSegment(uri, index);
if (DEBUG) Slog.d(TAG, "Collecting non-leaf observers @ #" + index + " / "
+ segment);
// Notify any observers at this level who are interested in descendants
collectMyObserversLocked(false, observer, observerWantsSelfNotifications,
targetUserHandle, calls);
flags, targetUserHandle, calls);
}
int N = mChildren.size();
@@ -1360,8 +1382,8 @@ public final class ContentService extends IContentService.Stub {
ObserverNode node = mChildren.get(i);
if (segment == null || node.mName.equals(segment)) {
// We found the child,
node.collectObserversLocked(uri, index + 1,
observer, observerWantsSelfNotifications, targetUserHandle, calls);
node.collectObserversLocked(uri, index + 1, observer,
observerWantsSelfNotifications, flags, targetUserHandle, calls);
if (segment != null) {
break;
}

View File

@@ -304,7 +304,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
toCancel = mJobs.getJobByUidAndJobId(uId, job.getId());
if (toCancel != null) {
cancelJobImpl(toCancel);
cancelJobImpl(toCancel, jobStatus);
}
startTrackingJob(jobStatus, toCancel);
}
@@ -331,7 +331,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
}
for (int i=0; i<jobsForUser.size(); i++) {
JobStatus toRemove = jobsForUser.get(i);
cancelJobImpl(toRemove);
cancelJobImpl(toRemove, null);
}
}
@@ -360,7 +360,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
} catch (RemoteException e) {
}
}
cancelJobImpl(toRemove);
cancelJobImpl(toRemove, null);
}
}
@@ -377,13 +377,13 @@ public final class JobSchedulerService extends com.android.server.SystemService
toCancel = mJobs.getJobByUidAndJobId(uid, jobId);
}
if (toCancel != null) {
cancelJobImpl(toCancel);
cancelJobImpl(toCancel, null);
}
}
private void cancelJobImpl(JobStatus cancelled) {
private void cancelJobImpl(JobStatus cancelled, JobStatus incomingJob) {
if (DEBUG) Slog.d(TAG, "CANCEL: " + cancelled.toShortString());
stopTrackingJob(cancelled, true /* writeBack */);
stopTrackingJob(cancelled, incomingJob, true /* writeBack */);
synchronized (mLock) {
// Remove from pending queue.
mPendingJobs.remove(cancelled);
@@ -549,7 +549,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
for (int i = 0; i < mControllers.size(); i++) {
StateController controller = mControllers.get(i);
if (update) {
controller.maybeStopTrackingJobLocked(jobStatus, true);
controller.maybeStopTrackingJobLocked(jobStatus, null, true);
}
controller.maybeStartTrackingJobLocked(jobStatus, lastJob);
}
@@ -561,14 +561,15 @@ public final class JobSchedulerService extends com.android.server.SystemService
* Called when we want to remove a JobStatus object that we've finished executing. Returns the
* object removed.
*/
private boolean stopTrackingJob(JobStatus jobStatus, boolean writeBack) {
private boolean stopTrackingJob(JobStatus jobStatus, JobStatus incomingJob,
boolean writeBack) {
synchronized (mLock) {
// Remove from store as well as controllers.
final boolean removed = mJobs.remove(jobStatus, writeBack);
if (removed && mReadyToRock) {
for (int i=0; i<mControllers.size(); i++) {
StateController controller = mControllers.get(i);
controller.maybeStopTrackingJobLocked(jobStatus, false);
controller.maybeStopTrackingJobLocked(jobStatus, incomingJob, false);
}
}
return removed;
@@ -696,7 +697,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
}
// Do not write back immediately if this is a periodic job. The job may get lost if system
// shuts down before it is added back.
if (!stopTrackingJob(jobStatus, !jobStatus.getJob().isPeriodic())) {
if (!stopTrackingJob(jobStatus, null, !jobStatus.getJob().isPeriodic())) {
if (DEBUG) {
Slog.d(TAG, "Could not find job to remove. Was job removed while executing?");
}
@@ -780,7 +781,7 @@ public final class JobSchedulerService extends com.android.server.SystemService
}
break;
case MSG_STOP_JOB:
cancelJobImpl((JobStatus)message.obj);
cancelJobImpl((JobStatus)message.obj, null);
break;
}
maybeRunPendingJobsH();

View File

@@ -77,7 +77,7 @@ public class AppIdleController extends StateController {
}
@Override
public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) {
public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean forUpdate) {
mTrackedTasks.remove(jobStatus);
}

View File

@@ -87,7 +87,7 @@ public class BatteryController extends StateController {
}
@Override
public void maybeStopTrackingJobLocked(JobStatus taskStatus, boolean forUpdate) {
public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob, boolean forUpdate) {
if (taskStatus.hasChargingConstraint()) {
mTrackedTasks.remove(taskStatus);
}

View File

@@ -92,7 +92,7 @@ public class ConnectivityController extends StateController implements
}
@Override
public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) {
public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean forUpdate) {
if (jobStatus.hasConnectivityConstraint() || jobStatus.hasUnmeteredConstraint()) {
mTrackedJobs.remove(jobStatus);
}

View File

@@ -84,17 +84,8 @@ public class ContentObserverController extends StateController {
boolean havePendingUris = false;
// If there is a previous job associated with the new job, propagate over
// any pending content URI trigger reports.
if (lastJob != null && lastJob.contentObserverJobInstance != null
&& lastJob.contentObserverJobInstance
!= taskStatus.contentObserverJobInstance
&& lastJob.contentObserverJobInstance.mChangedAuthorities != null) {
if (taskStatus.contentObserverJobInstance.mChangedAuthorities != null) {
havePendingUris = true;
taskStatus.contentObserverJobInstance.mChangedAuthorities
= lastJob.contentObserverJobInstance.mChangedAuthorities;
taskStatus.contentObserverJobInstance.mChangedUris
= lastJob.contentObserverJobInstance.mChangedUris;
lastJob.contentObserverJobInstance.mChangedAuthorities = null;
lastJob.contentObserverJobInstance.mChangedUris = null;
}
// If we have previously reported changed authorities/uris, then we failed
// to complete the job with them so will re-record them to report again.
@@ -138,15 +129,34 @@ public class ContentObserverController extends StateController {
}
@Override
public void maybeStopTrackingJobLocked(JobStatus taskStatus, boolean forUpdate) {
public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob,
boolean forUpdate) {
if (taskStatus.hasContentTriggerConstraint()) {
if (!forUpdate) {
// We won't do this reset if being called for an update, because
// we know it will be immediately followed by maybeStartTrackingJobLocked...
// and we don't want to lose any content changes in-between.
if (taskStatus.contentObserverJobInstance != null) {
taskStatus.contentObserverJobInstance.detach();
taskStatus.contentObserverJobInstance = null;
if (taskStatus.contentObserverJobInstance != null) {
if (incomingJob != null && taskStatus.contentObserverJobInstance != null
&& taskStatus.contentObserverJobInstance.mChangedAuthorities != null) {
// We are stopping this job, but it is going to be replaced by this given
// incoming job. We want to propagate our state over to it, so we don't
// lose any content changes that had happend since the last one started.
// If there is a previous job associated with the new job, propagate over
// any pending content URI trigger reports.
if (incomingJob.contentObserverJobInstance == null) {
incomingJob.contentObserverJobInstance = new JobInstance(incomingJob);
}
incomingJob.contentObserverJobInstance.mChangedAuthorities
= taskStatus.contentObserverJobInstance.mChangedAuthorities;
incomingJob.contentObserverJobInstance.mChangedUris
= taskStatus.contentObserverJobInstance.mChangedUris;
taskStatus.contentObserverJobInstance.mChangedAuthorities = null;
taskStatus.contentObserverJobInstance.mChangedUris = null;
} else {
// We won't do this reset if being called for an update, because
// we know it will be immediately followed by maybeStartTrackingJobLocked...
// and we don't want to lose any content changes in-between.
if (taskStatus.contentObserverJobInstance != null) {
taskStatus.contentObserverJobInstance.detach();
taskStatus.contentObserverJobInstance = null;
}
}
}
mTrackedTasks.remove(taskStatus);

View File

@@ -166,7 +166,7 @@ public class DeviceIdleJobsController extends StateController {
}
@Override
public void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate) {
public void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean forUpdate) {
mTrackedTasks.remove(jobStatus);
}

View File

@@ -75,7 +75,7 @@ public class IdleController extends StateController {
}
@Override
public void maybeStopTrackingJobLocked(JobStatus taskStatus, boolean forUpdate) {
public void maybeStopTrackingJobLocked(JobStatus taskStatus, JobStatus incomingJob, boolean forUpdate) {
mTrackedTasks.remove(taskStatus);
}

View File

@@ -56,7 +56,8 @@ public abstract class StateController {
/**
* Remove task - this will happen if the task is cancelled, completed, etc.
*/
public abstract void maybeStopTrackingJobLocked(JobStatus jobStatus, boolean forUpdate);
public abstract void maybeStopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob,
boolean forUpdate);
/**
* Called when a new job is being created to reschedule an old failed job.
*/

View File

@@ -74,7 +74,7 @@ public class TimeController extends StateController {
@Override
public void maybeStartTrackingJobLocked(JobStatus job, JobStatus lastJob) {
if (job.hasTimingDelayConstraint() || job.hasDeadlineConstraint()) {
maybeStopTrackingJobLocked(job, false);
maybeStopTrackingJobLocked(job, null, false);
boolean isInsert = false;
ListIterator<JobStatus> it = mTrackedJobs.listIterator(mTrackedJobs.size());
while (it.hasPrevious()) {
@@ -101,7 +101,7 @@ public class TimeController extends StateController {
* Really an == comparison should be enough, but why play with fate? We'll do <=.
*/
@Override
public void maybeStopTrackingJobLocked(JobStatus job, boolean forUpdate) {
public void maybeStopTrackingJobLocked(JobStatus job, JobStatus incomingJob, boolean forUpdate) {
if (mTrackedJobs.remove(job)) {
checkExpiredDelaysAndResetAlarm();
checkExpiredDeadlinesAndResetAlarm();

View File

@@ -62,7 +62,7 @@ public class ObserverNodeTest extends AndroidTestCase {
ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
for (int i = nums.length - 1; i >=0; --i) {
root.collectObserversLocked(uris[i], 0, null, false, myUserHandle, calls);
root.collectObserversLocked(uris[i], 0, null, false, 0, myUserHandle, calls);
assertEquals(nums[i], calls.size());
calls.clear();
}
@@ -92,7 +92,7 @@ public class ObserverNodeTest extends AndroidTestCase {
ArrayList<ObserverCall> calls = new ArrayList<ObserverCall>();
for (int i = uris.length - 1; i >=0; --i) {
root.collectObserversLocked(uris[i], 0, null, false, myUserHandle, calls);
root.collectObserversLocked(uris[i], 0, null, false, 0, myUserHandle, calls);
assertEquals(nums[i], calls.size());
calls.clear();
}