Loading services/core/java/com/android/server/job/JobSchedulerService.java +4 −4 Original line number Diff line number Diff line Loading @@ -1498,16 +1498,16 @@ public class JobSchedulerService extends com.android.server.SystemService } /** * Called when we want to remove a JobStatus object that we've finished executing. Returns the * object removed. * Called when we want to remove a JobStatus object that we've finished executing. * @return true if the job was removed. */ private boolean stopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean writeBack) { boolean removeFromPersisted) { // Deal with any remaining work items in the old job. jobStatus.stopTrackingJobLocked(ActivityManager.getService(), incomingJob); // Remove from store as well as controllers. final boolean removed = mJobs.remove(jobStatus, writeBack); final boolean removed = mJobs.remove(jobStatus, removeFromPersisted); if (removed && mReadyToRock) { for (int i=0; i<mControllers.size(); i++) { StateController controller = mControllers.get(i); Loading services/core/java/com/android/server/job/JobStore.java +20 −4 Original line number Diff line number Diff line Loading @@ -235,10 +235,11 @@ public final class JobStore { /** * Remove the provided job. Will also delete the job if it was persisted. * @param writeBack If true, the job will be deleted (if it was persisted) immediately. * @param removeFromPersisted If true, the job will be removed from the persisted job list * immediately (if it was persisted). * @return Whether or not the job existed to be removed. */ public boolean remove(JobStatus jobStatus, boolean writeBack) { public boolean remove(JobStatus jobStatus, boolean removeFromPersisted) { boolean removed = mJobSet.remove(jobStatus); if (!removed) { if (DEBUG) { Loading @@ -246,7 +247,7 @@ public final class JobStore { } return false; } if (writeBack && jobStatus.isPersisted()) { if (removeFromPersisted && jobStatus.isPersisted()) { maybeWriteStatusToDiskAsync(); } return removed; Loading Loading @@ -344,6 +345,19 @@ public final class JobStore { new ReadJobMapFromDiskRunnable(jobSet, rtcGood).run(); } /** Write persisted JobStore state to disk synchronously. Should only be used for testing. */ @VisibleForTesting public void writeStatusToDiskForTesting() { synchronized (mWriteScheduleLock) { if (mWriteScheduled) { throw new IllegalStateException("An asynchronous write is already scheduled."); } mWriteScheduled = mWriteInProgress = true; mWriteRunnable.run(); } } /** * Wait for any pending write to the persistent store to clear * @param maxWaitMillis Maximum time from present to wait Loading Loading @@ -1049,7 +1063,9 @@ public final class JobStore { } } static final class JobSet { /** Set of all tracked jobs. */ @VisibleForTesting public static final class JobSet { @VisibleForTesting // Key is the getUid() originator of the jobs in each sheaf final SparseArray<ArraySet<JobStatus>> mJobs; Loading services/core/java/com/android/server/job/controllers/JobStatus.java +5 −18 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ import android.app.job.JobInfo; import android.app.job.JobWorkItem; import android.content.ClipData; import android.content.ComponentName; import android.content.pm.PackageManagerInternal; import android.net.Network; import android.net.Uri; import android.os.RemoteException; Loading Loading @@ -131,7 +130,6 @@ public final class JobStatus { * that underly Sync Manager operation. */ final int callingUid; final int targetSdkVersion; final String batteryName; /** Loading Loading @@ -344,7 +342,6 @@ public final class JobStatus { * @param job The actual requested parameters for the job * @param callingUid Identity of the app that is scheduling the job. This may not be the * app in which the job is implemented; such as with sync jobs. * @param targetSdkVersion The targetSdkVersion of the app in which the job will run. * @param sourcePackageName The package name of the app in which the job will run. * @param sourceUserId The user in which the job will run * @param standbyBucket The standby bucket that the source package is currently assigned to, Loading @@ -363,13 +360,12 @@ public final class JobStatus { * @param lastFailedRunTime When did we last run this job only to have it stop incomplete? * @param internalFlags Non-API property flags about this job */ private JobStatus(JobInfo job, int callingUid, int targetSdkVersion, String sourcePackageName, private JobStatus(JobInfo job, int callingUid, String sourcePackageName, int sourceUserId, int standbyBucket, long heartbeat, String tag, int numFailures, long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis, long lastSuccessfulRunTime, long lastFailedRunTime, int internalFlags) { this.job = job; this.callingUid = callingUid; this.targetSdkVersion = targetSdkVersion; this.standbyBucket = standbyBucket; this.baseHeartbeat = heartbeat; Loading Loading @@ -439,7 +435,7 @@ public final class JobStatus { /** Copy constructor: used specifically when cloning JobStatus objects for persistence, * so we preserve RTC window bounds if the source object has them. */ public JobStatus(JobStatus jobStatus) { this(jobStatus.getJob(), jobStatus.getUid(), jobStatus.targetSdkVersion, this(jobStatus.getJob(), jobStatus.getUid(), jobStatus.getSourcePackageName(), jobStatus.getSourceUserId(), jobStatus.getStandbyBucket(), jobStatus.getBaseHeartbeat(), jobStatus.getSourceTag(), jobStatus.getNumFailures(), Loading Loading @@ -468,7 +464,7 @@ public final class JobStatus { long lastSuccessfulRunTime, long lastFailedRunTime, Pair<Long, Long> persistedExecutionTimesUTC, int innerFlags) { this(job, callingUid, resolveTargetSdkVersion(job), sourcePkgName, sourceUserId, this(job, callingUid, sourcePkgName, sourceUserId, standbyBucket, baseHeartbeat, sourceTag, 0, earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis, Loading @@ -491,7 +487,7 @@ public final class JobStatus { long newEarliestRuntimeElapsedMillis, long newLatestRuntimeElapsedMillis, int backoffAttempt, long lastSuccessfulRunTime, long lastFailedRunTime) { this(rescheduling.job, rescheduling.getUid(), resolveTargetSdkVersion(rescheduling.job), this(rescheduling.job, rescheduling.getUid(), rescheduling.getSourcePackageName(), rescheduling.getSourceUserId(), rescheduling.getStandbyBucket(), newBaseHeartbeat, rescheduling.getSourceTag(), backoffAttempt, newEarliestRuntimeElapsedMillis, Loading Loading @@ -533,7 +529,7 @@ public final class JobStatus { long currentHeartbeat = js != null ? js.baseHeartbeatForApp(jobPackage, sourceUserId, standbyBucket) : 0; return new JobStatus(job, callingUid, resolveTargetSdkVersion(job), sourcePkg, sourceUserId, return new JobStatus(job, callingUid, sourcePkg, sourceUserId, standbyBucket, currentHeartbeat, tag, 0, earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis, 0 /* lastSuccessfulRunTime */, 0 /* lastFailedRunTime */, Loading Loading @@ -681,10 +677,6 @@ public final class JobStatus { return job.getId(); } public int getTargetSdkVersion() { return targetSdkVersion; } public void printUniqueId(PrintWriter pw) { UserHandle.formatUid(pw, callingUid); pw.print("/"); Loading Loading @@ -1441,11 +1433,6 @@ public final class JobStatus { } } private static int resolveTargetSdkVersion(JobInfo job) { return LocalServices.getService(PackageManagerInternal.class) .getPackageTargetSdkVersion(job.getService().getPackageName()); } // Dumpsys infrastructure public void dump(PrintWriter pw, String prefix, boolean full, long elapsedRealtimeMillis) { pw.print(prefix); UserHandle.formatUid(pw, callingUid); Loading tests/JobSchedulerPerfTests/Android.bp 0 → 100644 +25 −0 Original line number Diff line number Diff line // Copyright (C) 2019 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. android_test { name: "JobSchedulerPerfTests", srcs: ["src/**/*.java"], static_libs: [ "androidx.test.rules", "apct-perftests-utils", "services", ], platform_apis: true, certificate: "platform", } tests/JobSchedulerPerfTests/AndroidManifest.xml 0 → 100644 +27 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2018 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.frameworks.perftests.job"> <uses-sdk android:minSdkVersion="21" /> <application> <uses-library android:name="android.test.runner" /> </application> <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" android:targetPackage="com.android.frameworks.perftests.job"/> </manifest> Loading
services/core/java/com/android/server/job/JobSchedulerService.java +4 −4 Original line number Diff line number Diff line Loading @@ -1498,16 +1498,16 @@ public class JobSchedulerService extends com.android.server.SystemService } /** * Called when we want to remove a JobStatus object that we've finished executing. Returns the * object removed. * Called when we want to remove a JobStatus object that we've finished executing. * @return true if the job was removed. */ private boolean stopTrackingJobLocked(JobStatus jobStatus, JobStatus incomingJob, boolean writeBack) { boolean removeFromPersisted) { // Deal with any remaining work items in the old job. jobStatus.stopTrackingJobLocked(ActivityManager.getService(), incomingJob); // Remove from store as well as controllers. final boolean removed = mJobs.remove(jobStatus, writeBack); final boolean removed = mJobs.remove(jobStatus, removeFromPersisted); if (removed && mReadyToRock) { for (int i=0; i<mControllers.size(); i++) { StateController controller = mControllers.get(i); Loading
services/core/java/com/android/server/job/JobStore.java +20 −4 Original line number Diff line number Diff line Loading @@ -235,10 +235,11 @@ public final class JobStore { /** * Remove the provided job. Will also delete the job if it was persisted. * @param writeBack If true, the job will be deleted (if it was persisted) immediately. * @param removeFromPersisted If true, the job will be removed from the persisted job list * immediately (if it was persisted). * @return Whether or not the job existed to be removed. */ public boolean remove(JobStatus jobStatus, boolean writeBack) { public boolean remove(JobStatus jobStatus, boolean removeFromPersisted) { boolean removed = mJobSet.remove(jobStatus); if (!removed) { if (DEBUG) { Loading @@ -246,7 +247,7 @@ public final class JobStore { } return false; } if (writeBack && jobStatus.isPersisted()) { if (removeFromPersisted && jobStatus.isPersisted()) { maybeWriteStatusToDiskAsync(); } return removed; Loading Loading @@ -344,6 +345,19 @@ public final class JobStore { new ReadJobMapFromDiskRunnable(jobSet, rtcGood).run(); } /** Write persisted JobStore state to disk synchronously. Should only be used for testing. */ @VisibleForTesting public void writeStatusToDiskForTesting() { synchronized (mWriteScheduleLock) { if (mWriteScheduled) { throw new IllegalStateException("An asynchronous write is already scheduled."); } mWriteScheduled = mWriteInProgress = true; mWriteRunnable.run(); } } /** * Wait for any pending write to the persistent store to clear * @param maxWaitMillis Maximum time from present to wait Loading Loading @@ -1049,7 +1063,9 @@ public final class JobStore { } } static final class JobSet { /** Set of all tracked jobs. */ @VisibleForTesting public static final class JobSet { @VisibleForTesting // Key is the getUid() originator of the jobs in each sheaf final SparseArray<ArraySet<JobStatus>> mJobs; Loading
services/core/java/com/android/server/job/controllers/JobStatus.java +5 −18 Original line number Diff line number Diff line Loading @@ -24,7 +24,6 @@ import android.app.job.JobInfo; import android.app.job.JobWorkItem; import android.content.ClipData; import android.content.ComponentName; import android.content.pm.PackageManagerInternal; import android.net.Network; import android.net.Uri; import android.os.RemoteException; Loading Loading @@ -131,7 +130,6 @@ public final class JobStatus { * that underly Sync Manager operation. */ final int callingUid; final int targetSdkVersion; final String batteryName; /** Loading Loading @@ -344,7 +342,6 @@ public final class JobStatus { * @param job The actual requested parameters for the job * @param callingUid Identity of the app that is scheduling the job. This may not be the * app in which the job is implemented; such as with sync jobs. * @param targetSdkVersion The targetSdkVersion of the app in which the job will run. * @param sourcePackageName The package name of the app in which the job will run. * @param sourceUserId The user in which the job will run * @param standbyBucket The standby bucket that the source package is currently assigned to, Loading @@ -363,13 +360,12 @@ public final class JobStatus { * @param lastFailedRunTime When did we last run this job only to have it stop incomplete? * @param internalFlags Non-API property flags about this job */ private JobStatus(JobInfo job, int callingUid, int targetSdkVersion, String sourcePackageName, private JobStatus(JobInfo job, int callingUid, String sourcePackageName, int sourceUserId, int standbyBucket, long heartbeat, String tag, int numFailures, long earliestRunTimeElapsedMillis, long latestRunTimeElapsedMillis, long lastSuccessfulRunTime, long lastFailedRunTime, int internalFlags) { this.job = job; this.callingUid = callingUid; this.targetSdkVersion = targetSdkVersion; this.standbyBucket = standbyBucket; this.baseHeartbeat = heartbeat; Loading Loading @@ -439,7 +435,7 @@ public final class JobStatus { /** Copy constructor: used specifically when cloning JobStatus objects for persistence, * so we preserve RTC window bounds if the source object has them. */ public JobStatus(JobStatus jobStatus) { this(jobStatus.getJob(), jobStatus.getUid(), jobStatus.targetSdkVersion, this(jobStatus.getJob(), jobStatus.getUid(), jobStatus.getSourcePackageName(), jobStatus.getSourceUserId(), jobStatus.getStandbyBucket(), jobStatus.getBaseHeartbeat(), jobStatus.getSourceTag(), jobStatus.getNumFailures(), Loading Loading @@ -468,7 +464,7 @@ public final class JobStatus { long lastSuccessfulRunTime, long lastFailedRunTime, Pair<Long, Long> persistedExecutionTimesUTC, int innerFlags) { this(job, callingUid, resolveTargetSdkVersion(job), sourcePkgName, sourceUserId, this(job, callingUid, sourcePkgName, sourceUserId, standbyBucket, baseHeartbeat, sourceTag, 0, earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis, Loading @@ -491,7 +487,7 @@ public final class JobStatus { long newEarliestRuntimeElapsedMillis, long newLatestRuntimeElapsedMillis, int backoffAttempt, long lastSuccessfulRunTime, long lastFailedRunTime) { this(rescheduling.job, rescheduling.getUid(), resolveTargetSdkVersion(rescheduling.job), this(rescheduling.job, rescheduling.getUid(), rescheduling.getSourcePackageName(), rescheduling.getSourceUserId(), rescheduling.getStandbyBucket(), newBaseHeartbeat, rescheduling.getSourceTag(), backoffAttempt, newEarliestRuntimeElapsedMillis, Loading Loading @@ -533,7 +529,7 @@ public final class JobStatus { long currentHeartbeat = js != null ? js.baseHeartbeatForApp(jobPackage, sourceUserId, standbyBucket) : 0; return new JobStatus(job, callingUid, resolveTargetSdkVersion(job), sourcePkg, sourceUserId, return new JobStatus(job, callingUid, sourcePkg, sourceUserId, standbyBucket, currentHeartbeat, tag, 0, earliestRunTimeElapsedMillis, latestRunTimeElapsedMillis, 0 /* lastSuccessfulRunTime */, 0 /* lastFailedRunTime */, Loading Loading @@ -681,10 +677,6 @@ public final class JobStatus { return job.getId(); } public int getTargetSdkVersion() { return targetSdkVersion; } public void printUniqueId(PrintWriter pw) { UserHandle.formatUid(pw, callingUid); pw.print("/"); Loading Loading @@ -1441,11 +1433,6 @@ public final class JobStatus { } } private static int resolveTargetSdkVersion(JobInfo job) { return LocalServices.getService(PackageManagerInternal.class) .getPackageTargetSdkVersion(job.getService().getPackageName()); } // Dumpsys infrastructure public void dump(PrintWriter pw, String prefix, boolean full, long elapsedRealtimeMillis) { pw.print(prefix); UserHandle.formatUid(pw, callingUid); Loading
tests/JobSchedulerPerfTests/Android.bp 0 → 100644 +25 −0 Original line number Diff line number Diff line // Copyright (C) 2019 The Android Open Source Project // // Licensed under the Apache License, Version 2.0 (the "License"); // you may not use this file except in compliance with the License. // You may obtain a copy of the License at // // http://www.apache.org/licenses/LICENSE-2.0 // // Unless required by applicable law or agreed to in writing, software // distributed under the License is distributed on an "AS IS" BASIS, // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. // See the License for the specific language governing permissions and // limitations under the License. android_test { name: "JobSchedulerPerfTests", srcs: ["src/**/*.java"], static_libs: [ "androidx.test.rules", "apct-perftests-utils", "services", ], platform_apis: true, certificate: "platform", }
tests/JobSchedulerPerfTests/AndroidManifest.xml 0 → 100644 +27 −0 Original line number Diff line number Diff line <?xml version="1.0" encoding="utf-8"?> <!-- Copyright (C) 2018 The Android Open Source Project Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. --> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.android.frameworks.perftests.job"> <uses-sdk android:minSdkVersion="21" /> <application> <uses-library android:name="android.test.runner" /> </application> <instrumentation android:name="androidx.test.runner.AndroidJUnitRunner" android:targetPackage="com.android.frameworks.perftests.job"/> </manifest>