Loading services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +1 −2 Original line number Diff line number Diff line Loading @@ -649,8 +649,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { // hasn't actually been updated. onPackageReplaced(apexPackageName); } mPackageHealthObserver.onBootCompleted(); mPackageHealthObserver.onBootCompletedAsync(); }); } Loading services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java +65 −13 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 */ Loading @@ -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(); Loading @@ -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 Loading Loading @@ -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()) { Loading @@ -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; } } Loading @@ -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); } } Loading Loading @@ -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()); } } Loading
services/core/java/com/android/server/rollback/RollbackManagerServiceImpl.java +1 −2 Original line number Diff line number Diff line Loading @@ -649,8 +649,7 @@ class RollbackManagerServiceImpl extends IRollbackManager.Stub { // hasn't actually been updated. onPackageReplaced(apexPackageName); } mPackageHealthObserver.onBootCompleted(); mPackageHealthObserver.onBootCompletedAsync(); }); } Loading
services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java +65 −13 Original line number Diff line number Diff line Loading @@ -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; Loading @@ -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 */ Loading @@ -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(); Loading @@ -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 Loading Loading @@ -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()) { Loading @@ -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; } } Loading @@ -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); } } Loading Loading @@ -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()); } }