Merge "Fix the algorithm counting the package failures"
This commit is contained in:
committed by
Android (Google) Code Review
commit
e4828cb97c
@@ -34,6 +34,7 @@ import android.text.TextUtils;
|
||||
import android.util.ArrayMap;
|
||||
import android.util.ArraySet;
|
||||
import android.util.AtomicFile;
|
||||
import android.util.LongArrayQueue;
|
||||
import android.util.Slog;
|
||||
import android.util.Xml;
|
||||
|
||||
@@ -969,6 +970,9 @@ public class PackageWatchdog {
|
||||
class MonitoredPackage {
|
||||
//TODO(b/120598832): VersionedPackage?
|
||||
private final String mName;
|
||||
// Times when package failures happen sorted in ascending order
|
||||
@GuardedBy("mLock")
|
||||
private final LongArrayQueue mFailureHistory = new LongArrayQueue();
|
||||
// One of STATE_[ACTIVE|INACTIVE|PASSED|FAILED]. Updated on construction and after
|
||||
// methods that could change the health check state: handleElapsedTimeLocked and
|
||||
// tryPassHealthCheckLocked
|
||||
@@ -988,12 +992,6 @@ public class PackageWatchdog {
|
||||
// of the package, see #getHealthCheckStateLocked
|
||||
@GuardedBy("mLock")
|
||||
private long mHealthCheckDurationMs = Long.MAX_VALUE;
|
||||
// System uptime of first package failure
|
||||
@GuardedBy("mLock")
|
||||
private long mUptimeStartMs;
|
||||
// Number of failures since mUptimeStartMs
|
||||
@GuardedBy("mLock")
|
||||
private int mFailures;
|
||||
|
||||
MonitoredPackage(String name, long durationMs, boolean hasPassedHealthCheck) {
|
||||
this(name, durationMs, Long.MAX_VALUE, hasPassedHealthCheck);
|
||||
@@ -1028,20 +1026,17 @@ public class PackageWatchdog {
|
||||
*/
|
||||
@GuardedBy("mLock")
|
||||
public boolean onFailureLocked() {
|
||||
// Sliding window algorithm: find out if there exists a window containing failures >=
|
||||
// mTriggerFailureCount.
|
||||
final long now = mSystemClock.uptimeMillis();
|
||||
final long duration = now - mUptimeStartMs;
|
||||
if (duration > mTriggerFailureDurationMs) {
|
||||
// TODO(b/120598832): Reseting to 1 is not correct
|
||||
// because there may be more than 1 failure in the last trigger window from now
|
||||
// This is the RescueParty impl, will leave for now
|
||||
mFailures = 1;
|
||||
mUptimeStartMs = now;
|
||||
} else {
|
||||
mFailures++;
|
||||
mFailureHistory.addLast(now);
|
||||
while (now - mFailureHistory.peekFirst() > mTriggerFailureDurationMs) {
|
||||
// Prune values falling out of the window
|
||||
mFailureHistory.removeFirst();
|
||||
}
|
||||
boolean failed = mFailures >= mTriggerFailureCount;
|
||||
boolean failed = mFailureHistory.size() >= mTriggerFailureCount;
|
||||
if (failed) {
|
||||
mFailures = 0;
|
||||
mFailureHistory.clear();
|
||||
}
|
||||
return failed;
|
||||
}
|
||||
|
||||
@@ -765,6 +765,39 @@ public class PackageWatchdogTest {
|
||||
assertThat(observer.mHealthCheckFailedPackages).containsExactly(APP_B);
|
||||
}
|
||||
|
||||
/** Test we are notified when enough failures are triggered within any window. */
|
||||
@Test
|
||||
public void testFailureTriggerWindow() {
|
||||
adoptShellPermissions(
|
||||
Manifest.permission.WRITE_DEVICE_CONFIG,
|
||||
Manifest.permission.READ_DEVICE_CONFIG);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
|
||||
PackageWatchdog.PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT,
|
||||
Integer.toString(3), /*makeDefault*/false);
|
||||
DeviceConfig.setProperty(DeviceConfig.NAMESPACE_ROLLBACK,
|
||||
PackageWatchdog.PROPERTY_WATCHDOG_TRIGGER_DURATION_MILLIS,
|
||||
Integer.toString(1000), /*makeDefault*/false);
|
||||
PackageWatchdog watchdog = createWatchdog();
|
||||
TestObserver observer = new TestObserver(OBSERVER_NAME_1);
|
||||
|
||||
watchdog.startObservingHealth(observer, Arrays.asList(APP_A), Long.MAX_VALUE);
|
||||
// Raise 2 failures at t=0 and t=900 respectively
|
||||
watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
|
||||
mTestLooper.dispatchAll();
|
||||
moveTimeForwardAndDispatch(900);
|
||||
watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
|
||||
mTestLooper.dispatchAll();
|
||||
|
||||
// Raise 2 failures at t=1100
|
||||
moveTimeForwardAndDispatch(200);
|
||||
watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
|
||||
watchdog.onPackageFailure(Arrays.asList(new VersionedPackage(APP_A, VERSION_CODE)));
|
||||
mTestLooper.dispatchAll();
|
||||
|
||||
// We should receive APP_A since there are 3 failures within 1000ms window
|
||||
assertThat(observer.mHealthCheckFailedPackages).containsExactly(APP_A);
|
||||
}
|
||||
|
||||
private void adoptShellPermissions(String... permissions) {
|
||||
InstrumentationRegistry
|
||||
.getInstrumentation()
|
||||
|
||||
Reference in New Issue
Block a user