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

Commit 600e89cf authored by android-build-team Robot's avatar android-build-team Robot
Browse files

Snap for 6676242 from e076abfa to rvc-qpr1-release

Change-Id: I642e886b63d6294cd10a3bcefbe83950833e9da0
parents 7ea97589 e076abfa
Loading
Loading
Loading
Loading
+18 −6
Original line number Original line Diff line number Diff line
@@ -59,9 +59,9 @@ import java.util.List;
 *
 *
 * <p class="caution"><strong>Note:</strong> Beginning with API 30
 * <p class="caution"><strong>Note:</strong> Beginning with API 30
 * ({@link android.os.Build.VERSION_CODES#R}), JobScheduler will throttle runaway applications.
 * ({@link android.os.Build.VERSION_CODES#R}), JobScheduler will throttle runaway applications.
 * Calling {@link #schedule(JobInfo)} and other such methods with very high frequency is indicative
 * Calling {@link #schedule(JobInfo)} and other such methods with very high frequency can have a
 * of an app bug and so, to make sure the system doesn't get overwhelmed, JobScheduler will begin
 * high cost and so, to make sure the system doesn't get overwhelmed, JobScheduler will begin
 * to throttle apps that show buggy behavior, regardless of target SDK version.
 * to throttle apps, regardless of target SDK version.
 */
 */
@SystemService(Context.JOB_SCHEDULER_SERVICE)
@SystemService(Context.JOB_SCHEDULER_SERVICE)
public abstract class JobScheduler {
public abstract class JobScheduler {
@@ -74,9 +74,16 @@ public abstract class JobScheduler {
    public @interface Result {}
    public @interface Result {}


    /**
    /**
     * Returned from {@link #schedule(JobInfo)} when an invalid parameter was supplied. This can occur
     * Returned from {@link #schedule(JobInfo)} if a job wasn't scheduled successfully. Scheduling
     * if the run-time for your job is too short, or perhaps the system can't resolve the
     * can fail for a variety of reasons, including, but not limited to:
     * requisite {@link JobService} in your package.
     * <ul>
     * <li>an invalid parameter was supplied (eg. the run-time for your job is too short, or the
     * system can't resolve the requisite {@link JobService} in your package)</li>
     * <li>the app has too many jobs scheduled</li>
     * <li>the app has tried to schedule too many jobs in a short amount of time</li>
     * </ul>
     * Attempting to schedule the job again immediately after receiving this result will not
     * guarantee a successful schedule.
     */
     */
    public static final int RESULT_FAILURE = 0;
    public static final int RESULT_FAILURE = 0;
    /**
    /**
@@ -89,6 +96,11 @@ public abstract class JobScheduler {
     * ID with the new information in the {@link JobInfo}.  If a job with the given ID is currently
     * ID with the new information in the {@link JobInfo}.  If a job with the given ID is currently
     * running, it will be stopped.
     * running, it will be stopped.
     *
     *
     * <p class="caution"><strong>Note:</strong> Scheduling a job can have a high cost, even if it's
     * rescheduling the same job and the job didn't execute, especially on platform versions before
     * version {@link android.os.Build.VERSION_CODES#Q}. As such, the system may throttle calls to
     * this API if calls are made too frequently in a short amount of time.
     *
     * @param job The job you wish scheduled. See
     * @param job The job you wish scheduled. See
     * {@link android.app.job.JobInfo.Builder JobInfo.Builder} for more detail on the sorts of jobs
     * {@link android.app.job.JobInfo.Builder JobInfo.Builder} for more detail on the sorts of jobs
     * you can schedule.
     * you can schedule.
+57 −13
Original line number Original line Diff line number Diff line
@@ -255,6 +255,18 @@ public class JobSchedulerService extends com.android.server.SystemService


    private final CountQuotaTracker mQuotaTracker;
    private final CountQuotaTracker mQuotaTracker;
    private static final String QUOTA_TRACKER_SCHEDULE_PERSISTED_TAG = ".schedulePersisted()";
    private static final String QUOTA_TRACKER_SCHEDULE_PERSISTED_TAG = ".schedulePersisted()";
    private static final String QUOTA_TRACKER_SCHEDULE_LOGGED =
            ".schedulePersisted out-of-quota logged";
    private static final Category QUOTA_TRACKER_CATEGORY_SCHEDULE_PERSISTED = new Category(
            ".schedulePersisted()");
    private static final Category QUOTA_TRACKER_CATEGORY_SCHEDULE_LOGGED = new Category(
            ".schedulePersisted out-of-quota logged");
    private static final Categorizer QUOTA_CATEGORIZER = (userId, packageName, tag) -> {
        if (QUOTA_TRACKER_SCHEDULE_PERSISTED_TAG.equals(tag)) {
            return QUOTA_TRACKER_CATEGORY_SCHEDULE_PERSISTED;
        }
        return QUOTA_TRACKER_CATEGORY_SCHEDULE_LOGGED;
    };


    /**
    /**
     * Queue of pending jobs. The JobServiceContext class will receive jobs from this list
     * Queue of pending jobs. The JobServiceContext class will receive jobs from this list
@@ -271,6 +283,7 @@ public class JobSchedulerService extends com.android.server.SystemService
    ActivityManagerInternal mActivityManagerInternal;
    ActivityManagerInternal mActivityManagerInternal;
    IBatteryStats mBatteryStats;
    IBatteryStats mBatteryStats;
    DeviceIdleInternal mLocalDeviceIdleController;
    DeviceIdleInternal mLocalDeviceIdleController;
    @VisibleForTesting
    AppStateTracker mAppStateTracker;
    AppStateTracker mAppStateTracker;
    final UsageStatsManagerInternal mUsageStats;
    final UsageStatsManagerInternal mUsageStats;
    private final AppStandbyInternal mAppStandbyInternal;
    private final AppStandbyInternal mAppStandbyInternal;
@@ -343,10 +356,7 @@ public class JobSchedulerService extends com.android.server.SystemService
                        final StateController sc = mControllers.get(controller);
                        final StateController sc = mControllers.get(controller);
                        sc.onConstantsUpdatedLocked();
                        sc.onConstantsUpdatedLocked();
                    }
                    }
                    mQuotaTracker.setEnabled(mConstants.ENABLE_API_QUOTAS);
                    updateQuotaTracker();
                    mQuotaTracker.setCountLimit(Category.SINGLE_CATEGORY,
                            mConstants.API_QUOTA_SCHEDULE_COUNT,
                            mConstants.API_QUOTA_SCHEDULE_WINDOW_MS);
                } catch (IllegalArgumentException e) {
                } catch (IllegalArgumentException e) {
                    // Failed to parse the settings string, log this and move on
                    // Failed to parse the settings string, log this and move on
                    // with defaults.
                    // with defaults.
@@ -356,6 +366,14 @@ public class JobSchedulerService extends com.android.server.SystemService
        }
        }
    }
    }


    @VisibleForTesting
    void updateQuotaTracker() {
        mQuotaTracker.setEnabled(mConstants.ENABLE_API_QUOTAS);
        mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_SCHEDULE_PERSISTED,
                mConstants.API_QUOTA_SCHEDULE_COUNT,
                mConstants.API_QUOTA_SCHEDULE_WINDOW_MS);
    }

    static class MaxJobCounts {
    static class MaxJobCounts {
        private final KeyValueListParser.IntValue mTotal;
        private final KeyValueListParser.IntValue mTotal;
        private final KeyValueListParser.IntValue mMaxBg;
        private final KeyValueListParser.IntValue mMaxBg;
@@ -508,6 +526,8 @@ public class JobSchedulerService extends com.android.server.SystemService
        private static final String KEY_API_QUOTA_SCHEDULE_WINDOW_MS = "aq_schedule_window_ms";
        private static final String KEY_API_QUOTA_SCHEDULE_WINDOW_MS = "aq_schedule_window_ms";
        private static final String KEY_API_QUOTA_SCHEDULE_THROW_EXCEPTION =
        private static final String KEY_API_QUOTA_SCHEDULE_THROW_EXCEPTION =
                "aq_schedule_throw_exception";
                "aq_schedule_throw_exception";
        private static final String KEY_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT =
                "aq_schedule_return_failure";


        private static final int DEFAULT_MIN_READY_NON_ACTIVE_JOBS_COUNT = 5;
        private static final int DEFAULT_MIN_READY_NON_ACTIVE_JOBS_COUNT = 5;
        private static final long DEFAULT_MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS = 31 * MINUTE_IN_MILLIS;
        private static final long DEFAULT_MAX_NON_ACTIVE_JOB_BATCH_DELAY_MS = 31 * MINUTE_IN_MILLIS;
@@ -521,6 +541,7 @@ public class JobSchedulerService extends com.android.server.SystemService
        private static final int DEFAULT_API_QUOTA_SCHEDULE_COUNT = 250;
        private static final int DEFAULT_API_QUOTA_SCHEDULE_COUNT = 250;
        private static final long DEFAULT_API_QUOTA_SCHEDULE_WINDOW_MS = MINUTE_IN_MILLIS;
        private static final long DEFAULT_API_QUOTA_SCHEDULE_WINDOW_MS = MINUTE_IN_MILLIS;
        private static final boolean DEFAULT_API_QUOTA_SCHEDULE_THROW_EXCEPTION = true;
        private static final boolean DEFAULT_API_QUOTA_SCHEDULE_THROW_EXCEPTION = true;
        private static final boolean DEFAULT_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = false;


        /**
        /**
         * Minimum # of non-ACTIVE jobs for which the JMS will be happy running some work early.
         * Minimum # of non-ACTIVE jobs for which the JMS will be happy running some work early.
@@ -624,6 +645,11 @@ public class JobSchedulerService extends com.android.server.SystemService
         */
         */
        public boolean API_QUOTA_SCHEDULE_THROW_EXCEPTION =
        public boolean API_QUOTA_SCHEDULE_THROW_EXCEPTION =
                DEFAULT_API_QUOTA_SCHEDULE_THROW_EXCEPTION;
                DEFAULT_API_QUOTA_SCHEDULE_THROW_EXCEPTION;
        /**
         * Whether or not to return a failure result when an app hits its schedule quota limit.
         */
        public boolean API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT =
                DEFAULT_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT;


        private final KeyValueListParser mParser = new KeyValueListParser(',');
        private final KeyValueListParser mParser = new KeyValueListParser(',');


@@ -679,6 +705,9 @@ public class JobSchedulerService extends com.android.server.SystemService
            API_QUOTA_SCHEDULE_THROW_EXCEPTION = mParser.getBoolean(
            API_QUOTA_SCHEDULE_THROW_EXCEPTION = mParser.getBoolean(
                    KEY_API_QUOTA_SCHEDULE_THROW_EXCEPTION,
                    KEY_API_QUOTA_SCHEDULE_THROW_EXCEPTION,
                    DEFAULT_API_QUOTA_SCHEDULE_THROW_EXCEPTION);
                    DEFAULT_API_QUOTA_SCHEDULE_THROW_EXCEPTION);
            API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT = mParser.getBoolean(
                    KEY_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT,
                    DEFAULT_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT);
        }
        }


        void dump(IndentingPrintWriter pw) {
        void dump(IndentingPrintWriter pw) {
@@ -713,6 +742,8 @@ public class JobSchedulerService extends com.android.server.SystemService
            pw.printPair(KEY_API_QUOTA_SCHEDULE_WINDOW_MS, API_QUOTA_SCHEDULE_WINDOW_MS).println();
            pw.printPair(KEY_API_QUOTA_SCHEDULE_WINDOW_MS, API_QUOTA_SCHEDULE_WINDOW_MS).println();
            pw.printPair(KEY_API_QUOTA_SCHEDULE_THROW_EXCEPTION,
            pw.printPair(KEY_API_QUOTA_SCHEDULE_THROW_EXCEPTION,
                    API_QUOTA_SCHEDULE_THROW_EXCEPTION).println();
                    API_QUOTA_SCHEDULE_THROW_EXCEPTION).println();
            pw.printPair(KEY_API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT,
                    API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT).println();


            pw.decreaseIndent();
            pw.decreaseIndent();
        }
        }
@@ -741,6 +772,8 @@ public class JobSchedulerService extends com.android.server.SystemService
            proto.write(ConstantsProto.API_QUOTA_SCHEDULE_WINDOW_MS, API_QUOTA_SCHEDULE_WINDOW_MS);
            proto.write(ConstantsProto.API_QUOTA_SCHEDULE_WINDOW_MS, API_QUOTA_SCHEDULE_WINDOW_MS);
            proto.write(ConstantsProto.API_QUOTA_SCHEDULE_THROW_EXCEPTION,
            proto.write(ConstantsProto.API_QUOTA_SCHEDULE_THROW_EXCEPTION,
                    API_QUOTA_SCHEDULE_THROW_EXCEPTION);
                    API_QUOTA_SCHEDULE_THROW_EXCEPTION);
            proto.write(ConstantsProto.API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT,
                    API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT);
        }
        }
    }
    }


@@ -974,12 +1007,17 @@ public class JobSchedulerService extends com.android.server.SystemService


    public int scheduleAsPackage(JobInfo job, JobWorkItem work, int uId, String packageName,
    public int scheduleAsPackage(JobInfo job, JobWorkItem work, int uId, String packageName,
            int userId, String tag) {
            int userId, String tag) {
        if (job.isPersisted()) {
        final String servicePkg = job.getService().getPackageName();
            // Only limit schedule calls for persisted jobs.
        if (job.isPersisted() && (packageName == null || packageName.equals(servicePkg))) {
            // Only limit schedule calls for persisted jobs scheduled by the app itself.
            final String pkg =
            final String pkg =
                    packageName == null ? job.getService().getPackageName() : packageName;
                    packageName == null ? job.getService().getPackageName() : packageName;
            if (!mQuotaTracker.isWithinQuota(userId, pkg, QUOTA_TRACKER_SCHEDULE_PERSISTED_TAG)) {
            if (!mQuotaTracker.isWithinQuota(userId, pkg, QUOTA_TRACKER_SCHEDULE_PERSISTED_TAG)) {
                Slog.e(TAG, userId + "-" + pkg + " has called schedule() too many times");
                if (mQuotaTracker.isWithinQuota(userId, pkg, QUOTA_TRACKER_SCHEDULE_LOGGED)) {
                    // Don't log too frequently
                    Slog.wtf(TAG, userId + "-" + pkg + " has called schedule() too many times");
                    mQuotaTracker.noteEvent(userId, pkg, QUOTA_TRACKER_SCHEDULE_LOGGED);
                }
                mAppStandbyInternal.restrictApp(
                mAppStandbyInternal.restrictApp(
                        pkg, userId, UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY);
                        pkg, userId, UsageStatsManager.REASON_SUB_FORCED_SYSTEM_FLAG_BUGGY);
                if (mConstants.API_QUOTA_SCHEDULE_THROW_EXCEPTION) {
                if (mConstants.API_QUOTA_SCHEDULE_THROW_EXCEPTION) {
@@ -1005,14 +1043,18 @@ public class JobSchedulerService extends com.android.server.SystemService
                        // Only throw the exception for debuggable apps.
                        // Only throw the exception for debuggable apps.
                        throw new LimitExceededException(
                        throw new LimitExceededException(
                                "schedule()/enqueue() called more than "
                                "schedule()/enqueue() called more than "
                                        + mQuotaTracker.getLimit(Category.SINGLE_CATEGORY)
                                        + mQuotaTracker.getLimit(
                                        QUOTA_TRACKER_CATEGORY_SCHEDULE_PERSISTED)
                                        + " times in the past "
                                        + " times in the past "
                                        + mQuotaTracker.getWindowSizeMs(Category.SINGLE_CATEGORY)
                                        + mQuotaTracker.getWindowSizeMs(
                                        + "ms");
                                        QUOTA_TRACKER_CATEGORY_SCHEDULE_PERSISTED)
                                        + "ms. See the documentation for more information.");
                    }
                    }
                }
                }
                if (mConstants.API_QUOTA_SCHEDULE_RETURN_FAILURE_RESULT) {
                    return JobScheduler.RESULT_FAILURE;
                    return JobScheduler.RESULT_FAILURE;
                }
                }
            }
            mQuotaTracker.noteEvent(userId, pkg, QUOTA_TRACKER_SCHEDULE_PERSISTED_TAG);
            mQuotaTracker.noteEvent(userId, pkg, QUOTA_TRACKER_SCHEDULE_PERSISTED_TAG);
        }
        }


@@ -1372,10 +1414,12 @@ public class JobSchedulerService extends com.android.server.SystemService
        // Set up the app standby bucketing tracker
        // Set up the app standby bucketing tracker
        mStandbyTracker = new StandbyTracker();
        mStandbyTracker = new StandbyTracker();
        mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
        mUsageStats = LocalServices.getService(UsageStatsManagerInternal.class);
        mQuotaTracker = new CountQuotaTracker(context, Categorizer.SINGLE_CATEGORIZER);
        mQuotaTracker = new CountQuotaTracker(context, QUOTA_CATEGORIZER);
        mQuotaTracker.setCountLimit(Category.SINGLE_CATEGORY,
        mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_SCHEDULE_PERSISTED,
                mConstants.API_QUOTA_SCHEDULE_COUNT,
                mConstants.API_QUOTA_SCHEDULE_COUNT,
                mConstants.API_QUOTA_SCHEDULE_WINDOW_MS);
                mConstants.API_QUOTA_SCHEDULE_WINDOW_MS);
        // Log at most once per minute.
        mQuotaTracker.setCountLimit(QUOTA_TRACKER_CATEGORY_SCHEDULE_LOGGED, 1, 60_000);


        mAppStandbyInternal = LocalServices.getService(AppStandbyInternal.class);
        mAppStandbyInternal = LocalServices.getService(AppStandbyInternal.class);
        mAppStandbyInternal.addListener(mStandbyTracker);
        mAppStandbyInternal.addListener(mStandbyTracker);
+8 −1
Original line number Original line Diff line number Diff line
@@ -2640,7 +2640,10 @@ public class ChooserActivity extends ResolverActivity implements
        }
        }
        RecyclerView recyclerView = mChooserMultiProfilePagerAdapter.getActiveAdapterView();
        RecyclerView recyclerView = mChooserMultiProfilePagerAdapter.getActiveAdapterView();
        ChooserGridAdapter gridAdapter = mChooserMultiProfilePagerAdapter.getCurrentRootAdapter();
        ChooserGridAdapter gridAdapter = mChooserMultiProfilePagerAdapter.getCurrentRootAdapter();
        if (gridAdapter == null || recyclerView == null) {
        // Skip height calculation if recycler view was scrolled to prevent it inaccurately
        // calculating the height, as the logic below does not account for the scrolled offset.
        if (gridAdapter == null || recyclerView == null
                || recyclerView.computeVerticalScrollOffset() != 0) {
            return;
            return;
        }
        }


