Merge "Introduce framework-minus-apex and create jobscheduler-framework.jar"
This commit is contained in:
@@ -1,121 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
// in android.app so ContextImpl has package access
|
||||
package android.app;
|
||||
|
||||
import android.app.job.IJobScheduler;
|
||||
import android.app.job.JobInfo;
|
||||
import android.app.job.JobScheduler;
|
||||
import android.app.job.JobSnapshot;
|
||||
import android.app.job.JobWorkItem;
|
||||
import android.os.RemoteException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
|
||||
// APEX NOTE: Class path referred to by robolectric, so can't move it.
|
||||
|
||||
/**
|
||||
* Concrete implementation of the JobScheduler interface
|
||||
* @hide
|
||||
*/
|
||||
public class JobSchedulerImpl extends JobScheduler {
|
||||
IJobScheduler mBinder;
|
||||
|
||||
public JobSchedulerImpl(IJobScheduler binder) {
|
||||
mBinder = binder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int schedule(JobInfo job) {
|
||||
try {
|
||||
return mBinder.schedule(job);
|
||||
} catch (RemoteException e) {
|
||||
return JobScheduler.RESULT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int enqueue(JobInfo job, JobWorkItem work) {
|
||||
try {
|
||||
return mBinder.enqueue(job, work);
|
||||
} catch (RemoteException e) {
|
||||
return JobScheduler.RESULT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int scheduleAsPackage(JobInfo job, String packageName, int userId, String tag) {
|
||||
try {
|
||||
return mBinder.scheduleAsPackage(job, packageName, userId, tag);
|
||||
} catch (RemoteException e) {
|
||||
return JobScheduler.RESULT_FAILURE;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel(int jobId) {
|
||||
try {
|
||||
mBinder.cancel(jobId);
|
||||
} catch (RemoteException e) {}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancelAll() {
|
||||
try {
|
||||
mBinder.cancelAll();
|
||||
} catch (RemoteException e) {}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JobInfo> getAllPendingJobs() {
|
||||
try {
|
||||
return mBinder.getAllPendingJobs().getList();
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JobInfo getPendingJob(int jobId) {
|
||||
try {
|
||||
return mBinder.getPendingJob(jobId);
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JobInfo> getStartedJobs() {
|
||||
try {
|
||||
return mBinder.getStartedJobs();
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JobSnapshot> getAllJobSnapshots() {
|
||||
try {
|
||||
return mBinder.getAllJobSnapshots().getList();
|
||||
} catch (RemoteException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,68 +0,0 @@
|
||||
/**
|
||||
* Copyright 2014, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.app.job;
|
||||
|
||||
import android.app.job.JobWorkItem;
|
||||
|
||||
/**
|
||||
* The server side of the JobScheduler IPC protocols. The app-side implementation
|
||||
* invokes on this interface to indicate completion of the (asynchronous) instructions
|
||||
* issued by the server.
|
||||
*
|
||||
* In all cases, the 'who' parameter is the caller's service binder, used to track
|
||||
* which Job Service instance is reporting.
|
||||
*
|
||||
* {@hide}
|
||||
*/
|
||||
interface IJobCallback {
|
||||
/**
|
||||
* Immediate callback to the system after sending a start signal, used to quickly detect ANR.
|
||||
*
|
||||
* @param jobId Unique integer used to identify this job.
|
||||
* @param ongoing True to indicate that the client is processing the job. False if the job is
|
||||
* complete
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
void acknowledgeStartMessage(int jobId, boolean ongoing);
|
||||
/**
|
||||
* Immediate callback to the system after sending a stop signal, used to quickly detect ANR.
|
||||
*
|
||||
* @param jobId Unique integer used to identify this job.
|
||||
* @param reschedule Whether or not to reschedule this job.
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
void acknowledgeStopMessage(int jobId, boolean reschedule);
|
||||
/*
|
||||
* Called to deqeue next work item for the job.
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
JobWorkItem dequeueWork(int jobId);
|
||||
/*
|
||||
* Called to report that job has completed processing a work item.
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
boolean completeWork(int jobId, int workId);
|
||||
/*
|
||||
* Tell the job manager that the client is done with its execution, so that it can go on to
|
||||
* the next one and stop attributing wakelock time to us etc.
|
||||
*
|
||||
* @param jobId Unique integer used to identify this job.
|
||||
* @param reschedule Whether or not to reschedule this job.
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
void jobFinished(int jobId, boolean reschedule);
|
||||
}
|
||||
@@ -1,38 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.app.job;
|
||||
|
||||
import android.app.job.JobInfo;
|
||||
import android.app.job.JobSnapshot;
|
||||
import android.app.job.JobWorkItem;
|
||||
import android.content.pm.ParceledListSlice;
|
||||
|
||||
/**
|
||||
* IPC interface that supports the app-facing {@link #JobScheduler} api.
|
||||
* {@hide}
|
||||
*/
|
||||
interface IJobScheduler {
|
||||
int schedule(in JobInfo job);
|
||||
int enqueue(in JobInfo job, in JobWorkItem work);
|
||||
int scheduleAsPackage(in JobInfo job, String packageName, int userId, String tag);
|
||||
void cancel(int jobId);
|
||||
void cancelAll();
|
||||
ParceledListSlice getAllPendingJobs();
|
||||
JobInfo getPendingJob(int jobId);
|
||||
List<JobInfo> getStartedJobs();
|
||||
ParceledListSlice getAllJobSnapshots();
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
/**
|
||||
* Copyright 2014, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.app.job;
|
||||
|
||||
import android.app.job.JobParameters;
|
||||
|
||||
/**
|
||||
* Interface that the framework uses to communicate with application code that implements a
|
||||
* JobService. End user code does not implement this interface directly; instead, the app's
|
||||
* service implementation will extend android.app.job.JobService.
|
||||
* {@hide}
|
||||
*/
|
||||
oneway interface IJobService {
|
||||
/** Begin execution of application's job. */
|
||||
@UnsupportedAppUsage
|
||||
void startJob(in JobParameters jobParams);
|
||||
/** Stop execution of application's job. */
|
||||
@UnsupportedAppUsage
|
||||
void stopJob(in JobParameters jobParams);
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.app.job;
|
||||
|
||||
parcelable JobInfo;
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,19 +0,0 @@
|
||||
/**
|
||||
* Copyright 2014, The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.app.job;
|
||||
|
||||
parcelable JobParameters;
|
||||
@@ -1,372 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package android.app.job;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.UnsupportedAppUsage;
|
||||
import android.app.job.IJobCallback;
|
||||
import android.content.ClipData;
|
||||
import android.net.Network;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import android.os.IBinder;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
import android.os.PersistableBundle;
|
||||
import android.os.RemoteException;
|
||||
|
||||
/**
|
||||
* Contains the parameters used to configure/identify your job. You do not create this object
|
||||
* yourself, instead it is handed in to your application by the System.
|
||||
*/
|
||||
public class JobParameters implements Parcelable {
|
||||
|
||||
/** @hide */
|
||||
public static final int REASON_CANCELED = JobProtoEnums.STOP_REASON_CANCELLED; // 0.
|
||||
/** @hide */
|
||||
public static final int REASON_CONSTRAINTS_NOT_SATISFIED =
|
||||
JobProtoEnums.STOP_REASON_CONSTRAINTS_NOT_SATISFIED; //1.
|
||||
/** @hide */
|
||||
public static final int REASON_PREEMPT = JobProtoEnums.STOP_REASON_PREEMPT; // 2.
|
||||
/** @hide */
|
||||
public static final int REASON_TIMEOUT = JobProtoEnums.STOP_REASON_TIMEOUT; // 3.
|
||||
/** @hide */
|
||||
public static final int REASON_DEVICE_IDLE = JobProtoEnums.STOP_REASON_DEVICE_IDLE; // 4.
|
||||
/** @hide */
|
||||
public static final int REASON_DEVICE_THERMAL = JobProtoEnums.STOP_REASON_DEVICE_THERMAL; // 5.
|
||||
|
||||
/**
|
||||
* All the stop reason codes. This should be regarded as an immutable array at runtime.
|
||||
* @hide
|
||||
*/
|
||||
public static final int[] JOB_STOP_REASON_CODES = {
|
||||
REASON_CANCELED,
|
||||
REASON_CONSTRAINTS_NOT_SATISFIED,
|
||||
REASON_PREEMPT,
|
||||
REASON_TIMEOUT,
|
||||
REASON_DEVICE_IDLE,
|
||||
REASON_DEVICE_THERMAL,
|
||||
};
|
||||
|
||||
/** @hide */
|
||||
public static String getReasonName(int reason) {
|
||||
switch (reason) {
|
||||
case REASON_CANCELED: return "canceled";
|
||||
case REASON_CONSTRAINTS_NOT_SATISFIED: return "constraints";
|
||||
case REASON_PREEMPT: return "preempt";
|
||||
case REASON_TIMEOUT: return "timeout";
|
||||
case REASON_DEVICE_IDLE: return "device_idle";
|
||||
case REASON_DEVICE_THERMAL: return "thermal";
|
||||
default: return "unknown:" + reason;
|
||||
}
|
||||
}
|
||||
|
||||
@UnsupportedAppUsage
|
||||
private final int jobId;
|
||||
private final PersistableBundle extras;
|
||||
private final Bundle transientExtras;
|
||||
private final ClipData clipData;
|
||||
private final int clipGrantFlags;
|
||||
@UnsupportedAppUsage
|
||||
private final IBinder callback;
|
||||
private final boolean overrideDeadlineExpired;
|
||||
private final Uri[] mTriggeredContentUris;
|
||||
private final String[] mTriggeredContentAuthorities;
|
||||
private final Network network;
|
||||
|
||||
private int stopReason; // Default value of stopReason is REASON_CANCELED
|
||||
private String debugStopReason; // Human readable stop reason for debugging.
|
||||
|
||||
/** @hide */
|
||||
public JobParameters(IBinder callback, int jobId, PersistableBundle extras,
|
||||
Bundle transientExtras, ClipData clipData, int clipGrantFlags,
|
||||
boolean overrideDeadlineExpired, Uri[] triggeredContentUris,
|
||||
String[] triggeredContentAuthorities, Network network) {
|
||||
this.jobId = jobId;
|
||||
this.extras = extras;
|
||||
this.transientExtras = transientExtras;
|
||||
this.clipData = clipData;
|
||||
this.clipGrantFlags = clipGrantFlags;
|
||||
this.callback = callback;
|
||||
this.overrideDeadlineExpired = overrideDeadlineExpired;
|
||||
this.mTriggeredContentUris = triggeredContentUris;
|
||||
this.mTriggeredContentAuthorities = triggeredContentAuthorities;
|
||||
this.network = network;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The unique id of this job, specified at creation time.
|
||||
*/
|
||||
public int getJobId() {
|
||||
return jobId;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reason onStopJob() was called on this job.
|
||||
* @hide
|
||||
*/
|
||||
public int getStopReason() {
|
||||
return stopReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reason onStopJob() was called on this job.
|
||||
* @hide
|
||||
*/
|
||||
public String getDebugStopReason() {
|
||||
return debugStopReason;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The extras you passed in when constructing this job with
|
||||
* {@link android.app.job.JobInfo.Builder#setExtras(android.os.PersistableBundle)}. This will
|
||||
* never be null. If you did not set any extras this will be an empty bundle.
|
||||
*/
|
||||
public @NonNull PersistableBundle getExtras() {
|
||||
return extras;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The transient extras you passed in when constructing this job with
|
||||
* {@link android.app.job.JobInfo.Builder#setTransientExtras(android.os.Bundle)}. This will
|
||||
* never be null. If you did not set any extras this will be an empty bundle.
|
||||
*/
|
||||
public @NonNull Bundle getTransientExtras() {
|
||||
return transientExtras;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The clip you passed in when constructing this job with
|
||||
* {@link android.app.job.JobInfo.Builder#setClipData(ClipData, int)}. Will be null
|
||||
* if it was not set.
|
||||
*/
|
||||
public @Nullable ClipData getClipData() {
|
||||
return clipData;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The clip grant flags you passed in when constructing this job with
|
||||
* {@link android.app.job.JobInfo.Builder#setClipData(ClipData, int)}. Will be 0
|
||||
* if it was not set.
|
||||
*/
|
||||
public int getClipGrantFlags() {
|
||||
return clipGrantFlags;
|
||||
}
|
||||
|
||||
/**
|
||||
* For jobs with {@link android.app.job.JobInfo.Builder#setOverrideDeadline(long)} set, this
|
||||
* provides an easy way to tell whether the job is being executed due to the deadline
|
||||
* expiring. Note: If the job is running because its deadline expired, it implies that its
|
||||
* constraints will not be met.
|
||||
*/
|
||||
public boolean isOverrideDeadlineExpired() {
|
||||
return overrideDeadlineExpired;
|
||||
}
|
||||
|
||||
/**
|
||||
* For jobs with {@link android.app.job.JobInfo.Builder#addTriggerContentUri} set, this
|
||||
* reports which URIs have triggered the job. This will be null if either no URIs have
|
||||
* triggered it (it went off due to a deadline or other reason), or the number of changed
|
||||
* URIs is too large to report. Whether or not the number of URIs is too large, you can
|
||||
* always use {@link #getTriggeredContentAuthorities()} to determine whether the job was
|
||||
* triggered due to any content changes and the authorities they are associated with.
|
||||
*/
|
||||
public @Nullable Uri[] getTriggeredContentUris() {
|
||||
return mTriggeredContentUris;
|
||||
}
|
||||
|
||||
/**
|
||||
* For jobs with {@link android.app.job.JobInfo.Builder#addTriggerContentUri} set, this
|
||||
* reports which content authorities have triggered the job. It will only be null if no
|
||||
* authorities have triggered it -- that is, the job executed for some other reason, such
|
||||
* as a deadline expiring. If this is non-null, you can use {@link #getTriggeredContentUris()}
|
||||
* to retrieve the details of which URIs changed (as long as that has not exceeded the maximum
|
||||
* number it can reported).
|
||||
*/
|
||||
public @Nullable String[] getTriggeredContentAuthorities() {
|
||||
return mTriggeredContentAuthorities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the network that should be used to perform any network requests
|
||||
* for this job.
|
||||
* <p>
|
||||
* Devices may have multiple active network connections simultaneously, or
|
||||
* they may not have a default network route at all. To correctly handle all
|
||||
* situations like this, your job should always use the network returned by
|
||||
* this method instead of implicitly using the default network route.
|
||||
* <p>
|
||||
* Note that the system may relax the constraints you originally requested,
|
||||
* such as allowing a {@link JobInfo#NETWORK_TYPE_UNMETERED} job to run over
|
||||
* a metered network when there is a surplus of metered data available.
|
||||
*
|
||||
* @return the network that should be used to perform any network requests
|
||||
* for this job, or {@code null} if this job didn't set any required
|
||||
* network type.
|
||||
* @see JobInfo.Builder#setRequiredNetworkType(int)
|
||||
*/
|
||||
public @Nullable Network getNetwork() {
|
||||
return network;
|
||||
}
|
||||
|
||||
/**
|
||||
* Dequeue the next pending {@link JobWorkItem} from these JobParameters associated with their
|
||||
* currently running job. Calling this method when there is no more work available and all
|
||||
* previously dequeued work has been completed will result in the system taking care of
|
||||
* stopping the job for you --
|
||||
* you should not call {@link JobService#jobFinished(JobParameters, boolean)} yourself
|
||||
* (otherwise you risk losing an upcoming JobWorkItem that is being enqueued at the same time).
|
||||
*
|
||||
* <p>Once you are done with the {@link JobWorkItem} returned by this method, you must call
|
||||
* {@link #completeWork(JobWorkItem)} with it to inform the system that you are done
|
||||
* executing the work. The job will not be finished until all dequeued work has been
|
||||
* completed. You do not, however, have to complete each returned work item before deqeueing
|
||||
* the next one -- you can use {@link #dequeueWork()} multiple times before completing
|
||||
* previous work if you want to process work in parallel, and you can complete the work
|
||||
* in whatever order you want.</p>
|
||||
*
|
||||
* <p>If the job runs to the end of its available time period before all work has been
|
||||
* completed, it will stop as normal. You should return true from
|
||||
* {@link JobService#onStopJob(JobParameters)} in order to have the job rescheduled, and by
|
||||
* doing so any pending as well as remaining uncompleted work will be re-queued
|
||||
* for the next time the job runs.</p>
|
||||
*
|
||||
* <p>This example shows how to construct a JobService that will serially dequeue and
|
||||
* process work that is available for it:</p>
|
||||
*
|
||||
* {@sample development/samples/ApiDemos/src/com/example/android/apis/app/JobWorkService.java
|
||||
* service}
|
||||
*
|
||||
* @return Returns a new {@link JobWorkItem} if there is one pending, otherwise null.
|
||||
* If null is returned, the system will also stop the job if all work has also been completed.
|
||||
* (This means that for correct operation, you must always call dequeueWork() after you have
|
||||
* completed other work, to check either for more work or allow the system to stop the job.)
|
||||
*/
|
||||
public @Nullable JobWorkItem dequeueWork() {
|
||||
try {
|
||||
return getCallback().dequeueWork(getJobId());
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Report the completion of executing a {@link JobWorkItem} previously returned by
|
||||
* {@link #dequeueWork()}. This tells the system you are done with the
|
||||
* work associated with that item, so it will not be returned again. Note that if this
|
||||
* is the last work in the queue, completing it here will <em>not</em> finish the overall
|
||||
* job -- for that to happen, you still need to call {@link #dequeueWork()}
|
||||
* again.
|
||||
*
|
||||
* <p>If you are enqueueing work into a job, you must call this method for each piece
|
||||
* of work you process. Do <em>not</em> call
|
||||
* {@link JobService#jobFinished(JobParameters, boolean)}
|
||||
* or else you can lose work in your queue.</p>
|
||||
*
|
||||
* @param work The work you have completed processing, as previously returned by
|
||||
* {@link #dequeueWork()}
|
||||
*/
|
||||
public void completeWork(@NonNull JobWorkItem work) {
|
||||
try {
|
||||
if (!getCallback().completeWork(getJobId(), work.getWorkId())) {
|
||||
throw new IllegalArgumentException("Given work is not active: " + work);
|
||||
}
|
||||
} catch (RemoteException e) {
|
||||
throw e.rethrowFromSystemServer();
|
||||
}
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
@UnsupportedAppUsage
|
||||
public IJobCallback getCallback() {
|
||||
return IJobCallback.Stub.asInterface(callback);
|
||||
}
|
||||
|
||||
private JobParameters(Parcel in) {
|
||||
jobId = in.readInt();
|
||||
extras = in.readPersistableBundle();
|
||||
transientExtras = in.readBundle();
|
||||
if (in.readInt() != 0) {
|
||||
clipData = ClipData.CREATOR.createFromParcel(in);
|
||||
clipGrantFlags = in.readInt();
|
||||
} else {
|
||||
clipData = null;
|
||||
clipGrantFlags = 0;
|
||||
}
|
||||
callback = in.readStrongBinder();
|
||||
overrideDeadlineExpired = in.readInt() == 1;
|
||||
mTriggeredContentUris = in.createTypedArray(Uri.CREATOR);
|
||||
mTriggeredContentAuthorities = in.createStringArray();
|
||||
if (in.readInt() != 0) {
|
||||
network = Network.CREATOR.createFromParcel(in);
|
||||
} else {
|
||||
network = null;
|
||||
}
|
||||
stopReason = in.readInt();
|
||||
debugStopReason = in.readString();
|
||||
}
|
||||
|
||||
/** @hide */
|
||||
public void setStopReason(int reason, String debugStopReason) {
|
||||
stopReason = reason;
|
||||
this.debugStopReason = debugStopReason;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel dest, int flags) {
|
||||
dest.writeInt(jobId);
|
||||
dest.writePersistableBundle(extras);
|
||||
dest.writeBundle(transientExtras);
|
||||
if (clipData != null) {
|
||||
dest.writeInt(1);
|
||||
clipData.writeToParcel(dest, flags);
|
||||
dest.writeInt(clipGrantFlags);
|
||||
} else {
|
||||
dest.writeInt(0);
|
||||
}
|
||||
dest.writeStrongBinder(callback);
|
||||
dest.writeInt(overrideDeadlineExpired ? 1 : 0);
|
||||
dest.writeTypedArray(mTriggeredContentUris, flags);
|
||||
dest.writeStringArray(mTriggeredContentAuthorities);
|
||||
if (network != null) {
|
||||
dest.writeInt(1);
|
||||
network.writeToParcel(dest, flags);
|
||||
} else {
|
||||
dest.writeInt(0);
|
||||
}
|
||||
dest.writeInt(stopReason);
|
||||
dest.writeString(debugStopReason);
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull Creator<JobParameters> CREATOR = new Creator<JobParameters>() {
|
||||
@Override
|
||||
public JobParameters createFromParcel(Parcel in) {
|
||||
return new JobParameters(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JobParameters[] newArray(int size) {
|
||||
return new JobParameters[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,191 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package android.app.job;
|
||||
|
||||
import android.annotation.IntDef;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.annotation.RequiresPermission;
|
||||
import android.annotation.SystemApi;
|
||||
import android.annotation.SystemService;
|
||||
import android.content.ClipData;
|
||||
import android.content.Context;
|
||||
import android.os.Bundle;
|
||||
import android.os.PersistableBundle;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* This is an API for scheduling various types of jobs against the framework that will be executed
|
||||
* in your application's own process.
|
||||
* <p>
|
||||
* See {@link android.app.job.JobInfo} for more description of the types of jobs that can be run
|
||||
* and how to construct them. You will construct these JobInfo objects and pass them to the
|
||||
* JobScheduler with {@link #schedule(JobInfo)}. When the criteria declared are met, the
|
||||
* system will execute this job on your application's {@link android.app.job.JobService}.
|
||||
* You identify the service component that implements the logic for your job when you
|
||||
* construct the JobInfo using
|
||||
* {@link android.app.job.JobInfo.Builder#JobInfo.Builder(int,android.content.ComponentName)}.
|
||||
* </p>
|
||||
* <p>
|
||||
* The framework will be intelligent about when it executes jobs, and attempt to batch
|
||||
* and defer them as much as possible. Typically if you don't specify a deadline on a job, it
|
||||
* can be run at any moment depending on the current state of the JobScheduler's internal queue.
|
||||
* <p>
|
||||
* While a job is running, the system holds a wakelock on behalf of your app. For this reason,
|
||||
* you do not need to take any action to guarantee that the device stays awake for the
|
||||
* duration of the job.
|
||||
* </p>
|
||||
* <p>You do not
|
||||
* instantiate this class directly; instead, retrieve it through
|
||||
* {@link android.content.Context#getSystemService
|
||||
* Context.getSystemService(Context.JOB_SCHEDULER_SERVICE)}.
|
||||
*/
|
||||
@SystemService(Context.JOB_SCHEDULER_SERVICE)
|
||||
public abstract class JobScheduler {
|
||||
/** @hide */
|
||||
@IntDef(prefix = { "RESULT_" }, value = {
|
||||
RESULT_FAILURE,
|
||||
RESULT_SUCCESS,
|
||||
})
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface Result {}
|
||||
|
||||
/**
|
||||
* Returned from {@link #schedule(JobInfo)} when an invalid parameter was supplied. This can occur
|
||||
* if the run-time for your job is too short, or perhaps the system can't resolve the
|
||||
* requisite {@link JobService} in your package.
|
||||
*/
|
||||
public static final int RESULT_FAILURE = 0;
|
||||
/**
|
||||
* Returned from {@link #schedule(JobInfo)} if this job has been successfully scheduled.
|
||||
*/
|
||||
public static final int RESULT_SUCCESS = 1;
|
||||
|
||||
/**
|
||||
* Schedule a job to be executed. Will replace any currently scheduled job with the same
|
||||
* ID with the new information in the {@link JobInfo}. If a job with the given ID is currently
|
||||
* running, it will be stopped.
|
||||
*
|
||||
* @param job The job you wish scheduled. See
|
||||
* {@link android.app.job.JobInfo.Builder JobInfo.Builder} for more detail on the sorts of jobs
|
||||
* you can schedule.
|
||||
* @return the result of the schedule request.
|
||||
*/
|
||||
public abstract @Result int schedule(@NonNull JobInfo job);
|
||||
|
||||
/**
|
||||
* Similar to {@link #schedule}, but allows you to enqueue work for a new <em>or existing</em>
|
||||
* job. If a job with the same ID is already scheduled, it will be replaced with the
|
||||
* new {@link JobInfo}, but any previously enqueued work will remain and be dispatched the
|
||||
* next time it runs. If a job with the same ID is already running, the new work will be
|
||||
* enqueued for it.
|
||||
*
|
||||
* <p>The work you enqueue is later retrieved through
|
||||
* {@link JobParameters#dequeueWork() JobParameters.dequeueWork}. Be sure to see there
|
||||
* about how to process work; the act of enqueueing work changes how you should handle the
|
||||
* overall lifecycle of an executing job.</p>
|
||||
*
|
||||
* <p>It is strongly encouraged that you use the same {@link JobInfo} for all work you
|
||||
* enqueue. This will allow the system to optimally schedule work along with any pending
|
||||
* and/or currently running work. If the JobInfo changes from the last time the job was
|
||||
* enqueued, the system will need to update the associated JobInfo, which can cause a disruption
|
||||
* in execution. In particular, this can result in any currently running job that is processing
|
||||
* previous work to be stopped and restarted with the new JobInfo.</p>
|
||||
*
|
||||
* <p>It is recommended that you avoid using
|
||||
* {@link JobInfo.Builder#setExtras(PersistableBundle)} or
|
||||
* {@link JobInfo.Builder#setTransientExtras(Bundle)} with a JobInfo you are using to
|
||||
* enqueue work. The system will try to compare these extras with the previous JobInfo,
|
||||
* but there are situations where it may get this wrong and count the JobInfo as changing.
|
||||
* (That said, you should be relatively safe with a simple set of consistent data in these
|
||||
* fields.) You should never use {@link JobInfo.Builder#setClipData(ClipData, int)} with
|
||||
* work you are enqueue, since currently this will always be treated as a different JobInfo,
|
||||
* even if the ClipData contents are exactly the same.</p>
|
||||
*
|
||||
* @param job The job you wish to enqueue work for. See
|
||||
* {@link android.app.job.JobInfo.Builder JobInfo.Builder} for more detail on the sorts of jobs
|
||||
* you can schedule.
|
||||
* @param work New work to enqueue. This will be available later when the job starts running.
|
||||
* @return the result of the enqueue request.
|
||||
*/
|
||||
public abstract @Result int enqueue(@NonNull JobInfo job, @NonNull JobWorkItem work);
|
||||
|
||||
/**
|
||||
*
|
||||
* @param job The job to be scheduled.
|
||||
* @param packageName The package on behalf of which the job is to be scheduled. This will be
|
||||
* used to track battery usage and appIdleState.
|
||||
* @param userId User on behalf of whom this job is to be scheduled.
|
||||
* @param tag Debugging tag for dumps associated with this job (instead of the service class)
|
||||
* @hide
|
||||
*/
|
||||
@SystemApi
|
||||
@RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
|
||||
public abstract @Result int scheduleAsPackage(@NonNull JobInfo job, @NonNull String packageName,
|
||||
int userId, String tag);
|
||||
|
||||
/**
|
||||
* Cancel the specified job. If the job is currently executing, it is stopped
|
||||
* immediately and the return value from its {@link JobService#onStopJob(JobParameters)}
|
||||
* method is ignored.
|
||||
*
|
||||
* @param jobId unique identifier for the job to be canceled, as supplied to
|
||||
* {@link JobInfo.Builder#JobInfo.Builder(int, android.content.ComponentName)
|
||||
* JobInfo.Builder(int, android.content.ComponentName)}.
|
||||
*/
|
||||
public abstract void cancel(int jobId);
|
||||
|
||||
/**
|
||||
* Cancel <em>all</em> jobs that have been scheduled by the calling application.
|
||||
*/
|
||||
public abstract void cancelAll();
|
||||
|
||||
/**
|
||||
* Retrieve all jobs that have been scheduled by the calling application.
|
||||
*
|
||||
* @return a list of all of the app's scheduled jobs. This includes jobs that are
|
||||
* currently started as well as those that are still waiting to run.
|
||||
*/
|
||||
public abstract @NonNull List<JobInfo> getAllPendingJobs();
|
||||
|
||||
/**
|
||||
* Look up the description of a scheduled job.
|
||||
*
|
||||
* @return The {@link JobInfo} description of the given scheduled job, or {@code null}
|
||||
* if the supplied job ID does not correspond to any job.
|
||||
*/
|
||||
public abstract @Nullable JobInfo getPendingJob(int jobId);
|
||||
|
||||
/**
|
||||
* <b>For internal system callers only!</b>
|
||||
* Returns a list of all currently-executing jobs.
|
||||
* @hide
|
||||
*/
|
||||
public abstract List<JobInfo> getStartedJobs();
|
||||
|
||||
/**
|
||||
* <b>For internal system callers only!</b>
|
||||
* Returns a snapshot of the state of all jobs known to the system.
|
||||
*
|
||||
* <p class="note">This is a slow operation, so it should be called sparingly.
|
||||
* @hide
|
||||
*/
|
||||
public abstract List<JobSnapshot> getAllJobSnapshots();
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2019 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.app.job;
|
||||
|
||||
import android.app.JobSchedulerImpl;
|
||||
import android.app.SystemServiceRegistry;
|
||||
import android.content.Context;
|
||||
import android.os.BatteryStats;
|
||||
|
||||
/**
|
||||
* This class needs to be pre-loaded by zygote. This is where the job scheduler service wrapper
|
||||
* is registered.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
public class JobSchedulerFrameworkInitializer {
|
||||
static {
|
||||
SystemServiceRegistry.registerStaticService(
|
||||
Context.JOB_SCHEDULER_SERVICE, JobScheduler.class,
|
||||
(b) -> new JobSchedulerImpl(IJobScheduler.Stub.asInterface(b)));
|
||||
|
||||
BatteryStats.setJobStopReasons(JobParameters.JOB_STOP_REASON_CODES,
|
||||
JobParameters::getReasonName);
|
||||
}
|
||||
}
|
||||
@@ -1,157 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package android.app.job;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
|
||||
/**
|
||||
* <p>Entry point for the callback from the {@link android.app.job.JobScheduler}.</p>
|
||||
* <p>This is the base class that handles asynchronous requests that were previously scheduled. You
|
||||
* are responsible for overriding {@link JobService#onStartJob(JobParameters)}, which is where
|
||||
* you will implement your job logic.</p>
|
||||
* <p>This service executes each incoming job on a {@link android.os.Handler} running on your
|
||||
* application's main thread. This means that you <b>must</b> offload your execution logic to
|
||||
* another thread/handler/{@link android.os.AsyncTask} of your choosing. Not doing so will result
|
||||
* in blocking any future callbacks from the JobManager - specifically
|
||||
* {@link #onStopJob(android.app.job.JobParameters)}, which is meant to inform you that the
|
||||
* scheduling requirements are no longer being met.</p>
|
||||
*/
|
||||
public abstract class JobService extends Service {
|
||||
private static final String TAG = "JobService";
|
||||
|
||||
/**
|
||||
* Job services must be protected with this permission:
|
||||
*
|
||||
* <pre class="prettyprint">
|
||||
* <service android:name="MyJobService"
|
||||
* android:permission="android.permission.BIND_JOB_SERVICE" >
|
||||
* ...
|
||||
* </service>
|
||||
* </pre>
|
||||
*
|
||||
* <p>If a job service is declared in the manifest but not protected with this
|
||||
* permission, that service will be ignored by the system.
|
||||
*/
|
||||
public static final String PERMISSION_BIND =
|
||||
"android.permission.BIND_JOB_SERVICE";
|
||||
|
||||
private JobServiceEngine mEngine;
|
||||
|
||||
/** @hide */
|
||||
public final IBinder onBind(Intent intent) {
|
||||
if (mEngine == null) {
|
||||
mEngine = new JobServiceEngine(this) {
|
||||
@Override
|
||||
public boolean onStartJob(JobParameters params) {
|
||||
return JobService.this.onStartJob(params);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onStopJob(JobParameters params) {
|
||||
return JobService.this.onStopJob(params);
|
||||
}
|
||||
};
|
||||
}
|
||||
return mEngine.getBinder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call this to inform the JobScheduler that the job has finished its work. When the
|
||||
* system receives this message, it releases the wakelock being held for the job.
|
||||
* <p>
|
||||
* You can request that the job be scheduled again by passing {@code true} as
|
||||
* the <code>wantsReschedule</code> parameter. This will apply back-off policy
|
||||
* for the job; this policy can be adjusted through the
|
||||
* {@link android.app.job.JobInfo.Builder#setBackoffCriteria(long, int)} method
|
||||
* when the job is originally scheduled. The job's initial
|
||||
* requirements are preserved when jobs are rescheduled, regardless of backed-off
|
||||
* policy.
|
||||
* <p class="note">
|
||||
* A job running while the device is dozing will not be rescheduled with the normal back-off
|
||||
* policy. Instead, the job will be re-added to the queue and executed again during
|
||||
* a future idle maintenance window.
|
||||
* </p>
|
||||
*
|
||||
* @param params The parameters identifying this job, as supplied to
|
||||
* the job in the {@link #onStartJob(JobParameters)} callback.
|
||||
* @param wantsReschedule {@code true} if this job should be rescheduled according
|
||||
* to the back-off criteria specified when it was first scheduled; {@code false}
|
||||
* otherwise.
|
||||
*/
|
||||
public final void jobFinished(JobParameters params, boolean wantsReschedule) {
|
||||
mEngine.jobFinished(params, wantsReschedule);
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to indicate that the job has begun executing. Override this method with the
|
||||
* logic for your job. Like all other component lifecycle callbacks, this method executes
|
||||
* on your application's main thread.
|
||||
* <p>
|
||||
* Return {@code true} from this method if your job needs to continue running. If you
|
||||
* do this, the job remains active until you call
|
||||
* {@link #jobFinished(JobParameters, boolean)} to tell the system that it has completed
|
||||
* its work, or until the job's required constraints are no longer satisfied. For
|
||||
* example, if the job was scheduled using
|
||||
* {@link JobInfo.Builder#setRequiresCharging(boolean) setRequiresCharging(true)},
|
||||
* it will be immediately halted by the system if the user unplugs the device from power,
|
||||
* the job's {@link #onStopJob(JobParameters)} callback will be invoked, and the app
|
||||
* will be expected to shut down all ongoing work connected with that job.
|
||||
* <p>
|
||||
* The system holds a wakelock on behalf of your app as long as your job is executing.
|
||||
* This wakelock is acquired before this method is invoked, and is not released until either
|
||||
* you call {@link #jobFinished(JobParameters, boolean)}, or after the system invokes
|
||||
* {@link #onStopJob(JobParameters)} to notify your job that it is being shut down
|
||||
* prematurely.
|
||||
* <p>
|
||||
* Returning {@code false} from this method means your job is already finished. The
|
||||
* system's wakelock for the job will be released, and {@link #onStopJob(JobParameters)}
|
||||
* will not be invoked.
|
||||
*
|
||||
* @param params Parameters specifying info about this job, including the optional
|
||||
* extras configured with {@link JobInfo.Builder#setExtras(android.os.PersistableBundle).
|
||||
* This object serves to identify this specific running job instance when calling
|
||||
* {@link #jobFinished(JobParameters, boolean)}.
|
||||
* @return {@code true} if your service will continue running, using a separate thread
|
||||
* when appropriate. {@code false} means that this job has completed its work.
|
||||
*/
|
||||
public abstract boolean onStartJob(JobParameters params);
|
||||
|
||||
/**
|
||||
* This method is called if the system has determined that you must stop execution of your job
|
||||
* even before you've had a chance to call {@link #jobFinished(JobParameters, boolean)}.
|
||||
*
|
||||
* <p>This will happen if the requirements specified at schedule time are no longer met. For
|
||||
* example you may have requested WiFi with
|
||||
* {@link android.app.job.JobInfo.Builder#setRequiredNetworkType(int)}, yet while your
|
||||
* job was executing the user toggled WiFi. Another example is if you had specified
|
||||
* {@link android.app.job.JobInfo.Builder#setRequiresDeviceIdle(boolean)}, and the phone left its
|
||||
* idle maintenance window. You are solely responsible for the behavior of your application
|
||||
* upon receipt of this message; your app will likely start to misbehave if you ignore it.
|
||||
* <p>
|
||||
* Once this method returns, the system releases the wakelock that it is holding on
|
||||
* behalf of the job.</p>
|
||||
*
|
||||
* @param params The parameters identifying this job, as supplied to
|
||||
* the job in the {@link #onStartJob(JobParameters)} callback.
|
||||
* @return {@code true} to indicate to the JobManager whether you'd like to reschedule
|
||||
* this job based on the retry criteria provided at job creation-time; or {@code false}
|
||||
* to end the job entirely. Regardless of the value returned, your job must stop executing.
|
||||
*/
|
||||
public abstract boolean onStopJob(JobParameters params);
|
||||
}
|
||||
@@ -1,220 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2014 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package android.app.job;
|
||||
|
||||
import android.app.Service;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Looper;
|
||||
import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.annotations.GuardedBy;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
* Helper for implementing a {@link android.app.Service} that interacts with
|
||||
* {@link JobScheduler}. This is not intended for use by regular applications, but
|
||||
* allows frameworks built on top of the platform to create their own
|
||||
* {@link android.app.Service} that interact with {@link JobScheduler} as well as
|
||||
* add in additional functionality. If you just want to execute jobs normally, you
|
||||
* should instead be looking at {@link JobService}.
|
||||
*/
|
||||
public abstract class JobServiceEngine {
|
||||
private static final String TAG = "JobServiceEngine";
|
||||
|
||||
/**
|
||||
* Identifier for a message that will result in a call to
|
||||
* {@link #onStartJob(android.app.job.JobParameters)}.
|
||||
*/
|
||||
private static final int MSG_EXECUTE_JOB = 0;
|
||||
/**
|
||||
* Message that will result in a call to {@link #onStopJob(android.app.job.JobParameters)}.
|
||||
*/
|
||||
private static final int MSG_STOP_JOB = 1;
|
||||
/**
|
||||
* Message that the client has completed execution of this job.
|
||||
*/
|
||||
private static final int MSG_JOB_FINISHED = 2;
|
||||
|
||||
private final IJobService mBinder;
|
||||
|
||||
/**
|
||||
* Handler we post jobs to. Responsible for calling into the client logic, and handling the
|
||||
* callback to the system.
|
||||
*/
|
||||
JobHandler mHandler;
|
||||
|
||||
static final class JobInterface extends IJobService.Stub {
|
||||
final WeakReference<JobServiceEngine> mService;
|
||||
|
||||
JobInterface(JobServiceEngine service) {
|
||||
mService = new WeakReference<>(service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startJob(JobParameters jobParams) throws RemoteException {
|
||||
JobServiceEngine service = mService.get();
|
||||
if (service != null) {
|
||||
Message m = Message.obtain(service.mHandler, MSG_EXECUTE_JOB, jobParams);
|
||||
m.sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void stopJob(JobParameters jobParams) throws RemoteException {
|
||||
JobServiceEngine service = mService.get();
|
||||
if (service != null) {
|
||||
Message m = Message.obtain(service.mHandler, MSG_STOP_JOB, jobParams);
|
||||
m.sendToTarget();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs on application's main thread - callbacks are meant to offboard work to some other
|
||||
* (app-specified) mechanism.
|
||||
* @hide
|
||||
*/
|
||||
class JobHandler extends Handler {
|
||||
JobHandler(Looper looper) {
|
||||
super(looper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
final JobParameters params = (JobParameters) msg.obj;
|
||||
switch (msg.what) {
|
||||
case MSG_EXECUTE_JOB:
|
||||
try {
|
||||
boolean workOngoing = JobServiceEngine.this.onStartJob(params);
|
||||
ackStartMessage(params, workOngoing);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Error while executing job: " + params.getJobId());
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
break;
|
||||
case MSG_STOP_JOB:
|
||||
try {
|
||||
boolean ret = JobServiceEngine.this.onStopJob(params);
|
||||
ackStopMessage(params, ret);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Application unable to handle onStopJob.", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
break;
|
||||
case MSG_JOB_FINISHED:
|
||||
final boolean needsReschedule = (msg.arg2 == 1);
|
||||
IJobCallback callback = params.getCallback();
|
||||
if (callback != null) {
|
||||
try {
|
||||
callback.jobFinished(params.getJobId(), needsReschedule);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error reporting job finish to system: binder has gone" +
|
||||
"away.");
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "finishJob() called for a nonexistent job id.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
Log.e(TAG, "Unrecognised message received.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void ackStartMessage(JobParameters params, boolean workOngoing) {
|
||||
final IJobCallback callback = params.getCallback();
|
||||
final int jobId = params.getJobId();
|
||||
if (callback != null) {
|
||||
try {
|
||||
callback.acknowledgeStartMessage(jobId, workOngoing);
|
||||
} catch(RemoteException e) {
|
||||
Log.e(TAG, "System unreachable for starting job.");
|
||||
}
|
||||
} else {
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log.d(TAG, "Attempting to ack a job that has already been processed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void ackStopMessage(JobParameters params, boolean reschedule) {
|
||||
final IJobCallback callback = params.getCallback();
|
||||
final int jobId = params.getJobId();
|
||||
if (callback != null) {
|
||||
try {
|
||||
callback.acknowledgeStopMessage(jobId, reschedule);
|
||||
} catch(RemoteException e) {
|
||||
Log.e(TAG, "System unreachable for stopping job.");
|
||||
}
|
||||
} else {
|
||||
if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log.d(TAG, "Attempting to ack a job that has already been processed.");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new engine, ready for use.
|
||||
*
|
||||
* @param service The {@link Service} that is creating this engine and in which it will run.
|
||||
*/
|
||||
public JobServiceEngine(Service service) {
|
||||
mBinder = new JobInterface(this);
|
||||
mHandler = new JobHandler(service.getMainLooper());
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieve the engine's IPC interface that should be returned by
|
||||
* {@link Service#onBind(Intent)}.
|
||||
*/
|
||||
public final IBinder getBinder() {
|
||||
return mBinder.asBinder();
|
||||
}
|
||||
|
||||
/**
|
||||
* Engine's report that a job has started. See
|
||||
* {@link JobService#onStartJob(JobParameters) JobService.onStartJob} for more information.
|
||||
*/
|
||||
public abstract boolean onStartJob(JobParameters params);
|
||||
|
||||
/**
|
||||
* Engine's report that a job has stopped. See
|
||||
* {@link JobService#onStopJob(JobParameters) JobService.onStopJob} for more information.
|
||||
*/
|
||||
public abstract boolean onStopJob(JobParameters params);
|
||||
|
||||
/**
|
||||
* Call in to engine to report that a job has finished executing. See
|
||||
* {@link JobService#jobFinished(JobParameters, boolean)} JobService.jobFinished} for more
|
||||
* information.
|
||||
*/
|
||||
public void jobFinished(JobParameters params, boolean needsReschedule) {
|
||||
if (params == null) {
|
||||
throw new NullPointerException("params");
|
||||
}
|
||||
Message m = Message.obtain(mHandler, MSG_JOB_FINISHED, params);
|
||||
m.arg2 = needsReschedule ? 1 : 0;
|
||||
m.sendToTarget();
|
||||
}
|
||||
}
|
||||
@@ -1,19 +0,0 @@
|
||||
/**
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.app.job;
|
||||
|
||||
parcelable JobSnapshot;
|
||||
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2018 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.app.job;
|
||||
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* Current-state snapshot of a scheduled job. These snapshots are not used in apps;
|
||||
* they exist only within the system process across the local call surface where JobStatus
|
||||
* is not directly accessible at build time.
|
||||
*
|
||||
* Constraints that the underlying job does not require are always reported as
|
||||
* being currently satisfied.
|
||||
* @hide
|
||||
*/
|
||||
public class JobSnapshot implements Parcelable {
|
||||
private final JobInfo mJob;
|
||||
private final int mSatisfiedConstraints;
|
||||
private final boolean mIsRunnable;
|
||||
|
||||
public JobSnapshot(JobInfo info, int satisfiedMask, boolean runnable) {
|
||||
mJob = info;
|
||||
mSatisfiedConstraints = satisfiedMask;
|
||||
mIsRunnable = runnable;
|
||||
}
|
||||
|
||||
public JobSnapshot(Parcel in) {
|
||||
mJob = JobInfo.CREATOR.createFromParcel(in);
|
||||
mSatisfiedConstraints = in.readInt();
|
||||
mIsRunnable = in.readBoolean();
|
||||
}
|
||||
|
||||
private boolean satisfied(int flag) {
|
||||
return (mSatisfiedConstraints & flag) != 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returning JobInfo bound to this snapshot
|
||||
* @return JobInfo of this snapshot
|
||||
*/
|
||||
public JobInfo getJobInfo() {
|
||||
return mJob;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is this job actually runnable at this moment?
|
||||
*/
|
||||
public boolean isRunnable() {
|
||||
return mIsRunnable;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see JobInfo.Builder#setRequiresCharging(boolean)
|
||||
*/
|
||||
public boolean isChargingSatisfied() {
|
||||
return !mJob.isRequireCharging()
|
||||
|| satisfied(JobInfo.CONSTRAINT_FLAG_CHARGING);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see JobInfo.Builder#setRequiresBatteryNotLow(boolean)
|
||||
*/
|
||||
public boolean isBatteryNotLowSatisfied() {
|
||||
return !mJob.isRequireBatteryNotLow()
|
||||
|| satisfied(JobInfo.CONSTRAINT_FLAG_BATTERY_NOT_LOW);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see JobInfo.Builder#setRequiresDeviceIdle(boolean)
|
||||
*/
|
||||
public boolean isRequireDeviceIdleSatisfied() {
|
||||
return !mJob.isRequireDeviceIdle()
|
||||
|| satisfied(JobInfo.CONSTRAINT_FLAG_DEVICE_IDLE);
|
||||
}
|
||||
|
||||
public boolean isRequireStorageNotLowSatisfied() {
|
||||
return !mJob.isRequireStorageNotLow()
|
||||
|| satisfied(JobInfo.CONSTRAINT_FLAG_STORAGE_NOT_LOW);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
mJob.writeToParcel(out, flags);
|
||||
out.writeInt(mSatisfiedConstraints);
|
||||
out.writeBoolean(mIsRunnable);
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull Creator<JobSnapshot> CREATOR = new Creator<JobSnapshot>() {
|
||||
@Override
|
||||
public JobSnapshot createFromParcel(Parcel in) {
|
||||
return new JobSnapshot(in);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JobSnapshot[] newArray(int size) {
|
||||
return new JobSnapshot[size];
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,20 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.app.job;
|
||||
|
||||
/** @hide */
|
||||
parcelable JobWorkItem;
|
||||
@@ -1,212 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2017 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package android.app.job;
|
||||
|
||||
import static android.app.job.JobInfo.NETWORK_BYTES_UNKNOWN;
|
||||
|
||||
import android.annotation.BytesLong;
|
||||
import android.annotation.UnsupportedAppUsage;
|
||||
import android.content.Intent;
|
||||
import android.os.Build;
|
||||
import android.os.Parcel;
|
||||
import android.os.Parcelable;
|
||||
|
||||
/**
|
||||
* A unit of work that can be enqueued for a job using
|
||||
* {@link JobScheduler#enqueue JobScheduler.enqueue}. See
|
||||
* {@link JobParameters#dequeueWork() JobParameters.dequeueWork} for more details.
|
||||
*/
|
||||
final public class JobWorkItem implements Parcelable {
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
|
||||
final Intent mIntent;
|
||||
final long mNetworkDownloadBytes;
|
||||
final long mNetworkUploadBytes;
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
|
||||
int mDeliveryCount;
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
|
||||
int mWorkId;
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
|
||||
Object mGrants;
|
||||
|
||||
/**
|
||||
* Create a new piece of work, which can be submitted to
|
||||
* {@link JobScheduler#enqueue JobScheduler.enqueue}.
|
||||
*
|
||||
* @param intent The general Intent describing this work.
|
||||
*/
|
||||
public JobWorkItem(Intent intent) {
|
||||
mIntent = intent;
|
||||
mNetworkDownloadBytes = NETWORK_BYTES_UNKNOWN;
|
||||
mNetworkUploadBytes = NETWORK_BYTES_UNKNOWN;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new piece of work, which can be submitted to
|
||||
* {@link JobScheduler#enqueue JobScheduler.enqueue}.
|
||||
* <p>
|
||||
* See {@link JobInfo.Builder#setEstimatedNetworkBytes(long, long)} for
|
||||
* details about how to estimate network traffic.
|
||||
*
|
||||
* @param intent The general Intent describing this work.
|
||||
* @param downloadBytes The estimated size of network traffic that will be
|
||||
* downloaded by this job work item, in bytes.
|
||||
* @param uploadBytes The estimated size of network traffic that will be
|
||||
* uploaded by this job work item, in bytes.
|
||||
*/
|
||||
public JobWorkItem(Intent intent, @BytesLong long downloadBytes, @BytesLong long uploadBytes) {
|
||||
mIntent = intent;
|
||||
mNetworkDownloadBytes = downloadBytes;
|
||||
mNetworkUploadBytes = uploadBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the Intent associated with this work.
|
||||
*/
|
||||
public Intent getIntent() {
|
||||
return mIntent;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the estimated size of download traffic that will be performed by
|
||||
* this job, in bytes.
|
||||
*
|
||||
* @return Estimated size of download traffic, or
|
||||
* {@link JobInfo#NETWORK_BYTES_UNKNOWN} when unknown.
|
||||
*/
|
||||
public @BytesLong long getEstimatedNetworkDownloadBytes() {
|
||||
return mNetworkDownloadBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the estimated size of upload traffic that will be performed by
|
||||
* this job work item, in bytes.
|
||||
*
|
||||
* @return Estimated size of upload traffic, or
|
||||
* {@link JobInfo#NETWORK_BYTES_UNKNOWN} when unknown.
|
||||
*/
|
||||
public @BytesLong long getEstimatedNetworkUploadBytes() {
|
||||
return mNetworkUploadBytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the count of the number of times this work item has been delivered
|
||||
* to the job. The value will be > 1 if it has been redelivered because the job
|
||||
* was stopped or crashed while it had previously been delivered but before the
|
||||
* job had called {@link JobParameters#completeWork JobParameters.completeWork} for it.
|
||||
*/
|
||||
public int getDeliveryCount() {
|
||||
return mDeliveryCount;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public void bumpDeliveryCount() {
|
||||
mDeliveryCount++;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public void setWorkId(int id) {
|
||||
mWorkId = id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public int getWorkId() {
|
||||
return mWorkId;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public void setGrants(Object grants) {
|
||||
mGrants = grants;
|
||||
}
|
||||
|
||||
/**
|
||||
* @hide
|
||||
*/
|
||||
public Object getGrants() {
|
||||
return mGrants;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder(64);
|
||||
sb.append("JobWorkItem{id=");
|
||||
sb.append(mWorkId);
|
||||
sb.append(" intent=");
|
||||
sb.append(mIntent);
|
||||
if (mNetworkDownloadBytes != NETWORK_BYTES_UNKNOWN) {
|
||||
sb.append(" downloadBytes=");
|
||||
sb.append(mNetworkDownloadBytes);
|
||||
}
|
||||
if (mNetworkUploadBytes != NETWORK_BYTES_UNKNOWN) {
|
||||
sb.append(" uploadBytes=");
|
||||
sb.append(mNetworkUploadBytes);
|
||||
}
|
||||
if (mDeliveryCount != 0) {
|
||||
sb.append(" dcount=");
|
||||
sb.append(mDeliveryCount);
|
||||
}
|
||||
sb.append("}");
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public int describeContents() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public void writeToParcel(Parcel out, int flags) {
|
||||
if (mIntent != null) {
|
||||
out.writeInt(1);
|
||||
mIntent.writeToParcel(out, 0);
|
||||
} else {
|
||||
out.writeInt(0);
|
||||
}
|
||||
out.writeLong(mNetworkDownloadBytes);
|
||||
out.writeLong(mNetworkUploadBytes);
|
||||
out.writeInt(mDeliveryCount);
|
||||
out.writeInt(mWorkId);
|
||||
}
|
||||
|
||||
public static final @android.annotation.NonNull Parcelable.Creator<JobWorkItem> CREATOR
|
||||
= new Parcelable.Creator<JobWorkItem>() {
|
||||
public JobWorkItem createFromParcel(Parcel in) {
|
||||
return new JobWorkItem(in);
|
||||
}
|
||||
|
||||
public JobWorkItem[] newArray(int size) {
|
||||
return new JobWorkItem[size];
|
||||
}
|
||||
};
|
||||
|
||||
@UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.P, trackingBug = 115609023)
|
||||
JobWorkItem(Parcel in) {
|
||||
if (in.readInt() != 0) {
|
||||
mIntent = Intent.CREATOR.createFromParcel(in);
|
||||
} else {
|
||||
mIntent = null;
|
||||
}
|
||||
mNetworkDownloadBytes = in.readLong();
|
||||
mNetworkUploadBytes = in.readLong();
|
||||
mDeliveryCount = in.readInt();
|
||||
mWorkId = in.readInt();
|
||||
}
|
||||
}
|
||||
@@ -1,119 +0,0 @@
|
||||
/*
|
||||
* Copyright (C) 2016 The Android Open Source Project
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License
|
||||
*/
|
||||
|
||||
package com.android.server.job;
|
||||
|
||||
import android.app.job.JobInfo;
|
||||
import android.util.proto.ProtoOutputStream;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* JobScheduler local system service interface.
|
||||
* {@hide} Only for use within the system server.
|
||||
*/
|
||||
public interface JobSchedulerInternal {
|
||||
|
||||
/**
|
||||
* Returns a list of pending jobs scheduled by the system service.
|
||||
*/
|
||||
List<JobInfo> getSystemScheduledPendingJobs();
|
||||
|
||||
/**
|
||||
* Cancel the jobs for a given uid (e.g. when app data is cleared)
|
||||
*/
|
||||
void cancelJobsForUid(int uid, String reason);
|
||||
|
||||
/**
|
||||
* These are for activity manager to communicate to use what is currently performing backups.
|
||||
*/
|
||||
void addBackingUpUid(int uid);
|
||||
void removeBackingUpUid(int uid);
|
||||
void clearAllBackingUpUids();
|
||||
|
||||
/**
|
||||
* The user has started interacting with the app. Take any appropriate action.
|
||||
*/
|
||||
void reportAppUsage(String packageName, int userId);
|
||||
|
||||
/**
|
||||
* Report a snapshot of sync-related jobs back to the sync manager
|
||||
*/
|
||||
JobStorePersistStats getPersistStats();
|
||||
|
||||
/**
|
||||
* Stats about the first load after boot and the most recent save.
|
||||
*/
|
||||
public class JobStorePersistStats {
|
||||
public int countAllJobsLoaded = -1;
|
||||
public int countSystemServerJobsLoaded = -1;
|
||||
public int countSystemSyncManagerJobsLoaded = -1;
|
||||
|
||||
public int countAllJobsSaved = -1;
|
||||
public int countSystemServerJobsSaved = -1;
|
||||
public int countSystemSyncManagerJobsSaved = -1;
|
||||
|
||||
public JobStorePersistStats() {
|
||||
}
|
||||
|
||||
public JobStorePersistStats(JobStorePersistStats source) {
|
||||
countAllJobsLoaded = source.countAllJobsLoaded;
|
||||
countSystemServerJobsLoaded = source.countSystemServerJobsLoaded;
|
||||
countSystemSyncManagerJobsLoaded = source.countSystemSyncManagerJobsLoaded;
|
||||
|
||||
countAllJobsSaved = source.countAllJobsSaved;
|
||||
countSystemServerJobsSaved = source.countSystemServerJobsSaved;
|
||||
countSystemSyncManagerJobsSaved = source.countSystemSyncManagerJobsSaved;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "FirstLoad: "
|
||||
+ countAllJobsLoaded + "/"
|
||||
+ countSystemServerJobsLoaded + "/"
|
||||
+ countSystemSyncManagerJobsLoaded
|
||||
+ " LastSave: "
|
||||
+ countAllJobsSaved + "/"
|
||||
+ countSystemServerJobsSaved + "/"
|
||||
+ countSystemSyncManagerJobsSaved;
|
||||
}
|
||||
|
||||
/**
|
||||
* Write the persist stats to the specified field.
|
||||
*/
|
||||
public void writeToProto(ProtoOutputStream proto, long fieldId) {
|
||||
final long token = proto.start(fieldId);
|
||||
|
||||
final long flToken = proto.start(JobStorePersistStatsProto.FIRST_LOAD);
|
||||
proto.write(JobStorePersistStatsProto.Stats.NUM_TOTAL_JOBS, countAllJobsLoaded);
|
||||
proto.write(JobStorePersistStatsProto.Stats.NUM_SYSTEM_SERVER_JOBS,
|
||||
countSystemServerJobsLoaded);
|
||||
proto.write(JobStorePersistStatsProto.Stats.NUM_SYSTEM_SYNC_MANAGER_JOBS,
|
||||
countSystemSyncManagerJobsLoaded);
|
||||
proto.end(flToken);
|
||||
|
||||
final long lsToken = proto.start(JobStorePersistStatsProto.LAST_SAVE);
|
||||
proto.write(JobStorePersistStatsProto.Stats.NUM_TOTAL_JOBS, countAllJobsSaved);
|
||||
proto.write(JobStorePersistStatsProto.Stats.NUM_SYSTEM_SERVER_JOBS,
|
||||
countSystemServerJobsSaved);
|
||||
proto.write(JobStorePersistStatsProto.Stats.NUM_SYSTEM_SYNC_MANAGER_JOBS,
|
||||
countSystemSyncManagerJobsSaved);
|
||||
proto.end(lsToken);
|
||||
|
||||
proto.end(token);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user