diff --git a/runner/monitor/CHANGELOG.md b/runner/monitor/CHANGELOG.md index 92c24cb64..43979c96b 100644 --- a/runner/monitor/CHANGELOG.md +++ b/runner/monitor/CHANGELOG.md @@ -5,6 +5,7 @@ `androidx.test:monitor:{version}` is released. **Bug Fixes** +* Activities can be started from any thread. **New Features** @@ -14,6 +15,7 @@ * Update to minSdkVersion 21 * Make ReflectionException a RuntimeException +* Hid IntentStubberRegistry.getInstance() **Breaking API Changes** diff --git a/runner/monitor/java/androidx/test/runner/MonitoringInstrumentation.java b/runner/monitor/java/androidx/test/runner/MonitoringInstrumentation.java index 67954ce60..7b23fb96e 100644 --- a/runner/monitor/java/androidx/test/runner/MonitoringInstrumentation.java +++ b/runner/monitor/java/androidx/test/runner/MonitoringInstrumentation.java @@ -677,7 +677,7 @@ private static class StubResultCallable implements Callable { @Override public ActivityResult call() { - return IntentStubberRegistry.getInstance().getActivityResultForIntent(intent); + return IntentStubberRegistry.getActivityResultForIntent(intent); } } @@ -707,7 +707,7 @@ private ActivityResult stubResultFor(Intent intent) { throw new RuntimeException(e); } } else { - return IntentStubberRegistry.getInstance().getActivityResultForIntent(intent); + return IntentStubberRegistry.getActivityResultForIntent(intent); } } return null; diff --git a/runner/monitor/java/androidx/test/runner/intent/IntentStubberRegistry.java b/runner/monitor/java/androidx/test/runner/intent/IntentStubberRegistry.java index 6ed313ec6..9058e3e1c 100644 --- a/runner/monitor/java/androidx/test/runner/intent/IntentStubberRegistry.java +++ b/runner/monitor/java/androidx/test/runner/intent/IntentStubberRegistry.java @@ -19,15 +19,17 @@ import static androidx.test.internal.util.Checks.checkNotNull; import static androidx.test.internal.util.Checks.checkState; -import android.os.Looper; +import android.app.Instrumentation.ActivityResult; +import android.content.Intent; import java.util.concurrent.atomic.AtomicBoolean; +import java.util.concurrent.atomic.AtomicReference; /** Exposes an implementation of {@link IntentStubber}. */ public final class IntentStubberRegistry { - private static IntentStubber instance; + private static final AtomicReference instance = new AtomicReference<>(); - private static AtomicBoolean isLoaded = new AtomicBoolean(); + private static final AtomicBoolean isLoaded = new AtomicBoolean(); /** * Loads an {@link IntentStubber} into this registry. There can only be one active stubber at a @@ -37,44 +39,51 @@ public final class IntentStubberRegistry { * *

This method can be called from any thread. */ - public static void load(IntentStubber intentStubber) { + public static synchronized void load(IntentStubber intentStubber) { checkNotNull(intentStubber, "IntentStubber cannot be null!"); checkState( !isLoaded.getAndSet(true), "Intent stubber already registered! Multiple stubbers are not" + "allowedAre you running under an "); - instance = intentStubber; + instance.set(intentStubber); } - /** @return if an {@link IntentStubber} has been loaded. */ + /** Returns if an {@link IntentStubber} has been loaded. */ public static boolean isLoaded() { return isLoaded.get(); } + /** Clears the current instance of Intent Stubber. */ + public static synchronized void reset() { + instance.set(null); + isLoaded.set(false); + } + + /** + * Returns the activity result for the given intent.. + * + *

This method can be called from any thread. + * + * @throws IllegalStateException if no Intent Stubber has been loaded. + */ + public static ActivityResult getActivityResultForIntent(Intent intent) { + return getInstance().getActivityResultForIntent(intent); + } + /** * Returns the loaded Intent Stubber instance. * - * @throws IllegalStateException if this method is not called on the main thread. + *

This method can be called from any thread. + * * @throws IllegalStateException if no Intent Stubber has been loaded. */ - public static IntentStubber getInstance() { - checkMain(); - checkState( - null != instance, + private static IntentStubber getInstance() { + checkNotNull( + instance, "No intent monitor registered! Are you running under an " + "Instrumentation which registers intent monitors?"); - return instance; - } - - private static void checkMain() { - checkState(Looper.myLooper() == Looper.getMainLooper(), "Must be called on main thread."); + return instance.get(); } private IntentStubberRegistry() {} - - /** Clears the current instance of Intent Stubber. */ - public static synchronized void reset() { - instance = null; - isLoaded.set(false); - } } diff --git a/runner/monitor/javatests/androidx/test/runner/intent/IntentStubberRegistryTest.java b/runner/monitor/javatests/androidx/test/runner/intent/IntentStubberRegistryTest.java index 1de1d0d04..334c5d0d2 100644 --- a/runner/monitor/javatests/androidx/test/runner/intent/IntentStubberRegistryTest.java +++ b/runner/monitor/javatests/androidx/test/runner/intent/IntentStubberRegistryTest.java @@ -58,8 +58,6 @@ public void tearDown() throws Exception { public void testIntentStubberLoading() { IntentStubberRegistry.load(mIntentStubber); assertThat(IntentStubberRegistry.isLoaded()).isTrue(); - - assertThat(IntentStubberRegistry.getInstance()).isNotNull(); } @Test @@ -83,22 +81,17 @@ public void testLoadPassingNullThrows() { } @Test - public void testGetInstanceCanOnlyBeCalledOnMainThread() { + public void testGetActivityResultForIntent_loaded_returnsActivityResult() { IntentStubberRegistry.load(mIntentStubber); - try { - IntentStubberRegistry.getInstance(); - fail( - "IllegalStateException expected. getInstance() should only be allowed on main" - + "thread!"); - } catch (IllegalStateException expected) { - } + + assertThat(IntentStubberRegistry.getActivityResultForIntent(new Intent())).isNotNull(); } @Test - public void testNoInstanceLoadedThrows() { + public void testGetActivityResultForIntent_notLoaded_throws() { try { - IntentStubberRegistry.getInstance(); - fail("IllegalStateException expected. No instance available, load must be called" + "first"); + IntentStubberRegistry.getActivityResultForIntent(new Intent()); + fail("IllegalStateException expected. No instance available, load must be called first"); } catch (IllegalStateException expected) { } }