Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 73ce8d4e authored by Kweku Adams's avatar Kweku Adams Committed by Android (Google) Code Review
Browse files

Merge "Adjust execution limits for new job types."

parents eae34494 6a1058da
Loading
Loading
Loading
Loading
+200 −15
Original line number Diff line number Diff line
@@ -266,6 +266,8 @@ public class JobSchedulerService extends com.android.server.SystemService
    private final List<RestrictingController> mRestrictiveControllers;
    /** Need direct access to this for testing. */
    private final StorageController mStorageController;
    /** Needed to get estimated transfer time. */
    private final ConnectivityController mConnectivityController;
    /** Need directly for sending uid state changes */
    private final DeviceIdleJobsController mDeviceIdleJobsController;
    /** Needed to get next estimated launch time. */
@@ -464,6 +466,13 @@ public class JobSchedulerService extends com.android.server.SystemService
                        case Constants.KEY_RUNTIME_MIN_GUARANTEE_MS:
                        case Constants.KEY_RUNTIME_MIN_EJ_GUARANTEE_MS:
                        case Constants.KEY_RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS:
                        case Constants.KEY_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS:
                        case Constants.KEY_RUNTIME_DATA_TRANSFER_LIMIT_MS:
                        case Constants.KEY_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS:
                        case Constants.KEY_RUNTIME_USER_INITIATED_LIMIT_MS:
                        case Constants.KEY_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR:
                        case Constants.KEY_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS:
                        case Constants.KEY_RUNTIME_USER_INITIATED_DATA_TRANSFER_LIMIT_MS:
                            if (!runtimeUpdated) {
                                mConstants.updateRuntimeConstantsLocked();
                                runtimeUpdated = true;
@@ -555,6 +564,21 @@ public class JobSchedulerService extends com.android.server.SystemService
        private static final String KEY_RUNTIME_MIN_EJ_GUARANTEE_MS = "runtime_min_ej_guarantee_ms";
        private static final String KEY_RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS =
                "runtime_min_high_priority_guarantee_ms";
        private static final String KEY_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS =
                "runtime_min_data_transfer_guarantee_ms";
        private static final String KEY_RUNTIME_DATA_TRANSFER_LIMIT_MS =
                "runtime_data_transfer_limit_ms";
        private static final String KEY_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS =
                "runtime_min_user_initiated_guarantee_ms";
        private static final String KEY_RUNTIME_USER_INITIATED_LIMIT_MS =
                "runtime_user_initiated_limit_ms";
        private static final String
                KEY_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR =
                "runtime_min_user_initiated_data_transfer_guarantee_buffer_factor";
        private static final String KEY_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS =
                "runtime_min_user_initiated_data_transfer_guarantee_ms";
        private static final String KEY_RUNTIME_USER_INITIATED_DATA_TRANSFER_LIMIT_MS =
                "runtime_user_initiated_data_transfer_limit_ms";

        private static final String KEY_PERSIST_IN_SPLIT_FILES = "persist_in_split_files";

@@ -584,6 +608,20 @@ public class JobSchedulerService extends com.android.server.SystemService
        public static final long DEFAULT_RUNTIME_MIN_EJ_GUARANTEE_MS = 3 * MINUTE_IN_MILLIS;
        @VisibleForTesting
        static final long DEFAULT_RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS = 5 * MINUTE_IN_MILLIS;
        public static final long DEFAULT_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS =
                DEFAULT_RUNTIME_MIN_GUARANTEE_MS;
        public static final long DEFAULT_RUNTIME_DATA_TRANSFER_LIMIT_MS =
                DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS;
        public static final long DEFAULT_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS =
                Math.max(10 * MINUTE_IN_MILLIS, DEFAULT_RUNTIME_MIN_GUARANTEE_MS);
        public static final long DEFAULT_RUNTIME_USER_INITIATED_LIMIT_MS =
                Math.max(60 * MINUTE_IN_MILLIS, DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS);
        public static final float
                DEFAULT_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR = 1.35f;
        public static final long DEFAULT_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS =
                Math.max(10 * MINUTE_IN_MILLIS, DEFAULT_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS);
        public static final long DEFAULT_RUNTIME_USER_INITIATED_DATA_TRANSFER_LIMIT_MS =
                Math.max(Long.MAX_VALUE, DEFAULT_RUNTIME_USER_INITIATED_LIMIT_MS);
        static final boolean DEFAULT_PERSIST_IN_SPLIT_FILES = true;
        private static final boolean DEFAULT_USE_TARE_POLICY = false;

@@ -699,6 +737,49 @@ public class JobSchedulerService extends com.android.server.SystemService
        public long RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS =
                DEFAULT_RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS;

        /**
         * The minimum amount of time we try to guarantee normal data transfer jobs will run for.
         */
        public long RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS =
                DEFAULT_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS;

        /**
         * The maximum amount of time we will let a normal data transfer job run for. This will only
         * apply if there are no other limits that apply to the specific data transfer job.
         */
        public long RUNTIME_DATA_TRANSFER_LIMIT_MS = DEFAULT_RUNTIME_DATA_TRANSFER_LIMIT_MS;

        /**
         * The minimum amount of time we try to guarantee normal user-initiated jobs will run for.
         */
        public long RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS =
                DEFAULT_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS;

        /**
         * The maximum amount of time we will let a user-initiated job run for. This will only
         * apply if there are no other limits that apply to the specific user-initiated job.
         */
        public long RUNTIME_USER_INITIATED_LIMIT_MS = DEFAULT_RUNTIME_USER_INITIATED_LIMIT_MS;

        /**
         * A factor to apply to estimated transfer durations for user-initiated data transfer jobs
         * so that we give some extra time for unexpected situations. This will be at least 1 and
         * so can just be multiplied with the original value to get the final value.
         */
        public float RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR =
                DEFAULT_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR;

        /**
         * The minimum amount of time we try to guarantee user-initiated data transfer jobs
         * will run for.
         */
        public long RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS =
                DEFAULT_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS;

        /** The maximum amount of time we will let a user-initiated data transfer job run for. */
        public long RUNTIME_USER_INITIATED_DATA_TRANSFER_LIMIT_MS =
                DEFAULT_RUNTIME_USER_INITIATED_DATA_TRANSFER_LIMIT_MS;

        /**
         * Whether to persist jobs in split files (by UID). If false, all persisted jobs will be
         * saved in a single file.
@@ -801,7 +882,14 @@ public class JobSchedulerService extends com.android.server.SystemService
                    DeviceConfig.NAMESPACE_JOB_SCHEDULER,
                    KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                    KEY_RUNTIME_MIN_GUARANTEE_MS, KEY_RUNTIME_MIN_EJ_GUARANTEE_MS,
                    KEY_RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS);
                    KEY_RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS,
                    KEY_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR,
                    KEY_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
                    KEY_RUNTIME_DATA_TRANSFER_LIMIT_MS,
                    KEY_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS,
                    KEY_RUNTIME_USER_INITIATED_LIMIT_MS,
                    KEY_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS,
                    KEY_RUNTIME_USER_INITIATED_DATA_TRANSFER_LIMIT_MS);

            // Make sure min runtime for regular jobs is at least 10 minutes.
            RUNTIME_MIN_GUARANTEE_MS = Math.max(10 * MINUTE_IN_MILLIS,
@@ -819,6 +907,49 @@ public class JobSchedulerService extends com.android.server.SystemService
            RUNTIME_FREE_QUOTA_MAX_LIMIT_MS = Math.max(RUNTIME_MIN_GUARANTEE_MS,
                    properties.getLong(KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                            DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS));
            // Make sure min runtime is at least as long as regular jobs.
            RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS = Math.max(RUNTIME_MIN_GUARANTEE_MS,
                    properties.getLong(
                            KEY_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
                            DEFAULT_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS));
            // Max limit should be at least the min guarantee AND the free quota.
            RUNTIME_DATA_TRANSFER_LIMIT_MS = Math.max(RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                    Math.max(RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
                            properties.getLong(
                                    KEY_RUNTIME_DATA_TRANSFER_LIMIT_MS,
                                    DEFAULT_RUNTIME_DATA_TRANSFER_LIMIT_MS)));
            // Make sure min runtime is at least as long as regular jobs.
            RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS = Math.max(RUNTIME_MIN_GUARANTEE_MS,
                    properties.getLong(
                            KEY_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS,
                            DEFAULT_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS));
            // Max limit should be at least the min guarantee AND the free quota.
            RUNTIME_USER_INITIATED_LIMIT_MS = Math.max(RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                    Math.max(RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS,
                            properties.getLong(
                                    KEY_RUNTIME_USER_INITIATED_LIMIT_MS,
                                    DEFAULT_RUNTIME_USER_INITIATED_LIMIT_MS)));
            // The buffer factor should be at least 1 (so we don't decrease the time).
            RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR = Math.max(1,
                    properties.getFloat(
                            KEY_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR,
                            DEFAULT_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR
                    ));
            // Make sure min runtime is at least as long as other user-initiated jobs.
            RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS = Math.max(
                    RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS,
                    properties.getLong(
                            KEY_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS,
                            DEFAULT_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS));
            // Data transfer requires RUN_LONG_JOBS permission, so the upper limit will be higher
            // than other jobs.
            // Max limit should be the min guarantee and the max of other user-initiated jobs.
            RUNTIME_USER_INITIATED_DATA_TRANSFER_LIMIT_MS = Math.max(
                    RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS,
                    Math.max(RUNTIME_USER_INITIATED_LIMIT_MS,
                            properties.getLong(
                                    KEY_RUNTIME_USER_INITIATED_DATA_TRANSFER_LIMIT_MS,
                                    DEFAULT_RUNTIME_USER_INITIATED_DATA_TRANSFER_LIMIT_MS)));
        }

        private boolean updateTareSettingsLocked(boolean isTareEnabled) {
@@ -867,6 +998,20 @@ public class JobSchedulerService extends com.android.server.SystemService
                    RUNTIME_MIN_HIGH_PRIORITY_GUARANTEE_MS).println();
            pw.print(KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS, RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)
                    .println();
            pw.print(KEY_RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS,
                    RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS).println();
            pw.print(KEY_RUNTIME_DATA_TRANSFER_LIMIT_MS,
                    RUNTIME_DATA_TRANSFER_LIMIT_MS).println();
            pw.print(KEY_RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS,
                    RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS).println();
            pw.print(KEY_RUNTIME_USER_INITIATED_LIMIT_MS,
                    RUNTIME_USER_INITIATED_LIMIT_MS).println();
            pw.print(KEY_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR,
                    RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR).println();
            pw.print(KEY_RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS,
                    RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS).println();
            pw.print(KEY_RUNTIME_USER_INITIATED_DATA_TRANSFER_LIMIT_MS,
                    RUNTIME_USER_INITIATED_DATA_TRANSFER_LIMIT_MS).println();

            pw.print(KEY_PERSIST_IN_SPLIT_FILES, PERSIST_IN_SPLIT_FILES).println();

@@ -1858,9 +2003,9 @@ public class JobSchedulerService extends com.android.server.SystemService
        final FlexibilityController flexibilityController =
                new FlexibilityController(this, mPrefetchController);
        mControllers.add(flexibilityController);
        final ConnectivityController connectivityController =
        mConnectivityController =
                new ConnectivityController(this, flexibilityController);
        mControllers.add(connectivityController);
        mControllers.add(mConnectivityController);
        mControllers.add(new TimeController(this));
        final IdleController idleController = new IdleController(this, flexibilityController);
        mControllers.add(idleController);
@@ -1876,16 +2021,16 @@ public class JobSchedulerService extends com.android.server.SystemService
        mDeviceIdleJobsController = new DeviceIdleJobsController(this);
        mControllers.add(mDeviceIdleJobsController);
        mQuotaController =
                new QuotaController(this, backgroundJobsController, connectivityController);
                new QuotaController(this, backgroundJobsController, mConnectivityController);
        mControllers.add(mQuotaController);
        mControllers.add(new ComponentController(this));
        mTareController =
                new TareController(this, backgroundJobsController, connectivityController);
                new TareController(this, backgroundJobsController, mConnectivityController);
        mControllers.add(mTareController);

        mRestrictiveControllers = new ArrayList<>();
        mRestrictiveControllers.add(batteryController);
        mRestrictiveControllers.add(connectivityController);
        mRestrictiveControllers.add(mConnectivityController);
        mRestrictiveControllers.add(idleController);

        // Create restrictions
@@ -3028,7 +3173,30 @@ public class JobSchedulerService extends com.android.server.SystemService
    /** Returns the minimum amount of time we should let this job run before timing out. */
    public long getMinJobExecutionGuaranteeMs(JobStatus job) {
        synchronized (mLock) {
            if (job.shouldTreatAsExpeditedJob()) {
            final boolean shouldTreatAsDataTransfer = job.getJob().isDataTransfer()
                    && checkRunLongJobsPermission(job.getSourceUid(), job.getSourcePackageName());
            if (job.shouldTreatAsUserInitiated()) {
                if (shouldTreatAsDataTransfer) {
                    final long estimatedTransferTimeMs =
                            mConnectivityController.getEstimatedTransferTimeMs(job);
                    if (estimatedTransferTimeMs == ConnectivityController.UNKNOWN_TIME) {
                        return mConstants.RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS;
                    }
                    // Try to give the job at least as much time as we think the transfer will take,
                    // but cap it at the maximum limit
                    final long factoredTransferTimeMs = (long) (estimatedTransferTimeMs
                            * mConstants
                            .RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_BUFFER_FACTOR);
                    return Math.min(mConstants.RUNTIME_USER_INITIATED_DATA_TRANSFER_LIMIT_MS,
                            Math.max(factoredTransferTimeMs,
                                    mConstants.RUNTIME_MIN_USER_INITIATED_DATA_TRANSFER_GUARANTEE_MS
                            ));
                }
                return mConstants.RUNTIME_MIN_USER_INITIATED_GUARANTEE_MS;
            } else if (shouldTreatAsDataTransfer) {
                // For now, don't increase a bg data transfer's minimum guarantee.
                return mConstants.RUNTIME_MIN_DATA_TRANSFER_GUARANTEE_MS;
            } else if (job.shouldTreatAsExpeditedJob()) {
                // Don't guarantee RESTRICTED jobs more than 5 minutes.
                return job.getEffectiveStandbyBucket() != RESTRICTED_INDEX
                        ? mConstants.RUNTIME_MIN_EJ_GUARANTEE_MS
@@ -3044,6 +3212,16 @@ public class JobSchedulerService extends com.android.server.SystemService
    /** Returns the maximum amount of time this job could run for. */
    public long getMaxJobExecutionTimeMs(JobStatus job) {
        synchronized (mLock) {
            final boolean shouldTreatAsDataTransfer = job.getJob().isDataTransfer()
                    && checkRunLongJobsPermission(job.getSourceUid(), job.getSourcePackageName());
            if (job.shouldTreatAsUserInitiated()) {
                if (shouldTreatAsDataTransfer) {
                    return mConstants.RUNTIME_USER_INITIATED_DATA_TRANSFER_LIMIT_MS;
                }
                return mConstants.RUNTIME_USER_INITIATED_LIMIT_MS;
            } else if (shouldTreatAsDataTransfer) {
                return mConstants.RUNTIME_DATA_TRANSFER_LIMIT_MS;
            }
            return Math.min(mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS,
                    mConstants.USE_TARE_POLICY
                            ? mTareController.getMaxJobExecutionTimeMsLocked(job)
@@ -3703,13 +3881,6 @@ public class JobSchedulerService extends com.android.server.SystemService
            return checkRunLongJobsPermission(uid, packageName);
        }

        private boolean checkRunLongJobsPermission(int packageUid, String packageName) {
            // Returns true if both the appop and permission are granted.
            return PermissionChecker.checkPermissionForPreflight(getContext(),
                    android.Manifest.permission.RUN_LONG_JOBS, PermissionChecker.PID_UNKNOWN,
                    packageUid, packageName) == PermissionChecker.PERMISSION_GRANTED;
        }

        /**
         * "dumpsys" infrastructure
         */
@@ -3985,13 +4156,27 @@ public class JobSchedulerService extends com.android.server.SystemService
        }
    }

    private boolean checkRunLongJobsPermission(int packageUid, String packageName) {
        // Returns true if both the appop and permission are granted.
        return PermissionChecker.checkPermissionForPreflight(getTestableContext(),
                android.Manifest.permission.RUN_LONG_JOBS, PermissionChecker.PID_UNKNOWN,
                packageUid, packageName) == PermissionChecker.PERMISSION_GRANTED;
    }

    @VisibleForTesting
    protected ConnectivityController getConnectivityController() {
        return mConnectivityController;
    }

    // Shell command infrastructure
    int getJobState(PrintWriter pw, String pkgName, int userId, int jobId) {
        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(")");
                pw.print("unknown(");
                pw.print(pkgName);
                pw.println(")");
                return JobSchedulerShellCommand.CMD_ERR_NO_PACKAGE;
            }

+50 −13
Original line number Diff line number Diff line
@@ -42,7 +42,6 @@ import android.telephony.TelephonyManager;
import android.text.format.DateUtils;
import android.util.ArrayMap;
import android.util.ArraySet;
import android.util.DataUnit;
import android.util.IndentingPrintWriter;
import android.util.Log;
import android.util.Pools;
@@ -82,6 +81,8 @@ public final class ConnectivityController extends RestrictingController implemen
    private static final boolean DEBUG = JobSchedulerService.DEBUG
            || Log.isLoggable(TAG, Log.DEBUG);

    public static final long UNKNOWN_TIME = -1L;

    // The networking stack has a hard limit so we can't make this configurable.
    private static final int MAX_NETWORK_CALLBACKS = 125;
    /**
@@ -570,9 +571,8 @@ public final class ConnectivityController extends RestrictingController implemen
            // If we don't know the bandwidth, all we can do is hope the job finishes the minimum
            // chunk in time.
            if (bandwidthDown > 0) {
                // Divide by 8 to convert bits to bytes.
                final long estimatedMillis = ((minimumChunkBytes * DateUtils.SECOND_IN_MILLIS)
                        / (DataUnit.KIBIBYTES.toBytes(bandwidthDown) / 8));
                final long estimatedMillis =
                        calculateTransferTimeMs(minimumChunkBytes, bandwidthDown);
                if (estimatedMillis > maxJobExecutionTimeMs) {
                    // If we'd never finish the minimum chunk before the timeout, we'd be insane!
                    Slog.w(TAG, "Minimum chunk " + minimumChunkBytes + " bytes over "
@@ -585,9 +585,8 @@ public final class ConnectivityController extends RestrictingController implemen
            final long bandwidthUp = capabilities.getLinkUpstreamBandwidthKbps();
            // If we don't know the bandwidth, all we can do is hope the job finishes in time.
            if (bandwidthUp > 0) {
                // Divide by 8 to convert bits to bytes.
                final long estimatedMillis = ((minimumChunkBytes * DateUtils.SECOND_IN_MILLIS)
                        / (DataUnit.KIBIBYTES.toBytes(bandwidthUp) / 8));
                final long estimatedMillis =
                        calculateTransferTimeMs(minimumChunkBytes, bandwidthUp);
                if (estimatedMillis > maxJobExecutionTimeMs) {
                    // If we'd never finish the minimum chunk before the timeout, we'd be insane!
                    Slog.w(TAG, "Minimum chunk " + minimumChunkBytes + " bytes over " + bandwidthUp
@@ -615,9 +614,7 @@ public final class ConnectivityController extends RestrictingController implemen
            final long bandwidth = capabilities.getLinkDownstreamBandwidthKbps();
            // If we don't know the bandwidth, all we can do is hope the job finishes in time.
            if (bandwidth > 0) {
                // Divide by 8 to convert bits to bytes.
                final long estimatedMillis = ((downloadBytes * DateUtils.SECOND_IN_MILLIS)
                        / (DataUnit.KIBIBYTES.toBytes(bandwidth) / 8));
                final long estimatedMillis = calculateTransferTimeMs(downloadBytes, bandwidth);
                if (estimatedMillis > maxJobExecutionTimeMs) {
                    // If we'd never finish before the timeout, we'd be insane!
                    Slog.w(TAG, "Estimated " + downloadBytes + " download bytes over " + bandwidth
@@ -633,9 +630,7 @@ public final class ConnectivityController extends RestrictingController implemen
            final long bandwidth = capabilities.getLinkUpstreamBandwidthKbps();
            // If we don't know the bandwidth, all we can do is hope the job finishes in time.
            if (bandwidth > 0) {
                // Divide by 8 to convert bits to bytes.
                final long estimatedMillis = ((uploadBytes * DateUtils.SECOND_IN_MILLIS)
                        / (DataUnit.KIBIBYTES.toBytes(bandwidth) / 8));
                final long estimatedMillis = calculateTransferTimeMs(uploadBytes, bandwidth);
                if (estimatedMillis > maxJobExecutionTimeMs) {
                    // If we'd never finish before the timeout, we'd be insane!
                    Slog.w(TAG, "Estimated " + uploadBytes + " upload bytes over " + bandwidth
@@ -649,6 +644,48 @@ public final class ConnectivityController extends RestrictingController implemen
        return false;
    }

    /**
     * Return the estimated amount of time this job will be transferring data,
     * based on the current network speed.
     */
    public long getEstimatedTransferTimeMs(JobStatus jobStatus) {
        final long downloadBytes = jobStatus.getEstimatedNetworkDownloadBytes();
        final long uploadBytes = jobStatus.getEstimatedNetworkUploadBytes();
        if (downloadBytes == JobInfo.NETWORK_BYTES_UNKNOWN
                && uploadBytes == JobInfo.NETWORK_BYTES_UNKNOWN) {
            return UNKNOWN_TIME;
        }
        if (jobStatus.network == null) {
            // This job doesn't have a network assigned.
            return UNKNOWN_TIME;
        }
        NetworkCapabilities capabilities = getNetworkCapabilities(jobStatus.network);
        if (capabilities == null) {
            return UNKNOWN_TIME;
        }
        final long estimatedDownloadTimeMs = calculateTransferTimeMs(downloadBytes,
                capabilities.getLinkDownstreamBandwidthKbps());
        final long estimatedUploadTimeMs = calculateTransferTimeMs(uploadBytes,
                capabilities.getLinkUpstreamBandwidthKbps());
        if (estimatedDownloadTimeMs == UNKNOWN_TIME) {
            return estimatedUploadTimeMs;
        } else if (estimatedUploadTimeMs == UNKNOWN_TIME) {
            return estimatedDownloadTimeMs;
        }
        return estimatedDownloadTimeMs + estimatedUploadTimeMs;
    }

    @VisibleForTesting
    static long calculateTransferTimeMs(long transferBytes, long bandwidthKbps) {
        if (transferBytes == JobInfo.NETWORK_BYTES_UNKNOWN || bandwidthKbps <= 0) {
            return UNKNOWN_TIME;
        }
        return (transferBytes * DateUtils.SECOND_IN_MILLIS)
                // Multiply by 1000 to convert kilobits to bits.
                // Divide by 8 to convert bits to bytes.
                / (bandwidthKbps * 1000 / 8);
    }

    private static boolean isCongestionDelayed(JobStatus jobStatus, Network network,
            NetworkCapabilities capabilities, Constants constants) {
        // If network is congested, and job is less than 50% through the
+9 −0
Original line number Diff line number Diff line
@@ -1344,6 +1344,15 @@ public final class JobStatus {
        return mExpeditedQuotaApproved && mExpeditedTareApproved && isRequestedExpeditedJob();
    }

    /**
     * @return true if the job was scheduled as a user-initiated job and it hasn't been downgraded
     * for any reason.
     */
    public boolean shouldTreatAsUserInitiated() {
        // TODO(248386641): implement
        return false;
    }

    /**
     * Return a summary that uniquely identifies the underlying job.
     */
+109 −0

File changed.

Preview size limit exceeded, changes collapsed.

+86 −8

File changed.

Preview size limit exceeded, changes collapsed.