Merge "More work on issue #26390151: Add new JobScheduler API..." into nyc-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
d273f0d659
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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";
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user