Loading apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +65 −6 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import android.app.usage.UsageStatsManager; import android.app.usage.UsageStatsManagerInternal; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; Loading @@ -50,6 +51,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; import android.content.pm.ParceledListSlice; import android.content.pm.ServiceInfo; import android.database.ContentObserver; import android.net.Uri; import android.os.BatteryStats; import android.os.BatteryStatsInternal; Loading @@ -66,6 +68,7 @@ import android.os.SystemClock; import android.os.UserHandle; import android.os.WorkSource; import android.provider.DeviceConfig; import android.provider.Settings; import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.ArraySet; Loading Loading @@ -106,6 +109,7 @@ import com.android.server.job.controllers.QuotaController; import com.android.server.job.controllers.RestrictingController; import com.android.server.job.controllers.StateController; import com.android.server.job.controllers.StorageController; import com.android.server.job.controllers.TareController; import com.android.server.job.controllers.TimeController; import com.android.server.job.restrictions.JobRestriction; import com.android.server.job.restrictions.ThermalStatusRestriction; Loading Loading @@ -250,6 +254,8 @@ public class JobSchedulerService extends com.android.server.SystemService private final DeviceIdleJobsController mDeviceIdleJobsController; /** Needed to get remaining quota time. */ private final QuotaController mQuotaController; /** Needed to get max execution time and expedited-job allowance. */ private final TareController mTareController; /** * List of restrictions. * Note: do not add to or remove from this list at runtime except in the constructor, because we Loading Loading @@ -344,14 +350,40 @@ public class JobSchedulerService extends com.android.server.SystemService // (ScheduledJobStateChanged and JobStatusDumpProto). public static final int RESTRICTED_INDEX = 5; private class ConstantsObserver implements DeviceConfig.OnPropertiesChangedListener { private class ConstantsObserver extends ContentObserver implements DeviceConfig.OnPropertiesChangedListener { private final ContentResolver mContentResolver; ConstantsObserver(Handler handler, Context context) { super(handler); mContentResolver = context.getContentResolver(); } public void start() { DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_JOB_SCHEDULER, JobSchedulerBackgroundThread.getExecutor(), this); mContentResolver.registerContentObserver( Settings.Global.getUriFor(Settings.Global.ENABLE_TARE), false, this); // Load all the constants. synchronized (mLock) { mConstants.updateSettingsConstantsLocked(mContentResolver); } onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_JOB_SCHEDULER)); } @Override public void onChange(boolean selfChange) { synchronized (mLock) { if (mConstants.updateSettingsConstantsLocked(mContentResolver)) { for (int controller = 0; controller < mControllers.size(); controller++) { final StateController sc = mControllers.get(controller); sc.onConstantsUpdatedLocked(); } onControllerStateChanged(null); } } } @Override public void onPropertiesChanged(DeviceConfig.Properties properties) { boolean apiQuotaScheduleUpdated = false; Loading Loading @@ -482,6 +514,7 @@ public class JobSchedulerService extends com.android.server.SystemService public static final long DEFAULT_RUNTIME_MIN_GUARANTEE_MS = 10 * MINUTE_IN_MILLIS; @VisibleForTesting public static final long DEFAULT_RUNTIME_MIN_EJ_GUARANTEE_MS = 3 * MINUTE_IN_MILLIS; private static final boolean DEFAULT_USE_TARE_POLICY = false; /** * Minimum # of non-ACTIVE jobs for which the JMS will be happy running some work early. Loading Loading @@ -559,6 +592,11 @@ public class JobSchedulerService extends com.android.server.SystemService */ public long RUNTIME_MIN_EJ_GUARANTEE_MS = DEFAULT_RUNTIME_MIN_EJ_GUARANTEE_MS; /** * If true, use TARE policy for job limiting. If false, use quotas. */ public boolean USE_TARE_POLICY = DEFAULT_USE_TARE_POLICY; private void updateBatchingConstantsLocked() { MIN_READY_NON_ACTIVE_JOBS_COUNT = DeviceConfig.getInt( DeviceConfig.NAMESPACE_JOB_SCHEDULER, Loading Loading @@ -637,6 +675,17 @@ public class JobSchedulerService extends com.android.server.SystemService DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)); } private boolean updateSettingsConstantsLocked(ContentResolver contentResolver) { boolean changed = false; final boolean isTareEnabled = Settings.Global.getInt(contentResolver, Settings.Global.ENABLE_TARE, Settings.Global.DEFAULT_ENABLE_TARE) == 1; if (USE_TARE_POLICY != isTareEnabled) { USE_TARE_POLICY = isTareEnabled; changed = true; } return changed; } void dump(IndentingPrintWriter pw) { pw.println("Settings:"); pw.increaseIndent(); Loading Loading @@ -665,6 +714,8 @@ public class JobSchedulerService extends com.android.server.SystemService pw.print(KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS, RUNTIME_FREE_QUOTA_MAX_LIMIT_MS) .println(); pw.print(Settings.Global.ENABLE_TARE, USE_TARE_POLICY).println(); pw.decreaseIndent(); } Loading Loading @@ -1130,10 +1181,13 @@ public class JobSchedulerService extends com.android.server.SystemService JobStatus jobStatus = JobStatus.createFromJobInfo(job, uId, packageName, userId, tag); // Return failure early if expedited job quota used up. if (jobStatus.isRequestedExpeditedJob() && !mQuotaController.isWithinEJQuotaLocked(jobStatus)) { if (jobStatus.isRequestedExpeditedJob()) { if ((mConstants.USE_TARE_POLICY && !mTareController.canScheduleEJ(jobStatus)) || (!mConstants.USE_TARE_POLICY && !mQuotaController.isWithinEJQuotaLocked(jobStatus))) { return JobScheduler.RESULT_FAILURE; } } // Give exemption if the source is in the foreground just now. // Note if it's a sync job, this method is called on the handler so it's not exactly Loading Loading @@ -1474,7 +1528,7 @@ public class JobSchedulerService extends com.android.server.SystemService mHandler = new JobHandler(context.getMainLooper()); mConstants = new Constants(); mConstantsObserver = new ConstantsObserver(); mConstantsObserver = new ConstantsObserver(mHandler, context); mJobSchedulerStub = new JobSchedulerStub(); mConcurrencyManager = new JobConcurrencyManager(this); Loading Loading @@ -1519,6 +1573,9 @@ public class JobSchedulerService extends com.android.server.SystemService new QuotaController(this, backgroundJobsController, connectivityController); mControllers.add(mQuotaController); mControllers.add(new ComponentController(this)); mTareController = new TareController(this, backgroundJobsController, connectivityController); mControllers.add(mTareController); mRestrictiveControllers = new ArrayList<>(); mRestrictiveControllers.add(mBatteryController); Loading Loading @@ -2560,7 +2617,9 @@ public class JobSchedulerService extends com.android.server.SystemService public long getMaxJobExecutionTimeMs(JobStatus job) { synchronized (mLock) { return Math.min(mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS, mQuotaController.getMaxJobExecutionTimeMsLocked(job)); mConstants.USE_TARE_POLICY ? mTareController.getMaxJobExecutionTimeMsLocked(job) : mQuotaController.getMaxJobExecutionTimeMsLocked(job)); } } Loading apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java +38 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,9 @@ import com.android.internal.util.FrameworkStatsLog; import com.android.server.EventLogTags; import com.android.server.LocalServices; import com.android.server.job.controllers.JobStatus; import com.android.server.tare.EconomicPolicy; import com.android.server.tare.EconomyManagerInternal; import com.android.server.tare.JobSchedulerEconomicPolicy; /** * Handles client binding and lifecycle of a job. Jobs execute one at a time on an instance of this Loading Loading @@ -107,6 +110,7 @@ public final class JobServiceContext implements ServiceConnection { private final Context mContext; private final Object mLock; private final IBatteryStats mBatteryStats; private final EconomyManagerInternal mEconomyManagerInternal; private final JobPackageTracker mJobPackageTracker; private final PowerManager mPowerManager; private PowerManager.WakeLock mWakeLock; Loading Loading @@ -211,6 +215,7 @@ public final class JobServiceContext implements ServiceConnection { mLock = service.getLock(); mService = service; mBatteryStats = batteryStats; mEconomyManagerInternal = LocalServices.getService(EconomyManagerInternal.class); mJobPackageTracker = tracker; mCallbackHandler = new JobServiceHandler(looper); mJobConcurrencyManager = concurrencyManager; Loading Loading @@ -288,6 +293,11 @@ public final class JobServiceContext implements ServiceConnection { mWakeLock.setReferenceCounted(false); mWakeLock.acquire(); // Note the start when we try to bind so that the app is charged for some processing // even if binding fails. mEconomyManagerInternal.noteInstantaneousEvent( job.getSourceUserId(), job.getSourcePackageName(), getStartActionId(job), String.valueOf(job.getJobId())); mVerb = VERB_BINDING; scheduleOpTimeOutLocked(); final Intent intent = new Intent().setComponent(job.getServiceComponent()); Loading Loading @@ -350,6 +360,9 @@ public final class JobServiceContext implements ServiceConnection { } catch (RemoteException e) { // Whatever. } mEconomyManagerInternal.noteOngoingEventStarted( job.getSourceUserId(), job.getSourcePackageName(), getRunningActionId(job), String.valueOf(job.getJobId())); final String jobPackage = job.getSourcePackageName(); final int jobUserId = job.getSourceUserId(); UsageStatsManagerInternal usageStats = Loading @@ -363,6 +376,22 @@ public final class JobServiceContext implements ServiceConnection { } } @EconomicPolicy.AppAction private static int getStartActionId(@NonNull JobStatus job) { if (job.startedAsExpeditedJob || job.shouldTreatAsExpeditedJob()) { return JobSchedulerEconomicPolicy.ACTION_JOB_MAX_START; } return JobSchedulerEconomicPolicy.ACTION_JOB_DEFAULT_START; } @EconomicPolicy.AppAction private static int getRunningActionId(@NonNull JobStatus job) { if (job.startedAsExpeditedJob || job.shouldTreatAsExpeditedJob()) { return JobSchedulerEconomicPolicy.ACTION_JOB_MAX_RUNNING; } return JobSchedulerEconomicPolicy.ACTION_JOB_DEFAULT_RUNNING; } /** * Used externally to query the running job. Will return null if there is no job running. */ Loading Loading @@ -982,6 +1011,15 @@ public final class JobServiceContext implements ServiceConnection { } catch (RemoteException e) { // Whatever. } mEconomyManagerInternal.noteOngoingEventStopped( mRunningJob.getSourceUserId(), mRunningJob.getSourcePackageName(), getRunningActionId(mRunningJob), String.valueOf(mRunningJob.getJobId())); if (mParams.getStopReason() == JobParameters.STOP_REASON_TIMEOUT) { mEconomyManagerInternal.noteInstantaneousEvent( mRunningJob.getSourceUserId(), mRunningJob.getSourcePackageName(), JobSchedulerEconomicPolicy.ACTION_JOB_TIMEOUT, String.valueOf(mRunningJob.getJobId())); } if (mWakeLock != null) { mWakeLock.release(); } Loading apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java +2 −1 Original line number Diff line number Diff line Loading @@ -661,7 +661,8 @@ public final class ConnectivityController extends RestrictingController implemen NetworkCapabilities capabilities, Constants constants) { // A restricted job that's out of quota MUST use an unmetered network. if (jobStatus.getEffectiveStandbyBucket() == RESTRICTED_INDEX && !jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA)) { && (!jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA) || !jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_TARE_WEALTH))) { final NetworkCapabilities.Builder builder = copyCapabilities(jobStatus.getJob().getRequiredNetwork()); builder.addCapability(NET_CAPABILITY_NOT_METERED); Loading apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java +3 −2 Original line number Diff line number Diff line Loading @@ -1141,7 +1141,7 @@ public final class JobStatus { * treated as an expedited job. */ public boolean shouldTreatAsExpeditedJob() { return mExpeditedQuotaApproved && isRequestedExpeditedJob(); return mExpeditedQuotaApproved && mExpeditedTareApproved && isRequestedExpeditedJob(); } /** Loading Loading @@ -1564,7 +1564,8 @@ public final class JobStatus { // sessions (exempt from dynamic restrictions), we need the additional check to ensure // that NEVER jobs don't run. // TODO: cleanup quota and standby bucket management so we don't need the additional checks if ((!mReadyWithinQuota && !mReadyDynamicSatisfied && !shouldTreatAsExpeditedJob()) if (((!mReadyWithinQuota || !mReadyTareWealth) && !mReadyDynamicSatisfied && !shouldTreatAsExpeditedJob()) || getEffectiveStandbyBucket() == NEVER_INDEX) { return false; } Loading apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java +16 −1 Original line number Diff line number Diff line Loading @@ -372,6 +372,9 @@ public final class QuotaController extends StateController { private final BackgroundJobsController mBackgroundJobsController; private final ConnectivityController mConnectivityController; @GuardedBy("mLock") private boolean mIsEnabled; /** How much time each app will have to run jobs within their standby bucket window. */ private long mAllowedTimePerPeriodMs = QcConstants.DEFAULT_ALLOWED_TIME_PER_PERIOD_MS; Loading Loading @@ -590,6 +593,7 @@ public final class QuotaController extends StateController { mQcConstants = new QcConstants(); mBackgroundJobsController = backgroundJobsController; mConnectivityController = connectivityController; mIsEnabled = !mConstants.USE_TARE_POLICY; // Set up the app standby bucketing tracker AppStandbyInternal appStandby = LocalServices.getService(AppStandbyInternal.class); Loading Loading @@ -837,6 +841,9 @@ public final class QuotaController extends StateController { /** @return true if the job is within expedited job quota. */ @GuardedBy("mLock") public boolean isWithinEJQuotaLocked(@NonNull final JobStatus jobStatus) { if (!mIsEnabled) { return true; } if (isQuotaFreeLocked(jobStatus.getEffectiveStandbyBucket())) { return true; } Loading Loading @@ -884,6 +891,9 @@ public final class QuotaController extends StateController { @VisibleForTesting boolean isWithinQuotaLocked(@NonNull final JobStatus jobStatus) { if (!mIsEnabled) { return true; } final int standbyBucket = jobStatus.getEffectiveStandbyBucket(); // A job is within quota if one of the following is true: // 1. it was started while the app was in the TOP state Loading @@ -910,6 +920,9 @@ public final class QuotaController extends StateController { @GuardedBy("mLock") boolean isWithinQuotaLocked(final int userId, @NonNull final String packageName, final int standbyBucket) { if (!mIsEnabled) { return true; } if (standbyBucket == NEVER_INDEX) return false; if (isQuotaFreeLocked(standbyBucket)) return true; Loading Loading @@ -2980,7 +2993,8 @@ public final class QuotaController extends StateController { @Override public void onConstantsUpdatedLocked() { if (mQcConstants.mShouldReevaluateConstraints) { if (mQcConstants.mShouldReevaluateConstraints || mIsEnabled == mConstants.USE_TARE_POLICY) { mIsEnabled = !mConstants.USE_TARE_POLICY; // Update job bookkeeping out of band. JobSchedulerBackgroundThread.getHandler().post(() -> { synchronized (mLock) { Loading Loading @@ -4120,6 +4134,7 @@ public final class QuotaController extends StateController { @Override public void dumpControllerStateLocked(final IndentingPrintWriter pw, final Predicate<JobStatus> predicate) { pw.println("Is enabled: " + mIsEnabled); pw.println("Is charging: " + mChargeTracker.isChargingLocked()); pw.println("Current elapsed time: " + sElapsedRealtimeClock.millis()); pw.println(); Loading Loading
apex/jobscheduler/service/java/com/android/server/job/JobSchedulerService.java +65 −6 Original line number Diff line number Diff line Loading @@ -40,6 +40,7 @@ import android.app.usage.UsageStatsManager; import android.app.usage.UsageStatsManagerInternal; import android.content.BroadcastReceiver; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; Loading @@ -50,6 +51,7 @@ import android.content.pm.PackageManager.NameNotFoundException; import android.content.pm.PackageManagerInternal; import android.content.pm.ParceledListSlice; import android.content.pm.ServiceInfo; import android.database.ContentObserver; import android.net.Uri; import android.os.BatteryStats; import android.os.BatteryStatsInternal; Loading @@ -66,6 +68,7 @@ import android.os.SystemClock; import android.os.UserHandle; import android.os.WorkSource; import android.provider.DeviceConfig; import android.provider.Settings; import android.text.format.DateUtils; import android.util.ArrayMap; import android.util.ArraySet; Loading Loading @@ -106,6 +109,7 @@ import com.android.server.job.controllers.QuotaController; import com.android.server.job.controllers.RestrictingController; import com.android.server.job.controllers.StateController; import com.android.server.job.controllers.StorageController; import com.android.server.job.controllers.TareController; import com.android.server.job.controllers.TimeController; import com.android.server.job.restrictions.JobRestriction; import com.android.server.job.restrictions.ThermalStatusRestriction; Loading Loading @@ -250,6 +254,8 @@ public class JobSchedulerService extends com.android.server.SystemService private final DeviceIdleJobsController mDeviceIdleJobsController; /** Needed to get remaining quota time. */ private final QuotaController mQuotaController; /** Needed to get max execution time and expedited-job allowance. */ private final TareController mTareController; /** * List of restrictions. * Note: do not add to or remove from this list at runtime except in the constructor, because we Loading Loading @@ -344,14 +350,40 @@ public class JobSchedulerService extends com.android.server.SystemService // (ScheduledJobStateChanged and JobStatusDumpProto). public static final int RESTRICTED_INDEX = 5; private class ConstantsObserver implements DeviceConfig.OnPropertiesChangedListener { private class ConstantsObserver extends ContentObserver implements DeviceConfig.OnPropertiesChangedListener { private final ContentResolver mContentResolver; ConstantsObserver(Handler handler, Context context) { super(handler); mContentResolver = context.getContentResolver(); } public void start() { DeviceConfig.addOnPropertiesChangedListener(DeviceConfig.NAMESPACE_JOB_SCHEDULER, JobSchedulerBackgroundThread.getExecutor(), this); mContentResolver.registerContentObserver( Settings.Global.getUriFor(Settings.Global.ENABLE_TARE), false, this); // Load all the constants. synchronized (mLock) { mConstants.updateSettingsConstantsLocked(mContentResolver); } onPropertiesChanged(DeviceConfig.getProperties(DeviceConfig.NAMESPACE_JOB_SCHEDULER)); } @Override public void onChange(boolean selfChange) { synchronized (mLock) { if (mConstants.updateSettingsConstantsLocked(mContentResolver)) { for (int controller = 0; controller < mControllers.size(); controller++) { final StateController sc = mControllers.get(controller); sc.onConstantsUpdatedLocked(); } onControllerStateChanged(null); } } } @Override public void onPropertiesChanged(DeviceConfig.Properties properties) { boolean apiQuotaScheduleUpdated = false; Loading Loading @@ -482,6 +514,7 @@ public class JobSchedulerService extends com.android.server.SystemService public static final long DEFAULT_RUNTIME_MIN_GUARANTEE_MS = 10 * MINUTE_IN_MILLIS; @VisibleForTesting public static final long DEFAULT_RUNTIME_MIN_EJ_GUARANTEE_MS = 3 * MINUTE_IN_MILLIS; private static final boolean DEFAULT_USE_TARE_POLICY = false; /** * Minimum # of non-ACTIVE jobs for which the JMS will be happy running some work early. Loading Loading @@ -559,6 +592,11 @@ public class JobSchedulerService extends com.android.server.SystemService */ public long RUNTIME_MIN_EJ_GUARANTEE_MS = DEFAULT_RUNTIME_MIN_EJ_GUARANTEE_MS; /** * If true, use TARE policy for job limiting. If false, use quotas. */ public boolean USE_TARE_POLICY = DEFAULT_USE_TARE_POLICY; private void updateBatchingConstantsLocked() { MIN_READY_NON_ACTIVE_JOBS_COUNT = DeviceConfig.getInt( DeviceConfig.NAMESPACE_JOB_SCHEDULER, Loading Loading @@ -637,6 +675,17 @@ public class JobSchedulerService extends com.android.server.SystemService DEFAULT_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS)); } private boolean updateSettingsConstantsLocked(ContentResolver contentResolver) { boolean changed = false; final boolean isTareEnabled = Settings.Global.getInt(contentResolver, Settings.Global.ENABLE_TARE, Settings.Global.DEFAULT_ENABLE_TARE) == 1; if (USE_TARE_POLICY != isTareEnabled) { USE_TARE_POLICY = isTareEnabled; changed = true; } return changed; } void dump(IndentingPrintWriter pw) { pw.println("Settings:"); pw.increaseIndent(); Loading Loading @@ -665,6 +714,8 @@ public class JobSchedulerService extends com.android.server.SystemService pw.print(KEY_RUNTIME_FREE_QUOTA_MAX_LIMIT_MS, RUNTIME_FREE_QUOTA_MAX_LIMIT_MS) .println(); pw.print(Settings.Global.ENABLE_TARE, USE_TARE_POLICY).println(); pw.decreaseIndent(); } Loading Loading @@ -1130,10 +1181,13 @@ public class JobSchedulerService extends com.android.server.SystemService JobStatus jobStatus = JobStatus.createFromJobInfo(job, uId, packageName, userId, tag); // Return failure early if expedited job quota used up. if (jobStatus.isRequestedExpeditedJob() && !mQuotaController.isWithinEJQuotaLocked(jobStatus)) { if (jobStatus.isRequestedExpeditedJob()) { if ((mConstants.USE_TARE_POLICY && !mTareController.canScheduleEJ(jobStatus)) || (!mConstants.USE_TARE_POLICY && !mQuotaController.isWithinEJQuotaLocked(jobStatus))) { return JobScheduler.RESULT_FAILURE; } } // Give exemption if the source is in the foreground just now. // Note if it's a sync job, this method is called on the handler so it's not exactly Loading Loading @@ -1474,7 +1528,7 @@ public class JobSchedulerService extends com.android.server.SystemService mHandler = new JobHandler(context.getMainLooper()); mConstants = new Constants(); mConstantsObserver = new ConstantsObserver(); mConstantsObserver = new ConstantsObserver(mHandler, context); mJobSchedulerStub = new JobSchedulerStub(); mConcurrencyManager = new JobConcurrencyManager(this); Loading Loading @@ -1519,6 +1573,9 @@ public class JobSchedulerService extends com.android.server.SystemService new QuotaController(this, backgroundJobsController, connectivityController); mControllers.add(mQuotaController); mControllers.add(new ComponentController(this)); mTareController = new TareController(this, backgroundJobsController, connectivityController); mControllers.add(mTareController); mRestrictiveControllers = new ArrayList<>(); mRestrictiveControllers.add(mBatteryController); Loading Loading @@ -2560,7 +2617,9 @@ public class JobSchedulerService extends com.android.server.SystemService public long getMaxJobExecutionTimeMs(JobStatus job) { synchronized (mLock) { return Math.min(mConstants.RUNTIME_FREE_QUOTA_MAX_LIMIT_MS, mQuotaController.getMaxJobExecutionTimeMsLocked(job)); mConstants.USE_TARE_POLICY ? mTareController.getMaxJobExecutionTimeMsLocked(job) : mQuotaController.getMaxJobExecutionTimeMsLocked(job)); } } Loading
apex/jobscheduler/service/java/com/android/server/job/JobServiceContext.java +38 −0 Original line number Diff line number Diff line Loading @@ -54,6 +54,9 @@ import com.android.internal.util.FrameworkStatsLog; import com.android.server.EventLogTags; import com.android.server.LocalServices; import com.android.server.job.controllers.JobStatus; import com.android.server.tare.EconomicPolicy; import com.android.server.tare.EconomyManagerInternal; import com.android.server.tare.JobSchedulerEconomicPolicy; /** * Handles client binding and lifecycle of a job. Jobs execute one at a time on an instance of this Loading Loading @@ -107,6 +110,7 @@ public final class JobServiceContext implements ServiceConnection { private final Context mContext; private final Object mLock; private final IBatteryStats mBatteryStats; private final EconomyManagerInternal mEconomyManagerInternal; private final JobPackageTracker mJobPackageTracker; private final PowerManager mPowerManager; private PowerManager.WakeLock mWakeLock; Loading Loading @@ -211,6 +215,7 @@ public final class JobServiceContext implements ServiceConnection { mLock = service.getLock(); mService = service; mBatteryStats = batteryStats; mEconomyManagerInternal = LocalServices.getService(EconomyManagerInternal.class); mJobPackageTracker = tracker; mCallbackHandler = new JobServiceHandler(looper); mJobConcurrencyManager = concurrencyManager; Loading Loading @@ -288,6 +293,11 @@ public final class JobServiceContext implements ServiceConnection { mWakeLock.setReferenceCounted(false); mWakeLock.acquire(); // Note the start when we try to bind so that the app is charged for some processing // even if binding fails. mEconomyManagerInternal.noteInstantaneousEvent( job.getSourceUserId(), job.getSourcePackageName(), getStartActionId(job), String.valueOf(job.getJobId())); mVerb = VERB_BINDING; scheduleOpTimeOutLocked(); final Intent intent = new Intent().setComponent(job.getServiceComponent()); Loading Loading @@ -350,6 +360,9 @@ public final class JobServiceContext implements ServiceConnection { } catch (RemoteException e) { // Whatever. } mEconomyManagerInternal.noteOngoingEventStarted( job.getSourceUserId(), job.getSourcePackageName(), getRunningActionId(job), String.valueOf(job.getJobId())); final String jobPackage = job.getSourcePackageName(); final int jobUserId = job.getSourceUserId(); UsageStatsManagerInternal usageStats = Loading @@ -363,6 +376,22 @@ public final class JobServiceContext implements ServiceConnection { } } @EconomicPolicy.AppAction private static int getStartActionId(@NonNull JobStatus job) { if (job.startedAsExpeditedJob || job.shouldTreatAsExpeditedJob()) { return JobSchedulerEconomicPolicy.ACTION_JOB_MAX_START; } return JobSchedulerEconomicPolicy.ACTION_JOB_DEFAULT_START; } @EconomicPolicy.AppAction private static int getRunningActionId(@NonNull JobStatus job) { if (job.startedAsExpeditedJob || job.shouldTreatAsExpeditedJob()) { return JobSchedulerEconomicPolicy.ACTION_JOB_MAX_RUNNING; } return JobSchedulerEconomicPolicy.ACTION_JOB_DEFAULT_RUNNING; } /** * Used externally to query the running job. Will return null if there is no job running. */ Loading Loading @@ -982,6 +1011,15 @@ public final class JobServiceContext implements ServiceConnection { } catch (RemoteException e) { // Whatever. } mEconomyManagerInternal.noteOngoingEventStopped( mRunningJob.getSourceUserId(), mRunningJob.getSourcePackageName(), getRunningActionId(mRunningJob), String.valueOf(mRunningJob.getJobId())); if (mParams.getStopReason() == JobParameters.STOP_REASON_TIMEOUT) { mEconomyManagerInternal.noteInstantaneousEvent( mRunningJob.getSourceUserId(), mRunningJob.getSourcePackageName(), JobSchedulerEconomicPolicy.ACTION_JOB_TIMEOUT, String.valueOf(mRunningJob.getJobId())); } if (mWakeLock != null) { mWakeLock.release(); } Loading
apex/jobscheduler/service/java/com/android/server/job/controllers/ConnectivityController.java +2 −1 Original line number Diff line number Diff line Loading @@ -661,7 +661,8 @@ public final class ConnectivityController extends RestrictingController implemen NetworkCapabilities capabilities, Constants constants) { // A restricted job that's out of quota MUST use an unmetered network. if (jobStatus.getEffectiveStandbyBucket() == RESTRICTED_INDEX && !jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA)) { && (!jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_WITHIN_QUOTA) || !jobStatus.isConstraintSatisfied(JobStatus.CONSTRAINT_TARE_WEALTH))) { final NetworkCapabilities.Builder builder = copyCapabilities(jobStatus.getJob().getRequiredNetwork()); builder.addCapability(NET_CAPABILITY_NOT_METERED); Loading
apex/jobscheduler/service/java/com/android/server/job/controllers/JobStatus.java +3 −2 Original line number Diff line number Diff line Loading @@ -1141,7 +1141,7 @@ public final class JobStatus { * treated as an expedited job. */ public boolean shouldTreatAsExpeditedJob() { return mExpeditedQuotaApproved && isRequestedExpeditedJob(); return mExpeditedQuotaApproved && mExpeditedTareApproved && isRequestedExpeditedJob(); } /** Loading Loading @@ -1564,7 +1564,8 @@ public final class JobStatus { // sessions (exempt from dynamic restrictions), we need the additional check to ensure // that NEVER jobs don't run. // TODO: cleanup quota and standby bucket management so we don't need the additional checks if ((!mReadyWithinQuota && !mReadyDynamicSatisfied && !shouldTreatAsExpeditedJob()) if (((!mReadyWithinQuota || !mReadyTareWealth) && !mReadyDynamicSatisfied && !shouldTreatAsExpeditedJob()) || getEffectiveStandbyBucket() == NEVER_INDEX) { return false; } Loading
apex/jobscheduler/service/java/com/android/server/job/controllers/QuotaController.java +16 −1 Original line number Diff line number Diff line Loading @@ -372,6 +372,9 @@ public final class QuotaController extends StateController { private final BackgroundJobsController mBackgroundJobsController; private final ConnectivityController mConnectivityController; @GuardedBy("mLock") private boolean mIsEnabled; /** How much time each app will have to run jobs within their standby bucket window. */ private long mAllowedTimePerPeriodMs = QcConstants.DEFAULT_ALLOWED_TIME_PER_PERIOD_MS; Loading Loading @@ -590,6 +593,7 @@ public final class QuotaController extends StateController { mQcConstants = new QcConstants(); mBackgroundJobsController = backgroundJobsController; mConnectivityController = connectivityController; mIsEnabled = !mConstants.USE_TARE_POLICY; // Set up the app standby bucketing tracker AppStandbyInternal appStandby = LocalServices.getService(AppStandbyInternal.class); Loading Loading @@ -837,6 +841,9 @@ public final class QuotaController extends StateController { /** @return true if the job is within expedited job quota. */ @GuardedBy("mLock") public boolean isWithinEJQuotaLocked(@NonNull final JobStatus jobStatus) { if (!mIsEnabled) { return true; } if (isQuotaFreeLocked(jobStatus.getEffectiveStandbyBucket())) { return true; } Loading Loading @@ -884,6 +891,9 @@ public final class QuotaController extends StateController { @VisibleForTesting boolean isWithinQuotaLocked(@NonNull final JobStatus jobStatus) { if (!mIsEnabled) { return true; } final int standbyBucket = jobStatus.getEffectiveStandbyBucket(); // A job is within quota if one of the following is true: // 1. it was started while the app was in the TOP state Loading @@ -910,6 +920,9 @@ public final class QuotaController extends StateController { @GuardedBy("mLock") boolean isWithinQuotaLocked(final int userId, @NonNull final String packageName, final int standbyBucket) { if (!mIsEnabled) { return true; } if (standbyBucket == NEVER_INDEX) return false; if (isQuotaFreeLocked(standbyBucket)) return true; Loading Loading @@ -2980,7 +2993,8 @@ public final class QuotaController extends StateController { @Override public void onConstantsUpdatedLocked() { if (mQcConstants.mShouldReevaluateConstraints) { if (mQcConstants.mShouldReevaluateConstraints || mIsEnabled == mConstants.USE_TARE_POLICY) { mIsEnabled = !mConstants.USE_TARE_POLICY; // Update job bookkeeping out of band. JobSchedulerBackgroundThread.getHandler().post(() -> { synchronized (mLock) { Loading Loading @@ -4120,6 +4134,7 @@ public final class QuotaController extends StateController { @Override public void dumpControllerStateLocked(final IndentingPrintWriter pw, final Predicate<JobStatus> predicate) { pw.println("Is enabled: " + mIsEnabled); pw.println("Is charging: " + mChargeTracker.isChargingLocked()); pw.println("Current elapsed time: " + sElapsedRealtimeClock.millis()); pw.println(); Loading