Loading services/core/java/com/android/server/PackageWatchdog.java +10 −8 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; import android.annotation.IntDef; import android.annotation.Nullable; import android.content.Context; import android.content.pm.VersionedPackage; import android.os.Environment; import android.os.Handler; import android.os.Looper; Loading Loading @@ -230,7 +231,6 @@ public class PackageWatchdog { return null; } // TODO(zezeozue:) Accept current versionCodes of failing packages? /** * Called when a process fails either due to a crash or ANR. * Loading @@ -239,15 +239,16 @@ public class PackageWatchdog { * * <p>This method could be called frequently if there is a severe problem on the device. */ public void onPackageFailure(String[] packages) { public void onPackageFailure(List<VersionedPackage> packages) { mWorkerHandler.post(() -> { synchronized (mLock) { if (mAllObservers.isEmpty()) { return; } for (int pIndex = 0; pIndex < packages.length; pIndex++) { String packageToReport = packages[pIndex]; for (int pIndex = 0; pIndex < packages.size(); pIndex++) { String packageToReport = packages.get(pIndex).getPackageName(); long packageVersionCode = packages.get(pIndex).getVersionCode(); // Observer that will receive failure for packageToReport PackageHealthObserver currentObserverToNotify = null; int currentObserverImpact = Integer.MAX_VALUE; Loading @@ -258,7 +259,8 @@ public class PackageWatchdog { PackageHealthObserver registeredObserver = observer.mRegisteredObserver; if (registeredObserver != null && observer.onPackageFailure(packageToReport)) { int impact = registeredObserver.onHealthCheckFailed(packageToReport); int impact = registeredObserver.onHealthCheckFailed(packageToReport, packageVersionCode); if (impact != PackageHealthObserverImpact.USER_IMPACT_NONE && impact < currentObserverImpact) { currentObserverToNotify = registeredObserver; Loading @@ -269,7 +271,7 @@ public class PackageWatchdog { // Execute action with least user impact if (currentObserverToNotify != null) { currentObserverToNotify.execute(packageToReport); currentObserverToNotify.execute(packageToReport, packageVersionCode); } } } Loading Loading @@ -313,14 +315,14 @@ public class PackageWatchdog { * @return any one of {@link PackageHealthObserverImpact} to express the impact * to the user on {@link #execute} */ @PackageHealthObserverImpact int onHealthCheckFailed(String packageName); @PackageHealthObserverImpact int onHealthCheckFailed(String packageName, long versionCdoe); /** * Executes mitigation for {@link #onHealthCheckFailed}. * * @return {@code true} if action was executed successfully, {@code false} otherwise */ boolean execute(String packageName); boolean execute(String packageName, long versionCode); // TODO(zezeozue): Ensure uniqueness? /** Loading services/core/java/com/android/server/am/AppErrors.java +5 −3 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.VersionedPackage; import android.net.Uri; import android.os.Binder; import android.os.Message; Loading @@ -60,6 +61,7 @@ import com.android.server.wm.WindowProcessController; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Collections; import java.util.List; /** * Controls error conditions in applications. Loading Loading @@ -411,7 +413,7 @@ class AppErrors { } else { // If a non-persistent app is stuck in crash loop, we want to inform // the package watchdog, maybe an update or experiment can be rolled back. mPackageWatchdog.onPackageFailure(r.getPackageList()); mPackageWatchdog.onPackageFailure(r.getPackageListWithVersionCode()); } } Loading Loading @@ -830,7 +832,7 @@ class AppErrors { void handleShowAnrUi(Message msg) { Dialog dialogToShow = null; String[] packageList = null; List<VersionedPackage> packageList = null; synchronized (mService) { AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj; final ProcessRecord proc = data.proc; Loading @@ -839,7 +841,7 @@ class AppErrors { return; } if (!proc.isPersistent()) { packageList = proc.getPackageList(); packageList = proc.getPackageListWithVersionCode(); } if (proc.anrDialog != null) { Slog.e(TAG, "App already has anr dialog: " + proc); Loading services/core/java/com/android/server/am/ProcessRecord.java +14 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.ServiceInfo; import android.content.pm.VersionedPackage; import android.content.res.CompatibilityInfo; import android.os.Binder; import android.os.Debug; Loading Loading @@ -66,6 +67,7 @@ import java.io.File; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Full information about a particular process that Loading Loading @@ -974,6 +976,18 @@ final class ProcessRecord implements WindowProcessListener { return list; } public List<VersionedPackage> getPackageListWithVersionCode() { int size = pkgList.size(); if (size == 0) { return null; } List<VersionedPackage> list = new ArrayList<>(); for (int i = 0; i < pkgList.size(); i++) { list.add(new VersionedPackage(pkgList.keyAt(i), pkgList.valueAt(i).appVersion)); } return list; } WindowProcessController getWindowProcessController() { return mWindowProcessController; } Loading services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java +8 −7 Original line number Diff line number Diff line Loading @@ -54,8 +54,8 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve } @Override public int onHealthCheckFailed(String packageName) { RollbackInfo rollback = getAvailableRollback(packageName); public int onHealthCheckFailed(String packageName, long versionCode) { RollbackInfo rollback = getAvailableRollback(packageName, versionCode); if (rollback == null) { // Don't handle the notification, no rollbacks available for the package return PackageHealthObserverImpact.USER_IMPACT_NONE; Loading @@ -65,8 +65,8 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve } @Override public boolean execute(String packageName) { RollbackInfo rollback = getAvailableRollback(packageName); public boolean execute(String packageName, long versionCode) { RollbackInfo rollback = getAvailableRollback(packageName, versionCode); if (rollback == null) { // Expected a rollback to be available, what happened? return false; Loading Loading @@ -110,11 +110,12 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve PackageWatchdog.getInstance(mContext).startObservingHealth(this, packages, durationMs); } private RollbackInfo getAvailableRollback(String packageName) { private RollbackInfo getAvailableRollback(String packageName, long versionCode) { for (RollbackInfo rollback : mRollbackManager.getAvailableRollbacks()) { for (PackageRollbackInfo packageRollback : rollback.getPackages()) { if (packageName.equals(packageRollback.getPackageName())) { // TODO(zezeozue): Only rollback if rollback version == failed package version if (packageName.equals(packageRollback.getPackageName()) && packageRollback.getVersionRolledBackFrom().getVersionCode() == versionCode) { return rollback; } } Loading tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java +53 −16 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import android.content.pm.VersionedPackage; import android.os.test.TestLooper; import android.support.test.InstrumentationRegistry; Loading @@ -47,6 +48,7 @@ public class PackageWatchdogTest { private static final String APP_B = "com.package.b"; private static final String APP_C = "com.package.c"; private static final String APP_D = "com.package.d"; private static final long VERSION_CODE = 1L; private static final String OBSERVER_NAME_1 = "observer1"; private static final String OBSERVER_NAME_2 = "observer2"; private static final String OBSERVER_NAME_3 = "observer3"; Loading Loading @@ -193,7 +195,7 @@ public class PackageWatchdogTest { // Then fail APP_A below the threshold for (int i = 0; i < TRIGGER_FAILURE_COUNT - 1; i++) { watchdog.onPackageFailure(new String[]{APP_A}); watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); } // Run handler so package failures are dispatched to observers Loading @@ -209,12 +211,10 @@ public class PackageWatchdogTest { * the failed packages. */ @Test public void testPackageFailureNotifyNone() throws Exception { public void testPackageFailureDifferentPackageNotifyNone() throws Exception { PackageWatchdog watchdog = createWatchdog(); TestObserver observer1 = new TestObserver(OBSERVER_NAME_1, PackageHealthObserverImpact.USER_IMPACT_HIGH); TestObserver observer2 = new TestObserver(OBSERVER_NAME_2, PackageHealthObserverImpact.USER_IMPACT_HIGH); TestObserver observer1 = new TestObserver(OBSERVER_NAME_1); TestObserver observer2 = new TestObserver(OBSERVER_NAME_2); watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), SHORT_DURATION); Loading @@ -222,7 +222,7 @@ public class PackageWatchdogTest { // Then fail APP_C (not observed) above the threshold for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) { watchdog.onPackageFailure(new String[]{APP_C}); watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_C, VERSION_CODE))); } // Run handler so package failures are dispatched to observers Loading @@ -233,6 +233,40 @@ public class PackageWatchdogTest { assertEquals(0, observer2.mFailedPackages.size()); } /** * Test package failure and does not notify any observer because the failed package version * does not match the available rollback-from-version. */ @Test public void testPackageFailureDifferentVersionNotifyNone() throws Exception { PackageWatchdog watchdog = createWatchdog(); long differentVersionCode = 2L; TestObserver observer = new TestObserver(OBSERVER_NAME_1) { public int onHealthCheckFailed(String packageName, long versionCode) { if (versionCode == VERSION_CODE) { // Only rollback for specific versionCode return PackageHealthObserverImpact.USER_IMPACT_MEDIUM; } return PackageHealthObserverImpact.USER_IMPACT_NONE; } }; watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION); // Then fail APP_A (different version) above the threshold for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) { watchdog.onPackageFailure(Arrays.asList( new VersionedPackage(APP_A, differentVersionCode))); } // Run handler so package failures are dispatched to observers mTestLooper.dispatchAll(); // Verify that observers are not notified assertEquals(0, observer.mFailedPackages.size()); } /** * Test package failure and notifies only least impact observers. */ Loading Loading @@ -260,7 +294,10 @@ public class PackageWatchdogTest { // Then fail all apps above the threshold for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) { watchdog.onPackageFailure(new String[]{APP_A, APP_B, APP_C, APP_D}); watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE), new VersionedPackage(APP_B, VERSION_CODE), new VersionedPackage(APP_C, VERSION_CODE), new VersionedPackage(APP_D, VERSION_CODE))); } // Run handler so package failures are dispatched to observers Loading Loading @@ -297,7 +334,7 @@ public class PackageWatchdogTest { * <ul> */ @Test public void testPackageFailureNotifyLeastSuccessively() throws Exception { public void testPackageFailureNotifyLeastImpactSuccessively() throws Exception { PackageWatchdog watchdog = createWatchdog(); TestObserver observerFirst = new TestObserver(OBSERVER_NAME_1, PackageHealthObserverImpact.USER_IMPACT_LOW); Loading @@ -310,7 +347,7 @@ public class PackageWatchdogTest { // Then fail APP_A above the threshold for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) { watchdog.onPackageFailure(new String[]{APP_A}); watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); } // Run handler so package failures are dispatched to observers mTestLooper.dispatchAll(); Loading @@ -327,7 +364,7 @@ public class PackageWatchdogTest { // Then fail APP_A again above the threshold for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) { watchdog.onPackageFailure(new String[]{APP_A}); watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); } // Run handler so package failures are dispatched to observers mTestLooper.dispatchAll(); Loading @@ -344,7 +381,7 @@ public class PackageWatchdogTest { // Then fail APP_A again above the threshold for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) { watchdog.onPackageFailure(new String[]{APP_A}); watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); } // Run handler so package failures are dispatched to observers mTestLooper.dispatchAll(); Loading @@ -361,7 +398,7 @@ public class PackageWatchdogTest { // Then fail APP_A again above the threshold for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) { watchdog.onPackageFailure(new String[]{APP_A}); watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); } // Run handler so package failures are dispatched to observers mTestLooper.dispatchAll(); Loading @@ -388,7 +425,7 @@ public class PackageWatchdogTest { // Then fail APP_A above the threshold for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) { watchdog.onPackageFailure(new String[]{APP_A}); watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); } // Run handler so package failures are dispatched to observers Loading Loading @@ -420,11 +457,11 @@ public class PackageWatchdogTest { mImpact = impact; } public int onHealthCheckFailed(String packageName) { public int onHealthCheckFailed(String packageName, long versionCode) { return mImpact; } public boolean execute(String packageName) { public boolean execute(String packageName, long versionCode) { mFailedPackages.add(packageName); return true; } Loading Loading
services/core/java/com/android/server/PackageWatchdog.java +10 −8 Original line number Diff line number Diff line Loading @@ -21,6 +21,7 @@ import static java.lang.annotation.RetentionPolicy.SOURCE; import android.annotation.IntDef; import android.annotation.Nullable; import android.content.Context; import android.content.pm.VersionedPackage; import android.os.Environment; import android.os.Handler; import android.os.Looper; Loading Loading @@ -230,7 +231,6 @@ public class PackageWatchdog { return null; } // TODO(zezeozue:) Accept current versionCodes of failing packages? /** * Called when a process fails either due to a crash or ANR. * Loading @@ -239,15 +239,16 @@ public class PackageWatchdog { * * <p>This method could be called frequently if there is a severe problem on the device. */ public void onPackageFailure(String[] packages) { public void onPackageFailure(List<VersionedPackage> packages) { mWorkerHandler.post(() -> { synchronized (mLock) { if (mAllObservers.isEmpty()) { return; } for (int pIndex = 0; pIndex < packages.length; pIndex++) { String packageToReport = packages[pIndex]; for (int pIndex = 0; pIndex < packages.size(); pIndex++) { String packageToReport = packages.get(pIndex).getPackageName(); long packageVersionCode = packages.get(pIndex).getVersionCode(); // Observer that will receive failure for packageToReport PackageHealthObserver currentObserverToNotify = null; int currentObserverImpact = Integer.MAX_VALUE; Loading @@ -258,7 +259,8 @@ public class PackageWatchdog { PackageHealthObserver registeredObserver = observer.mRegisteredObserver; if (registeredObserver != null && observer.onPackageFailure(packageToReport)) { int impact = registeredObserver.onHealthCheckFailed(packageToReport); int impact = registeredObserver.onHealthCheckFailed(packageToReport, packageVersionCode); if (impact != PackageHealthObserverImpact.USER_IMPACT_NONE && impact < currentObserverImpact) { currentObserverToNotify = registeredObserver; Loading @@ -269,7 +271,7 @@ public class PackageWatchdog { // Execute action with least user impact if (currentObserverToNotify != null) { currentObserverToNotify.execute(packageToReport); currentObserverToNotify.execute(packageToReport, packageVersionCode); } } } Loading Loading @@ -313,14 +315,14 @@ public class PackageWatchdog { * @return any one of {@link PackageHealthObserverImpact} to express the impact * to the user on {@link #execute} */ @PackageHealthObserverImpact int onHealthCheckFailed(String packageName); @PackageHealthObserverImpact int onHealthCheckFailed(String packageName, long versionCdoe); /** * Executes mitigation for {@link #onHealthCheckFailed}. * * @return {@code true} if action was executed successfully, {@code false} otherwise */ boolean execute(String packageName); boolean execute(String packageName, long versionCode); // TODO(zezeozue): Ensure uniqueness? /** Loading
services/core/java/com/android/server/am/AppErrors.java +5 −3 Original line number Diff line number Diff line Loading @@ -34,6 +34,7 @@ import android.content.ActivityNotFoundException; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.VersionedPackage; import android.net.Uri; import android.os.Binder; import android.os.Message; Loading @@ -60,6 +61,7 @@ import com.android.server.wm.WindowProcessController; import java.io.FileDescriptor; import java.io.PrintWriter; import java.util.Collections; import java.util.List; /** * Controls error conditions in applications. Loading Loading @@ -411,7 +413,7 @@ class AppErrors { } else { // If a non-persistent app is stuck in crash loop, we want to inform // the package watchdog, maybe an update or experiment can be rolled back. mPackageWatchdog.onPackageFailure(r.getPackageList()); mPackageWatchdog.onPackageFailure(r.getPackageListWithVersionCode()); } } Loading Loading @@ -830,7 +832,7 @@ class AppErrors { void handleShowAnrUi(Message msg) { Dialog dialogToShow = null; String[] packageList = null; List<VersionedPackage> packageList = null; synchronized (mService) { AppNotRespondingDialog.Data data = (AppNotRespondingDialog.Data) msg.obj; final ProcessRecord proc = data.proc; Loading @@ -839,7 +841,7 @@ class AppErrors { return; } if (!proc.isPersistent()) { packageList = proc.getPackageList(); packageList = proc.getPackageListWithVersionCode(); } if (proc.anrDialog != null) { Slog.e(TAG, "App already has anr dialog: " + proc); Loading
services/core/java/com/android/server/am/ProcessRecord.java +14 −0 Original line number Diff line number Diff line Loading @@ -32,6 +32,7 @@ import android.content.ComponentName; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.ServiceInfo; import android.content.pm.VersionedPackage; import android.content.res.CompatibilityInfo; import android.os.Binder; import android.os.Debug; Loading Loading @@ -66,6 +67,7 @@ import java.io.File; import java.io.PrintWriter; import java.util.ArrayList; import java.util.Arrays; import java.util.List; /** * Full information about a particular process that Loading Loading @@ -974,6 +976,18 @@ final class ProcessRecord implements WindowProcessListener { return list; } public List<VersionedPackage> getPackageListWithVersionCode() { int size = pkgList.size(); if (size == 0) { return null; } List<VersionedPackage> list = new ArrayList<>(); for (int i = 0; i < pkgList.size(); i++) { list.add(new VersionedPackage(pkgList.keyAt(i), pkgList.valueAt(i).appVersion)); } return list; } WindowProcessController getWindowProcessController() { return mWindowProcessController; } Loading
services/core/java/com/android/server/rollback/RollbackPackageHealthObserver.java +8 −7 Original line number Diff line number Diff line Loading @@ -54,8 +54,8 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve } @Override public int onHealthCheckFailed(String packageName) { RollbackInfo rollback = getAvailableRollback(packageName); public int onHealthCheckFailed(String packageName, long versionCode) { RollbackInfo rollback = getAvailableRollback(packageName, versionCode); if (rollback == null) { // Don't handle the notification, no rollbacks available for the package return PackageHealthObserverImpact.USER_IMPACT_NONE; Loading @@ -65,8 +65,8 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve } @Override public boolean execute(String packageName) { RollbackInfo rollback = getAvailableRollback(packageName); public boolean execute(String packageName, long versionCode) { RollbackInfo rollback = getAvailableRollback(packageName, versionCode); if (rollback == null) { // Expected a rollback to be available, what happened? return false; Loading Loading @@ -110,11 +110,12 @@ public final class RollbackPackageHealthObserver implements PackageHealthObserve PackageWatchdog.getInstance(mContext).startObservingHealth(this, packages, durationMs); } private RollbackInfo getAvailableRollback(String packageName) { private RollbackInfo getAvailableRollback(String packageName, long versionCode) { for (RollbackInfo rollback : mRollbackManager.getAvailableRollbacks()) { for (PackageRollbackInfo packageRollback : rollback.getPackages()) { if (packageName.equals(packageRollback.getPackageName())) { // TODO(zezeozue): Only rollback if rollback version == failed package version if (packageName.equals(packageRollback.getPackageName()) && packageRollback.getVersionRolledBackFrom().getVersionCode() == versionCode) { return rollback; } } Loading
tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java +53 −16 Original line number Diff line number Diff line Loading @@ -22,6 +22,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import android.content.pm.VersionedPackage; import android.os.test.TestLooper; import android.support.test.InstrumentationRegistry; Loading @@ -47,6 +48,7 @@ public class PackageWatchdogTest { private static final String APP_B = "com.package.b"; private static final String APP_C = "com.package.c"; private static final String APP_D = "com.package.d"; private static final long VERSION_CODE = 1L; private static final String OBSERVER_NAME_1 = "observer1"; private static final String OBSERVER_NAME_2 = "observer2"; private static final String OBSERVER_NAME_3 = "observer3"; Loading Loading @@ -193,7 +195,7 @@ public class PackageWatchdogTest { // Then fail APP_A below the threshold for (int i = 0; i < TRIGGER_FAILURE_COUNT - 1; i++) { watchdog.onPackageFailure(new String[]{APP_A}); watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); } // Run handler so package failures are dispatched to observers Loading @@ -209,12 +211,10 @@ public class PackageWatchdogTest { * the failed packages. */ @Test public void testPackageFailureNotifyNone() throws Exception { public void testPackageFailureDifferentPackageNotifyNone() throws Exception { PackageWatchdog watchdog = createWatchdog(); TestObserver observer1 = new TestObserver(OBSERVER_NAME_1, PackageHealthObserverImpact.USER_IMPACT_HIGH); TestObserver observer2 = new TestObserver(OBSERVER_NAME_2, PackageHealthObserverImpact.USER_IMPACT_HIGH); TestObserver observer1 = new TestObserver(OBSERVER_NAME_1); TestObserver observer2 = new TestObserver(OBSERVER_NAME_2); watchdog.startObservingHealth(observer2, Arrays.asList(APP_A), SHORT_DURATION); Loading @@ -222,7 +222,7 @@ public class PackageWatchdogTest { // Then fail APP_C (not observed) above the threshold for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) { watchdog.onPackageFailure(new String[]{APP_C}); watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_C, VERSION_CODE))); } // Run handler so package failures are dispatched to observers Loading @@ -233,6 +233,40 @@ public class PackageWatchdogTest { assertEquals(0, observer2.mFailedPackages.size()); } /** * Test package failure and does not notify any observer because the failed package version * does not match the available rollback-from-version. */ @Test public void testPackageFailureDifferentVersionNotifyNone() throws Exception { PackageWatchdog watchdog = createWatchdog(); long differentVersionCode = 2L; TestObserver observer = new TestObserver(OBSERVER_NAME_1) { public int onHealthCheckFailed(String packageName, long versionCode) { if (versionCode == VERSION_CODE) { // Only rollback for specific versionCode return PackageHealthObserverImpact.USER_IMPACT_MEDIUM; } return PackageHealthObserverImpact.USER_IMPACT_NONE; } }; watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION); // Then fail APP_A (different version) above the threshold for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) { watchdog.onPackageFailure(Arrays.asList( new VersionedPackage(APP_A, differentVersionCode))); } // Run handler so package failures are dispatched to observers mTestLooper.dispatchAll(); // Verify that observers are not notified assertEquals(0, observer.mFailedPackages.size()); } /** * Test package failure and notifies only least impact observers. */ Loading Loading @@ -260,7 +294,10 @@ public class PackageWatchdogTest { // Then fail all apps above the threshold for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) { watchdog.onPackageFailure(new String[]{APP_A, APP_B, APP_C, APP_D}); watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE), new VersionedPackage(APP_B, VERSION_CODE), new VersionedPackage(APP_C, VERSION_CODE), new VersionedPackage(APP_D, VERSION_CODE))); } // Run handler so package failures are dispatched to observers Loading Loading @@ -297,7 +334,7 @@ public class PackageWatchdogTest { * <ul> */ @Test public void testPackageFailureNotifyLeastSuccessively() throws Exception { public void testPackageFailureNotifyLeastImpactSuccessively() throws Exception { PackageWatchdog watchdog = createWatchdog(); TestObserver observerFirst = new TestObserver(OBSERVER_NAME_1, PackageHealthObserverImpact.USER_IMPACT_LOW); Loading @@ -310,7 +347,7 @@ public class PackageWatchdogTest { // Then fail APP_A above the threshold for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) { watchdog.onPackageFailure(new String[]{APP_A}); watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); } // Run handler so package failures are dispatched to observers mTestLooper.dispatchAll(); Loading @@ -327,7 +364,7 @@ public class PackageWatchdogTest { // Then fail APP_A again above the threshold for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) { watchdog.onPackageFailure(new String[]{APP_A}); watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); } // Run handler so package failures are dispatched to observers mTestLooper.dispatchAll(); Loading @@ -344,7 +381,7 @@ public class PackageWatchdogTest { // Then fail APP_A again above the threshold for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) { watchdog.onPackageFailure(new String[]{APP_A}); watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); } // Run handler so package failures are dispatched to observers mTestLooper.dispatchAll(); Loading @@ -361,7 +398,7 @@ public class PackageWatchdogTest { // Then fail APP_A again above the threshold for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) { watchdog.onPackageFailure(new String[]{APP_A}); watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); } // Run handler so package failures are dispatched to observers mTestLooper.dispatchAll(); Loading @@ -388,7 +425,7 @@ public class PackageWatchdogTest { // Then fail APP_A above the threshold for (int i = 0; i < TRIGGER_FAILURE_COUNT; i++) { watchdog.onPackageFailure(new String[]{APP_A}); watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE))); } // Run handler so package failures are dispatched to observers Loading Loading @@ -420,11 +457,11 @@ public class PackageWatchdogTest { mImpact = impact; } public int onHealthCheckFailed(String packageName) { public int onHealthCheckFailed(String packageName, long versionCode) { return mImpact; } public boolean execute(String packageName) { public boolean execute(String packageName, long versionCode) { mFailedPackages.add(packageName); return true; } Loading