diff options
author | Gavin Corkery <gavincorkery@google.com> | 2021-02-15 14:00:50 +0000 |
---|---|---|
committer | Gavin Corkery <gavincorkery@google.com> | 2021-02-15 14:05:41 +0000 |
commit | f72f94ee549cfe6c07ff2c40b8ff89dc9db1e201 (patch) | |
tree | f4841a82cb7b7752b962cb742d4f37b0b1d6da2c | |
parent | c726ac66bad178daa436953a55cb62273950a260 (diff) |
Allow observers to be loaded correctly
Removes dependency on PackageManager when loading observers early
in the boot. This is done by associating each MonitoredPackage with
a "packageName" string rather than a VersionedPackage. Incoming
failure calls will be matched against this string.
Added test case to cover this condition.
Test: Manual. Install apk with rollback enabled,
reboot, adb shell dumpsys rollback,
ensure package is still being monitored
Test: atest StagedRollbackTest
Bug: 177793481
Change-Id: I282ac75a9e97a58c3c0bf3e8978fd010ec5294cd
3 files changed, 75 insertions, 13 deletions
diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java index 41903fcd165f..67f6ec9f9a41 100644 --- a/services/core/java/com/android/server/PackageWatchdog.java +++ b/services/core/java/com/android/server/PackageWatchdog.java @@ -902,10 +902,13 @@ public class PackageWatchdog { if (registeredObserver != null) { Iterator<MonitoredPackage> it = failedPackages.iterator(); while (it.hasNext()) { - VersionedPackage versionedPkg = it.next().mPackage; - Slog.i(TAG, "Explicit health check failed for package " + versionedPkg); - registeredObserver.execute(versionedPkg, - PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK, 1); + VersionedPackage versionedPkg = getVersionedPackage(it.next().getName()); + if (versionedPkg != null) { + Slog.i(TAG, + "Explicit health check failed for package " + versionedPkg); + registeredObserver.execute(versionedPkg, + PackageWatchdog.FAILURE_REASON_EXPLICIT_HEALTH_CHECK, 1); + } } } } @@ -1342,11 +1345,7 @@ public class PackageWatchdog { MonitoredPackage newMonitoredPackage(String name, long durationMs, long healthCheckDurationMs, boolean hasPassedHealthCheck, LongArrayQueue mitigationCalls) { - VersionedPackage pkg = getVersionedPackage(name); - if (pkg == null) { - return null; - } - return new MonitoredPackage(pkg, durationMs, healthCheckDurationMs, + return new MonitoredPackage(name, durationMs, healthCheckDurationMs, hasPassedHealthCheck, mitigationCalls); } @@ -1371,7 +1370,7 @@ public class PackageWatchdog { * instances of this class. */ class MonitoredPackage { - private final VersionedPackage mPackage; + private final String mPackageName; // Times when package failures happen sorted in ascending order @GuardedBy("mLock") private final LongArrayQueue mFailureHistory = new LongArrayQueue(); @@ -1399,10 +1398,10 @@ public class PackageWatchdog { @GuardedBy("mLock") private long mHealthCheckDurationMs = Long.MAX_VALUE; - MonitoredPackage(VersionedPackage pkg, long durationMs, + MonitoredPackage(String packageName, long durationMs, long healthCheckDurationMs, boolean hasPassedHealthCheck, LongArrayQueue mitigationCalls) { - mPackage = pkg; + mPackageName = packageName; mDurationMs = durationMs; mHealthCheckDurationMs = healthCheckDurationMs; mHasPassedHealthCheck = hasPassedHealthCheck; @@ -1556,7 +1555,7 @@ public class PackageWatchdog { /** Returns the monitored package name. */ private String getName() { - return mPackage.getPackageName(); + return mPackageName; } /** diff --git a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java index 8b34755f73b8..0508125edfc8 100644 --- a/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java +++ b/tests/RollbackTest/RollbackTest/src/com/android/tests/rollback/StagedRollbackTest.java @@ -496,6 +496,45 @@ public class StagedRollbackTest { } @Test + public void testWatchdogMonitorsAcrossReboots_Phase1_Install() throws Exception { + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(-1); + Install.single(TestApp.A1).commit(); + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + InstallUtils.processUserData(TestApp.A); + + Install.single(TestApp.ACrashing2).setEnableRollback().setStaged().commit(); + } + + @Test + public void testWatchdogMonitorsAcrossReboots_Phase2_VerifyInstall() throws Exception { + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(2); + + // Trigger rollback of test app. + DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK, + PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT, + Integer.toString(5), false); + + // The final crash that causes rollback will come from the host side. + RollbackUtils.sendCrashBroadcast(TestApp.A, 4); + } + + @Test + public void testWatchdogMonitorsAcrossReboots_Phase3_VerifyRollback() { + assertThat(InstallUtils.getInstalledVersion(TestApp.A)).isEqualTo(1); + InstallUtils.processUserData(TestApp.A); + + RollbackManager rm = RollbackUtils.getRollbackManager(); + RollbackInfo rollback = getUniqueRollbackInfoForPackage( + rm.getRecentlyCommittedRollbacks(), TestApp.A); + assertThat(rollback).isNotNull(); + assertThat(rollback).packagesContainsExactly( + Rollback.from(TestApp.A2).to(TestApp.A1)); + assertThat(rollback).causePackagesContainsExactly(TestApp.ACrashing2); + assertThat(rollback).isStaged(); + assertThat(rollback.getCommittedSessionId()).isNotEqualTo(-1); + } + + @Test public void hasMainlineModule() throws Exception { String pkgName = getModuleMetadataPackageName(); boolean existed = InstrumentationRegistry.getInstrumentation().getContext() diff --git a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java index 67417bd39864..65fb7b6c8cc6 100644 --- a/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java +++ b/tests/RollbackTest/StagedRollbackTest/src/com/android/tests/rollback/host/StagedRollbackTest.java @@ -554,6 +554,30 @@ public class StagedRollbackTest extends BaseHostJUnit4Test { }); } + /** + * Tests that packages are monitored across multiple reboots. + */ + @Test + public void testWatchdogMonitorsAcrossReboots() throws Exception { + runPhase("testWatchdogMonitorsAcrossReboots_Phase1_Install"); + + // The first reboot will make the rollback available. + // Information about which packages are monitored will be persisted to a file before the + // second reboot, and read from disk after the second reboot. + getDevice().reboot(); + getDevice().reboot(); + + runPhase("testWatchdogMonitorsAcrossReboots_Phase2_VerifyInstall"); + + // Launch the app to crash to trigger rollback + startActivity(TESTAPP_A); + // Wait for reboot to happen + waitForDeviceNotAvailable(2, TimeUnit.MINUTES); + getDevice().waitForDeviceAvailable(); + + runPhase("testWatchdogMonitorsAcrossReboots_Phase3_VerifyRollback"); + } + private void pushTestApex() throws Exception { CompatibilityBuildHelper buildHelper = new CompatibilityBuildHelper(getBuild()); final String fileName = APK_IN_APEX_TESTAPEX_NAME + "_v1.apex"; |