Loading apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java +34 −0 Original line number Diff line number Diff line Loading @@ -1703,6 +1703,40 @@ class JobConcurrencyManager { return foundSome; } /** * Returns the estimated network bytes if the job is running. Returns {@code null} if the job * isn't running. */ @Nullable @GuardedBy("mLock") Pair<Long, Long> getEstimatedNetworkBytesLocked(String pkgName, int uid, int jobId) { for (int i = 0; i < mActiveServices.size(); i++) { final JobServiceContext jc = mActiveServices.get(i); final JobStatus js = jc.getRunningJobLocked(); if (js != null && js.matches(uid, jobId) && js.getSourcePackageName().equals(pkgName)) { return jc.getEstimatedNetworkBytes(); } } return null; } /** * Returns the transferred network bytes if the job is running. Returns {@code null} if the job * isn't running. */ @Nullable @GuardedBy("mLock") Pair<Long, Long> getTransferredNetworkBytesLocked(String pkgName, int uid, int jobId) { for (int i = 0; i < mActiveServices.size(); i++) { final JobServiceContext jc = mActiveServices.get(i); final JobStatus js = jc.getRunningJobLocked(); if (js != null && js.matches(uid, jobId) && js.getSourcePackageName().equals(pkgName)) { return jc.getTransferredNetworkBytes(); } } return null; } @NonNull private JobServiceContext createNewJobServiceContext() { return mInjector.createJobServiceContext(mService, this, mNotificationCoordinator, Loading apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +95 −0 Original line number Diff line number Diff line Loading @@ -86,6 +86,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.IndentingPrintWriter; import android.util.Log; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; Loading Loading @@ -4168,6 +4169,100 @@ public class JobSchedulerService extends com.android.server.SystemService } } int getEstimatedNetworkBytes(PrintWriter pw, String pkgName, int userId, int jobId, int byteOption) { try { final int uid = AppGlobals.getPackageManager().getPackageUid(pkgName, 0, userId != UserHandle.USER_ALL ? userId : UserHandle.USER_SYSTEM); if (uid < 0) { pw.print("unknown("); pw.print(pkgName); pw.println(")"); return JobSchedulerShellCommand.CMD_ERR_NO_PACKAGE; } synchronized (mLock) { final JobStatus js = mJobs.getJobByUidAndJobId(uid, jobId); if (DEBUG) { Slog.d(TAG, "get-estimated-network-bytes " + uid + "/" + jobId + ": " + js); } if (js == null) { pw.print("unknown("); UserHandle.formatUid(pw, uid); pw.print("/jid"); pw.print(jobId); pw.println(")"); return JobSchedulerShellCommand.CMD_ERR_NO_JOB; } final long downloadBytes; final long uploadBytes; final Pair<Long, Long> bytes = mConcurrencyManager.getEstimatedNetworkBytesLocked(pkgName, uid, jobId); if (bytes == null) { downloadBytes = js.getEstimatedNetworkDownloadBytes(); uploadBytes = js.getEstimatedNetworkUploadBytes(); } else { downloadBytes = bytes.first; uploadBytes = bytes.second; } if (byteOption == JobSchedulerShellCommand.BYTE_OPTION_DOWNLOAD) { pw.println(downloadBytes); } else { pw.println(uploadBytes); } pw.println(); } } catch (RemoteException e) { // can't happen } return 0; } int getTransferredNetworkBytes(PrintWriter pw, String pkgName, int userId, int jobId, int byteOption) { try { final int uid = AppGlobals.getPackageManager().getPackageUid(pkgName, 0, userId != UserHandle.USER_ALL ? userId : UserHandle.USER_SYSTEM); if (uid < 0) { pw.print("unknown("); pw.print(pkgName); pw.println(")"); return JobSchedulerShellCommand.CMD_ERR_NO_PACKAGE; } synchronized (mLock) { final JobStatus js = mJobs.getJobByUidAndJobId(uid, jobId); if (DEBUG) { Slog.d(TAG, "get-transferred-network-bytes " + uid + "/" + jobId + ": " + js); } if (js == null) { pw.print("unknown("); UserHandle.formatUid(pw, uid); pw.print("/jid"); pw.print(jobId); pw.println(")"); return JobSchedulerShellCommand.CMD_ERR_NO_JOB; } final long downloadBytes; final long uploadBytes; final Pair<Long, Long> bytes = mConcurrencyManager.getTransferredNetworkBytesLocked(pkgName, uid, jobId); if (bytes == null) { downloadBytes = 0; uploadBytes = 0; } else { downloadBytes = bytes.first; uploadBytes = bytes.second; } if (byteOption == JobSchedulerShellCommand.BYTE_OPTION_DOWNLOAD) { pw.println(downloadBytes); } else { pw.println(uploadBytes); } pw.println(); } } catch (RemoteException e) { // can't happen } return 0; } private boolean checkRunLongJobsPermission(int packageUid, String packageName) { // Returns true if both the appop and permission are granted. return PermissionChecker.checkPermissionForPreflight(getTestableContext(), Loading apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java +106 −2 Original line number Diff line number Diff line Loading @@ -32,6 +32,9 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler { public static final int CMD_ERR_NO_JOB = -1001; public static final int CMD_ERR_CONSTRAINTS = -1002; static final int BYTE_OPTION_DOWNLOAD = 0; static final int BYTE_OPTION_UPLOAD = 1; JobSchedulerService mInternal; IPackageManager mPM; Loading Loading @@ -59,10 +62,18 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler { return getBatteryCharging(pw); case "get-battery-not-low": return getBatteryNotLow(pw); case "get-estimated-download-bytes": return getEstimatedNetworkBytes(pw, BYTE_OPTION_DOWNLOAD); case "get-estimated-upload-bytes": return getEstimatedNetworkBytes(pw, BYTE_OPTION_UPLOAD); case "get-storage-seq": return getStorageSeq(pw); case "get-storage-not-low": return getStorageNotLow(pw); case "get-transferred-download-bytes": return getTransferredNetworkBytes(pw, BYTE_OPTION_DOWNLOAD); case "get-transferred-upload-bytes": return getTransferredNetworkBytes(pw, BYTE_OPTION_UPLOAD); case "get-job-state": return getJobState(pw); case "heartbeat": Loading Loading @@ -304,6 +315,43 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler { return 0; } private int getEstimatedNetworkBytes(PrintWriter pw, int byteOption) throws Exception { checkPermission("get estimated bytes"); int userId = UserHandle.USER_SYSTEM; String opt; while ((opt = getNextOption()) != null) { switch (opt) { case "-u": case "--user": userId = UserHandle.parseUserArg(getNextArgRequired()); break; default: pw.println("Error: unknown option '" + opt + "'"); return -1; } } if (userId == UserHandle.USER_CURRENT) { userId = ActivityManager.getCurrentUser(); } final String pkgName = getNextArgRequired(); final String jobIdStr = getNextArgRequired(); final int jobId = Integer.parseInt(jobIdStr); final long ident = Binder.clearCallingIdentity(); try { int ret = mInternal.getEstimatedNetworkBytes(pw, pkgName, userId, jobId, byteOption); printError(ret, pkgName, userId, jobId); return ret; } finally { Binder.restoreCallingIdentity(ident); } } private int getStorageSeq(PrintWriter pw) { int seq = mInternal.getStorageSeq(); pw.println(seq); Loading @@ -316,8 +364,45 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler { return 0; } private int getTransferredNetworkBytes(PrintWriter pw, int byteOption) throws Exception { checkPermission("get transferred bytes"); int userId = UserHandle.USER_SYSTEM; String opt; while ((opt = getNextOption()) != null) { switch (opt) { case "-u": case "--user": userId = UserHandle.parseUserArg(getNextArgRequired()); break; default: pw.println("Error: unknown option '" + opt + "'"); return -1; } } if (userId == UserHandle.USER_CURRENT) { userId = ActivityManager.getCurrentUser(); } final String pkgName = getNextArgRequired(); final String jobIdStr = getNextArgRequired(); final int jobId = Integer.parseInt(jobIdStr); final long ident = Binder.clearCallingIdentity(); try { int ret = mInternal.getTransferredNetworkBytes(pw, pkgName, userId, jobId, byteOption); printError(ret, pkgName, userId, jobId); return ret; } finally { Binder.restoreCallingIdentity(ident); } } private int getJobState(PrintWriter pw) throws Exception { checkPermission("force timeout jobs"); checkPermission("get job state"); int userId = UserHandle.USER_SYSTEM; Loading Loading @@ -473,10 +558,30 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler { pw.println(" Return whether the battery is currently considered to be charging."); pw.println(" get-battery-not-low"); pw.println(" Return whether the battery is currently considered to not be low."); pw.println(" get-estimated-download-bytes [-u | --user USER_ID] PACKAGE JOB_ID"); pw.println(" Return the most recent estimated download bytes for the job."); pw.println(" Options:"); pw.println(" -u or --user: specify which user's job is to be run; the default is"); pw.println(" the primary or system user"); pw.println(" get-estimated-upload-bytes [-u | --user USER_ID] PACKAGE JOB_ID"); pw.println(" Return the most recent estimated upload bytes for the job."); pw.println(" Options:"); pw.println(" -u or --user: specify which user's job is to be run; the default is"); pw.println(" the primary or system user"); pw.println(" get-storage-seq"); pw.println(" Return the last storage update sequence number that was received."); pw.println(" get-storage-not-low"); pw.println(" Return whether storage is currently considered to not be low."); pw.println(" get-transferred-download-bytes [-u | --user USER_ID] PACKAGE JOB_ID"); pw.println(" Return the most recent transferred download bytes for the job."); pw.println(" Options:"); pw.println(" -u or --user: specify which user's job is to be run; the default is"); pw.println(" the primary or system user"); pw.println(" get-transferred-upload-bytes [-u | --user USER_ID] PACKAGE JOB_ID"); pw.println(" Return the most recent transferred upload bytes for the job."); pw.println(" Options:"); pw.println(" -u or --user: specify which user's job is to be run; the default is"); pw.println(" the primary or system user"); pw.println(" get-job-state [-u | --user USER_ID] PACKAGE JOB_ID"); pw.println(" Return the current state of a job, may be any combination of:"); pw.println(" pending: currently on the pending list, waiting to be active"); Loading @@ -493,5 +598,4 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler { pw.println(" Trigger wireless charging dock state. Active by default."); pw.println(); } } apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java +57 −12 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import android.os.Trace; import android.os.UserHandle; import android.util.EventLog; import android.util.IndentingPrintWriter; import android.util.Pair; import android.util.Slog; import android.util.TimeUtils; Loading Loading @@ -171,6 +172,11 @@ public final class JobServiceContext implements ServiceConnection { /** The absolute maximum amount of time the job can run */ private long mMaxExecutionTimeMillis; private long mEstimatedDownloadBytes; private long mEstimatedUploadBytes; private long mTransferredDownloadBytes; private long mTransferredUploadBytes; /** * The stop reason for a pending cancel. If there's not pending cancel, then the value should be * {@link JobParameters#STOP_REASON_UNDEFINED}. Loading Loading @@ -306,6 +312,9 @@ public final class JobServiceContext implements ServiceConnection { mMinExecutionGuaranteeMillis = mService.getMinJobExecutionGuaranteeMs(job); mMaxExecutionTimeMillis = Math.max(mService.getMaxJobExecutionTimeMs(job), mMinExecutionGuaranteeMillis); mEstimatedDownloadBytes = job.getEstimatedNetworkDownloadBytes(); mEstimatedUploadBytes = job.getEstimatedNetworkUploadBytes(); mTransferredDownloadBytes = mTransferredUploadBytes = 0; final long whenDeferred = job.getWhenStandbyDeferred(); if (whenDeferred > 0) { Loading Loading @@ -524,6 +533,16 @@ public final class JobServiceContext implements ServiceConnection { return false; } @GuardedBy("mLock") Pair<Long, Long> getEstimatedNetworkBytes() { return Pair.create(mEstimatedDownloadBytes, mEstimatedUploadBytes); } @GuardedBy("mLock") Pair<Long, Long> getTransferredNetworkBytes() { return Pair.create(mTransferredDownloadBytes, mTransferredUploadBytes); } void doJobFinished(JobCallback cb, int jobId, boolean reschedule) { final long ident = Binder.clearCallingIdentity(); try { Loading @@ -541,14 +560,26 @@ public final class JobServiceContext implements ServiceConnection { } } private void doAcknowledgeGetTransferredDownloadBytesMessage(JobCallback jobCallback, int jobId, private void doAcknowledgeGetTransferredDownloadBytesMessage(JobCallback cb, int jobId, int workId, @BytesLong long transferredBytes) { // TODO(255393346): Make sure apps call this appropriately and monitor for abuse synchronized (mLock) { if (!verifyCallerLocked(cb)) { return; } mTransferredDownloadBytes = transferredBytes; } } private void doAcknowledgeGetTransferredUploadBytesMessage(JobCallback jobCallback, int jobId, private void doAcknowledgeGetTransferredUploadBytesMessage(JobCallback cb, int jobId, int workId, @BytesLong long transferredBytes) { // TODO(255393346): Make sure apps call this appropriately and monitor for abuse synchronized (mLock) { if (!verifyCallerLocked(cb)) { return; } mTransferredUploadBytes = transferredBytes; } } void doAcknowledgeStopMessage(JobCallback cb, int jobId, boolean reschedule) { Loading Loading @@ -603,6 +634,30 @@ public final class JobServiceContext implements ServiceConnection { } } private void doUpdateEstimatedNetworkBytes(JobCallback cb, int jobId, @Nullable JobWorkItem item, long downloadBytes, long uploadBytes) { // TODO(255393346): Make sure apps call this appropriately and monitor for abuse synchronized (mLock) { if (!verifyCallerLocked(cb)) { return; } mEstimatedDownloadBytes = downloadBytes; mEstimatedUploadBytes = uploadBytes; } } private void doUpdateTransferredNetworkBytes(JobCallback cb, int jobId, @Nullable JobWorkItem item, long downloadBytes, long uploadBytes) { // TODO(255393346): Make sure apps call this appropriately and monitor for abuse synchronized (mLock) { if (!verifyCallerLocked(cb)) { return; } mTransferredDownloadBytes = downloadBytes; mTransferredUploadBytes = uploadBytes; } } private void doSetNotification(JobCallback cb, int jodId, int notificationId, Notification notification, int jobEndNotificationPolicy) { final int callingPid = Binder.getCallingPid(); Loading @@ -627,16 +682,6 @@ 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 Loading Loading
apex/jobscheduler/service/java/com/android/server/job/JobConcurrencyManager.java +34 −0 Original line number Diff line number Diff line Loading @@ -1703,6 +1703,40 @@ class JobConcurrencyManager { return foundSome; } /** * Returns the estimated network bytes if the job is running. Returns {@code null} if the job * isn't running. */ @Nullable @GuardedBy("mLock") Pair<Long, Long> getEstimatedNetworkBytesLocked(String pkgName, int uid, int jobId) { for (int i = 0; i < mActiveServices.size(); i++) { final JobServiceContext jc = mActiveServices.get(i); final JobStatus js = jc.getRunningJobLocked(); if (js != null && js.matches(uid, jobId) && js.getSourcePackageName().equals(pkgName)) { return jc.getEstimatedNetworkBytes(); } } return null; } /** * Returns the transferred network bytes if the job is running. Returns {@code null} if the job * isn't running. */ @Nullable @GuardedBy("mLock") Pair<Long, Long> getTransferredNetworkBytesLocked(String pkgName, int uid, int jobId) { for (int i = 0; i < mActiveServices.size(); i++) { final JobServiceContext jc = mActiveServices.get(i); final JobStatus js = jc.getRunningJobLocked(); if (js != null && js.matches(uid, jobId) && js.getSourcePackageName().equals(pkgName)) { return jc.getTransferredNetworkBytes(); } } return null; } @NonNull private JobServiceContext createNewJobServiceContext() { return mInjector.createJobServiceContext(mService, this, mNotificationCoordinator, Loading
apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +95 −0 Original line number Diff line number Diff line Loading @@ -86,6 +86,7 @@ import android.util.ArrayMap; import android.util.ArraySet; import android.util.IndentingPrintWriter; import android.util.Log; import android.util.Pair; import android.util.Slog; import android.util.SparseArray; import android.util.SparseBooleanArray; Loading Loading @@ -4168,6 +4169,100 @@ public class JobSchedulerService extends com.android.server.SystemService } } int getEstimatedNetworkBytes(PrintWriter pw, String pkgName, int userId, int jobId, int byteOption) { try { final int uid = AppGlobals.getPackageManager().getPackageUid(pkgName, 0, userId != UserHandle.USER_ALL ? userId : UserHandle.USER_SYSTEM); if (uid < 0) { pw.print("unknown("); pw.print(pkgName); pw.println(")"); return JobSchedulerShellCommand.CMD_ERR_NO_PACKAGE; } synchronized (mLock) { final JobStatus js = mJobs.getJobByUidAndJobId(uid, jobId); if (DEBUG) { Slog.d(TAG, "get-estimated-network-bytes " + uid + "/" + jobId + ": " + js); } if (js == null) { pw.print("unknown("); UserHandle.formatUid(pw, uid); pw.print("/jid"); pw.print(jobId); pw.println(")"); return JobSchedulerShellCommand.CMD_ERR_NO_JOB; } final long downloadBytes; final long uploadBytes; final Pair<Long, Long> bytes = mConcurrencyManager.getEstimatedNetworkBytesLocked(pkgName, uid, jobId); if (bytes == null) { downloadBytes = js.getEstimatedNetworkDownloadBytes(); uploadBytes = js.getEstimatedNetworkUploadBytes(); } else { downloadBytes = bytes.first; uploadBytes = bytes.second; } if (byteOption == JobSchedulerShellCommand.BYTE_OPTION_DOWNLOAD) { pw.println(downloadBytes); } else { pw.println(uploadBytes); } pw.println(); } } catch (RemoteException e) { // can't happen } return 0; } int getTransferredNetworkBytes(PrintWriter pw, String pkgName, int userId, int jobId, int byteOption) { try { final int uid = AppGlobals.getPackageManager().getPackageUid(pkgName, 0, userId != UserHandle.USER_ALL ? userId : UserHandle.USER_SYSTEM); if (uid < 0) { pw.print("unknown("); pw.print(pkgName); pw.println(")"); return JobSchedulerShellCommand.CMD_ERR_NO_PACKAGE; } synchronized (mLock) { final JobStatus js = mJobs.getJobByUidAndJobId(uid, jobId); if (DEBUG) { Slog.d(TAG, "get-transferred-network-bytes " + uid + "/" + jobId + ": " + js); } if (js == null) { pw.print("unknown("); UserHandle.formatUid(pw, uid); pw.print("/jid"); pw.print(jobId); pw.println(")"); return JobSchedulerShellCommand.CMD_ERR_NO_JOB; } final long downloadBytes; final long uploadBytes; final Pair<Long, Long> bytes = mConcurrencyManager.getTransferredNetworkBytesLocked(pkgName, uid, jobId); if (bytes == null) { downloadBytes = 0; uploadBytes = 0; } else { downloadBytes = bytes.first; uploadBytes = bytes.second; } if (byteOption == JobSchedulerShellCommand.BYTE_OPTION_DOWNLOAD) { pw.println(downloadBytes); } else { pw.println(uploadBytes); } pw.println(); } } catch (RemoteException e) { // can't happen } return 0; } private boolean checkRunLongJobsPermission(int packageUid, String packageName) { // Returns true if both the appop and permission are granted. return PermissionChecker.checkPermissionForPreflight(getTestableContext(), Loading
apex/jobscheduler/service/java/com/android/server/job/JobSchedulerShellCommand.java +106 −2 Original line number Diff line number Diff line Loading @@ -32,6 +32,9 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler { public static final int CMD_ERR_NO_JOB = -1001; public static final int CMD_ERR_CONSTRAINTS = -1002; static final int BYTE_OPTION_DOWNLOAD = 0; static final int BYTE_OPTION_UPLOAD = 1; JobSchedulerService mInternal; IPackageManager mPM; Loading Loading @@ -59,10 +62,18 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler { return getBatteryCharging(pw); case "get-battery-not-low": return getBatteryNotLow(pw); case "get-estimated-download-bytes": return getEstimatedNetworkBytes(pw, BYTE_OPTION_DOWNLOAD); case "get-estimated-upload-bytes": return getEstimatedNetworkBytes(pw, BYTE_OPTION_UPLOAD); case "get-storage-seq": return getStorageSeq(pw); case "get-storage-not-low": return getStorageNotLow(pw); case "get-transferred-download-bytes": return getTransferredNetworkBytes(pw, BYTE_OPTION_DOWNLOAD); case "get-transferred-upload-bytes": return getTransferredNetworkBytes(pw, BYTE_OPTION_UPLOAD); case "get-job-state": return getJobState(pw); case "heartbeat": Loading Loading @@ -304,6 +315,43 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler { return 0; } private int getEstimatedNetworkBytes(PrintWriter pw, int byteOption) throws Exception { checkPermission("get estimated bytes"); int userId = UserHandle.USER_SYSTEM; String opt; while ((opt = getNextOption()) != null) { switch (opt) { case "-u": case "--user": userId = UserHandle.parseUserArg(getNextArgRequired()); break; default: pw.println("Error: unknown option '" + opt + "'"); return -1; } } if (userId == UserHandle.USER_CURRENT) { userId = ActivityManager.getCurrentUser(); } final String pkgName = getNextArgRequired(); final String jobIdStr = getNextArgRequired(); final int jobId = Integer.parseInt(jobIdStr); final long ident = Binder.clearCallingIdentity(); try { int ret = mInternal.getEstimatedNetworkBytes(pw, pkgName, userId, jobId, byteOption); printError(ret, pkgName, userId, jobId); return ret; } finally { Binder.restoreCallingIdentity(ident); } } private int getStorageSeq(PrintWriter pw) { int seq = mInternal.getStorageSeq(); pw.println(seq); Loading @@ -316,8 +364,45 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler { return 0; } private int getTransferredNetworkBytes(PrintWriter pw, int byteOption) throws Exception { checkPermission("get transferred bytes"); int userId = UserHandle.USER_SYSTEM; String opt; while ((opt = getNextOption()) != null) { switch (opt) { case "-u": case "--user": userId = UserHandle.parseUserArg(getNextArgRequired()); break; default: pw.println("Error: unknown option '" + opt + "'"); return -1; } } if (userId == UserHandle.USER_CURRENT) { userId = ActivityManager.getCurrentUser(); } final String pkgName = getNextArgRequired(); final String jobIdStr = getNextArgRequired(); final int jobId = Integer.parseInt(jobIdStr); final long ident = Binder.clearCallingIdentity(); try { int ret = mInternal.getTransferredNetworkBytes(pw, pkgName, userId, jobId, byteOption); printError(ret, pkgName, userId, jobId); return ret; } finally { Binder.restoreCallingIdentity(ident); } } private int getJobState(PrintWriter pw) throws Exception { checkPermission("force timeout jobs"); checkPermission("get job state"); int userId = UserHandle.USER_SYSTEM; Loading Loading @@ -473,10 +558,30 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler { pw.println(" Return whether the battery is currently considered to be charging."); pw.println(" get-battery-not-low"); pw.println(" Return whether the battery is currently considered to not be low."); pw.println(" get-estimated-download-bytes [-u | --user USER_ID] PACKAGE JOB_ID"); pw.println(" Return the most recent estimated download bytes for the job."); pw.println(" Options:"); pw.println(" -u or --user: specify which user's job is to be run; the default is"); pw.println(" the primary or system user"); pw.println(" get-estimated-upload-bytes [-u | --user USER_ID] PACKAGE JOB_ID"); pw.println(" Return the most recent estimated upload bytes for the job."); pw.println(" Options:"); pw.println(" -u or --user: specify which user's job is to be run; the default is"); pw.println(" the primary or system user"); pw.println(" get-storage-seq"); pw.println(" Return the last storage update sequence number that was received."); pw.println(" get-storage-not-low"); pw.println(" Return whether storage is currently considered to not be low."); pw.println(" get-transferred-download-bytes [-u | --user USER_ID] PACKAGE JOB_ID"); pw.println(" Return the most recent transferred download bytes for the job."); pw.println(" Options:"); pw.println(" -u or --user: specify which user's job is to be run; the default is"); pw.println(" the primary or system user"); pw.println(" get-transferred-upload-bytes [-u | --user USER_ID] PACKAGE JOB_ID"); pw.println(" Return the most recent transferred upload bytes for the job."); pw.println(" Options:"); pw.println(" -u or --user: specify which user's job is to be run; the default is"); pw.println(" the primary or system user"); pw.println(" get-job-state [-u | --user USER_ID] PACKAGE JOB_ID"); pw.println(" Return the current state of a job, may be any combination of:"); pw.println(" pending: currently on the pending list, waiting to be active"); Loading @@ -493,5 +598,4 @@ public final class JobSchedulerShellCommand extends BasicShellCommandHandler { pw.println(" Trigger wireless charging dock state. Active by default."); pw.println(); } }
apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java +57 −12 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ import android.os.Trace; import android.os.UserHandle; import android.util.EventLog; import android.util.IndentingPrintWriter; import android.util.Pair; import android.util.Slog; import android.util.TimeUtils; Loading Loading @@ -171,6 +172,11 @@ public final class JobServiceContext implements ServiceConnection { /** The absolute maximum amount of time the job can run */ private long mMaxExecutionTimeMillis; private long mEstimatedDownloadBytes; private long mEstimatedUploadBytes; private long mTransferredDownloadBytes; private long mTransferredUploadBytes; /** * The stop reason for a pending cancel. If there's not pending cancel, then the value should be * {@link JobParameters#STOP_REASON_UNDEFINED}. Loading Loading @@ -306,6 +312,9 @@ public final class JobServiceContext implements ServiceConnection { mMinExecutionGuaranteeMillis = mService.getMinJobExecutionGuaranteeMs(job); mMaxExecutionTimeMillis = Math.max(mService.getMaxJobExecutionTimeMs(job), mMinExecutionGuaranteeMillis); mEstimatedDownloadBytes = job.getEstimatedNetworkDownloadBytes(); mEstimatedUploadBytes = job.getEstimatedNetworkUploadBytes(); mTransferredDownloadBytes = mTransferredUploadBytes = 0; final long whenDeferred = job.getWhenStandbyDeferred(); if (whenDeferred > 0) { Loading Loading @@ -524,6 +533,16 @@ public final class JobServiceContext implements ServiceConnection { return false; } @GuardedBy("mLock") Pair<Long, Long> getEstimatedNetworkBytes() { return Pair.create(mEstimatedDownloadBytes, mEstimatedUploadBytes); } @GuardedBy("mLock") Pair<Long, Long> getTransferredNetworkBytes() { return Pair.create(mTransferredDownloadBytes, mTransferredUploadBytes); } void doJobFinished(JobCallback cb, int jobId, boolean reschedule) { final long ident = Binder.clearCallingIdentity(); try { Loading @@ -541,14 +560,26 @@ public final class JobServiceContext implements ServiceConnection { } } private void doAcknowledgeGetTransferredDownloadBytesMessage(JobCallback jobCallback, int jobId, private void doAcknowledgeGetTransferredDownloadBytesMessage(JobCallback cb, int jobId, int workId, @BytesLong long transferredBytes) { // TODO(255393346): Make sure apps call this appropriately and monitor for abuse synchronized (mLock) { if (!verifyCallerLocked(cb)) { return; } mTransferredDownloadBytes = transferredBytes; } } private void doAcknowledgeGetTransferredUploadBytesMessage(JobCallback jobCallback, int jobId, private void doAcknowledgeGetTransferredUploadBytesMessage(JobCallback cb, int jobId, int workId, @BytesLong long transferredBytes) { // TODO(255393346): Make sure apps call this appropriately and monitor for abuse synchronized (mLock) { if (!verifyCallerLocked(cb)) { return; } mTransferredUploadBytes = transferredBytes; } } void doAcknowledgeStopMessage(JobCallback cb, int jobId, boolean reschedule) { Loading Loading @@ -603,6 +634,30 @@ public final class JobServiceContext implements ServiceConnection { } } private void doUpdateEstimatedNetworkBytes(JobCallback cb, int jobId, @Nullable JobWorkItem item, long downloadBytes, long uploadBytes) { // TODO(255393346): Make sure apps call this appropriately and monitor for abuse synchronized (mLock) { if (!verifyCallerLocked(cb)) { return; } mEstimatedDownloadBytes = downloadBytes; mEstimatedUploadBytes = uploadBytes; } } private void doUpdateTransferredNetworkBytes(JobCallback cb, int jobId, @Nullable JobWorkItem item, long downloadBytes, long uploadBytes) { // TODO(255393346): Make sure apps call this appropriately and monitor for abuse synchronized (mLock) { if (!verifyCallerLocked(cb)) { return; } mTransferredDownloadBytes = downloadBytes; mTransferredUploadBytes = uploadBytes; } } private void doSetNotification(JobCallback cb, int jodId, int notificationId, Notification notification, int jobEndNotificationPolicy) { final int callingPid = Binder.getCallingPid(); Loading @@ -627,16 +682,6 @@ 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 Loading