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
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -495,6 +495,45 @@ public class StagedRollbackTest {
|
||||
assertThat(sm.isCheckpointSupported()).isTrue();
|
||||
}
|
||||
|
||||
@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();
|
||||
|
||||
@@ -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";
|
||||
|
||||
Reference in New Issue
Block a user