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

Commit 2b353f86 authored by Kweku Adams's avatar Kweku Adams
Browse files

Add permission check to setBias.

The job bias is meant to be an indication of the job type and the state
the app was in when the job was scheduled. This can only be determined
by the system and certain privileged apps. The job bias can affect some
things such as which system health factors are taken into consideration
when deciding when to run a job. Given all this, the bias should only be
set by the system or certain privileged apps. Note the required permission
on the hidden API and enforce that the calling app has the permission
when the job is scheduled.

Bug: 300477393
Test: atest CtsJobSchedulerTestCases:JobInfoTest
Test: atest CtsSyncManagerTestCases
Test: atest DownloadManagerApi28Test
Test: atest FrameworksServicesTests:BiasSchedulingTest
Change-Id: I1cb37eafc42f961dee9d2e7bc7d496a31dff31f4
parent 8943b729
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -1265,6 +1265,7 @@ public class JobInfo implements Parcelable {

        /** @hide */
        @NonNull
        @RequiresPermission(android.Manifest.permission.UPDATE_DEVICE_STATS)
        public Builder setBias(int bias) {
            mBias = bias;
            return this;
+33 −0
Original line number Diff line number Diff line
@@ -202,6 +202,15 @@ public class JobSchedulerService extends com.android.server.SystemService
    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.TIRAMISU)
    static final long REQUIRE_NETWORK_PERMISSIONS_FOR_CONNECTIVITY_JOBS = 271850009L;

    /**
     * Throw an exception when biases are set by an unsupported client.
     *
     * @hide
     */
    @ChangeId
    @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
    public static final long THROW_ON_UNSUPPORTED_BIAS_USAGE = 300477393L;

    @VisibleForTesting(visibility = VisibleForTesting.Visibility.PACKAGE)
    public static Clock sSystemClock = Clock.systemUTC();

@@ -4331,6 +4340,24 @@ public class JobSchedulerService extends com.android.server.SystemService
            }
        }

        private JobInfo enforceBuilderApiPermissions(int uid, int pid, JobInfo job) {
            if (job.getBias() != JobInfo.BIAS_DEFAULT
                        && !hasPermission(uid, pid, Manifest.permission.UPDATE_DEVICE_STATS)) {
                if (CompatChanges.isChangeEnabled(THROW_ON_UNSUPPORTED_BIAS_USAGE, uid)) {
                    throw new SecurityException("Apps may not call setBias()");
                } else {
                    // We can't throw the exception. Log the issue and modify the job to remove
                    // the invalid value.
                    Slog.w(TAG, "Uid " + uid + " set bias on its job");
                    return new JobInfo.Builder(job)
                            .setBias(JobInfo.BIAS_DEFAULT)
                            .build(false, false);
                }
            }

            return job;
        }

        private boolean canPersistJobs(int pid, int uid) {
            // Persisting jobs is tantamount to running at boot, so we permit
            // it when the app has declared that it uses the RECEIVE_BOOT_COMPLETED
@@ -4512,6 +4539,8 @@ public class JobSchedulerService extends com.android.server.SystemService

            namespace = validateNamespace(namespace);

            job = enforceBuilderApiPermissions(uid, pid, job);

            final long ident = Binder.clearCallingIdentity();
            try {
                return JobSchedulerService.this.scheduleAsPackage(job, null, uid, null, userId,
@@ -4543,6 +4572,8 @@ public class JobSchedulerService extends com.android.server.SystemService

            namespace = validateNamespace(namespace);

            job = enforceBuilderApiPermissions(uid, pid, job);

            final long ident = Binder.clearCallingIdentity();
            try {
                return JobSchedulerService.this.scheduleAsPackage(job, work, uid, null, userId,
@@ -4582,6 +4613,8 @@ public class JobSchedulerService extends com.android.server.SystemService

            namespace = validateNamespace(namespace);

            job = enforceBuilderApiPermissions(callerUid, callerPid, job);

            final long ident = Binder.clearCallingIdentity();
            try {
                return JobSchedulerService.this.scheduleAsPackage(job, null, callerUid,