summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Christopher Tate <ctate@google.com> 2019-03-15 14:56:53 -0700
committer Christopher Tate <ctate@google.com> 2019-03-15 15:03:13 -0700
commit8e73785780fcf65f974681073ce5419aa3b9c37f (patch)
tree5629d88689118236f73d251b4396f26a0507c04a
parente4edae37982c1092f721b0a28bbc9c1fec3fe6dd (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
-rw-r--r--core/java/android/app/ActivityManagerInternal.java3
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java11
-rw-r--r--services/core/java/com/android/server/job/JobSchedulerService.java25
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) {