Loading services/core/java/com/android/server/ExplicitHealthCheckController.java +13 −6 Original line number Original line Diff line number Diff line Loading @@ -35,7 +35,9 @@ import android.os.RemoteException; import android.os.UserHandle; import android.os.UserHandle; import android.service.watchdog.ExplicitHealthCheckService; import android.service.watchdog.ExplicitHealthCheckService; import android.service.watchdog.IExplicitHealthCheckService; import android.service.watchdog.IExplicitHealthCheckService; import android.service.watchdog.PackageInfo; import android.text.TextUtils; import android.text.TextUtils; import android.util.ArraySet; import android.util.Slog; import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy; Loading Loading @@ -69,7 +71,7 @@ class ExplicitHealthCheckController { // To prevent deadlocks between the controller and watchdog threads, we have // To prevent deadlocks between the controller and watchdog threads, we have // a lock invariant to ALWAYS acquire the PackageWatchdog#mLock before #mLock in this class. // a lock invariant to ALWAYS acquire the PackageWatchdog#mLock before #mLock in this class. // It's easier to just NOT hold #mLock when calling into watchdog code on this consumer. // It's easier to just NOT hold #mLock when calling into watchdog code on this consumer. @GuardedBy("mLock") @Nullable private Consumer<List<String>> mSupportedConsumer; @GuardedBy("mLock") @Nullable private Consumer<List<PackageInfo>> mSupportedConsumer; // Called everytime we need to notify the watchdog to sync requests between itself and the // Called everytime we need to notify the watchdog to sync requests between itself and the // health check service. In practice, should never be null after it has been #setEnabled. // health check service. In practice, should never be null after it has been #setEnabled. // To prevent deadlocks between the controller and watchdog threads, we have // To prevent deadlocks between the controller and watchdog threads, we have Loading Loading @@ -104,7 +106,7 @@ class ExplicitHealthCheckController { * ensure a happens-before relationship of the set parameters and visibility on other threads. * ensure a happens-before relationship of the set parameters and visibility on other threads. */ */ public void setCallbacks(Consumer<String> passedConsumer, public void setCallbacks(Consumer<String> passedConsumer, Consumer<List<String>> supportedConsumer, Runnable notifySyncRunnable) { Consumer<List<PackageInfo>> supportedConsumer, Runnable notifySyncRunnable) { synchronized (mLock) { synchronized (mLock) { if (mPassedConsumer != null || mSupportedConsumer != null if (mPassedConsumer != null || mSupportedConsumer != null || mNotifySyncRunnable != null) { || mNotifySyncRunnable != null) { Loading Loading @@ -144,14 +146,18 @@ class ExplicitHealthCheckController { return; return; } } getSupportedPackages(supportedPackages -> { getSupportedPackages(supportedPackageInfos -> { // Notify the watchdog without lock held // Notify the watchdog without lock held mSupportedConsumer.accept(supportedPackages); mSupportedConsumer.accept(supportedPackageInfos); getRequestedPackages(previousRequestedPackages -> { getRequestedPackages(previousRequestedPackages -> { synchronized (mLock) { synchronized (mLock) { // Hold lock so requests and cancellations are sent atomically. // Hold lock so requests and cancellations are sent atomically. // It is important we don't mix requests from multiple threads. // It is important we don't mix requests from multiple threads. Set<String> supportedPackages = new ArraySet<>(); for (PackageInfo info : supportedPackageInfos) { supportedPackages.add(info.getPackageName()); } // Note, this may modify newRequestedPackages // Note, this may modify newRequestedPackages newRequestedPackages.retainAll(supportedPackages); newRequestedPackages.retainAll(supportedPackages); Loading Loading @@ -229,7 +235,7 @@ class ExplicitHealthCheckController { * Returns the packages that we can request explicit health checks for. * Returns the packages that we can request explicit health checks for. * The packages will be returned to the {@code consumer}. * The packages will be returned to the {@code consumer}. */ */ private void getSupportedPackages(Consumer<List<String>> consumer) { private void getSupportedPackages(Consumer<List<PackageInfo>> consumer) { synchronized (mLock) { synchronized (mLock) { if (!prepareServiceLocked("get health check supported packages")) { if (!prepareServiceLocked("get health check supported packages")) { return; return; Loading @@ -238,7 +244,8 @@ class ExplicitHealthCheckController { Slog.d(TAG, "Getting health check supported packages"); Slog.d(TAG, "Getting health check supported packages"); try { try { mRemoteService.getSupportedPackages(new RemoteCallback(result -> { mRemoteService.getSupportedPackages(new RemoteCallback(result -> { List<String> packages = result.getStringArrayList(EXTRA_SUPPORTED_PACKAGES); List<PackageInfo> packages = result.getParcelableArrayList(EXTRA_SUPPORTED_PACKAGES); Slog.i(TAG, "Explicit health check supported packages " + packages); Slog.i(TAG, "Explicit health check supported packages " + packages); consumer.accept(packages); consumer.accept(packages); })); })); Loading services/core/java/com/android/server/PackageWatchdog.java +311 −190 File changed.Preview size limit exceeded, changes collapsed. Show changes tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java +112 −3 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server; package com.android.server; import static com.android.server.PackageWatchdog.MonitoredPackage; import static com.android.server.PackageWatchdog.TRIGGER_FAILURE_COUNT; import static com.android.server.PackageWatchdog.TRIGGER_FAILURE_COUNT; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals; Loading @@ -27,6 +28,7 @@ import android.content.Context; import android.content.pm.VersionedPackage; import android.content.pm.VersionedPackage; import android.os.Handler; import android.os.Handler; import android.os.test.TestLooper; import android.os.test.TestLooper; import android.service.watchdog.PackageInfo; import android.util.AtomicFile; import android.util.AtomicFile; import androidx.test.InstrumentationRegistry; import androidx.test.InstrumentationRegistry; Loading Loading @@ -143,6 +145,31 @@ public class PackageWatchdogTest { assertNull(watchdog.getPackages(observer3)); assertNull(watchdog.getPackages(observer3)); } } /** Observing already observed package extends the observation time. */ @Test public void testObserveAlreadyObservedPackage() throws Exception { PackageWatchdog watchdog = createWatchdog(); TestObserver observer = new TestObserver(OBSERVER_NAME_1); // Start observing APP_A watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION); // Then advance time half-way Thread.sleep(SHORT_DURATION / 2); mTestLooper.dispatchAll(); // Start observing APP_A again watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION); // Then advance time such that it should have expired were it not for the second observation Thread.sleep((SHORT_DURATION / 2) + 1); mTestLooper.dispatchAll(); // Verify that APP_A not expired since second observation extended the time assertEquals(1, watchdog.getPackages(observer).size()); assertTrue(watchdog.getPackages(observer).contains(APP_A)); } /** /** * Test package observers are persisted and loaded on startup * Test package observers are persisted and loaded on startup */ */ Loading Loading @@ -577,6 +604,84 @@ public class PackageWatchdogTest { assertEquals(APP_C, observer.mFailedPackages.get(0)); assertEquals(APP_C, observer.mFailedPackages.get(0)); } } /** * Tests failure when health check duration is different from package observation duration * Failure is also notified only once. */ @Test public void testExplicitHealthCheckFailureBeforeExpiry() throws Exception { TestController controller = new TestController(); PackageWatchdog watchdog = createWatchdog(controller, true /* withPackagesReady */); TestObserver observer = new TestObserver(OBSERVER_NAME_1, PackageHealthObserverImpact.USER_IMPACT_MEDIUM); // Start observing with explicit health checks for APP_A and // package observation duration == LONG_DURATION // health check duration == SHORT_DURATION (set by default in the TestController) controller.setSupportedPackages(Arrays.asList(APP_A)); watchdog.startObservingHealth(observer, Arrays.asList(APP_A), LONG_DURATION); // Then APP_A has exceeded health check duration Thread.sleep(SHORT_DURATION); mTestLooper.dispatchAll(); // Verify that health check is failed assertEquals(1, observer.mFailedPackages.size()); assertEquals(APP_A, observer.mFailedPackages.get(0)); // Then clear failed packages and start observing a random package so requests are synced // and PackageWatchdog#onSupportedPackages is called and APP_A has a chance to fail again // this time due to package expiry. observer.mFailedPackages.clear(); watchdog.startObservingHealth(observer, Arrays.asList(APP_B), LONG_DURATION); // Verify that health check failure is not notified again assertTrue(observer.mFailedPackages.isEmpty()); } /** Tests {@link MonitoredPackage} health check state transitions. */ @Test public void testPackageHealthCheckStateTransitions() { MonitoredPackage m1 = new MonitoredPackage(APP_A, LONG_DURATION, false /* hasPassedHealthCheck */); MonitoredPackage m2 = new MonitoredPackage(APP_B, LONG_DURATION, false); MonitoredPackage m3 = new MonitoredPackage(APP_C, LONG_DURATION, false); MonitoredPackage m4 = new MonitoredPackage(APP_D, LONG_DURATION, SHORT_DURATION, true); // Verify transition: inactive -> active -> passed // Verify initially inactive assertEquals(MonitoredPackage.STATE_INACTIVE, m1.getHealthCheckStateLocked()); // Verify still inactive, until we #setHealthCheckActiveLocked assertEquals(MonitoredPackage.STATE_INACTIVE, m1.handleElapsedTimeLocked(SHORT_DURATION)); // Verify now active assertEquals(MonitoredPackage.STATE_ACTIVE, m1.setHealthCheckActiveLocked(SHORT_DURATION)); // Verify now passed assertEquals(MonitoredPackage.STATE_PASSED, m1.tryPassHealthCheckLocked()); // Verify transition: inactive -> active -> failed // Verify initially inactive assertEquals(MonitoredPackage.STATE_INACTIVE, m2.getHealthCheckStateLocked()); // Verify now active assertEquals(MonitoredPackage.STATE_ACTIVE, m2.setHealthCheckActiveLocked(SHORT_DURATION)); // Verify now failed assertEquals(MonitoredPackage.STATE_FAILED, m2.handleElapsedTimeLocked(SHORT_DURATION)); // Verify transition: inactive -> failed // Verify initially inactive assertEquals(MonitoredPackage.STATE_INACTIVE, m3.getHealthCheckStateLocked()); // Verify now failed because package expired assertEquals(MonitoredPackage.STATE_FAILED, m3.handleElapsedTimeLocked(LONG_DURATION)); // Verify remains failed even when asked to pass assertEquals(MonitoredPackage.STATE_FAILED, m3.tryPassHealthCheckLocked()); // Verify transition: passed assertEquals(MonitoredPackage.STATE_PASSED, m4.getHealthCheckStateLocked()); // Verify remains passed even if health check fails assertEquals(MonitoredPackage.STATE_PASSED, m4.handleElapsedTimeLocked(SHORT_DURATION)); // Verify remains passed even if package expires assertEquals(MonitoredPackage.STATE_PASSED, m4.handleElapsedTimeLocked(LONG_DURATION)); } private PackageWatchdog createWatchdog() { private PackageWatchdog createWatchdog() { return createWatchdog(new TestController(), true /* withPackagesReady */); return createWatchdog(new TestController(), true /* withPackagesReady */); } } Loading Loading @@ -636,7 +741,7 @@ public class PackageWatchdogTest { private List<String> mSupportedPackages = new ArrayList<>(); private List<String> mSupportedPackages = new ArrayList<>(); private List<String> mRequestedPackages = new ArrayList<>(); private List<String> mRequestedPackages = new ArrayList<>(); private Consumer<String> mPassedConsumer; private Consumer<String> mPassedConsumer; private Consumer<List<String>> mSupportedConsumer; private Consumer<List<PackageInfo>> mSupportedConsumer; private Runnable mNotifySyncRunnable; private Runnable mNotifySyncRunnable; @Override @Override Loading @@ -649,7 +754,7 @@ public class PackageWatchdogTest { @Override @Override public void setCallbacks(Consumer<String> passedConsumer, public void setCallbacks(Consumer<String> passedConsumer, Consumer<List<String>> supportedConsumer, Runnable notifySyncRunnable) { Consumer<List<PackageInfo>> supportedConsumer, Runnable notifySyncRunnable) { mPassedConsumer = passedConsumer; mPassedConsumer = passedConsumer; mSupportedConsumer = supportedConsumer; mSupportedConsumer = supportedConsumer; mNotifySyncRunnable = notifySyncRunnable; mNotifySyncRunnable = notifySyncRunnable; Loading @@ -661,7 +766,11 @@ public class PackageWatchdogTest { if (mIsEnabled) { if (mIsEnabled) { packages.retainAll(mSupportedPackages); packages.retainAll(mSupportedPackages); mRequestedPackages.addAll(packages); mRequestedPackages.addAll(packages); mSupportedConsumer.accept(mSupportedPackages); List<PackageInfo> packageInfos = new ArrayList<>(); for (String packageName: packages) { packageInfos.add(new PackageInfo(packageName, SHORT_DURATION)); } mSupportedConsumer.accept(packageInfos); } else { } else { mSupportedConsumer.accept(Collections.emptyList()); mSupportedConsumer.accept(Collections.emptyList()); } } Loading Loading
services/core/java/com/android/server/ExplicitHealthCheckController.java +13 −6 Original line number Original line Diff line number Diff line Loading @@ -35,7 +35,9 @@ import android.os.RemoteException; import android.os.UserHandle; import android.os.UserHandle; import android.service.watchdog.ExplicitHealthCheckService; import android.service.watchdog.ExplicitHealthCheckService; import android.service.watchdog.IExplicitHealthCheckService; import android.service.watchdog.IExplicitHealthCheckService; import android.service.watchdog.PackageInfo; import android.text.TextUtils; import android.text.TextUtils; import android.util.ArraySet; import android.util.Slog; import android.util.Slog; import com.android.internal.annotations.GuardedBy; import com.android.internal.annotations.GuardedBy; Loading Loading @@ -69,7 +71,7 @@ class ExplicitHealthCheckController { // To prevent deadlocks between the controller and watchdog threads, we have // To prevent deadlocks between the controller and watchdog threads, we have // a lock invariant to ALWAYS acquire the PackageWatchdog#mLock before #mLock in this class. // a lock invariant to ALWAYS acquire the PackageWatchdog#mLock before #mLock in this class. // It's easier to just NOT hold #mLock when calling into watchdog code on this consumer. // It's easier to just NOT hold #mLock when calling into watchdog code on this consumer. @GuardedBy("mLock") @Nullable private Consumer<List<String>> mSupportedConsumer; @GuardedBy("mLock") @Nullable private Consumer<List<PackageInfo>> mSupportedConsumer; // Called everytime we need to notify the watchdog to sync requests between itself and the // Called everytime we need to notify the watchdog to sync requests between itself and the // health check service. In practice, should never be null after it has been #setEnabled. // health check service. In practice, should never be null after it has been #setEnabled. // To prevent deadlocks between the controller and watchdog threads, we have // To prevent deadlocks between the controller and watchdog threads, we have Loading Loading @@ -104,7 +106,7 @@ class ExplicitHealthCheckController { * ensure a happens-before relationship of the set parameters and visibility on other threads. * ensure a happens-before relationship of the set parameters and visibility on other threads. */ */ public void setCallbacks(Consumer<String> passedConsumer, public void setCallbacks(Consumer<String> passedConsumer, Consumer<List<String>> supportedConsumer, Runnable notifySyncRunnable) { Consumer<List<PackageInfo>> supportedConsumer, Runnable notifySyncRunnable) { synchronized (mLock) { synchronized (mLock) { if (mPassedConsumer != null || mSupportedConsumer != null if (mPassedConsumer != null || mSupportedConsumer != null || mNotifySyncRunnable != null) { || mNotifySyncRunnable != null) { Loading Loading @@ -144,14 +146,18 @@ class ExplicitHealthCheckController { return; return; } } getSupportedPackages(supportedPackages -> { getSupportedPackages(supportedPackageInfos -> { // Notify the watchdog without lock held // Notify the watchdog without lock held mSupportedConsumer.accept(supportedPackages); mSupportedConsumer.accept(supportedPackageInfos); getRequestedPackages(previousRequestedPackages -> { getRequestedPackages(previousRequestedPackages -> { synchronized (mLock) { synchronized (mLock) { // Hold lock so requests and cancellations are sent atomically. // Hold lock so requests and cancellations are sent atomically. // It is important we don't mix requests from multiple threads. // It is important we don't mix requests from multiple threads. Set<String> supportedPackages = new ArraySet<>(); for (PackageInfo info : supportedPackageInfos) { supportedPackages.add(info.getPackageName()); } // Note, this may modify newRequestedPackages // Note, this may modify newRequestedPackages newRequestedPackages.retainAll(supportedPackages); newRequestedPackages.retainAll(supportedPackages); Loading Loading @@ -229,7 +235,7 @@ class ExplicitHealthCheckController { * Returns the packages that we can request explicit health checks for. * Returns the packages that we can request explicit health checks for. * The packages will be returned to the {@code consumer}. * The packages will be returned to the {@code consumer}. */ */ private void getSupportedPackages(Consumer<List<String>> consumer) { private void getSupportedPackages(Consumer<List<PackageInfo>> consumer) { synchronized (mLock) { synchronized (mLock) { if (!prepareServiceLocked("get health check supported packages")) { if (!prepareServiceLocked("get health check supported packages")) { return; return; Loading @@ -238,7 +244,8 @@ class ExplicitHealthCheckController { Slog.d(TAG, "Getting health check supported packages"); Slog.d(TAG, "Getting health check supported packages"); try { try { mRemoteService.getSupportedPackages(new RemoteCallback(result -> { mRemoteService.getSupportedPackages(new RemoteCallback(result -> { List<String> packages = result.getStringArrayList(EXTRA_SUPPORTED_PACKAGES); List<PackageInfo> packages = result.getParcelableArrayList(EXTRA_SUPPORTED_PACKAGES); Slog.i(TAG, "Explicit health check supported packages " + packages); Slog.i(TAG, "Explicit health check supported packages " + packages); consumer.accept(packages); consumer.accept(packages); })); })); Loading
services/core/java/com/android/server/PackageWatchdog.java +311 −190 File changed.Preview size limit exceeded, changes collapsed. Show changes
tests/PackageWatchdog/src/com/android/server/PackageWatchdogTest.java +112 −3 Original line number Original line Diff line number Diff line Loading @@ -16,6 +16,7 @@ package com.android.server; package com.android.server; import static com.android.server.PackageWatchdog.MonitoredPackage; import static com.android.server.PackageWatchdog.TRIGGER_FAILURE_COUNT; import static com.android.server.PackageWatchdog.TRIGGER_FAILURE_COUNT; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals; Loading @@ -27,6 +28,7 @@ import android.content.Context; import android.content.pm.VersionedPackage; import android.content.pm.VersionedPackage; import android.os.Handler; import android.os.Handler; import android.os.test.TestLooper; import android.os.test.TestLooper; import android.service.watchdog.PackageInfo; import android.util.AtomicFile; import android.util.AtomicFile; import androidx.test.InstrumentationRegistry; import androidx.test.InstrumentationRegistry; Loading Loading @@ -143,6 +145,31 @@ public class PackageWatchdogTest { assertNull(watchdog.getPackages(observer3)); assertNull(watchdog.getPackages(observer3)); } } /** Observing already observed package extends the observation time. */ @Test public void testObserveAlreadyObservedPackage() throws Exception { PackageWatchdog watchdog = createWatchdog(); TestObserver observer = new TestObserver(OBSERVER_NAME_1); // Start observing APP_A watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION); // Then advance time half-way Thread.sleep(SHORT_DURATION / 2); mTestLooper.dispatchAll(); // Start observing APP_A again watchdog.startObservingHealth(observer, Arrays.asList(APP_A), SHORT_DURATION); // Then advance time such that it should have expired were it not for the second observation Thread.sleep((SHORT_DURATION / 2) + 1); mTestLooper.dispatchAll(); // Verify that APP_A not expired since second observation extended the time assertEquals(1, watchdog.getPackages(observer).size()); assertTrue(watchdog.getPackages(observer).contains(APP_A)); } /** /** * Test package observers are persisted and loaded on startup * Test package observers are persisted and loaded on startup */ */ Loading Loading @@ -577,6 +604,84 @@ public class PackageWatchdogTest { assertEquals(APP_C, observer.mFailedPackages.get(0)); assertEquals(APP_C, observer.mFailedPackages.get(0)); } } /** * Tests failure when health check duration is different from package observation duration * Failure is also notified only once. */ @Test public void testExplicitHealthCheckFailureBeforeExpiry() throws Exception { TestController controller = new TestController(); PackageWatchdog watchdog = createWatchdog(controller, true /* withPackagesReady */); TestObserver observer = new TestObserver(OBSERVER_NAME_1, PackageHealthObserverImpact.USER_IMPACT_MEDIUM); // Start observing with explicit health checks for APP_A and // package observation duration == LONG_DURATION // health check duration == SHORT_DURATION (set by default in the TestController) controller.setSupportedPackages(Arrays.asList(APP_A)); watchdog.startObservingHealth(observer, Arrays.asList(APP_A), LONG_DURATION); // Then APP_A has exceeded health check duration Thread.sleep(SHORT_DURATION); mTestLooper.dispatchAll(); // Verify that health check is failed assertEquals(1, observer.mFailedPackages.size()); assertEquals(APP_A, observer.mFailedPackages.get(0)); // Then clear failed packages and start observing a random package so requests are synced // and PackageWatchdog#onSupportedPackages is called and APP_A has a chance to fail again // this time due to package expiry. observer.mFailedPackages.clear(); watchdog.startObservingHealth(observer, Arrays.asList(APP_B), LONG_DURATION); // Verify that health check failure is not notified again assertTrue(observer.mFailedPackages.isEmpty()); } /** Tests {@link MonitoredPackage} health check state transitions. */ @Test public void testPackageHealthCheckStateTransitions() { MonitoredPackage m1 = new MonitoredPackage(APP_A, LONG_DURATION, false /* hasPassedHealthCheck */); MonitoredPackage m2 = new MonitoredPackage(APP_B, LONG_DURATION, false); MonitoredPackage m3 = new MonitoredPackage(APP_C, LONG_DURATION, false); MonitoredPackage m4 = new MonitoredPackage(APP_D, LONG_DURATION, SHORT_DURATION, true); // Verify transition: inactive -> active -> passed // Verify initially inactive assertEquals(MonitoredPackage.STATE_INACTIVE, m1.getHealthCheckStateLocked()); // Verify still inactive, until we #setHealthCheckActiveLocked assertEquals(MonitoredPackage.STATE_INACTIVE, m1.handleElapsedTimeLocked(SHORT_DURATION)); // Verify now active assertEquals(MonitoredPackage.STATE_ACTIVE, m1.setHealthCheckActiveLocked(SHORT_DURATION)); // Verify now passed assertEquals(MonitoredPackage.STATE_PASSED, m1.tryPassHealthCheckLocked()); // Verify transition: inactive -> active -> failed // Verify initially inactive assertEquals(MonitoredPackage.STATE_INACTIVE, m2.getHealthCheckStateLocked()); // Verify now active assertEquals(MonitoredPackage.STATE_ACTIVE, m2.setHealthCheckActiveLocked(SHORT_DURATION)); // Verify now failed assertEquals(MonitoredPackage.STATE_FAILED, m2.handleElapsedTimeLocked(SHORT_DURATION)); // Verify transition: inactive -> failed // Verify initially inactive assertEquals(MonitoredPackage.STATE_INACTIVE, m3.getHealthCheckStateLocked()); // Verify now failed because package expired assertEquals(MonitoredPackage.STATE_FAILED, m3.handleElapsedTimeLocked(LONG_DURATION)); // Verify remains failed even when asked to pass assertEquals(MonitoredPackage.STATE_FAILED, m3.tryPassHealthCheckLocked()); // Verify transition: passed assertEquals(MonitoredPackage.STATE_PASSED, m4.getHealthCheckStateLocked()); // Verify remains passed even if health check fails assertEquals(MonitoredPackage.STATE_PASSED, m4.handleElapsedTimeLocked(SHORT_DURATION)); // Verify remains passed even if package expires assertEquals(MonitoredPackage.STATE_PASSED, m4.handleElapsedTimeLocked(LONG_DURATION)); } private PackageWatchdog createWatchdog() { private PackageWatchdog createWatchdog() { return createWatchdog(new TestController(), true /* withPackagesReady */); return createWatchdog(new TestController(), true /* withPackagesReady */); } } Loading Loading @@ -636,7 +741,7 @@ public class PackageWatchdogTest { private List<String> mSupportedPackages = new ArrayList<>(); private List<String> mSupportedPackages = new ArrayList<>(); private List<String> mRequestedPackages = new ArrayList<>(); private List<String> mRequestedPackages = new ArrayList<>(); private Consumer<String> mPassedConsumer; private Consumer<String> mPassedConsumer; private Consumer<List<String>> mSupportedConsumer; private Consumer<List<PackageInfo>> mSupportedConsumer; private Runnable mNotifySyncRunnable; private Runnable mNotifySyncRunnable; @Override @Override Loading @@ -649,7 +754,7 @@ public class PackageWatchdogTest { @Override @Override public void setCallbacks(Consumer<String> passedConsumer, public void setCallbacks(Consumer<String> passedConsumer, Consumer<List<String>> supportedConsumer, Runnable notifySyncRunnable) { Consumer<List<PackageInfo>> supportedConsumer, Runnable notifySyncRunnable) { mPassedConsumer = passedConsumer; mPassedConsumer = passedConsumer; mSupportedConsumer = supportedConsumer; mSupportedConsumer = supportedConsumer; mNotifySyncRunnable = notifySyncRunnable; mNotifySyncRunnable = notifySyncRunnable; Loading @@ -661,7 +766,11 @@ public class PackageWatchdogTest { if (mIsEnabled) { if (mIsEnabled) { packages.retainAll(mSupportedPackages); packages.retainAll(mSupportedPackages); mRequestedPackages.addAll(packages); mRequestedPackages.addAll(packages); mSupportedConsumer.accept(mSupportedPackages); List<PackageInfo> packageInfos = new ArrayList<>(); for (String packageName: packages) { packageInfos.add(new PackageInfo(packageName, SHORT_DURATION)); } mSupportedConsumer.accept(packageInfos); } else { } else { mSupportedConsumer.accept(Collections.emptyList()); mSupportedConsumer.accept(Collections.emptyList()); } } Loading