diff options
| -rw-r--r-- | core/java/android/service/watchdog/ExplicitHealthCheckService.java | 1 | ||||
| -rw-r--r-- | services/core/java/com/android/server/PackageWatchdog.java | 96 |
2 files changed, 81 insertions, 16 deletions
diff --git a/core/java/android/service/watchdog/ExplicitHealthCheckService.java b/core/java/android/service/watchdog/ExplicitHealthCheckService.java index eeefb4ae10fa..dc9c85808240 100644 --- a/core/java/android/service/watchdog/ExplicitHealthCheckService.java +++ b/core/java/android/service/watchdog/ExplicitHealthCheckService.java @@ -183,7 +183,6 @@ public abstract class ExplicitHealthCheckService extends Service { */ @SystemApi public static final class PackageConfig implements Parcelable { - // TODO: Receive from DeviceConfig flag private static final long DEFAULT_HEALTH_CHECK_TIMEOUT_MILLIS = TimeUnit.HOURS.toMillis(1); private final String mPackageName; diff --git a/services/core/java/com/android/server/PackageWatchdog.java b/services/core/java/com/android/server/PackageWatchdog.java index b44009fd6880..e383c522f474 100644 --- a/services/core/java/com/android/server/PackageWatchdog.java +++ b/services/core/java/com/android/server/PackageWatchdog.java @@ -29,6 +29,7 @@ import android.os.Environment; import android.os.Handler; import android.os.Looper; import android.os.SystemClock; +import android.provider.DeviceConfig; import android.text.TextUtils; import android.util.ArrayMap; import android.util.ArraySet; @@ -61,6 +62,7 @@ import java.util.Iterator; import java.util.List; import java.util.Map; import java.util.Set; +import java.util.concurrent.TimeUnit; /** * Monitors the health of packages on the system and notifies interested observers when packages @@ -69,10 +71,22 @@ import java.util.Set; */ public class PackageWatchdog { private static final String TAG = "PackageWatchdog"; + + static final String PROPERTY_WATCHDOG_TRIGGER_DURATION_MILLIS = + "watchdog_trigger_failure_duration_millis"; + static final String PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT = + "watchdog_trigger_failure_count"; + static final String PROPERTY_WATCHDOG_EXPLICIT_HEALTH_CHECK_ENABLED = + "watchdog_explicit_health_check_enabled"; + // Duration to count package failures before it resets to 0 - private static final int TRIGGER_DURATION_MS = 60000; + private static final int DEFAULT_TRIGGER_FAILURE_DURATION_MS = + (int) TimeUnit.MINUTES.toMillis(1); // Number of package failures within the duration above before we notify observers - static final int TRIGGER_FAILURE_COUNT = 5; + private static final int DEFAULT_TRIGGER_FAILURE_COUNT = 5; + // Whether explicit health checks are enabled or not + private static final boolean DEFAULT_EXPLICIT_HEALTH_CHECK_ENABLED = true; + private static final int DB_VERSION = 1; private static final String TAG_PACKAGE_WATCHDOG = "package-watchdog"; private static final String TAG_PACKAGE = "package"; @@ -83,6 +97,7 @@ public class PackageWatchdog { private static final String ATTR_EXPLICIT_HEALTH_CHECK_DURATION = "health-check-duration"; private static final String ATTR_PASSED_HEALTH_CHECK = "passed-health-check"; + @GuardedBy("PackageWatchdog.class") private static PackageWatchdog sPackageWatchdog; private final Object mLock = new Object(); @@ -100,11 +115,15 @@ public class PackageWatchdog { // File containing the XML data of monitored packages /data/system/package-watchdog.xml private final AtomicFile mPolicyFile; private final ExplicitHealthCheckController mHealthCheckController; + @GuardedBy("mLock") + private boolean mIsPackagesReady; // Flag to control whether explicit health checks are supported or not @GuardedBy("mLock") - private boolean mIsHealthCheckEnabled = true; + private boolean mIsHealthCheckEnabled = DEFAULT_EXPLICIT_HEALTH_CHECK_ENABLED; @GuardedBy("mLock") - private boolean mIsPackagesReady; + private int mTriggerFailureDurationMs = DEFAULT_TRIGGER_FAILURE_DURATION_MS; + @GuardedBy("mLock") + private int mTriggerFailureCount = DEFAULT_TRIGGER_FAILURE_COUNT; // SystemClock#uptimeMillis when we last executed #syncState // 0 if no prune is scheduled. @GuardedBy("mLock") @@ -153,8 +172,8 @@ public class PackageWatchdog { mHealthCheckController.setCallbacks(packageName -> onHealthCheckPassed(packageName), packages -> onSupportedPackages(packages), () -> syncRequestsAsync()); - // Controller is initially disabled until here where we may enable it and sync our state - setExplicitHealthCheckEnabled(mIsHealthCheckEnabled); + setPropertyChangedListenerLocked(); + updateConfigs(); } } @@ -332,7 +351,6 @@ public class PackageWatchdog { } } - // TODO(b/120598832): Set depending on DeviceConfig flag /** * Enables or disables explicit health checks. * <p> If explicit health checks are enabled, the health check service is started. @@ -390,6 +408,12 @@ public class PackageWatchdog { String getName(); } + long getTriggerFailureCount() { + synchronized (mLock) { + return mTriggerFailureCount; + } + } + /** * Serializes and syncs health check requests with the {@link ExplicitHealthCheckController}. */ @@ -646,7 +670,7 @@ public class PackageWatchdog { XmlUtils.beginDocument(parser, TAG_PACKAGE_WATCHDOG); int outerDepth = parser.getDepth(); while (XmlUtils.nextElementWithin(parser, outerDepth)) { - ObserverInternal observer = ObserverInternal.read(parser); + ObserverInternal observer = ObserverInternal.read(parser, this); if (observer != null) { mAllObservers.put(observer.mName, observer); } @@ -661,6 +685,48 @@ public class PackageWatchdog { } } + /** Adds a {@link DeviceConfig#OnPropertyChangedListener}. */ + private void setPropertyChangedListenerLocked() { + DeviceConfig.addOnPropertyChangedListener( + DeviceConfig.NAMESPACE_ROLLBACK, + mContext.getMainExecutor(), + (namespace, name, value) -> { + if (!DeviceConfig.NAMESPACE_ROLLBACK.equals(namespace)) { + return; + } + updateConfigs(); + }); + } + + /** + * Health check is enabled or disabled after reading the flags + * from DeviceConfig. + */ + private void updateConfigs() { + synchronized (mLock) { + mTriggerFailureCount = DeviceConfig.getInt( + DeviceConfig.NAMESPACE_ROLLBACK, + PROPERTY_WATCHDOG_TRIGGER_FAILURE_COUNT, + DEFAULT_TRIGGER_FAILURE_COUNT); + if (mTriggerFailureCount <= 0) { + mTriggerFailureCount = DEFAULT_TRIGGER_FAILURE_COUNT; + } + + mTriggerFailureDurationMs = DeviceConfig.getInt( + DeviceConfig.NAMESPACE_ROLLBACK, + PROPERTY_WATCHDOG_TRIGGER_DURATION_MILLIS, + DEFAULT_TRIGGER_FAILURE_DURATION_MS); + if (mTriggerFailureDurationMs <= 0) { + mTriggerFailureDurationMs = DEFAULT_TRIGGER_FAILURE_COUNT; + } + + setExplicitHealthCheckEnabled(DeviceConfig.getBoolean( + DeviceConfig.NAMESPACE_ROLLBACK, + PROPERTY_WATCHDOG_EXPLICIT_HEALTH_CHECK_ENABLED, + DEFAULT_EXPLICIT_HEALTH_CHECK_ENABLED)); + } + } + /** * Persists mAllObservers to file. Threshold information is ignored. */ @@ -805,7 +871,7 @@ public class PackageWatchdog { * #loadFromFile which in turn is only called on construction of the * singleton PackageWatchdog. **/ - public static ObserverInternal read(XmlPullParser parser) { + public static ObserverInternal read(XmlPullParser parser, PackageWatchdog watchdog) { String observerName = null; if (TAG_OBSERVER.equals(parser.getName())) { observerName = parser.getAttributeValue(null, ATTR_NAME); @@ -829,7 +895,7 @@ public class PackageWatchdog { boolean hasPassedHealthCheck = Boolean.parseBoolean( parser.getAttributeValue(null, ATTR_PASSED_HEALTH_CHECK)); if (!TextUtils.isEmpty(packageName)) { - packages.add(new MonitoredPackage(packageName, duration, + packages.add(watchdog.new MonitoredPackage(packageName, duration, healthCheckDuration, hasPassedHealthCheck)); } } catch (NumberFormatException e) { @@ -856,7 +922,7 @@ public class PackageWatchdog { * <p> Note, the PackageWatchdog#mLock must always be held when reading or writing * instances of this class. */ - static class MonitoredPackage { + class MonitoredPackage { // Health check states // TODO(b/120598832): Prefix with HEALTH_CHECK // mName has not passed health check but has requested a health check @@ -931,7 +997,7 @@ public class PackageWatchdog { public boolean onFailureLocked() { final long now = SystemClock.uptimeMillis(); final long duration = now - mUptimeStartMs; - if (duration > TRIGGER_DURATION_MS) { + 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 @@ -940,7 +1006,7 @@ public class PackageWatchdog { } else { mFailures++; } - boolean failed = mFailures >= TRIGGER_FAILURE_COUNT; + boolean failed = mFailures >= mTriggerFailureCount; if (failed) { mFailures = 0; } @@ -1065,7 +1131,7 @@ public class PackageWatchdog { } /** Returns a {@link String} representation of the current health check state. */ - private static String toString(int state) { + private String toString(int state) { switch (state) { case STATE_ACTIVE: return "ACTIVE"; @@ -1081,7 +1147,7 @@ public class PackageWatchdog { } /** Returns {@code value} if it is greater than 0 or {@link Long#MAX_VALUE} otherwise. */ - private static long toPositive(long value) { + private long toPositive(long value) { return value > 0 ? value : Long.MAX_VALUE; } } |