summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
author Songchun Fan <schfan@google.com> 2020-10-26 17:35:06 +0000
committer Android (Google) Code Review <android-gerrit@google.com> 2020-10-26 17:35:06 +0000
commitd9d9dbae1e0316a01be310c39c17b87cbe263445 (patch)
tree4a307d96f02207064cd16ba9b197270a6025bffc
parent23fb7a6adc797328ff5e2165a778656e04423add (diff)
parentdfd4162711f387d2a08b844be09af8d0182f6435 (diff)
Merge "[am/incremental] make package unstartable if it crashes/ANRs while loading"
-rw-r--r--services/core/java/android/content/pm/PackageManagerInternal.java4
-rw-r--r--services/core/java/com/android/server/am/ActivityManagerService.java4
-rw-r--r--services/core/java/com/android/server/am/ProcessRecord.java6
-rw-r--r--services/core/java/com/android/server/pm/IncrementalStates.java27
-rw-r--r--services/core/java/com/android/server/pm/PackageManagerService.java14
-rw-r--r--services/core/java/com/android/server/pm/PackageSettingBase.java8
-rw-r--r--services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java14
7 files changed, 77 insertions, 0 deletions
diff --git a/services/core/java/android/content/pm/PackageManagerInternal.java b/services/core/java/android/content/pm/PackageManagerInternal.java
index 4c8925bd4828..70cf04522c45 100644
--- a/services/core/java/android/content/pm/PackageManagerInternal.java
+++ b/services/core/java/android/content/pm/PackageManagerInternal.java
@@ -1122,4 +1122,8 @@ public abstract class PackageManagerInternal {
public abstract IncrementalStatesInfo getIncrementalStatesInfo(String packageName,
int filterCallingUid, int userId);
+ /**
+ * Notifies that a package has crashed or ANR'd.
+ */
+ public abstract void notifyPackageCrashOrAnr(String packageName);
}
diff --git a/services/core/java/com/android/server/am/ActivityManagerService.java b/services/core/java/com/android/server/am/ActivityManagerService.java
index 32d95f594ce9..51cbfcf64322 100644
--- a/services/core/java/com/android/server/am/ActivityManagerService.java
+++ b/services/core/java/com/android/server/am/ActivityManagerService.java
@@ -7595,6 +7595,10 @@ public class ActivityManagerService extends IActivityManager.Stub
eventType, r, processName, null, null, null, null, null, null, crashInfo);
mAppErrors.crashApplication(r, crashInfo);
+ // Notify package manager service to possibly update package state
+ if (r != null && r.info != null && r.info.packageName != null) {
+ mPackageManagerInt.notifyPackageCrashOrAnr(r.info.packageName);
+ }
}
public void handleApplicationStrictModeViolation(
diff --git a/services/core/java/com/android/server/am/ProcessRecord.java b/services/core/java/com/android/server/am/ProcessRecord.java
index 53c6758585cf..ccdd6a746239 100644
--- a/services/core/java/com/android/server/am/ProcessRecord.java
+++ b/services/core/java/com/android/server/am/ProcessRecord.java
@@ -1764,6 +1764,12 @@ class ProcessRecord implements WindowProcessListener {
makeAppNotRespondingLocked(activityShortComponentName,
annotation != null ? "ANR " + annotation : "ANR", info.toString());
+ // Notify package manager service to possibly update package state
+ if (aInfo != null && aInfo.packageName != null) {
+ mService.getPackageManagerInternalLocked().notifyPackageCrashOrAnr(
+ aInfo.packageName);
+ }
+
// mUiHandler can be null if the AMS is constructed with injector only. This will only
// happen in tests.
if (mService.mUiHandler != null) {
diff --git a/services/core/java/com/android/server/pm/IncrementalStates.java b/services/core/java/com/android/server/pm/IncrementalStates.java
index 26ace47776be..72803ac35a3f 100644
--- a/services/core/java/com/android/server/pm/IncrementalStates.java
+++ b/services/core/java/com/android/server/pm/IncrementalStates.java
@@ -119,6 +119,33 @@ public final class IncrementalStates {
}
}
+ /**
+ * Change the startable state if the app has crashed or ANR'd during loading.
+ * If the app is not loading (i.e., fully loaded), this event doesn't change startable state.
+ */
+ public void onCrashOrAnr() {
+ if (DEBUG) {
+ Slog.i(TAG, "received package crash or ANR event");
+ }
+ final boolean startableStateChanged;
+ synchronized (mLock) {
+ if (mStartableState.isStartable() && mLoadingState.isLoading()) {
+ // Changing from startable -> unstartable only if app is still loading.
+ mStartableState.adoptNewStartableStateLocked(false);
+ startableStateChanged = true;
+ } else {
+ // If the app is fully loaded, the crash or ANR is caused by the app itself, so
+ // we do not change the startable state.
+ startableStateChanged = false;
+ }
+ }
+ if (startableStateChanged) {
+ mHandler.post(PooledLambda.obtainRunnable(
+ IncrementalStates::reportStartableState,
+ IncrementalStates.this).recycleOnUse());
+ }
+ }
+
private void reportStartableState() {
final Callback callback;
final boolean startable;
diff --git a/services/core/java/com/android/server/pm/PackageManagerService.java b/services/core/java/com/android/server/pm/PackageManagerService.java
index 410fbe57bf26..37c39551bf40 100644
--- a/services/core/java/com/android/server/pm/PackageManagerService.java
+++ b/services/core/java/com/android/server/pm/PackageManagerService.java
@@ -25843,6 +25843,20 @@ public class PackageManagerService extends IPackageManager.Stub
}
return ps.getIncrementalStates();
}
+
+ @Override
+ public void notifyPackageCrashOrAnr(@NonNull String packageName) {
+ final PackageSetting ps;
+ synchronized (mLock) {
+ ps = mSettings.mPackages.get(packageName);
+ if (ps == null) {
+ Slog.w(TAG, "Failed notifyPackageCrash. Package " + packageName
+ + " is not installed");
+ return;
+ }
+ }
+ ps.setStatesOnCrashOrAnr();
+ }
}
diff --git a/services/core/java/com/android/server/pm/PackageSettingBase.java b/services/core/java/com/android/server/pm/PackageSettingBase.java
index be7c7c6ff1d6..ac76cf71ef67 100644
--- a/services/core/java/com/android/server/pm/PackageSettingBase.java
+++ b/services/core/java/com/android/server/pm/PackageSettingBase.java
@@ -772,6 +772,14 @@ public abstract class PackageSettingBase extends SettingBase {
}
/**
+ * Called to indicate that the running app has crashed or ANR'd. This might change the startable
+ * state of the package, depending on whether the package is fully loaded.
+ */
+ public void setStatesOnCrashOrAnr() {
+ incrementalStates.onCrashOrAnr();
+ }
+
+ /**
* Called to set the callback to listen for startable state changes.
*/
public void setIncrementalStatesCallback(IncrementalStates.Callback callback) {
diff --git a/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java b/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java
index 86758f18a407..40d959d9793d 100644
--- a/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java
+++ b/services/tests/servicestests/src/com/android/server/pm/IncrementalStatesTest.java
@@ -222,4 +222,18 @@ public class IncrementalStatesTest {
assertTrue(mFullyLoadedCalled.block(WAIT_TIMEOUT_MILLIS));
assertFalse(mIncrementalStates.isLoading());
}
+
+ /**
+ * Test startability transitions if app crashes or anrs
+ */
+ @Test
+ public void testStartableTransition_AppCrashOrAnr() {
+ mIncrementalStates.onCrashOrAnr();
+ assertFalse(mIncrementalStates.isStartable());
+ mIncrementalStates.setProgress(1.0f);
+ assertTrue(mIncrementalStates.isStartable());
+ mIncrementalStates.onCrashOrAnr();
+ // Test that if fully loaded, app remains startable even if it has crashed
+ assertTrue(mIncrementalStates.isStartable());
+ }
}