Loading services/core/java/com/android/server/job/JobSchedulerInternal.java +9 −0 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.job; package com.android.server.job; import android.annotation.UserIdInt; import android.app.job.JobInfo; import android.app.job.JobInfo; import java.util.List; import java.util.List; Loading @@ -38,6 +39,14 @@ public interface JobSchedulerInternal { */ */ long nextHeartbeatForBucket(int bucket); long nextHeartbeatForBucket(int bucket); /** * Heartbeat ordinal for the given app. This is typically the heartbeat at which * the app last ran jobs, so that a newly-scheduled job in an app that hasn't run * jobs in a long time is immediately runnable even if the app is bucketed into * an infrequent time allocation. */ public long baseHeartbeatForApp(String packageName, @UserIdInt int userId, int appBucket); /** /** * Returns a list of pending jobs scheduled by the system service. * Returns a list of pending jobs scheduled by the system service. */ */ Loading services/core/java/com/android/server/job/JobSchedulerService.java +30 −1 Original line number Original line Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.job; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER; import android.annotation.UserIdInt; import android.app.Activity; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManager; import android.app.AppGlobals; import android.app.AppGlobals; Loading @@ -38,6 +39,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentFilter; import android.content.Intent.UriFlags; import android.content.pm.IPackageManager; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.PackageManagerInternal; Loading Loading @@ -2019,6 +2021,29 @@ public final class JobSchedulerService extends com.android.server.SystemService } } } } /** * Heartbeat ordinal for the given app. This is typically the heartbeat at which * the app last ran jobs, so that a newly-scheduled job in an app that hasn't run * jobs in a long time is immediately runnable even if the app is bucketed into * an infrequent time allocation. */ public long baseHeartbeatForApp(String packageName, @UserIdInt int userId, final int appStandbyBucket) { if (appStandbyBucket == 0) { // Active => everything can be run right away return 0; } final long timeSinceLastJob = mStandbyTracker.getTimeSinceLastJobRun( packageName, userId); final long bucketLength = mConstants.STANDBY_BEATS[appStandbyBucket]; final long bucketsAgo = timeSinceLastJob / bucketLength; // If we haven't run any jobs for more than the app's current bucket period, just // consider anything new to be immediately runnable. Otherwise, base it on the // bucket at which we last ran jobs. return (bucketsAgo > bucketLength) ? 0 : (getCurrentHeartbeat() - bucketsAgo); } /** /** * Returns a list of all pending jobs. A running job is not considered pending. Periodic * Returns a list of all pending jobs. A running job is not considered pending. Periodic * jobs are always considered pending. * jobs are always considered pending. Loading Loading @@ -2094,10 +2119,14 @@ public final class JobSchedulerService extends com.android.server.SystemService mUsageStats = usageStats; mUsageStats = usageStats; } } public long getTimeSinceLastJobRun(String packageName, final @UserIdInt int userId) { return mUsageStats.getTimeSinceLastJobRun(packageName, userId); } // AppIdleStateChangeListener interface for live updates // AppIdleStateChangeListener interface for live updates @Override @Override public void onAppIdleStateChanged(final String packageName, final int userId, public void onAppIdleStateChanged(final String packageName, final @UserIdInt int userId, boolean idle, int bucket) { boolean idle, int bucket) { final int uid = mLocalPM.getPackageUid(packageName, final int uid = mLocalPM.getPackageUid(packageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); Loading services/core/java/com/android/server/job/controllers/JobStatus.java +3 −1 Original line number Original line Diff line number Diff line Loading @@ -391,7 +391,9 @@ public final class JobStatus { int standbyBucket = JobSchedulerService.standbyBucketForPackage(jobPackage, int standbyBucket = JobSchedulerService.standbyBucketForPackage(jobPackage, sourceUserId, elapsedNow); sourceUserId, elapsedNow); JobSchedulerInternal js = LocalServices.getService(JobSchedulerInternal.class); JobSchedulerInternal js = LocalServices.getService(JobSchedulerInternal.class); long currentHeartbeat = js != null ? js.currentHeartbeat() : 0; long currentHeartbeat = js != null ? js.baseHeartbeatForApp(jobPackage, sourceUserId, standbyBucket) : 0; return new JobStatus(job, callingUid, sourcePkg, sourceUserId, return new JobStatus(job, callingUid, sourcePkg, sourceUserId, standbyBucket, currentHeartbeat, tag, 0, standbyBucket, currentHeartbeat, tag, 0, earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis, earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis, Loading Loading
services/core/java/com/android/server/job/JobSchedulerInternal.java +9 −0 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server.job; package com.android.server.job; import android.annotation.UserIdInt; import android.app.job.JobInfo; import android.app.job.JobInfo; import java.util.List; import java.util.List; Loading @@ -38,6 +39,14 @@ public interface JobSchedulerInternal { */ */ long nextHeartbeatForBucket(int bucket); long nextHeartbeatForBucket(int bucket); /** * Heartbeat ordinal for the given app. This is typically the heartbeat at which * the app last ran jobs, so that a newly-scheduled job in an app that hasn't run * jobs in a long time is immediately runnable even if the app is bucketed into * an infrequent time allocation. */ public long baseHeartbeatForApp(String packageName, @UserIdInt int userId, int appBucket); /** /** * Returns a list of pending jobs scheduled by the system service. * Returns a list of pending jobs scheduled by the system service. */ */ Loading
services/core/java/com/android/server/job/JobSchedulerService.java +30 −1 Original line number Original line Diff line number Diff line Loading @@ -19,6 +19,7 @@ package com.android.server.job; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER; import static android.content.pm.PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER; import android.annotation.UserIdInt; import android.app.Activity; import android.app.Activity; import android.app.ActivityManager; import android.app.ActivityManager; import android.app.AppGlobals; import android.app.AppGlobals; Loading @@ -38,6 +39,7 @@ import android.content.ContentResolver; import android.content.Context; import android.content.Context; import android.content.Intent; import android.content.Intent; import android.content.IntentFilter; import android.content.IntentFilter; import android.content.Intent.UriFlags; import android.content.pm.IPackageManager; import android.content.pm.IPackageManager; import android.content.pm.PackageManager; import android.content.pm.PackageManager; import android.content.pm.PackageManagerInternal; import android.content.pm.PackageManagerInternal; Loading Loading @@ -2019,6 +2021,29 @@ public final class JobSchedulerService extends com.android.server.SystemService } } } } /** * Heartbeat ordinal for the given app. This is typically the heartbeat at which * the app last ran jobs, so that a newly-scheduled job in an app that hasn't run * jobs in a long time is immediately runnable even if the app is bucketed into * an infrequent time allocation. */ public long baseHeartbeatForApp(String packageName, @UserIdInt int userId, final int appStandbyBucket) { if (appStandbyBucket == 0) { // Active => everything can be run right away return 0; } final long timeSinceLastJob = mStandbyTracker.getTimeSinceLastJobRun( packageName, userId); final long bucketLength = mConstants.STANDBY_BEATS[appStandbyBucket]; final long bucketsAgo = timeSinceLastJob / bucketLength; // If we haven't run any jobs for more than the app's current bucket period, just // consider anything new to be immediately runnable. Otherwise, base it on the // bucket at which we last ran jobs. return (bucketsAgo > bucketLength) ? 0 : (getCurrentHeartbeat() - bucketsAgo); } /** /** * Returns a list of all pending jobs. A running job is not considered pending. Periodic * Returns a list of all pending jobs. A running job is not considered pending. Periodic * jobs are always considered pending. * jobs are always considered pending. Loading Loading @@ -2094,10 +2119,14 @@ public final class JobSchedulerService extends com.android.server.SystemService mUsageStats = usageStats; mUsageStats = usageStats; } } public long getTimeSinceLastJobRun(String packageName, final @UserIdInt int userId) { return mUsageStats.getTimeSinceLastJobRun(packageName, userId); } // AppIdleStateChangeListener interface for live updates // AppIdleStateChangeListener interface for live updates @Override @Override public void onAppIdleStateChanged(final String packageName, final int userId, public void onAppIdleStateChanged(final String packageName, final @UserIdInt int userId, boolean idle, int bucket) { boolean idle, int bucket) { final int uid = mLocalPM.getPackageUid(packageName, final int uid = mLocalPM.getPackageUid(packageName, PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); PackageManager.MATCH_UNINSTALLED_PACKAGES, userId); Loading
services/core/java/com/android/server/job/controllers/JobStatus.java +3 −1 Original line number Original line Diff line number Diff line Loading @@ -391,7 +391,9 @@ public final class JobStatus { int standbyBucket = JobSchedulerService.standbyBucketForPackage(jobPackage, int standbyBucket = JobSchedulerService.standbyBucketForPackage(jobPackage, sourceUserId, elapsedNow); sourceUserId, elapsedNow); JobSchedulerInternal js = LocalServices.getService(JobSchedulerInternal.class); JobSchedulerInternal js = LocalServices.getService(JobSchedulerInternal.class); long currentHeartbeat = js != null ? js.currentHeartbeat() : 0; long currentHeartbeat = js != null ? js.baseHeartbeatForApp(jobPackage, sourceUserId, standbyBucket) : 0; return new JobStatus(job, callingUid, sourcePkg, sourceUserId, return new JobStatus(job, callingUid, sourcePkg, sourceUserId, standbyBucket, currentHeartbeat, tag, 0, standbyBucket, currentHeartbeat, tag, 0, earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis, earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis, Loading