@@ -3127,6 +3130,10 @@ public class ChooserActivity extends ResolverActivity implements
        ChooserGridAdapter currentRootAdapter =
        ChooserGridAdapter currentRootAdapter =
                mChooserMultiProfilePagerAdapter.getCurrentRootAdapter();
                mChooserMultiProfilePagerAdapter.getCurrentRootAdapter();
        currentRootAdapter.updateDirectShareExpansion();
        currentRootAdapter.updateDirectShareExpansion();
        // This fixes an edge case where after performing a variety of gestures, vertical scrolling
        // ends up disabled. That's because at some point the old tab's vertical scrolling is
        // disabled and the new tab's is enabled. For context, see b/159997845
        setVerticalScrollEnabled(true);
    }
    }


    @Override
    @Override
+3 −1
Original line number Original line Diff line number Diff line
@@ -252,8 +252,10 @@ public class ChooserMultiProfilePagerAdapter extends AbstractMultiProfilePagerAd


    @Override
    @Override
    protected void setupContainerPadding(View container) {
    protected void setupContainerPadding(View container) {
        int initialBottomPadding = getContext().getResources().getDimensionPixelSize(
                R.dimen.resolver_empty_state_container_padding_bottom);
        container.setPadding(container.getPaddingLeft(), container.getPaddingTop(),
        container.setPadding(container.getPaddingLeft(), container.getPaddingTop(),
                container.getPaddingRight(), container.getPaddingBottom() + mBottomOffset);
                container.getPaddingRight(), initialBottomPadding + mBottomOffset);
    }
    }


    class ChooserProfileDescriptor extends ProfileDescriptor {
    class ChooserProfileDescriptor extends ProfileDescriptor {
+3 −1
Original line number Original line Diff line number Diff line
@@ -236,6 +236,8 @@ message ConstantsProto {
    optional int64 api_quota_schedule_window_ms = 33;
    optional int64 api_quota_schedule_window_ms = 33;
    // Whether or not to throw an exception when an app hits its schedule quota limit.
    // Whether or not to throw an exception when an app hits its schedule quota limit.
    optional bool api_quota_schedule_throw_exception = 34;
    optional bool api_quota_schedule_throw_exception = 34;
    // Whether or not to return a failure result when an app hits its schedule quota limit.
    optional bool api_quota_schedule_return_failure_result = 35;


    message QuotaController {
    message QuotaController {
        option (.android.msg_privacy).dest = DEST_AUTOMATIC;
        option (.android.msg_privacy).dest = DEST_AUTOMATIC;
@@ -335,7 +337,7 @@ message ConstantsProto {
    // In this time after screen turns on, we increase job concurrency.
    // In this time after screen turns on, we increase job concurrency.
    optional int32 screen_off_job_concurrency_increase_delay_ms = 28;
    optional int32 screen_off_job_concurrency_increase_delay_ms = 28;


    // Next tag: 35
    // Next tag: 36
}
}


// Next tag: 4
// Next tag: 4
Loading