summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java3
-rw-r--r--services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java78
2 files changed, 66 insertions, 15 deletions
diff --git a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
index db2c742b8d4e..16828588766d 100644
--- a/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
+++ b/services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java
@@ -649,8 +649,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub {
// hasn't actually been updated.
onPackageReplaced(apexPackageName);
}
-
- mPackageHealthObserver.onBootCompleted();
+ mPackageHealthObserver.onBootCompletedAsync();
});
}
diff --git a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
index 748a6613091e..bcef66ce2a53 100644
--- a/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
+++ b/services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java
@@ -32,6 +32,7 @@ import android.os.FileUtils;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.PowerManager;
+import android.os.SystemProperties;
import android.text.TextUtils;
import android.util.Slog;
import android.util.StatsLog;
@@ -49,9 +50,12 @@ import java.io.IOException;
import java.io.PrintWriter;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.TimeUnit;
/**
- * {@code PackageHealthObserver} for {@code RollbackManagerService}.
+ * {@link PackageHealthObserver} for {@link RollbackManagerService}.
+ * This class monitors crashes and triggers RollbackManager rollback accordingly.
+ * It also monitors native crashes for some short while after boot.
*
* @hide
*/
@@ -59,12 +63,21 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
private static final String TAG = "RollbackPackageHealthObserver";
private static final String NAME = "rollback-observer";
private static final int INVALID_ROLLBACK_ID = -1;
+ // TODO: make the following values configurable via DeviceConfig
+ private static final long NATIVE_CRASH_POLLING_INTERVAL_MILLIS =
+ TimeUnit.SECONDS.toMillis(30);
+ private static final long NUMBER_OF_NATIVE_CRASH_POLLS = 10;
+
private final Context mContext;
private final Handler mHandler;
private final File mLastStagedRollbackIdFile;
+ // this field is initialized in the c'tor and then only accessed from mHandler thread, so
+ // no need to guard with a lock
+ private long mNumberOfNativeCrashPollsRemaining;
RollbackPackageHealthObserver(Context context) {
mContext = context;
+ mNumberOfNativeCrashPollsRemaining = NUMBER_OF_NATIVE_CRASH_POLLS;
HandlerThread handlerThread = new HandlerThread("RollbackPackageHealthObserver");
handlerThread.start();
mHandler = handlerThread.getThreadHandler();
@@ -76,8 +89,6 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
@Override
public int onHealthCheckFailed(VersionedPackage failedPackage) {
- VersionedPackage moduleMetadataPackage = getModuleMetadataPackage();
-
if (getAvailableRollback(mContext.getSystemService(RollbackManager.class), failedPackage)
== null) {
// Don't handle the notification, no rollbacks available for the package
@@ -145,16 +156,29 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
PackageWatchdog.getInstance(mContext).startObservingHealth(this, packages, durationMs);
}
- /** Verifies the rollback state after a reboot. */
- public void onBootCompleted() {
+ /** Verifies the rollback state after a reboot and schedules polling for sometime after reboot
+ * to check for native crashes and mitigate them if needed.
+ */
+ public void onBootCompletedAsync() {
+ mHandler.post(()->onBootCompleted());
+ }
+
+ private void onBootCompleted() {
+ RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
+ PackageInstaller packageInstaller = mContext.getPackageManager().getPackageInstaller();
+ String moduleMetadataPackageName = getModuleMetadataPackageName();
+ VersionedPackage newModuleMetadataPackage = getModuleMetadataPackage();
+
+ if (getAvailableRollback(rollbackManager, newModuleMetadataPackage) != null) {
+ scheduleCheckAndMitigateNativeCrashes();
+ }
+
int rollbackId = popLastStagedRollbackId();
if (rollbackId == INVALID_ROLLBACK_ID) {
// No staged rollback before reboot
return;
}
- RollbackManager rollbackManager = mContext.getSystemService(RollbackManager.class);
- PackageInstaller packageInstaller = mContext.getPackageManager().getPackageInstaller();
RollbackInfo rollback = null;
for (RollbackInfo info : rollbackManager.getRecentlyCommittedRollbacks()) {
if (rollbackId == info.getRollbackId()) {
@@ -168,14 +192,12 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
return;
}
- String moduleMetadataPackageName = getModuleMetadataPackageName();
-
// Use the version of the metadata package that was installed before
// we rolled back for logging purposes.
- VersionedPackage moduleMetadataPackage = null;
+ VersionedPackage oldModuleMetadataPackage = null;
for (PackageRollbackInfo packageRollback : rollback.getPackages()) {
if (packageRollback.getPackageName().equals(moduleMetadataPackageName)) {
- moduleMetadataPackage = packageRollback.getVersionRolledBackFrom();
+ oldModuleMetadataPackage = packageRollback.getVersionRolledBackFrom();
break;
}
}
@@ -187,12 +209,12 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
return;
}
if (sessionInfo.isStagedSessionApplied()) {
- logEvent(moduleMetadataPackage,
+ logEvent(oldModuleMetadataPackage,
StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_SUCCESS);
} else if (sessionInfo.isStagedSessionReady()) {
// TODO: What do for staged session ready but not applied
} else {
- logEvent(moduleMetadataPackage,
+ logEvent(oldModuleMetadataPackage,
StatsLog.WATCHDOG_ROLLBACK_OCCURRED__ROLLBACK_TYPE__ROLLBACK_FAILURE);
}
}
@@ -320,4 +342,34 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve
moduleMetadataPackage.getPackageName(), moduleMetadataPackage.getVersionCode());
}
}
+
+ /**
+ * This method should be only called on mHandler thread, since it modifies
+ * {@link #mNumberOfNativeCrashPollsRemaining} and we want to keep this class lock free.
+ */
+ private void checkAndMitigateNativeCrashes() {
+ mNumberOfNativeCrashPollsRemaining--;
+ // Check if native watchdog reported a crash
+ if ("1".equals(SystemProperties.get("ro.init.updatable_crashing"))) {
+ execute(getModuleMetadataPackage());
+ // we stop polling after an attempt to execute rollback, regardless of whether the
+ // attempt succeeds or not
+ } else {
+ if (mNumberOfNativeCrashPollsRemaining > 0) {
+ mHandler.postDelayed(() -> checkAndMitigateNativeCrashes(),
+ NATIVE_CRASH_POLLING_INTERVAL_MILLIS);
+ }
+ }
+ }
+
+ /**
+ * Since this method can eventually trigger a RollbackManager rollback, it should be called
+ * only once boot has completed {@code onBootCompleted} and not earlier, because the install
+ * session must be entirely completed before we try to rollback.
+ */
+ private void scheduleCheckAndMitigateNativeCrashes() {
+ Slog.i(TAG, "Scheduling " + mNumberOfNativeCrashPollsRemaining + " polls to check "
+ + "and mitigate native crashes");
+ mHandler.post(()->checkAndMitigateNativeCrashes());
+ }
}