diff options
| author | 2019-03-15 14:56:53 -0700 | |
|---|---|---|
| committer | 2019-03-15 15:03:13 -0700 | |
| commit | 8e73785780fcf65f974681073ce5419aa3b9c37f (patch) | |
| tree | 5629d88689118236f73d251b4396f26a0507c04a | |
| parent | e4edae37982c1092f721b0a28bbc9c1fec3fe6dd (diff) | |
Don't schedule jobs in 'bad' apps
When an app has been temporarily marked 'bad' because it's been
crashing, binding to its services will appear to succeed but not
actually begin execution. This led to spurious timeouts when jobs were
scheduled in this state.
Fix by incorporating a 'bad' state check into the job runnability
determination.
Fixes: 125505588
Test: atest CtsJobSchedulerTestCases
Test: manual (repeatedly crashing app then running jobs)
Change-Id: I04003265086d74517e7838f1d1332cc4d3ef483c
3 files changed, 31 insertions, 8 deletions
diff --git a/core/java/android/app/ActivityManagerInternal.java b/core/java/android/app/ActivityManagerInternal.java index 664f0a37a459..f6cfe4855070 100644 --- a/core/java/android/app/ActivityManagerInternal.java +++ b/core/java/android/app/ActivityManagerInternal.java @@ -329,6 +329,9 @@ public abstract class ActivityManagerInternal { /** Returns true if the given uid is the app in the foreground. */ public abstract boolean isAppForeground(int uid); + /** Returns true if the given uid is currently marked 'bad' */ + public abstract boolean isAppBad(ApplicationInfo info); + /** Remove pending backup for the given userId. */ public abstract void clearPendingBackup(int userId); diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java index 178a55b9ca6d..9bd683f20f67 100644 --- a/services/core/java/com/android/server/am/ActivityManagerService.java +++ b/services/core/java/com/android/server/am/ActivityManagerService.java @@ -5492,6 +5492,12 @@ public class ActivityManagerService extends IActivityManager.Stub } } + private boolean isAppBad(ApplicationInfo info) { + synchronized (this) { + return mAppErrors.isBadProcessLocked(info); + } + } + // NOTE: this is an internal method used by the OnShellCommand implementation only and should // be guarded by permission checking. int getUidState(int uid) { @@ -18078,6 +18084,11 @@ public class ActivityManagerService extends IActivityManager.Stub } @Override + public boolean isAppBad(ApplicationInfo info) { + return ActivityManagerService.this.isAppBad(info); + } + + @Override public void clearPendingBackup(int userId) { ActivityManagerService.this.clearPendingBackup(userId); } diff --git a/services/core/java/com/android/server/job/JobSchedulerService.java b/services/core/java/com/android/server/job/JobSchedulerService.java index cefe583fc5d1..14b73012d126 100644 --- a/services/core/java/com/android/server/job/JobSchedulerService.java +++ b/services/core/java/com/android/server/job/JobSchedulerService.java @@ -2494,24 +2494,33 @@ public class JobSchedulerService extends com.android.server.SystemService } } - // The expensive check last: validate that the defined package+service is + // The expensive check: validate that the defined package+service is // still present & viable. - final boolean componentPresent; + final ServiceInfo service; try { - componentPresent = (AppGlobals.getPackageManager().getServiceInfo( + service = AppGlobals.getPackageManager().getServiceInfo( job.getServiceComponent(), PackageManager.MATCH_DEBUG_TRIAGED_MISSING, - job.getUserId()) != null); + job.getUserId()); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); } - if (DEBUG) { - Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString() - + " componentPresent=" + componentPresent); + if (service == null) { + if (DEBUG) { + Slog.v(TAG, "isReadyToBeExecutedLocked: " + job.toShortString() + + " component not present"); + } + return false; } // Everything else checked out so far, so this is the final yes/no check - return componentPresent; + final boolean appIsBad = mActivityManagerInternal.isAppBad(service.applicationInfo); + if (DEBUG) { + if (appIsBad) { + Slog.i(TAG, "App is bad for " + job.toShortString() + " so not runnable"); + } + } + return !appIsBad; } private void evaluateControllerStatesLocked(final JobStatus job) { |