Revert "Revert "Add data transfer JobService APIs.""
This reverts commit 8e06f6988e.
Hides APIs based on feedback in other CL.
Reason for revert: Premature revert
Change-Id: I5eb50d85de5bae8713f11b27b42b62370e57f386
This commit is contained in:
@@ -29,6 +29,25 @@ import android.app.job.JobWorkItem;
|
||||
* {@hide}
|
||||
*/
|
||||
interface IJobCallback {
|
||||
/**
|
||||
* Immediate callback to the system after sending a data transfer download progress request
|
||||
* signal; used to quickly detect ANR.
|
||||
*
|
||||
* @param jobId Unique integer used to identify this job.
|
||||
* @param workId Unique integer used to identify a specific work item.
|
||||
* @param transferredBytes How much data has been downloaded, in bytes.
|
||||
*/
|
||||
void acknowledgeGetTransferredDownloadBytesMessage(int jobId, int workId,
|
||||
long transferredBytes);
|
||||
/**
|
||||
* Immediate callback to the system after sending a data transfer upload progress request
|
||||
* signal; used to quickly detect ANR.
|
||||
*
|
||||
* @param jobId Unique integer used to identify this job.
|
||||
* @param workId Unique integer used to identify a specific work item.
|
||||
* @param transferredBytes How much data has been uploaded, in bytes.
|
||||
*/
|
||||
void acknowledgeGetTransferredUploadBytesMessage(int jobId, int workId, long transferredBytes);
|
||||
/**
|
||||
* Immediate callback to the system after sending a start signal, used to quickly detect ANR.
|
||||
*
|
||||
@@ -65,4 +84,24 @@ interface IJobCallback {
|
||||
*/
|
||||
@UnsupportedAppUsage
|
||||
void jobFinished(int jobId, boolean reschedule);
|
||||
/*
|
||||
* Inform JobScheduler of a change in the estimated transfer payload.
|
||||
*
|
||||
* @param jobId Unique integer used to identify this job.
|
||||
* @param item The particular JobWorkItem this progress is associated with, if any.
|
||||
* @param downloadBytes How many bytes the app expects to download.
|
||||
* @param uploadBytes How many bytes the app expects to upload.
|
||||
*/
|
||||
void updateEstimatedNetworkBytes(int jobId, in JobWorkItem item,
|
||||
long downloadBytes, long uploadBytes);
|
||||
/*
|
||||
* Update JobScheduler of how much data the job has successfully transferred.
|
||||
*
|
||||
* @param jobId Unique integer used to identify this job.
|
||||
* @param item The particular JobWorkItem this progress is associated with, if any.
|
||||
* @param transferredDownloadBytes The number of bytes that have successfully been downloaded.
|
||||
* @param transferredUploadBytes The number of bytes that have successfully been uploaded.
|
||||
*/
|
||||
void updateTransferredNetworkBytes(int jobId, in JobWorkItem item,
|
||||
long transferredDownloadBytes, long transferredUploadBytes);
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.app.job;
|
||||
|
||||
import android.app.job.JobParameters;
|
||||
import android.app.job.JobWorkItem;
|
||||
|
||||
/**
|
||||
* Interface that the framework uses to communicate with application code that implements a
|
||||
@@ -31,4 +32,8 @@ oneway interface IJobService {
|
||||
/** Stop execution of application's job. */
|
||||
@UnsupportedAppUsage
|
||||
void stopJob(in JobParameters jobParams);
|
||||
/** Update JS of how much data has been downloaded. */
|
||||
void getTransferredDownloadBytes(in JobParameters jobParams, in JobWorkItem jobWorkItem);
|
||||
/** Update JS of how much data has been uploaded. */
|
||||
void getTransferredUploadBytes(in JobParameters jobParams, in JobWorkItem jobWorkItem);
|
||||
}
|
||||
|
||||
@@ -23,8 +23,11 @@ import android.annotation.RequiresPermission;
|
||||
import android.annotation.SystemApi;
|
||||
import android.annotation.SystemService;
|
||||
import android.annotation.UserIdInt;
|
||||
import android.compat.annotation.ChangeId;
|
||||
import android.compat.annotation.EnabledAfter;
|
||||
import android.content.ClipData;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.PersistableBundle;
|
||||
|
||||
@@ -94,6 +97,16 @@ import java.util.List;
|
||||
*/
|
||||
@SystemService(Context.JOB_SCHEDULER_SERVICE)
|
||||
public abstract class JobScheduler {
|
||||
/**
|
||||
* Whether to throw an exception when an app doesn't properly implement all the necessary
|
||||
* data transfer APIs.
|
||||
*
|
||||
* @hide
|
||||
*/
|
||||
@ChangeId
|
||||
@EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
|
||||
public static final long THROW_ON_INVALID_DATA_TRANSFER_IMPLEMENTATION = 255371817L;
|
||||
|
||||
/** @hide */
|
||||
@IntDef(prefix = { "RESULT_" }, value = {
|
||||
RESULT_FAILURE,
|
||||
|
||||
@@ -16,7 +16,13 @@
|
||||
|
||||
package android.app.job;
|
||||
|
||||
import static android.app.job.JobScheduler.THROW_ON_INVALID_DATA_TRANSFER_IMPLEMENTATION;
|
||||
|
||||
import android.annotation.BytesLong;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Service;
|
||||
import android.compat.Compatibility;
|
||||
import android.content.Intent;
|
||||
import android.os.IBinder;
|
||||
|
||||
@@ -72,6 +78,28 @@ public abstract class JobService extends Service {
|
||||
public boolean onStopJob(JobParameters params) {
|
||||
return JobService.this.onStopJob(params);
|
||||
}
|
||||
|
||||
@Override
|
||||
@BytesLong
|
||||
public long getTransferredDownloadBytes(@NonNull JobParameters params,
|
||||
@Nullable JobWorkItem item) {
|
||||
if (item == null) {
|
||||
return JobService.this.getTransferredDownloadBytes();
|
||||
} else {
|
||||
return JobService.this.getTransferredDownloadBytes(item);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@BytesLong
|
||||
public long getTransferredUploadBytes(@NonNull JobParameters params,
|
||||
@Nullable JobWorkItem item) {
|
||||
if (item == null) {
|
||||
return JobService.this.getTransferredUploadBytes();
|
||||
} else {
|
||||
return JobService.this.getTransferredUploadBytes(item);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
return mEngine.getBinder();
|
||||
@@ -171,4 +199,169 @@ public abstract class JobService extends Service {
|
||||
* to end the job entirely. Regardless of the value returned, your job must stop executing.
|
||||
*/
|
||||
public abstract boolean onStopJob(JobParameters params);
|
||||
|
||||
/**
|
||||
* Update how much data this job will transfer. This method can
|
||||
* be called multiple times within the first 30 seconds after
|
||||
* {@link #onStartJob(JobParameters)} has been called. Only
|
||||
* one call will be heeded after that time has passed.
|
||||
*
|
||||
* This method (or an overload) must be called within the first
|
||||
* 30 seconds for a data transfer job if a payload size estimate
|
||||
* was not provided at the time of scheduling.
|
||||
*
|
||||
* @hide
|
||||
* @see JobInfo.Builder#setEstimatedNetworkBytes(long, long)
|
||||
*/
|
||||
public final void updateEstimatedNetworkBytes(@NonNull JobParameters params,
|
||||
@BytesLong long downloadBytes, @BytesLong long uploadBytes) {
|
||||
mEngine.updateEstimatedNetworkBytes(params, null, downloadBytes, uploadBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update how much data will transfer for the JobWorkItem. This
|
||||
* method can be called multiple times within the first 30 seconds
|
||||
* after {@link #onStartJob(JobParameters)} has been called.
|
||||
* Only one call will be heeded after that time has passed.
|
||||
*
|
||||
* This method (or an overload) must be called within the first
|
||||
* 30 seconds for a data transfer job if a payload size estimate
|
||||
* was not provided at the time of scheduling.
|
||||
*
|
||||
* @hide
|
||||
* @see JobInfo.Builder#setEstimatedNetworkBytes(long, long)
|
||||
*/
|
||||
public final void updateEstimatedNetworkBytes(@NonNull JobParameters params,
|
||||
@NonNull JobWorkItem jobWorkItem,
|
||||
@BytesLong long downloadBytes, @BytesLong long uploadBytes) {
|
||||
mEngine.updateEstimatedNetworkBytes(params, jobWorkItem, downloadBytes, uploadBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell JobScheduler how much data has successfully been transferred for the data transfer job.
|
||||
* @hide
|
||||
*/
|
||||
public final void updateTransferredNetworkBytes(@NonNull JobParameters params,
|
||||
@BytesLong long transferredDownloadBytes, @BytesLong long transferredUploadBytes) {
|
||||
mEngine.updateTransferredNetworkBytes(params, null,
|
||||
transferredDownloadBytes, transferredUploadBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Tell JobScheduler how much data has been transferred for the data transfer
|
||||
* {@link JobWorkItem}.
|
||||
* @hide
|
||||
*/
|
||||
public final void updateTransferredNetworkBytes(@NonNull JobParameters params,
|
||||
@NonNull JobWorkItem item,
|
||||
@BytesLong long transferredDownloadBytes, @BytesLong long transferredUploadBytes) {
|
||||
mEngine.updateTransferredNetworkBytes(params, item,
|
||||
transferredDownloadBytes, transferredUploadBytes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of bytes the app has successfully downloaded for this job. JobScheduler
|
||||
* will call this if the job has specified positive estimated download bytes and
|
||||
* {@link #updateTransferredNetworkBytes(JobParameters, long, long)}
|
||||
* hasn't been called recently.
|
||||
*
|
||||
* <p>
|
||||
* This must be implemented for all data transfer jobs.
|
||||
*
|
||||
* @hide
|
||||
* @see JobInfo.Builder#setEstimatedNetworkBytes(long, long)
|
||||
* @see JobInfo#NETWORK_BYTES_UNKNOWN
|
||||
*/
|
||||
// TODO(255371817): specify the actual time JS will wait for progress before requesting
|
||||
@BytesLong
|
||||
public long getTransferredDownloadBytes() {
|
||||
if (Compatibility.isChangeEnabled(THROW_ON_INVALID_DATA_TRANSFER_IMPLEMENTATION)) {
|
||||
// Regular jobs don't have to implement this and JobScheduler won't call this API for
|
||||
// non-data transfer jobs.
|
||||
throw new RuntimeException("Not implemented. Must override in a subclass.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of bytes the app has successfully downloaded for this job. JobScheduler
|
||||
* will call this if the job has specified positive estimated upload bytes and
|
||||
* {@link #updateTransferredNetworkBytes(JobParameters, long, long)}
|
||||
* hasn't been called recently.
|
||||
*
|
||||
* <p>
|
||||
* This must be implemented for all data transfer jobs.
|
||||
*
|
||||
* @hide
|
||||
* @see JobInfo.Builder#setEstimatedNetworkBytes(long, long)
|
||||
* @see JobInfo#NETWORK_BYTES_UNKNOWN
|
||||
*/
|
||||
// TODO(255371817): specify the actual time JS will wait for progress before requesting
|
||||
@BytesLong
|
||||
public long getTransferredUploadBytes() {
|
||||
if (Compatibility.isChangeEnabled(THROW_ON_INVALID_DATA_TRANSFER_IMPLEMENTATION)) {
|
||||
// Regular jobs don't have to implement this and JobScheduler won't call this API for
|
||||
// non-data transfer jobs.
|
||||
throw new RuntimeException("Not implemented. Must override in a subclass.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of bytes the app has successfully downloaded for this job. JobScheduler
|
||||
* will call this if the job has specified positive estimated download bytes and
|
||||
* {@link #updateTransferredNetworkBytes(JobParameters, JobWorkItem, long, long)}
|
||||
* hasn't been called recently and the job has
|
||||
* {@link JobWorkItem JobWorkItems} that have been
|
||||
* {@link JobParameters#dequeueWork dequeued} but not
|
||||
* {@link JobParameters#completeWork(JobWorkItem) completed}.
|
||||
*
|
||||
* <p>
|
||||
* This must be implemented for all data transfer jobs.
|
||||
*
|
||||
* @hide
|
||||
* @see JobInfo#NETWORK_BYTES_UNKNOWN
|
||||
*/
|
||||
// TODO(255371817): specify the actual time JS will wait for progress before requesting
|
||||
@BytesLong
|
||||
public long getTransferredDownloadBytes(@NonNull JobWorkItem item) {
|
||||
if (item == null) {
|
||||
return getTransferredDownloadBytes();
|
||||
}
|
||||
if (Compatibility.isChangeEnabled(THROW_ON_INVALID_DATA_TRANSFER_IMPLEMENTATION)) {
|
||||
// Regular jobs don't have to implement this and JobScheduler won't call this API for
|
||||
// non-data transfer jobs.
|
||||
throw new RuntimeException("Not implemented. Must override in a subclass.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the number of bytes the app has successfully downloaded for this job. JobScheduler
|
||||
* will call this if the job has specified positive estimated upload bytes and
|
||||
* {@link #updateTransferredNetworkBytes(JobParameters, JobWorkItem, long, long)}
|
||||
* hasn't been called recently and the job has
|
||||
* {@link JobWorkItem JobWorkItems} that have been
|
||||
* {@link JobParameters#dequeueWork dequeued} but not
|
||||
* {@link JobParameters#completeWork(JobWorkItem) completed}.
|
||||
*
|
||||
* <p>
|
||||
* This must be implemented for all data transfer jobs.
|
||||
*
|
||||
* @hide
|
||||
* @see JobInfo#NETWORK_BYTES_UNKNOWN
|
||||
*/
|
||||
// TODO(255371817): specify the actual time JS will wait for progress before requesting
|
||||
@BytesLong
|
||||
public long getTransferredUploadBytes(@NonNull JobWorkItem item) {
|
||||
if (item == null) {
|
||||
return getTransferredUploadBytes();
|
||||
}
|
||||
if (Compatibility.isChangeEnabled(THROW_ON_INVALID_DATA_TRANSFER_IMPLEMENTATION)) {
|
||||
// Regular jobs don't have to implement this and JobScheduler won't call this API for
|
||||
// non-data transfer jobs.
|
||||
throw new RuntimeException("Not implemented. Must override in a subclass.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,13 @@
|
||||
|
||||
package android.app.job;
|
||||
|
||||
import static android.app.job.JobScheduler.THROW_ON_INVALID_DATA_TRANSFER_IMPLEMENTATION;
|
||||
|
||||
import android.annotation.BytesLong;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.Service;
|
||||
import android.compat.Compatibility;
|
||||
import android.content.Intent;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
@@ -25,6 +31,8 @@ import android.os.Message;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import com.android.internal.os.SomeArgs;
|
||||
|
||||
import java.lang.ref.WeakReference;
|
||||
|
||||
/**
|
||||
@@ -51,6 +59,20 @@ public abstract class JobServiceEngine {
|
||||
* Message that the client has completed execution of this job.
|
||||
*/
|
||||
private static final int MSG_JOB_FINISHED = 2;
|
||||
/**
|
||||
* Message that will result in a call to
|
||||
* {@link #getTransferredDownloadBytes(JobParameters, JobWorkItem)}.
|
||||
*/
|
||||
private static final int MSG_GET_TRANSFERRED_DOWNLOAD_BYTES = 3;
|
||||
/**
|
||||
* Message that will result in a call to
|
||||
* {@link #getTransferredUploadBytes(JobParameters, JobWorkItem)}.
|
||||
*/
|
||||
private static final int MSG_GET_TRANSFERRED_UPLOAD_BYTES = 4;
|
||||
/** Message that the client wants to update JobScheduler of the data transfer progress. */
|
||||
private static final int MSG_UPDATE_TRANSFERRED_NETWORK_BYTES = 5;
|
||||
/** Message that the client wants to update JobScheduler of the estimated transfer size. */
|
||||
private static final int MSG_UPDATE_ESTIMATED_NETWORK_BYTES = 6;
|
||||
|
||||
private final IJobService mBinder;
|
||||
|
||||
@@ -67,6 +89,32 @@ public abstract class JobServiceEngine {
|
||||
mService = new WeakReference<>(service);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getTransferredDownloadBytes(@NonNull JobParameters jobParams,
|
||||
@Nullable JobWorkItem jobWorkItem) throws RemoteException {
|
||||
JobServiceEngine service = mService.get();
|
||||
if (service != null) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = jobParams;
|
||||
args.arg2 = jobWorkItem;
|
||||
service.mHandler.obtainMessage(MSG_GET_TRANSFERRED_DOWNLOAD_BYTES, args)
|
||||
.sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getTransferredUploadBytes(@NonNull JobParameters jobParams,
|
||||
@Nullable JobWorkItem jobWorkItem) throws RemoteException {
|
||||
JobServiceEngine service = mService.get();
|
||||
if (service != null) {
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = jobParams;
|
||||
args.arg2 = jobWorkItem;
|
||||
service.mHandler.obtainMessage(MSG_GET_TRANSFERRED_UPLOAD_BYTES, args)
|
||||
.sendToTarget();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startJob(JobParameters jobParams) throws RemoteException {
|
||||
JobServiceEngine service = mService.get();
|
||||
@@ -98,9 +146,9 @@ public abstract class JobServiceEngine {
|
||||
|
||||
@Override
|
||||
public void handleMessage(Message msg) {
|
||||
final JobParameters params = (JobParameters) msg.obj;
|
||||
switch (msg.what) {
|
||||
case MSG_EXECUTE_JOB:
|
||||
case MSG_EXECUTE_JOB: {
|
||||
final JobParameters params = (JobParameters) msg.obj;
|
||||
try {
|
||||
boolean workOngoing = JobServiceEngine.this.onStartJob(params);
|
||||
ackStartMessage(params, workOngoing);
|
||||
@@ -109,7 +157,9 @@ public abstract class JobServiceEngine {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
break;
|
||||
case MSG_STOP_JOB:
|
||||
}
|
||||
case MSG_STOP_JOB: {
|
||||
final JobParameters params = (JobParameters) msg.obj;
|
||||
try {
|
||||
boolean ret = JobServiceEngine.this.onStopJob(params);
|
||||
ackStopMessage(params, ret);
|
||||
@@ -118,7 +168,9 @@ public abstract class JobServiceEngine {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
break;
|
||||
case MSG_JOB_FINISHED:
|
||||
}
|
||||
case MSG_JOB_FINISHED: {
|
||||
final JobParameters params = (JobParameters) msg.obj;
|
||||
final boolean needsReschedule = (msg.arg2 == 1);
|
||||
IJobCallback callback = params.getCallback();
|
||||
if (callback != null) {
|
||||
@@ -132,19 +184,117 @@ public abstract class JobServiceEngine {
|
||||
Log.e(TAG, "finishJob() called for a nonexistent job id.");
|
||||
}
|
||||
break;
|
||||
}
|
||||
case MSG_GET_TRANSFERRED_DOWNLOAD_BYTES: {
|
||||
final SomeArgs args = (SomeArgs) msg.obj;
|
||||
final JobParameters params = (JobParameters) args.arg1;
|
||||
final JobWorkItem item = (JobWorkItem) args.arg2;
|
||||
try {
|
||||
long ret = JobServiceEngine.this.getTransferredDownloadBytes(params, item);
|
||||
ackGetTransferredDownloadBytesMessage(params, item, ret);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Application unable to handle getTransferredDownloadBytes.", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
args.recycle();
|
||||
break;
|
||||
}
|
||||
case MSG_GET_TRANSFERRED_UPLOAD_BYTES: {
|
||||
final SomeArgs args = (SomeArgs) msg.obj;
|
||||
final JobParameters params = (JobParameters) args.arg1;
|
||||
final JobWorkItem item = (JobWorkItem) args.arg2;
|
||||
try {
|
||||
long ret = JobServiceEngine.this.getTransferredUploadBytes(params, item);
|
||||
ackGetTransferredUploadBytesMessage(params, item, ret);
|
||||
} catch (Exception e) {
|
||||
Log.e(TAG, "Application unable to handle getTransferredUploadBytes.", e);
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
args.recycle();
|
||||
break;
|
||||
}
|
||||
case MSG_UPDATE_TRANSFERRED_NETWORK_BYTES: {
|
||||
final SomeArgs args = (SomeArgs) msg.obj;
|
||||
final JobParameters params = (JobParameters) args.arg1;
|
||||
IJobCallback callback = params.getCallback();
|
||||
if (callback != null) {
|
||||
try {
|
||||
callback.updateTransferredNetworkBytes(params.getJobId(),
|
||||
(JobWorkItem) args.arg2, args.argl1, args.argl2);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error updating data transfer progress to system:"
|
||||
+ " binder has gone away.");
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG, "updateDataTransferProgress() called for a nonexistent job id.");
|
||||
}
|
||||
args.recycle();
|
||||
break;
|
||||
}
|
||||
case MSG_UPDATE_ESTIMATED_NETWORK_BYTES: {
|
||||
final SomeArgs args = (SomeArgs) msg.obj;
|
||||
final JobParameters params = (JobParameters) args.arg1;
|
||||
IJobCallback callback = params.getCallback();
|
||||
if (callback != null) {
|
||||
try {
|
||||
callback.updateEstimatedNetworkBytes(params.getJobId(),
|
||||
(JobWorkItem) args.arg2, args.argl1, args.argl2);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "Error updating estimated transfer size to system:"
|
||||
+ " binder has gone away.");
|
||||
}
|
||||
} else {
|
||||
Log.e(TAG,
|
||||
"updateEstimatedNetworkBytes() called for a nonexistent job id.");
|
||||
}
|
||||
args.recycle();
|
||||
break;
|
||||
}
|
||||
default:
|
||||
Log.e(TAG, "Unrecognised message received.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
private void ackGetTransferredDownloadBytesMessage(@NonNull JobParameters params,
|
||||
@Nullable JobWorkItem item, long progress) {
|
||||
final IJobCallback callback = params.getCallback();
|
||||
final int jobId = params.getJobId();
|
||||
final int workId = item == null ? -1 : item.getWorkId();
|
||||
if (callback != null) {
|
||||
try {
|
||||
callback.acknowledgeGetTransferredDownloadBytesMessage(jobId, workId, progress);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "System unreachable for returning progress.");
|
||||
}
|
||||
} else if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log.d(TAG, "Attempting to ack a job that has already been processed.");
|
||||
}
|
||||
}
|
||||
|
||||
private void ackGetTransferredUploadBytesMessage(@NonNull JobParameters params,
|
||||
@Nullable JobWorkItem item, long progress) {
|
||||
final IJobCallback callback = params.getCallback();
|
||||
final int jobId = params.getJobId();
|
||||
final int workId = item == null ? -1 : item.getWorkId();
|
||||
if (callback != null) {
|
||||
try {
|
||||
callback.acknowledgeGetTransferredUploadBytesMessage(jobId, workId, progress);
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "System unreachable for returning progress.");
|
||||
}
|
||||
} else if (Log.isLoggable(TAG, Log.DEBUG)) {
|
||||
Log.d(TAG, "Attempting to ack a job that has already been processed.");
|
||||
}
|
||||
}
|
||||
|
||||
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) {
|
||||
} catch (RemoteException e) {
|
||||
Log.e(TAG, "System unreachable for starting job.");
|
||||
}
|
||||
} else {
|
||||
@@ -213,4 +363,73 @@ public abstract class JobServiceEngine {
|
||||
m.arg2 = needsReschedule ? 1 : 0;
|
||||
m.sendToTarget();
|
||||
}
|
||||
|
||||
/**
|
||||
* Engine's request to get how much data has been downloaded.
|
||||
*
|
||||
* @hide
|
||||
* @see JobService#getTransferredDownloadBytes()
|
||||
*/
|
||||
@BytesLong
|
||||
public long getTransferredDownloadBytes(@NonNull JobParameters params,
|
||||
@Nullable JobWorkItem item) {
|
||||
if (Compatibility.isChangeEnabled(THROW_ON_INVALID_DATA_TRANSFER_IMPLEMENTATION)) {
|
||||
throw new RuntimeException("Not implemented. Must override in a subclass.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Engine's request to get how much data has been uploaded.
|
||||
*
|
||||
* @hide
|
||||
* @see JobService#getTransferredUploadBytes()
|
||||
*/
|
||||
@BytesLong
|
||||
public long getTransferredUploadBytes(@NonNull JobParameters params,
|
||||
@Nullable JobWorkItem item) {
|
||||
if (Compatibility.isChangeEnabled(THROW_ON_INVALID_DATA_TRANSFER_IMPLEMENTATION)) {
|
||||
throw new RuntimeException("Not implemented. Must override in a subclass.");
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Call in to engine to report data transfer progress.
|
||||
*
|
||||
* @hide
|
||||
* @see JobService#updateTransferredNetworkBytes(JobParameters, long, long)
|
||||
*/
|
||||
public void updateTransferredNetworkBytes(@NonNull JobParameters params,
|
||||
@Nullable JobWorkItem item, long downloadBytes, long uploadBytes) {
|
||||
if (params == null) {
|
||||
throw new NullPointerException("params");
|
||||
}
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = params;
|
||||
args.arg2 = item;
|
||||
args.argl1 = downloadBytes;
|
||||
args.argl2 = uploadBytes;
|
||||
mHandler.obtainMessage(MSG_UPDATE_TRANSFERRED_NETWORK_BYTES, args).sendToTarget();
|
||||
}
|
||||
|
||||
/**
|
||||
* Call in to engine to report data transfer progress.
|
||||
*
|
||||
* @hide
|
||||
* @see JobService#updateEstimatedNetworkBytes(JobParameters, JobWorkItem, long, long)
|
||||
*/
|
||||
public void updateEstimatedNetworkBytes(@NonNull JobParameters params,
|
||||
@NonNull JobWorkItem item,
|
||||
@BytesLong long downloadBytes, @BytesLong long uploadBytes) {
|
||||
if (params == null) {
|
||||
throw new NullPointerException("params");
|
||||
}
|
||||
SomeArgs args = SomeArgs.obtain();
|
||||
args.arg1 = params;
|
||||
args.arg2 = item;
|
||||
args.argl1 = downloadBytes;
|
||||
args.argl2 = uploadBytes;
|
||||
mHandler.obtainMessage(MSG_UPDATE_ESTIMATED_NETWORK_BYTES, args).sendToTarget();
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@ import static android.app.job.JobInfo.getPriorityString;
|
||||
import static com.android.server.job.JobConcurrencyManager.WORK_TYPE_NONE;
|
||||
import static com.android.server.job.JobSchedulerService.sElapsedRealtimeClock;
|
||||
|
||||
import android.annotation.BytesLong;
|
||||
import android.annotation.NonNull;
|
||||
import android.annotation.Nullable;
|
||||
import android.app.job.IJobCallback;
|
||||
@@ -186,6 +187,18 @@ public final class JobServiceContext implements ServiceConnection {
|
||||
public String mStoppedReason;
|
||||
public long mStoppedTime;
|
||||
|
||||
@Override
|
||||
public void acknowledgeGetTransferredDownloadBytesMessage(int jobId, int workId,
|
||||
@BytesLong long transferredBytes) {
|
||||
doAcknowledgeGetTransferredDownloadBytesMessage(this, jobId, workId, transferredBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acknowledgeGetTransferredUploadBytesMessage(int jobId, int workId,
|
||||
@BytesLong long transferredBytes) {
|
||||
doAcknowledgeGetTransferredUploadBytesMessage(this, jobId, workId, transferredBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void acknowledgeStartMessage(int jobId, boolean ongoing) {
|
||||
doAcknowledgeStartMessage(this, jobId, ongoing);
|
||||
@@ -210,6 +223,18 @@ public final class JobServiceContext implements ServiceConnection {
|
||||
public void jobFinished(int jobId, boolean reschedule) {
|
||||
doJobFinished(this, jobId, reschedule);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateEstimatedNetworkBytes(int jobId, JobWorkItem item,
|
||||
long downloadBytes, long uploadBytes) {
|
||||
doUpdateEstimatedNetworkBytes(this, jobId, item, downloadBytes, uploadBytes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTransferredNetworkBytes(int jobId, JobWorkItem item,
|
||||
long downloadBytes, long uploadBytes) {
|
||||
doUpdateTransferredNetworkBytes(this, jobId, item, downloadBytes, uploadBytes);
|
||||
}
|
||||
}
|
||||
|
||||
JobServiceContext(JobSchedulerService service, JobConcurrencyManager concurrencyManager,
|
||||
@@ -506,6 +531,16 @@ public final class JobServiceContext implements ServiceConnection {
|
||||
}
|
||||
}
|
||||
|
||||
private void doAcknowledgeGetTransferredDownloadBytesMessage(JobCallback jobCallback, int jobId,
|
||||
int workId, @BytesLong long transferredBytes) {
|
||||
// TODO(255393346): Make sure apps call this appropriately and monitor for abuse
|
||||
}
|
||||
|
||||
private void doAcknowledgeGetTransferredUploadBytesMessage(JobCallback jobCallback, int jobId,
|
||||
int workId, @BytesLong long transferredBytes) {
|
||||
// TODO(255393346): Make sure apps call this appropriately and monitor for abuse
|
||||
}
|
||||
|
||||
void doAcknowledgeStopMessage(JobCallback cb, int jobId, boolean reschedule) {
|
||||
doCallback(cb, reschedule, null);
|
||||
}
|
||||
@@ -558,6 +593,16 @@ public final class JobServiceContext implements ServiceConnection {
|
||||
}
|
||||
}
|
||||
|
||||
private void doUpdateTransferredNetworkBytes(JobCallback jobCallback, int jobId,
|
||||
@Nullable JobWorkItem item, long downloadBytes, long uploadBytes) {
|
||||
// TODO(255393346): Make sure apps call this appropriately and monitor for abuse
|
||||
}
|
||||
|
||||
private void doUpdateEstimatedNetworkBytes(JobCallback jobCallback, int jobId,
|
||||
@Nullable JobWorkItem item, long downloadBytes, long uploadBytes) {
|
||||
// TODO(255393346): Make sure apps call this appropriately and monitor for abuse
|
||||
}
|
||||
|
||||
/**
|
||||
* We acquire/release a wakelock on onServiceConnected/unbindService. This mirrors the work
|
||||
* we intend to send to the client - we stop sending work when the service is unbound so until
|
||||
|
||||
Reference in New Issue
Block a user