Repository: wix/Detox
Pull request #2674 (2021-03-04 18:33:59)

Add note about fbsimctl deprecation
<!---
Thank you for contributing!
Before submitting a pull request that implements a new functionality or fixing a major bug,
please open an issue first and propose your solution. This way we can discuss before time is 
spent on a solution that may not work for us.

Please check the correct option in the below list and delete the irrelevant one.
For the second option, please fill the issue where the solution has been discussed.
-->

- [x] This is a small change 

---

**Description:** Adding this note will make it clearer for future readers of the documentation that this external library is no longer working.
I saw that some people are already working on a proper solution in #1371, so I am wondering if it is appropriate to reference this issue in the documentation?



Patch:
diff --git a/detox/android/detox/build.gradle b/detox/android/detox/build.gradle
index 46841c8f4..c590d068c 100644
--- a/detox/android/detox/build.gradle
+++ b/detox/android/detox/build.gradle
@@ -13,6 +13,7 @@ def _kotlinStdlib = _ext.has('detoxKotlinStdlib') ? _ext.detoxKotlinStdlib : 'ko
 android {
     compileSdkVersion _compileSdkVersion
     buildToolsVersion _buildToolsVersion
+
     defaultConfig {
         minSdkVersion _minSdkVersion
         targetSdkVersion _targetSdkVersion
@@ -22,10 +23,19 @@ android {
         consumerProguardFiles 'proguard-rules.pro'
     }
 
+    flavorDimensions 'detox'
+    productFlavors {
+        full {
+            dimension 'detox'
+        }
+        coreNative {
+            dimension 'detox'
+        }
+    }
+
     testOptions {
         unitTests.includeAndroidResources = true
         unitTests.returnDefaultValues = true
-
         unitTests.all { t ->
             reports {
                 html.enabled true
@@ -137,5 +147,5 @@ if (rootProject.hasProperty('isOfficialDetoxLib') ||
 
 // Enable publishing
 if (rootProject.hasProperty('isOfficialDetoxLib')) {
-    apply from: './detox-publishing.gradle'
+    apply from: './publishing.gradle'
 }
diff --git a/detox/android/detox/detox-publishing.gradle b/detox/android/detox/detox-publishing.gradle
deleted file mode 100644
index 812f4f992..000000000
--- a/detox/android/detox/detox-publishing.gradle
+++ /dev/null
@@ -1,160 +0,0 @@
-apply plugin: 'maven-publish'
-apply plugin: 'kotlin-android'
-apply plugin: 'org.jetbrains.dokka'
-
-def libOutputDir = "$buildDir/../../../Detox-android"
-
-// The official javadoc equivalent that supports kotlin KDoc (see https://github.com/Kotlin/dokka)
-dokka {
-
-    // Note: this only remains valid as long as we didn't move kotlin code to src/main/kotlin instead fo src/main/java.
-    // Will have to keep this up to date if we decided to do so.
-    sourceDirs = files(android.sourceSets.main.java.srcDirs)
-
-    // Nothing to add to what kotlinTasks() resolves on its own
-//    classpath = []
-//    classpath += files(android.bootClasspath)
-//    classpath += files(project.configurations.getByName('compile').asList())
-//    classpath += files(android.libraryVariants.collect { variant ->
-//        variant.javaCompile.classpath.files
-//    }.flatten())
-
-    reportUndocumented = false
-    skipEmptyPackages = true
-
-    outputFormat = 'javadoc' // https://github.com/Kotlin/dokka#output-formats
-    outputDirectory = "$buildDir/dokkaDoc" // Temp 'exploded' dir for .jar creation (i.e. by dokkaDocJar task)
-
-
-    def suppressedPackages = ["android_libs", "com.wix.detox.espresso.common.annot"]
-    for (String packagePrefix: suppressedPackages) {
-        packageOptions {
-            prefix = packagePrefix
-            suppress = true
-        }
-    }
-
-    // Side note / TODO:
-    // Dokka outputs R and BuildConfig; currently, there's nothing to do about it, as issues such as
-    // this on - https://github.com/Kotlin/dokka/issues/419 are still open :-/
-    // We might want to revisit this in the future -- see if they've decided to export a custom classes
-    // suppression config var or something.
-}
-
-task dokkaDocJar(type: Jar, dependsOn: dokka) {
-    from "$buildDir/dokkaDoc"
-    classifier = 'javadoc'
-}
-
-task sourcesJar(type: Jar) {
-    from android.sourceSets.main.java.srcDirs
-    classifier = 'sources'
-}
-
-project.afterEvaluate {
-    project.tasks.all { Task task ->
-        android.libraryVariants.all { variant ->
-            def v = variant.name.capitalize()
-            if (task.name == "publishMaven${v}AarPublicationToMavenRepository") {
-                task.dependsOn "assemble${v}"
-
-                // NOTE: Must "inject" this before actual publishing task run instead of inside publications def (see
-                // below) because publications runs in the configuration phase (i.e. otherwise the check would run - and
-                // fail, for *any* running gradle task, not just for publishing tasks).
-                task.doFirst {
-                    def versionName = System.getProperty('version')
-                    if (versionName == null) {
-                        throw new IllegalStateException("Publishing: Version not specified (should run 'gradle publish' with a -Dversion=1.2.3)")
-                    }
-                    logger.lifecycle("Publishing '$versionName' to: $libOutputDir")
-                }
-            }
-        }
-    }
-}
-
-publishing {
-    repositories {
-        maven {
-            url = "$libOutputDir"
-        }
-    }
-
-    publications {
-        android.libraryVariants.all { variant ->
-            if (variant.buildType.name == 'release') {
-                def versionName = System.getProperty('version')
-
-                "maven${variant.name.capitalize()}Aar"(MavenPublication) {
-                    groupId 'com.wix'
-                    artifactId 'detox'
-                    version "$versionName"
-
-                    // Register .aar as artifacts
-                    variant.outputs.forEach { output ->
-                        artifact output.outputFile
-                    }
-                    // Register sources, javadoc as artifacts
-                    artifact sourcesJar
-                    artifact dokkaDocJar
-
-                    // Add some detox metadata to the .pom
-                    pom {
-                        name = 'Detox'
-                        description = 'Gray box end-to-end testing and automation library for mobile apps'
-                        url = 'https://github.com/wix/Detox'
-                        scm {
-                            connection = 'scm:git:git://github.com/wix/detox.git'
-                            developerConnection = 'scm:git:git@github.com/wix/detox.git'
-                            url = 'https://github.com/wix/detox'
-                        }
-                        licenses {
-                            license {
-                                name = "The MIT License"
-                                url = "https://github.com/wix/Detox/blob/master/LICENSE"
-                            }
-                        }
-                    }
-
-                    // Add detox dependencies to the .pom
-                    pom.withXml {
-                        final rootNode = asNode().appendNode('dependencies')
-                        addConfigurationDependencies(rootNode, configurations.api, "compile")
-                        addConfigurationDependencies(rootNode, configurations.compile, "compile")
-                        addConfigurationDependencies(rootNode, configurations.implementation, "runtime")
-                    }
-                }
-            }
-        }
-    }
-
-    // Based on https://stackoverflow.com/a/42160584/453052
-    ext.addConfigurationDependencies = { rootNode, Configuration configuration, String scope ->
-        configuration.dependencies.each { dep -> addChildDependency(rootNode, dep, scope) }
-    }
-
-    ext.addChildDependency = { rootNode, Dependency dep, String scope ->
-        if (dep.group == null || dep.version == null || dep.name == null || dep.name == "unspecified")
-            return
-
-        final childNode = rootNode.appendNode('dependency')
-        childNode.appendNode('groupId', dep.group)
-        childNode.appendNode('artifactId', dep.name)
-        childNode.appendNode('version', dep.version)
-        childNode.appendNode('scope', scope)
-
-        if (!dep.transitive) {
-            // If this dependency is transitive, we should force exclude all its dependencies them from the POM
-            final exclusionNode = childNode.appendNode('exclusions').appendNode('exclusion')
-            exclusionNode.appendNode('groupId', '*')
-            exclusionNode.appendNode('artifactId', '*')
-        } else if (!dep.properties.excludeRules.empty) {
-            // Otherwise add specified exclude rules
-            final exclusionNode = childNode.appendNode('exclusions').appendNode('exclusion')
-            dep.properties.excludeRules.each { ExcludeRule rule ->
-                exclusionNode.appendNode('groupId', rule.group ?: '*')
-                exclusionNode.appendNode('artifactId', rule.module ?: '*')
-            }
-        }
-    }
-}
diff --git a/detox/android/detox/publish-pom.gradle b/detox/android/detox/publish-pom.gradle
new file mode 100644
index 000000000..0710b4834
--- /dev/null
+++ b/detox/android/detox/publish-pom.gradle
@@ -0,0 +1,39 @@
+// Based on https://stackoverflow.com/a/42160584/453052
+
+project.ext.buildPomXmlDependencies = { pom, configurations ->
+    pom.withXml {
+        final rootNode = asNode().appendNode('dependencies')
+        addConfigurationDependencies(rootNode, configurations.api, 'compile')
+        addConfigurationDependencies(rootNode, configurations.compile, 'compile')
+        addConfigurationDependencies(rootNode, configurations.implementation, 'runtime')
+    }
+}
+
+private static def addConfigurationDependencies(rootNode, Configuration configuration, String scope) {
+    configuration.dependencies.each { dep -> addChildDependency(rootNode, dep, scope) }
+}
+
+private static def addChildDependency(rootNode, Dependency dep, String scope) {
+    if (dep.group == null || dep.version == null || dep.name == null || dep.name == "unspecified")
+        return
+
+    final childNode = rootNode.appendNode('dependency')
+    childNode.appendNode('groupId', dep.group)
+    childNode.appendNode('artifactId', dep.name)
+    childNode.appendNode('version', dep.version)
+    childNode.appendNode('scope', scope)
+
+    if (!dep.transitive) {
+        // If this dependency is transitive, we should force exclude all its dependencies them from the POM
+        final exclusionNode = childNode.appendNode('exclusions').appendNode('exclusion')
+        exclusionNode.appendNode('groupId', '*')
+        exclusionNode.appendNode('artifactId', '*')
+    } else if (!dep.properties.excludeRules.empty) {
+        // Otherwise add specified exclude rules
+        final exclusionNode = childNode.appendNode('exclusions').appendNode('exclusion')
+        dep.properties.excludeRules.each { ExcludeRule rule ->
+            exclusionNode.appendNode('groupId', rule.group ?: '*')
+            exclusionNode.appendNode('artifactId', rule.module ?: '*')
+        }
+    }
+}
diff --git a/detox/android/detox/publishing.gradle b/detox/android/detox/publishing.gradle
new file mode 100644
index 000000000..80e548a1e
--- /dev/null
+++ b/detox/android/detox/publishing.gradle
@@ -0,0 +1,286 @@
+apply plugin: 'maven-publish'
+apply plugin: 'kotlin-android'
+apply plugin: 'org.jetbrains.dokka'
+apply plugin: 'signing'
+apply from: './publish-pom.gradle'
+
+String TARGET_LOCAL_DIR = "$buildDir/../../../Detox-android"
+String TARGET_MAVEN_CENTRAL_URL = 'https://oss.sonatype.org/service/local/staging/deploy/maven2'
+
+String PUB_FLAVOUR_FULL_DETOX = 'full'
+String PUB_FLAVOUR_DETOX_NATIVE = 'coreNative'
+
+def DEVELOPERS = [
+    [name: 'WixMobile', email: 'mobile1@wix.com'],
+    [name: 'd4vidi', email: 'amitd@wix.com'],
+]
+
+String _versionName = System.getProperty('version')
+String _flavour = System.getProperty('detoxFlavour', PUB_FLAVOUR_FULL_DETOX)
+
+String _mavenRepoUrl
+Map _mavenCredentials
+def _shouldSignArtifacts = false
+
+def _selectedVariant
+
+def initPublishing = {
+    switch (_flavour) {
+        case PUB_FLAVOUR_FULL_DETOX:
+            _mavenRepoUrl = TARGET_LOCAL_DIR
+            _mavenCredentials = null
+            _shouldSignArtifacts = false
+            break
+
+        case PUB_FLAVOUR_DETOX_NATIVE:
+            _mavenRepoUrl = TARGET_MAVEN_CENTRAL_URL
+            _mavenCredentials = [
+                    // This should come from ~/.gradle.properties
+                    username: sonatypeUsername,
+                    password: sonatypePassword,
+            ]
+            _shouldSignArtifacts = true
+            break
+
+        default:
+            assertNull(_flavour, "Don\'t know how to publish by flavour '${_flavour}'. Try '${PUB_FLAVOUR_FULL_DETOX}' or '${PUB_FLAVOUR_DETOX_NATIVE}'.")
+            break
+    }
+}
+
+def onPrePublish = {
+    assertDefined(_versionName, "Publishing: Version not specified (run 'gradle publish' with a -Dversion=1.2.3 argument)")
+    logger.lifecycle("Detox publishing is now in session! 📣\n  Version: $_versionName\n  Target URL: ${_mavenRepoUrl}\n  Build-variant: '${_selectedVariant.name}'")
+}
+
+def shouldPublishVariant = {
+    return isReleaseVariant(it) && isVariantOfProductFlavour(it, _flavour)
+}
+
+def declareArchive = { target ->
+    if (_shouldSignArtifacts) {
+        project.artifacts {
+            archives target
+        }
+    }
+}
+
+initPublishing()
+
+/*
+ * Documentation JAR configuration using dokka
+ * Dokka is the official javadoc equivalent that supports kotlin KDoc (see https://github.com/Kotlin/dokka)
+ */
+
+dokka {
+    // Note: this only remains valid as long as we don't move kotlin code to src/main/kotlin instead of src/main/java.
+    // Will have to keep this up to date if we decided to do so.
+    sourceDirs = files(android.sourceSets.main.java.srcDirs)
+
+    // Nothing to add to what kotlinTasks() resolves on its own
+//    classpath = []
+//    classpath += files(android.bootClasspath)
+//    classpath += files(project.configurations.getByName('compile').asList())
+//    classpath += files(android.libraryVariants.collect { variant ->
+//        variant.javaCompile.classpath.files
+//    }.flatten())
+
+    reportUndocumented = false
+    skipEmptyPackages = true
+
+    outputFormat = 'javadoc' // https://github.com/Kotlin/dokka#output-formats
+    outputDirectory = "$buildDir/dokkaDoc" // Temp 'exploded' dir for .jar creation (i.e. by dokkaDocJar task)
+
+    def suppressedPackages = ["android_libs", "com.wix.detox.espresso.common.annot"]
+    for (String packagePrefix: suppressedPackages) {
+        packageOptions {
+            prefix = packagePrefix
+            suppress = true
+        }
+    }
+
+    // Side note / TODO:
+    // Dokka outputs R and BuildConfig; currently, there's nothing to do about it, as issues such as
+    // this on - https://github.com/Kotlin/dokka/issues/419 are still open :-/
+    // We might want to revisit this in the future -- see if they've decided to export a custom classes
+    // suppression config var or something.
+}
+
+task dokkaDocJar(type: Jar, dependsOn: dokka) {
+    from "$buildDir/dokkaDoc"
+    classifier = 'javadoc'
+}
+
+/*
+ * Sources JAR configuration
+ */
+
+task sourcesJar(type: Jar) {
+    from android.sourceSets.main.java.srcDirs
+    classifier = 'sources'
+}
+
+/*
+ * Signing configuration
+ * https://docs.gradle.org/current/userguide/signing_plugin.html
+ */
+
+// Tell signing task to sign everything current and future we set as a project archive...
+signing {
+    required { _shouldSignArtifacts }
+    sign configurations.archives
+}
+
+/*
+ * Plumbing work for actually having the publishing task work properly, if executed
+ */
+
+project.afterEvaluate {
+    project.tasks.all { Task task ->
+        android.libraryVariants.all { variant ->
+            String variantName = variant.name.capitalize()
+            if (task.name == "publishMaven${variantName}AarPublicationToMavenRepository") {
+                task.dependsOn "assemble${variantName}"
+                task.dependsOn project.tasks.signArchives
+                task.doFirst {
+                    onPrePublish()
+                }
+            }
+        }
+    }
+}
+
+/*
+ * Publishing configuration
+ */
+
+publishing {
+    repositories {
+        maven {
+            url _mavenRepoUrl
+            if (_mavenCredentials != null) {
+                credentials {
+                    username _mavenCredentials.username
+                    password _mavenCredentials.password
+                }
+            }
+        }
+    }
+
+    publications {
+        android.libraryVariants.all { variant ->
+            if (shouldPublishVariant(variant)) {
+                _selectedVariant = variant
+
+                String variantNameCapitalized = variant.name.capitalize()
+
+                "maven${variantNameCapitalized}Aar"(MavenPublication) {
+                    groupId 'com.wix'
+                    artifactId 'detox'
+                    version "$_versionName"
+
+                    // Register built .aar as published artifact (as a file, explicitly)
+                    variant.outputs.forEach { output ->
+                        artifact output.outputFile
+
+                        // Also register as an archive-artifact, for signing (via equivalent task's output)
+                        declareArchive project.tasks["bundle${variantNameCapitalized}Aar"]
+                    }
+
+                    // Register sources, javadoc as published artifacts (via equivalent tasks' output)
+                    artifact sourcesJar
+                    artifact dokkaDocJar
+
+                    // Also register source, javadoc as archive-artifacts, for signing
+                    declareArchive sourcesJar
+                    declareArchive dokkaDocJar
+
+                    // Add detox package metadata to the .pom
+                    pom {
+                        name = 'Detox'
+                        description = 'Gray box end-to-end testing and automation library for mobile apps'
+                        url = 'https://github.com/wix/Detox'
+                        packaging 'aar' // Oh so important - or apps would ignore our code!!!!!
+                        scm {
+                            connection = 'scm:git:git://github.com/wix/detox.git'
+                            developerConnection = 'scm:git:git@github.com/wix/detox.git'
+                            url = 'https://github.com/wix/detox'
+                        }
+                        licenses {
+                            license {
+                                name = 'The MIT License'
+                                url = 'https://github.com/wix/Detox/blob/master/LICENSE'
+                            }
+                        }
+                        developers {
+                            DEVELOPERS.each { d ->
+                                developer {
+                                    name = d.name
+                                    email = d.email
+                                }
+                            }
+                        }
+                    }
+
+                    // Add detox dependencies to the .pom
+                    buildPomXmlDependencies(pom, configurations)
+
+                    // Register pom.xml's signature file (pom.xml.asc) as published artifact
+                    // Note: this is done manually, instead of registering the pom as an archived artifact
+                    if (_shouldSignArtifacts) {
+                        pom.withXml {
+                            def pomFile = file("${project.buildDir}/generated-pom.xml")
+                            writeTo(pomFile) // Need to force-write so as to have the signature generated over the finalized content
+
+                            def pomAscFile = signing.sign(pomFile).signatureFiles[0]
+                            artifact(pomAscFile) {
+                                classifier = null
+                                extension = 'pom.asc'
+                            }
+                        }
+                    }
+
+                    // Register all artifacts we've previously registered as archives (i.e. .jar.asc's, .aar.asc's) as published artifacts.
+                    // Note: this relies on preregistering the equivalent generator-tasks as archive artifacts
+                    // inside a project.artifacts { ... } clause.
+                    project.tasks.signArchives.signatureFiles.each {
+                        artifact(it) {
+                            def matcherSrcDocs = (it.file =~ /-(sources|javadoc)\.jar\.asc$/)
+                            def matcherAAR = (it.file =~ /\.aar\.asc$/)
+                            if (matcherSrcDocs.find()) {
+                                classifier = matcherSrcDocs.group(1)
+                                extension = 'jar.asc'
+                            } else if (matcherAAR.find()) {
+                                classifier = null
+                                extension = 'aar.asc'
+                            } else {
+                                classifier = null
+                                extension = null
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+private static def isReleaseVariant(variant) {
+    return variant.buildType.name == 'release'
+}
+
+private static def isVariantOfProductFlavour(variant, flavourName) {
+    return variant.productFlavors.name.find { name -> name == flavourName } != null
+}
+
+private static def assertDefined(target, message) {
+    if (target == null) {
+        throw new IllegalArgumentException(message)
+    }
+}
+
+private static def assertNull(target, message) {
+    if (target != null) {
+        throw new IllegalArgumentException(message)
+    }
+}
diff --git a/detox/android/detox/src/coreNative/java/com/wix/detox/actions/DetoxViewActions.kt b/detox/android/detox/src/coreNative/java/com/wix/detox/actions/DetoxViewActions.kt
new file mode 100644
index 000000000..d99d5e108
--- /dev/null
+++ b/detox/android/detox/src/coreNative/java/com/wix/detox/actions/DetoxViewActions.kt
@@ -0,0 +1,27 @@
+package com.wix.detox.actions
+
+import android.view.View
+import androidx.test.espresso.UiController
+import androidx.test.espresso.ViewAction
+import androidx.test.espresso.action.GeneralClickAction
+import androidx.test.espresso.action.GeneralLocation
+import androidx.test.espresso.action.Press
+import androidx.test.espresso.action.ViewActions
+import com.wix.detox.espresso.action.DetoxSingleTap
+import com.wix.detox.espresso.action.DetoxMultiTap
+import com.wix.detox.espresso.action.TakeViewScreenshotAction
+import com.wix.detox.espresso.action.ScreenshotResult
+import com.wix.detox.espresso.ViewActionWithResult
+
+public object DetoxViewActions {
+    public fun tap(): ViewAction =
+        ViewActions.actionWithAssertions(GeneralClickAction(DetoxSingleTap(), GeneralLocation.CENTER, Press.FINGER, 0, 0))
+
+    public fun doubleTap() = multiTap(2)
+
+    public fun multiTap(times: Int): ViewAction =
+        ViewActions.actionWithAssertions(GeneralClickAction(DetoxMultiTap(times), GeneralLocation.CENTER, Press.FINGER, 0, 0))
+
+    public fun takeScreenshot(): ViewActionWithResult<ScreenshotResult?> =
+        TakeViewScreenshotAction()
+}
diff --git a/detox/android/detox/src/main/java/com/wix/detox/Delegator.java b/detox/android/detox/src/full/java/com/wix/detox/Delegator.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/Delegator.java
rename to detox/android/detox/src/full/java/com/wix/detox/Delegator.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/Detox.java b/detox/android/detox/src/full/java/com/wix/detox/Detox.java
similarity index 99%
rename from detox/android/detox/src/main/java/com/wix/detox/Detox.java
rename to detox/android/detox/src/full/java/com/wix/detox/Detox.java
index 96bbad0bc..ef18428ea 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/Detox.java
+++ b/detox/android/detox/src/full/java/com/wix/detox/Detox.java
@@ -18,6 +18,8 @@ import androidx.test.espresso.IdlingPolicies;
 import androidx.test.platform.app.InstrumentationRegistry;
 import androidx.test.rule.ActivityTestRule;
 
+import static com.wix.detox.common.DetoxLog.LOG_TAG;
+
 /**
  * <p>Static class.</p>
  *
@@ -72,8 +74,6 @@ import androidx.test.rule.ActivityTestRule;
  * <p>If not set, then Detox tests are no ops. So it's safe to mix it with other tests.</p>
  */
 public final class Detox {
-    public static final String LOG_TAG = "Detox";
-
     private static final String INTENT_LAUNCH_ARGS_KEY = "launchArgs";
     private static final long ACTIVITY_LAUNCH_TIMEOUT = 10000L;
 
diff --git a/detox/android/detox/src/main/java/com/wix/detox/WebSocketClient.java b/detox/android/detox/src/full/java/com/wix/detox/WebSocketClient.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/WebSocketClient.java
rename to detox/android/detox/src/full/java/com/wix/detox/WebSocketClient.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/common/annot/MotionDefs.kt b/detox/android/detox/src/full/java/com/wix/detox/action/common/MotionDefs.kt
similarity index 95%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/common/annot/MotionDefs.kt
rename to detox/android/detox/src/full/java/com/wix/detox/action/common/MotionDefs.kt
index 2ebae453f..0846e73fb 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/espresso/common/annot/MotionDefs.kt
+++ b/detox/android/detox/src/full/java/com/wix/detox/action/common/MotionDefs.kt
@@ -1,6 +1,6 @@
 @file:JvmName("MotionDefs")
 
-package com.wix.detox.espresso.common.annot
+package com.wix.detox.action.common
 
 import androidx.annotation.IntDef
 
diff --git a/detox/android/detox/src/main/java/com/wix/detox/common/RNAnnotations.kt b/detox/android/detox/src/full/java/com/wix/detox/common/RNAnnotations.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/common/RNAnnotations.kt
rename to detox/android/detox/src/full/java/com/wix/detox/common/RNAnnotations.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/config/DetoxConfig.kt b/detox/android/detox/src/full/java/com/wix/detox/config/DetoxConfig.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/config/DetoxConfig.kt
rename to detox/android/detox/src/full/java/com/wix/detox/config/DetoxConfig.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/config/DetoxIdlePolicyConfig.kt b/detox/android/detox/src/full/java/com/wix/detox/config/DetoxIdlePolicyConfig.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/config/DetoxIdlePolicyConfig.kt
rename to detox/android/detox/src/full/java/com/wix/detox/config/DetoxIdlePolicyConfig.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/DetoxAction.java b/detox/android/detox/src/full/java/com/wix/detox/espresso/DetoxAction.java
similarity index 89%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/DetoxAction.java
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/DetoxAction.java
index 7179cf33f..73e6a6b7a 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/espresso/DetoxAction.java
+++ b/detox/android/detox/src/full/java/com/wix/detox/espresso/DetoxAction.java
@@ -2,13 +2,13 @@ package com.wix.detox.espresso;
 
 import android.view.View;
 
-import com.wix.detox.common.DetoxErrors;
 import com.wix.detox.common.DetoxErrors.DetoxRuntimeException;
 import com.wix.detox.common.DetoxErrors.StaleActionException;
 import com.wix.detox.espresso.action.DetoxMultiTap;
 import com.wix.detox.espresso.action.RNClickAction;
+import com.wix.detox.espresso.action.ScreenshotResult;
 import com.wix.detox.espresso.action.TakeViewScreenshotAction;
-import com.wix.detox.espresso.common.annot.MotionDir;
+import com.wix.detox.action.common.MotionDir;
 import com.wix.detox.espresso.scroll.ScrollEdgeException;
 import com.wix.detox.espresso.scroll.ScrollHelper;
 import com.wix.detox.espresso.scroll.SwipeHelper;
@@ -20,17 +20,11 @@ import androidx.test.espresso.ViewAction;
 import androidx.test.espresso.action.CoordinatesProvider;
 import androidx.test.espresso.action.GeneralClickAction;
 import androidx.test.espresso.action.GeneralLocation;
-import androidx.test.espresso.action.GeneralSwipeAction;
 import androidx.test.espresso.action.Press;
-import androidx.test.espresso.action.ViewActions;
 
 import static androidx.test.espresso.action.ViewActions.actionWithAssertions;
 import static androidx.test.espresso.matcher.ViewMatchers.isAssignableFrom;
 import static androidx.test.espresso.matcher.ViewMatchers.isDisplayed;
-import static com.wix.detox.espresso.common.annot.MotionDefs.MOTION_DIR_DOWN;
-import static com.wix.detox.espresso.common.annot.MotionDefs.MOTION_DIR_LEFT;
-import static com.wix.detox.espresso.common.annot.MotionDefs.MOTION_DIR_RIGHT;
-import static com.wix.detox.espresso.common.annot.MotionDefs.MOTION_DIR_UP;
 import static org.hamcrest.Matchers.allOf;
 
 
@@ -181,6 +175,29 @@ public class DetoxAction {
     }
 
     public static ViewAction takeViewScreenshot() {
-        return new TakeViewScreenshotAction();
+        return new ViewActionWithResult<String>() {
+            private TakeViewScreenshotAction action = new TakeViewScreenshotAction();
+
+            @Override
+            public Matcher<View> getConstraints() {
+                return action.getConstraints();
+            }
+
+            @Override
+            public String getDescription() {
+                return action.getDescription();
+            }
+
+            @Override
+            public void perform(UiController uiController, View view) {
+                action.perform(uiController, view);
+            }
+
+            @Override
+            public String getResult() {
+                ScreenshotResult result = action.getResult();
+                return (result == null ? null : result.asBase64String());
+            }
+        };
     }
 }
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/DetoxAssertion.java b/detox/android/detox/src/full/java/com/wix/detox/espresso/DetoxAssertion.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/DetoxAssertion.java
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/DetoxAssertion.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/DetoxMatcher.java b/detox/android/detox/src/full/java/com/wix/detox/espresso/DetoxMatcher.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/DetoxMatcher.java
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/DetoxMatcher.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/DetoxViewActions.java b/detox/android/detox/src/full/java/com/wix/detox/espresso/DetoxViewActions.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/DetoxViewActions.java
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/DetoxViewActions.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/EspressoDetox.java b/detox/android/detox/src/full/java/com/wix/detox/espresso/EspressoDetox.java
similarity index 98%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/EspressoDetox.java
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/EspressoDetox.java
index 9b4c9be0c..4526967e3 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/espresso/EspressoDetox.java
+++ b/detox/android/detox/src/full/java/com/wix/detox/espresso/EspressoDetox.java
@@ -37,8 +37,8 @@ public class EspressoDetox {
     public static Object perform(ViewInteraction interaction, ViewAction action) {
         interaction.perform(action);
 
-        if (action instanceof ActionWithResult) {
-            return ((ActionWithResult) action).getResult();
+        if (action instanceof ViewActionWithResult) {
+            return ((ViewActionWithResult) action).getResult();
         }
         return null;
     }
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/UiAutomatorHelper.java b/detox/android/detox/src/full/java/com/wix/detox/espresso/UiAutomatorHelper.java
similarity index 97%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/UiAutomatorHelper.java
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/UiAutomatorHelper.java
index c424a1b38..06eb3efb4 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/espresso/UiAutomatorHelper.java
+++ b/detox/android/detox/src/full/java/com/wix/detox/espresso/UiAutomatorHelper.java
@@ -5,19 +5,15 @@ import android.os.Handler;
 import android.util.DisplayMetrics;
 import android.util.Log;
 import android.view.Choreographer;
-import android.view.View;
 
 import com.wix.detox.espresso.common.utils.UiControllerUtils;
 
-import org.hamcrest.core.IsAnything;
 import org.joor.Reflect;
 import org.joor.ReflectException;
 
 import java.util.concurrent.CountDownLatch;
 import java.util.concurrent.TimeUnit;
 
-import androidx.test.espresso.Espresso;
-import androidx.test.espresso.ViewInteraction;
 import androidx.test.platform.app.InstrumentationRegistry;
 
 /**
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/action/DetoxTypeTextAction.java b/detox/android/detox/src/full/java/com/wix/detox/espresso/action/DetoxTypeTextAction.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/action/DetoxTypeTextAction.java
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/action/DetoxTypeTextAction.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/action/RNClickAction.java b/detox/android/detox/src/full/java/com/wix/detox/espresso/action/RNClickAction.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/action/RNClickAction.java
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/action/RNClickAction.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/assertion/ViewAssertions.java b/detox/android/detox/src/full/java/com/wix/detox/espresso/assertion/ViewAssertions.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/assertion/ViewAssertions.java
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/assertion/ViewAssertions.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/matcher/ViewAtIndexMatcher.kt b/detox/android/detox/src/full/java/com/wix/detox/espresso/matcher/ViewAtIndexMatcher.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/matcher/ViewAtIndexMatcher.kt
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/matcher/ViewAtIndexMatcher.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/matcher/ViewMatchers.kt b/detox/android/detox/src/full/java/com/wix/detox/espresso/matcher/ViewMatchers.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/matcher/ViewMatchers.kt
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/matcher/ViewMatchers.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/scroll/DetoxSwipe.kt b/detox/android/detox/src/full/java/com/wix/detox/espresso/scroll/DetoxSwipe.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/scroll/DetoxSwipe.kt
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/scroll/DetoxSwipe.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/scroll/DetoxSwiper.kt b/detox/android/detox/src/full/java/com/wix/detox/espresso/scroll/DetoxSwiper.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/scroll/DetoxSwiper.kt
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/scroll/DetoxSwiper.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/scroll/FlinglessSwiper.kt b/detox/android/detox/src/full/java/com/wix/detox/espresso/scroll/FlinglessSwiper.kt
similarity index 98%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/scroll/FlinglessSwiper.kt
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/scroll/FlinglessSwiper.kt
index 388ea9c7b..3a7f271f2 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/espresso/scroll/FlinglessSwiper.kt
+++ b/detox/android/detox/src/full/java/com/wix/detox/espresso/scroll/FlinglessSwiper.kt
@@ -3,7 +3,7 @@ package com.wix.detox.espresso.scroll
 import android.view.MotionEvent
 import android.view.ViewConfiguration
 import androidx.test.espresso.UiController
-import com.wix.detox.espresso.common.MotionEvents
+import com.wix.detox.espresso.action.common.MotionEvents
 
 /**
  * A detox-swiper that, given the total expected motions, tries to swipe fast and yet avoid an
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/scroll/ScrollEdgeException.kt b/detox/android/detox/src/full/java/com/wix/detox/espresso/scroll/ScrollEdgeException.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/scroll/ScrollEdgeException.kt
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/scroll/ScrollEdgeException.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/scroll/ScrollHelper.java b/detox/android/detox/src/full/java/com/wix/detox/espresso/scroll/ScrollHelper.java
similarity index 96%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/scroll/ScrollHelper.java
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/scroll/ScrollHelper.java
index 01dd3fccc..7b7c3e7a2 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/espresso/scroll/ScrollHelper.java
+++ b/detox/android/detox/src/full/java/com/wix/detox/espresso/scroll/ScrollHelper.java
@@ -6,16 +6,16 @@ import android.util.Log;
 import android.view.View;
 import android.view.ViewConfiguration;
 
+import com.wix.detox.action.common.MotionDir;
 import com.wix.detox.espresso.UiAutomatorHelper;
-import com.wix.detox.espresso.common.annot.MotionDir;
 
 import androidx.test.espresso.UiController;
 import androidx.test.platform.app.InstrumentationRegistry;
 
-import static com.wix.detox.espresso.common.annot.MotionDefs.MOTION_DIR_DOWN;
-import static com.wix.detox.espresso.common.annot.MotionDefs.MOTION_DIR_LEFT;
-import static com.wix.detox.espresso.common.annot.MotionDefs.MOTION_DIR_RIGHT;
-import static com.wix.detox.espresso.common.annot.MotionDefs.MOTION_DIR_UP;
+import static com.wix.detox.action.common.MotionDefs.MOTION_DIR_DOWN;
+import static com.wix.detox.action.common.MotionDefs.MOTION_DIR_LEFT;
+import static com.wix.detox.action.common.MotionDefs.MOTION_DIR_RIGHT;
+import static com.wix.detox.action.common.MotionDefs.MOTION_DIR_UP;
 import static com.wix.detox.espresso.scroll.ScrollProbes.getScrollableProbe;
 
 /**
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/scroll/ScrollProbes.kt b/detox/android/detox/src/full/java/com/wix/detox/espresso/scroll/ScrollProbes.kt
similarity index 98%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/scroll/ScrollProbes.kt
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/scroll/ScrollProbes.kt
index f9fe0448b..e490afee7 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/espresso/scroll/ScrollProbes.kt
+++ b/detox/android/detox/src/full/java/com/wix/detox/espresso/scroll/ScrollProbes.kt
@@ -5,7 +5,7 @@ package com.wix.detox.espresso.scroll
 import android.annotation.SuppressLint
 import android.view.View
 import android.widget.AbsListView
-import com.wix.detox.espresso.common.annot.*
+import com.wix.detox.action.common.*
 
 // TODO ViewPager?
 fun getScrollableProbe(view: View, @MotionDir direction: Int): ScrollableProbe {
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/scroll/SwipeHelper.kt b/detox/android/detox/src/full/java/com/wix/detox/espresso/scroll/SwipeHelper.kt
similarity index 97%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/scroll/SwipeHelper.kt
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/scroll/SwipeHelper.kt
index ac5b1e39e..64db09a01 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/espresso/scroll/SwipeHelper.kt
+++ b/detox/android/detox/src/full/java/com/wix/detox/espresso/scroll/SwipeHelper.kt
@@ -2,11 +2,10 @@ package com.wix.detox.espresso.scroll
 
 import androidx.test.espresso.ViewAction
 import androidx.test.espresso.action.*
-import com.wix.detox.espresso.common.annot.*
-import com.wix.detox.espresso.utils.*
-import kotlin.math.abs
-import kotlin.math.min
+import com.wix.detox.action.common.MOTION_DIR_DOWN
+import com.wix.detox.espresso.utils.Vector2D
 import kotlin.math.max
+import kotlin.math.min
 
 private const val EDGE_FUZZ_FACTOR = 0.083
 
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/utils/Vector2D.kt b/detox/android/detox/src/full/java/com/wix/detox/espresso/utils/Vector2D.kt
similarity index 74%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/utils/Vector2D.kt
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/utils/Vector2D.kt
index 266c05e47..11af8609d 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/espresso/utils/Vector2D.kt
+++ b/detox/android/detox/src/full/java/com/wix/detox/espresso/utils/Vector2D.kt
@@ -1,23 +1,19 @@
 package com.wix.detox.espresso.utils
 
 import com.wix.detox.common.DetoxErrors
-import com.wix.detox.espresso.common.annot.MOTION_DIR_DOWN
-import com.wix.detox.espresso.common.annot.MOTION_DIR_LEFT
-import com.wix.detox.espresso.common.annot.MOTION_DIR_RIGHT
-import com.wix.detox.espresso.common.annot.MOTION_DIR_UP
+import com.wix.detox.action.common.MOTION_DIR_DOWN
+import com.wix.detox.action.common.MOTION_DIR_LEFT
+import com.wix.detox.action.common.MOTION_DIR_RIGHT
+import com.wix.detox.action.common.MOTION_DIR_UP
 import kotlin.math.floor
 import kotlin.math.max
 import kotlin.math.min
 
-private fun frac(value: Double): Double = if (value < 0)
-    -frac(-value)
-else
-    value - floor(value)
+private fun frac(value: Double): Double =
+    if (value < 0) -frac(-value) else (value - floor(value))
 
-private fun normalize(value: Double): Double = if (value < 0)
-    1 + frac(value)
-else
-    frac(value)
+private fun normalize(value: Double): Double
+    = if (value < 0) (1 + frac(value)) else frac(value)
 
 private fun clockwise90DegRotationsToDown(direction: Int) = when (direction) {
     MOTION_DIR_LEFT -> 3
@@ -28,7 +24,7 @@ private fun clockwise90DegRotationsToDown(direction: Int) = when (direction) {
 }
 
 private fun angleBetween(fromDirection: Int, toDirection: Int): Int =
-        90 * ((4 + clockwise90DegRotationsToDown(fromDirection) - clockwise90DegRotationsToDown(toDirection)) % 4)
+    90 * ((4 + clockwise90DegRotationsToDown(fromDirection) - clockwise90DegRotationsToDown(toDirection)) % 4)
 
 data class Vector2D(val x: Double, val y: Double) {
     fun add(other: Vector2D) = Vector2D(x + other.x, y + other.y)
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/web/DetoxWebAtomMatcher.java b/detox/android/detox/src/full/java/com/wix/detox/espresso/web/DetoxWebAtomMatcher.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/web/DetoxWebAtomMatcher.java
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/web/DetoxWebAtomMatcher.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/web/EspressoWebDetox.java b/detox/android/detox/src/full/java/com/wix/detox/espresso/web/EspressoWebDetox.java
similarity index 99%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/web/EspressoWebDetox.java
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/web/EspressoWebDetox.java
index b0f47e3dc..2d475768b 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/espresso/web/EspressoWebDetox.java
+++ b/detox/android/detox/src/full/java/com/wix/detox/espresso/web/EspressoWebDetox.java
@@ -39,4 +39,4 @@ public class EspressoWebDetox {
     public static WebExpect expect(WebElement webElement) {
         return new WebExpect(webElement);
     }
-}
\ No newline at end of file
+}
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/web/WebElement.java b/detox/android/detox/src/full/java/com/wix/detox/espresso/web/WebElement.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/web/WebElement.java
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/web/WebElement.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/web/WebExpect.java b/detox/android/detox/src/full/java/com/wix/detox/espresso/web/WebExpect.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/web/WebExpect.java
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/web/WebExpect.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/web/WebViewElement.java b/detox/android/detox/src/full/java/com/wix/detox/espresso/web/WebViewElement.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/web/WebViewElement.java
rename to detox/android/detox/src/full/java/com/wix/detox/espresso/web/WebViewElement.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/instruments/DetoxInstrumentsException.java b/detox/android/detox/src/full/java/com/wix/detox/instruments/DetoxInstrumentsException.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/instruments/DetoxInstrumentsException.java
rename to detox/android/detox/src/full/java/com/wix/detox/instruments/DetoxInstrumentsException.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/instruments/DetoxInstrumentsManager.java b/detox/android/detox/src/full/java/com/wix/detox/instruments/DetoxInstrumentsManager.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/instruments/DetoxInstrumentsManager.java
rename to detox/android/detox/src/full/java/com/wix/detox/instruments/DetoxInstrumentsManager.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/instruments/Instruments.java b/detox/android/detox/src/full/java/com/wix/detox/instruments/Instruments.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/instruments/Instruments.java
rename to detox/android/detox/src/full/java/com/wix/detox/instruments/Instruments.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/instruments/InstrumentsRecording.java b/detox/android/detox/src/full/java/com/wix/detox/instruments/InstrumentsRecording.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/instruments/InstrumentsRecording.java
rename to detox/android/detox/src/full/java/com/wix/detox/instruments/InstrumentsRecording.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/instruments/reflected/InstrumentsRecordingReflected.java b/detox/android/detox/src/full/java/com/wix/detox/instruments/reflected/InstrumentsRecordingReflected.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/instruments/reflected/InstrumentsRecordingReflected.java
rename to detox/android/detox/src/full/java/com/wix/detox/instruments/reflected/InstrumentsRecordingReflected.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/instruments/reflected/InstrumentsReflected.java b/detox/android/detox/src/full/java/com/wix/detox/instruments/reflected/InstrumentsReflected.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/instruments/reflected/InstrumentsReflected.java
rename to detox/android/detox/src/full/java/com/wix/detox/instruments/reflected/InstrumentsReflected.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/reactnative/ReactNativeExtension.kt b/detox/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeExtension.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/reactnative/ReactNativeExtension.kt
rename to detox/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeExtension.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/reactnative/ReactNativeIdlingResources.kt b/detox/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeIdlingResources.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/reactnative/ReactNativeIdlingResources.kt
rename to detox/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeIdlingResources.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/reactnative/ReactNativeInfo.kt b/detox/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeInfo.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/reactnative/ReactNativeInfo.kt
rename to detox/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeInfo.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/reactnative/ReactNativeLoadingMonitor.kt b/detox/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeLoadingMonitor.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/reactnative/ReactNativeLoadingMonitor.kt
rename to detox/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeLoadingMonitor.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/reactnative/ReactNativeReloader.kt b/detox/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeReloader.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/reactnative/ReactNativeReloader.kt
rename to detox/android/detox/src/full/java/com/wix/detox/reactnative/ReactNativeReloader.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/reactnative/helpers/RNHelpers.kt b/detox/android/detox/src/full/java/com/wix/detox/reactnative/helpers/RNHelpers.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/reactnative/helpers/RNHelpers.kt
rename to detox/android/detox/src/full/java/com/wix/detox/reactnative/helpers/RNHelpers.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/AnimatedModuleIdlingResource.java b/detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/AnimatedModuleIdlingResource.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/AnimatedModuleIdlingResource.java
rename to detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/AnimatedModuleIdlingResource.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/AsyncStorageIdlingResource.kt b/detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/AsyncStorageIdlingResource.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/AsyncStorageIdlingResource.kt
rename to detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/AsyncStorageIdlingResource.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/BridgeIdlingResource.java b/detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/BridgeIdlingResource.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/BridgeIdlingResource.java
rename to detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/BridgeIdlingResource.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/DetoxBaseIdlingResource.java b/detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/DetoxBaseIdlingResource.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/DetoxBaseIdlingResource.java
rename to detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/DetoxBaseIdlingResource.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/NetworkIdlingResource.java b/detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/NetworkIdlingResource.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/NetworkIdlingResource.java
rename to detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/NetworkIdlingResource.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/NetworkingModuleReflected.kt b/detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/NetworkingModuleReflected.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/NetworkingModuleReflected.kt
rename to detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/NetworkingModuleReflected.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/SerialExecutorReflected.kt b/detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/SerialExecutorReflected.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/SerialExecutorReflected.kt
rename to detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/SerialExecutorReflected.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/UIModuleIdlingResource.java b/detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/UIModuleIdlingResource.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/UIModuleIdlingResource.java
rename to detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/UIModuleIdlingResource.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/timers/DefaultIdleInterrogationStrategy.kt b/detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/DefaultIdleInterrogationStrategy.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/timers/DefaultIdleInterrogationStrategy.kt
rename to detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/DefaultIdleInterrogationStrategy.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/timers/DelegatedIdleInterrogationStrategy.kt b/detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/DelegatedIdleInterrogationStrategy.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/timers/DelegatedIdleInterrogationStrategy.kt
rename to detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/DelegatedIdleInterrogationStrategy.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/timers/IdleInterrogationStrategy.kt b/detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/IdleInterrogationStrategy.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/timers/IdleInterrogationStrategy.kt
rename to detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/IdleInterrogationStrategy.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/timers/TimersIdlingResource.kt b/detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/TimersIdlingResource.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/reactnative/idlingresources/timers/TimersIdlingResource.kt
rename to detox/android/detox/src/full/java/com/wix/detox/reactnative/idlingresources/timers/TimersIdlingResource.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/uiautomator/UiAutomator.java b/detox/android/detox/src/full/java/com/wix/detox/uiautomator/UiAutomator.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/uiautomator/UiAutomator.java
rename to detox/android/detox/src/full/java/com/wix/detox/uiautomator/UiAutomator.java
diff --git a/detox/android/detox/src/main/java/com/wix/invoke/MethodInvocation.java b/detox/android/detox/src/full/java/com/wix/invoke/MethodInvocation.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/invoke/MethodInvocation.java
rename to detox/android/detox/src/full/java/com/wix/invoke/MethodInvocation.java
diff --git a/detox/android/detox/src/main/java/com/wix/invoke/MethodUtilsExt.java b/detox/android/detox/src/full/java/com/wix/invoke/MethodUtilsExt.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/invoke/MethodUtilsExt.java
rename to detox/android/detox/src/full/java/com/wix/invoke/MethodUtilsExt.java
diff --git a/detox/android/detox/src/main/java/com/wix/invoke/exceptions/EmptyInvocationInstructionException.java b/detox/android/detox/src/full/java/com/wix/invoke/exceptions/EmptyInvocationInstructionException.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/invoke/exceptions/EmptyInvocationInstructionException.java
rename to detox/android/detox/src/full/java/com/wix/invoke/exceptions/EmptyInvocationInstructionException.java
diff --git a/detox/android/detox/src/main/java/com/wix/invoke/parser/JsonParser.java b/detox/android/detox/src/full/java/com/wix/invoke/parser/JsonParser.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/invoke/parser/JsonParser.java
rename to detox/android/detox/src/full/java/com/wix/invoke/parser/JsonParser.java
diff --git a/detox/android/detox/src/main/java/com/wix/invoke/types/ClassTarget.java b/detox/android/detox/src/full/java/com/wix/invoke/types/ClassTarget.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/invoke/types/ClassTarget.java
rename to detox/android/detox/src/full/java/com/wix/invoke/types/ClassTarget.java
diff --git a/detox/android/detox/src/main/java/com/wix/invoke/types/Invocation.java b/detox/android/detox/src/full/java/com/wix/invoke/types/Invocation.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/invoke/types/Invocation.java
rename to detox/android/detox/src/full/java/com/wix/invoke/types/Invocation.java
diff --git a/detox/android/detox/src/main/java/com/wix/invoke/types/InvocationTarget.java b/detox/android/detox/src/full/java/com/wix/invoke/types/InvocationTarget.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/invoke/types/InvocationTarget.java
rename to detox/android/detox/src/full/java/com/wix/invoke/types/InvocationTarget.java
diff --git a/detox/android/detox/src/main/java/com/wix/invoke/types/ObjectInstanceTarget.java b/detox/android/detox/src/full/java/com/wix/invoke/types/ObjectInstanceTarget.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/invoke/types/ObjectInstanceTarget.java
rename to detox/android/detox/src/full/java/com/wix/invoke/types/ObjectInstanceTarget.java
diff --git a/detox/android/detox/src/main/java/com/wix/invoke/types/Target.java b/detox/android/detox/src/full/java/com/wix/invoke/types/Target.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/invoke/types/Target.java
rename to detox/android/detox/src/full/java/com/wix/invoke/types/Target.java
diff --git a/detox/android/detox/src/main/resources/fromJsonTargetInvocationWithListParams.json b/detox/android/detox/src/full/resources/fromJsonTargetInvocationWithListParams.json
similarity index 100%
rename from detox/android/detox/src/main/resources/fromJsonTargetInvocationWithListParams.json
rename to detox/android/detox/src/full/resources/fromJsonTargetInvocationWithListParams.json
diff --git a/detox/android/detox/src/main/resources/targetClassStaticMethodNoParams.json b/detox/android/detox/src/full/resources/targetClassStaticMethodNoParams.json
similarity index 100%
rename from detox/android/detox/src/main/resources/targetClassStaticMethodNoParams.json
rename to detox/android/detox/src/full/resources/targetClassStaticMethodNoParams.json
diff --git a/detox/android/detox/src/main/resources/targetClassStaticMethodOneParam.json b/detox/android/detox/src/full/resources/targetClassStaticMethodOneParam.json
similarity index 100%
rename from detox/android/detox/src/main/resources/targetClassStaticMethodOneParam.json
rename to detox/android/detox/src/full/resources/targetClassStaticMethodOneParam.json
diff --git a/detox/android/detox/src/main/resources/targetInvocationEspresso.json b/detox/android/detox/src/full/resources/targetInvocationEspresso.json
similarity index 100%
rename from detox/android/detox/src/main/resources/targetInvocationEspresso.json
rename to detox/android/detox/src/full/resources/targetInvocationEspresso.json
diff --git a/detox/android/detox/src/main/resources/targetInvocationEspressoDetox.json b/detox/android/detox/src/full/resources/targetInvocationEspressoDetox.json
similarity index 100%
rename from detox/android/detox/src/main/resources/targetInvocationEspressoDetox.json
rename to detox/android/detox/src/full/resources/targetInvocationEspressoDetox.json
diff --git a/detox/android/detox/src/main/resources/targetInvocationMethodOfClassStaticMethodOneParam.json b/detox/android/detox/src/full/resources/targetInvocationMethodOfClassStaticMethodOneParam.json
similarity index 100%
rename from detox/android/detox/src/main/resources/targetInvocationMethodOfClassStaticMethodOneParam.json
rename to detox/android/detox/src/full/resources/targetInvocationMethodOfClassStaticMethodOneParam.json
diff --git a/detox/android/detox/src/main/AndroidManifest.xml b/detox/android/detox/src/main/AndroidManifest.xml
index 74feb3c53..0f8f8c6ae 100644
--- a/detox/android/detox/src/main/AndroidManifest.xml
+++ b/detox/android/detox/src/main/AndroidManifest.xml
@@ -1,11 +1,2 @@
-<manifest package="com.wix.detox"
-          xmlns:android="http://schemas.android.com/apk/res/android">
-
-    <application
-        android:allowBackup="true"
-        android:label="@string/app_name"
-        android:supportsRtl="true">
-
-    </application>
-
-</manifest>
+<?xml version="1.0" encoding="utf-8"?>
+<manifest package="com.wix.detox"/>
diff --git a/detox/android/detox/src/main/java/com/wix/detox/common/DetoxLog.kt b/detox/android/detox/src/main/java/com/wix/detox/common/DetoxLog.kt
index f6ea011f4..e0d270265 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/common/DetoxLog.kt
+++ b/detox/android/detox/src/main/java/com/wix/detox/common/DetoxLog.kt
@@ -1,8 +1,11 @@
+@file:JvmName("DetoxLog")
+
 package com.wix.detox.common
 
 import android.util.Log
 
-class DetoxLog {
+class DetoxLog private constructor() {
+
     fun verbose(tag: String, log: String) = Log.v(tag, log)
     fun verbose(tag: String, log: String, error: Throwable) = Log.v(tag, log, error)
 
@@ -19,7 +22,8 @@ class DetoxLog {
     fun error(tag: String, log: String) = Log.e(tag, log)
     fun error(tag: String, log: String, error: Throwable) = Log.e(tag, log, error)
 
-    companion object {
-        val instance = DetoxLog()
+    internal companion object {
+        internal val instance = DetoxLog()
+        internal const val LOG_TAG = "Detox"
     }
 }
diff --git a/detox/android/detox/src/main/java/com/wix/detox/common/JsonConverter.kt b/detox/android/detox/src/main/java/com/wix/detox/common/JsonConverter.kt
index d9e76820a..8e058cab2 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/common/JsonConverter.kt
+++ b/detox/android/detox/src/main/java/com/wix/detox/common/JsonConverter.kt
@@ -4,7 +4,7 @@ import android.os.Bundle
 import org.json.JSONArray
 import org.json.JSONObject
 
-class JsonConverter(private val json: JSONObject) {
+internal class JsonConverter(private val json: JSONObject) {
     fun toBundle(): Bundle {
         val bundle = Bundle()
         json.keys().forEach { key: String ->
diff --git a/detox/android/detox/src/main/java/com/wix/detox/common/SDKSupports.kt b/detox/android/detox/src/main/java/com/wix/detox/common/SDKSupports.kt
index 31118db94..e5c4d3486 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/common/SDKSupports.kt
+++ b/detox/android/detox/src/main/java/com/wix/detox/common/SDKSupports.kt
@@ -2,6 +2,6 @@ package com.wix.detox.common
 
 import android.os.Build
 
-object SDKSupports {
+internal object SDKSupports {
     val API_19_KITKAT = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT)
 }
diff --git a/detox/android/detox/src/main/java/com/wix/detox/common/TextFileReader.kt b/detox/android/detox/src/main/java/com/wix/detox/common/TextFileReader.kt
index 34c8bbbe6..f826234c8 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/common/TextFileReader.kt
+++ b/detox/android/detox/src/main/java/com/wix/detox/common/TextFileReader.kt
@@ -2,6 +2,6 @@ package com.wix.detox.common
 
 import java.io.File
 
-class TextFileReader(private val fileName: String) {
+internal class TextFileReader(private val fileName: String) {
     fun read() = File(fileName).inputStream().readBytes().toString(Charsets.UTF_8)
 }
diff --git a/detox/android/detox/src/main/java/com/wix/detox/common/collect/PairsIterator.kt b/detox/android/detox/src/main/java/com/wix/detox/common/collect/PairsIterator.kt
index 79fd8a8b2..379bdae2c 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/common/collect/PairsIterator.kt
+++ b/detox/android/detox/src/main/java/com/wix/detox/common/collect/PairsIterator.kt
@@ -2,7 +2,7 @@ package com.wix.detox.common.collect
 
 import java.lang.IllegalStateException
 
-class PairsIterator<T>(private val delegate: Iterator<T>): Iterator<Pair<T, T>> {
+internal class PairsIterator<T>(private val delegate: Iterator<T>): Iterator<Pair<T, T>> {
     constructor(iterable: Iterable<T>): this(iterable.iterator())
 
     override fun hasNext(): Boolean = delegate.hasNext()
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/ActionWithResult.kt b/detox/android/detox/src/main/java/com/wix/detox/espresso/ActionWithResult.kt
deleted file mode 100644
index 037fcbc25..000000000
--- a/detox/android/detox/src/main/java/com/wix/detox/espresso/ActionWithResult.kt
+++ /dev/null
@@ -1,5 +0,0 @@
-package com.wix.detox.espresso
-
-interface ActionWithResult {
-    fun getResult(): Any?
-}
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/ViewActionWithResult.kt b/detox/android/detox/src/main/java/com/wix/detox/espresso/ViewActionWithResult.kt
new file mode 100644
index 000000000..6c9f8e160
--- /dev/null
+++ b/detox/android/detox/src/main/java/com/wix/detox/espresso/ViewActionWithResult.kt
@@ -0,0 +1,7 @@
+package com.wix.detox.espresso
+
+import androidx.test.espresso.ViewAction
+
+interface ViewActionWithResult<R: Any?>: ViewAction {
+    fun getResult(): R
+}
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/action/DetoxMultiTap.kt b/detox/android/detox/src/main/java/com/wix/detox/espresso/action/DetoxMultiTap.kt
index 86576c796..79c976f81 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/espresso/action/DetoxMultiTap.kt
+++ b/detox/android/detox/src/main/java/com/wix/detox/espresso/action/DetoxMultiTap.kt
@@ -3,27 +3,27 @@ package com.wix.detox.espresso.action
 import android.view.MotionEvent
 import androidx.test.espresso.UiController
 import androidx.test.espresso.action.Tapper
-import com.wix.detox.Detox
 import com.wix.detox.common.DetoxLog
+import com.wix.detox.common.DetoxLog.Companion.LOG_TAG
 import com.wix.detox.common.collect.PairsIterator
 import com.wix.detox.common.proxy.CallInfo
 import com.wix.detox.espresso.UiControllerSpy
-import com.wix.detox.espresso.common.DetoxViewConfigurations.getDoubleTapMinTime
-import com.wix.detox.espresso.common.DetoxViewConfigurations.getLongTapMinTime
-import com.wix.detox.espresso.common.DetoxViewConfigurations.getPostTapCoolDownTime
-import com.wix.detox.espresso.common.TapEvents
+import com.wix.detox.espresso.action.common.DetoxViewConfigurations.getDoubleTapMinTime
+import com.wix.detox.espresso.action.common.DetoxViewConfigurations.getLongTapMinTime
+import com.wix.detox.espresso.action.common.DetoxViewConfigurations.getPostTapCoolDownTime
+import com.wix.detox.espresso.action.common.TapEvents
 
 /**
  * An implementation that is an alternative to Espresso's implementations, namely
  * [androidx.test.espresso.action.Tap.SINGLE] and [androidx.test.espresso.action.Tap.DOUBLE].
  *
- * The main difference is: Instead of injecting distinct idle-waiting events (down, then up, etc.), we use
- * [UiController.injectMotionEventSequence] in order to inject all events in one go, such that no
+ * The main difference is: Instead of injecting distinct idle-waiting events (down, then up, etc.), here,
+ * [UiController.injectMotionEventSequence] is used in order to inject all events in one go, such that no
  * idle-wait is employed in between.
  *
  * The main goal here is to fix timing problems where, for example - in a single tap, the gap between
  * the tap's 'down' and 'up' actions becomes too long to the point where the tap gets registered as a
- * long tap (true story). As for double-taps, a different problem addressed here is where the wait in
+ * long tap (true story!). As for double-taps, a different problem addressed here is where the wait in
  * between taps becomes too long, such that eventually the system registers two distinct taps instead
  * of a single double-tap gesture.
  *
@@ -105,7 +105,7 @@ open class DetoxMultiTap
     private fun verifyTapEventTimes(upEvent: CallInfo, downEvent: CallInfo) {
         val delta: Long = (upEvent - downEvent)!!
         if (delta >= longTapMinTimeMs) {
-            log.warn(Detox.LOG_TAG, "Tap handled too slowly, and turned into a long-tap!") // TODO conditionally turn into an error, based on a global strict-mode detox config
+            log.warn(LOG_TAG, "Tap handled too slowly, and turned into a long-tap!") // TODO conditionally turn into an error, based on a global strict-mode detox config
         }
     }
-}
+}
\ No newline at end of file
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/action/DetoxSingleTap.kt b/detox/android/detox/src/main/java/com/wix/detox/espresso/action/DetoxSingleTap.kt
index 53e30ecdc..7ca0f14e2 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/espresso/action/DetoxSingleTap.kt
+++ b/detox/android/detox/src/main/java/com/wix/detox/espresso/action/DetoxSingleTap.kt
@@ -1,3 +1,3 @@
 package com.wix.detox.espresso.action
 
-open class DetoxSingleTap : DetoxMultiTap(1)
+open class DetoxSingleTap : DetoxMultiTap(1)
\ No newline at end of file
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/action/TakeViewScreenshotAction.kt b/detox/android/detox/src/main/java/com/wix/detox/espresso/action/TakeViewScreenshotAction.kt
index 02a9ef75b..4b40ec44d 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/espresso/action/TakeViewScreenshotAction.kt
+++ b/detox/android/detox/src/main/java/com/wix/detox/espresso/action/TakeViewScreenshotAction.kt
@@ -1,25 +1,21 @@
 package com.wix.detox.espresso.action
 
-import android.util.Base64
 import android.view.View
 import androidx.test.espresso.UiController
-import androidx.test.espresso.ViewAction
-import com.wix.detox.common.ViewScreenshot
-import com.wix.detox.espresso.ActionWithResult
-import com.wix.detox.espresso.DetoxMatcher
+import com.wix.detox.espresso.ViewActionWithResult
 import org.hamcrest.Matcher
+import org.hamcrest.Matchers
 
-class TakeViewScreenshotAction(private val viewScreenshot: ViewScreenshot = ViewScreenshot())
-    : ViewAction, ActionWithResult {
+open class TakeViewScreenshotAction(private val viewScreenshot: ViewScreenshot = ViewScreenshot())
+    : ViewActionWithResult<ScreenshotResult?> {
 
-    private var result: Any? = null
+    private var result: ScreenshotResult? = null
 
     override fun perform(uiController: UiController?, view: View?) {
-        val rawResult = viewScreenshot.takeOf(view!!).asRawBytes()
-        result = Base64.encodeToString(rawResult, Base64.NO_WRAP or Base64.NO_PADDING)
+        result = viewScreenshot.takeOf(view!!)
     }
 
     override fun getResult() = result
     override fun getDescription() = "View screenshot"
-    override fun getConstraints(): Matcher<View> = DetoxMatcher.matcherForNotNull()
+    override fun getConstraints(): Matcher<View> = Matchers.notNullValue(View::class.java)
 }
diff --git a/detox/android/detox/src/main/java/com/wix/detox/common/ViewScreenshot.kt b/detox/android/detox/src/main/java/com/wix/detox/espresso/action/ViewScreenshot.kt
similarity index 83%
rename from detox/android/detox/src/main/java/com/wix/detox/common/ViewScreenshot.kt
rename to detox/android/detox/src/main/java/com/wix/detox/espresso/action/ViewScreenshot.kt
index 9a34cb0e1..34c3d7594 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/common/ViewScreenshot.kt
+++ b/detox/android/detox/src/main/java/com/wix/detox/espresso/action/ViewScreenshot.kt
@@ -1,9 +1,11 @@
-package com.wix.detox.common
+package com.wix.detox.espresso.action
 
 import android.graphics.Bitmap
 import android.graphics.Canvas
 import android.graphics.Rect
+import android.util.Base64
 import android.view.View
+import com.wix.detox.common.SDKSupports
 import java.io.ByteArrayOutputStream
 
 class ScreenshotResult(private val bitmap: Bitmap) {
@@ -13,6 +15,8 @@ class ScreenshotResult(private val bitmap: Bitmap) {
         bitmap.compress(Bitmap.CompressFormat.PNG, 100, outStream)
         return outStream.toByteArray()
     }
+    fun asBase64String(): String =
+        Base64.encodeToString(asRawBytes(), Base64.NO_WRAP or Base64.NO_PADDING)
 }
 
 class ViewScreenshot() {
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/common/DetoxViewConfiguration.kt b/detox/android/detox/src/main/java/com/wix/detox/espresso/action/common/DetoxViewConfiguration.kt
similarity index 96%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/common/DetoxViewConfiguration.kt
rename to detox/android/detox/src/main/java/com/wix/detox/espresso/action/common/DetoxViewConfiguration.kt
index 63853c963..3f2d0fc13 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/espresso/common/DetoxViewConfiguration.kt
+++ b/detox/android/detox/src/main/java/com/wix/detox/espresso/action/common/DetoxViewConfiguration.kt
@@ -1,4 +1,4 @@
-package com.wix.detox.espresso.common
+package com.wix.detox.espresso.action.common
 
 import android.os.Build
 import android.util.Log
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/common/MotionEvents.kt b/detox/android/detox/src/main/java/com/wix/detox/espresso/action/common/MotionEvents.kt
similarity index 98%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/common/MotionEvents.kt
rename to detox/android/detox/src/main/java/com/wix/detox/espresso/action/common/MotionEvents.kt
index 3db1e2ff1..1a8e1d7e0 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/espresso/common/MotionEvents.kt
+++ b/detox/android/detox/src/main/java/com/wix/detox/espresso/action/common/MotionEvents.kt
@@ -1,4 +1,4 @@
-package com.wix.detox.espresso.common
+package com.wix.detox.espresso.action.common
 
 import android.os.SystemClock
 import android.view.InputDevice
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/common/TapEvents.kt b/detox/android/detox/src/main/java/com/wix/detox/espresso/action/common/TapEvents.kt
similarity index 97%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/common/TapEvents.kt
rename to detox/android/detox/src/main/java/com/wix/detox/espresso/action/common/TapEvents.kt
index 984305d6a..d08db638a 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/espresso/common/TapEvents.kt
+++ b/detox/android/detox/src/main/java/com/wix/detox/espresso/action/common/TapEvents.kt
@@ -1,4 +1,4 @@
-package com.wix.detox.espresso.common
+package com.wix.detox.espresso.action.common
 
 import android.view.MotionEvent
 
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/common/utils/UiControllerUtils.kt b/detox/android/detox/src/main/java/com/wix/detox/espresso/action/common/utils/UiControllerUtils.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/espresso/common/utils/UiControllerUtils.kt
rename to detox/android/detox/src/main/java/com/wix/detox/espresso/action/common/utils/UiControllerUtils.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/espresso/matcher/NullableTypeSafeMatcher.java b/detox/android/detox/src/main/java/com/wix/detox/espresso/matcher/NullableTypeSafeMatcher.java
deleted file mode 100644
index f52767106..000000000
--- a/detox/android/detox/src/main/java/com/wix/detox/espresso/matcher/NullableTypeSafeMatcher.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.wix.detox.espresso.matcher;
-
-import org.hamcrest.BaseMatcher;
-import org.hamcrest.Description;
-import org.hamcrest.internal.ReflectiveTypeFinder;
-
-/**
- * Identical to Espresso's {@link org.hamcrest.TypeSafeMatcher}, but allows nulls (in which case
- * the "item" is passed-in into the sub-class nonetheless, as a null).
- */
-public abstract class NullableTypeSafeMatcher<T> extends BaseMatcher<T> {
-    private static final ReflectiveTypeFinder TYPE_FINDER = new ReflectiveTypeFinder("matchesSafely", 1, 0);
-
-    final private Class<?> expectedType;
-
-    protected NullableTypeSafeMatcher() {
-        this(TYPE_FINDER);
-    }
-
-    protected NullableTypeSafeMatcher(Class<?> expectedType) {
-        this.expectedType = expectedType;
-    }
-
-    private NullableTypeSafeMatcher(ReflectiveTypeFinder typeFinder) {
-      this.expectedType = typeFinder.findExpectedType(getClass());
-    }
-
-    /**
-     * Subclasses should implement this. The item will already have been checked for
-     * the specific type and will never be null.
-     */
-    abstract boolean matchesSafely(T item);
-
-    /**
-     * Subclasses should override this. The item will already have been checked for
-     * the specific type and will never be null.
-     */
-    void describeMismatchSafely(T item, Description mismatchDescription) {
-        super.describeMismatch(item, mismatchDescription);
-    }
-
-    @Override
-    @SuppressWarnings({"unchecked"})
-    public final boolean matches(Object item) {
-        return (item == null || expectedType.isInstance(item)) && matchesSafely((T) item);
-    }
-
-    @SuppressWarnings("unchecked")
-    @Override
-    final public void describeMismatch(Object item, Description description) {
-        if (!expectedType.isInstance(item)) {
-            description.appendText("was a ")
-                       .appendText(item.getClass().getName())
-                       .appendText(" (")
-                       .appendValue(item)
-                       .appendText(")");
-        } else {
-            describeMismatchSafely((T) item, description);
-        }
-    }
-}
diff --git a/detox/android/detox/src/test/java/com/wix/detox/instruments/DetoxInstrumentsManagerSpec.kt b/detox/android/detox/src/testFull/java/com/wix/detox/instruments/DetoxInstrumentsManagerSpec.kt
similarity index 100%
rename from detox/android/detox/src/test/java/com/wix/detox/instruments/DetoxInstrumentsManagerSpec.kt
rename to detox/android/detox/src/testFull/java/com/wix/detox/instruments/DetoxInstrumentsManagerSpec.kt
diff --git a/detox/android/detox/src/test/java/com/wix/detox/reactnative/idlingresources/AsyncStorageIdlingResourceSpec.kt b/detox/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/AsyncStorageIdlingResourceSpec.kt
similarity index 100%
rename from detox/android/detox/src/test/java/com/wix/detox/reactnative/idlingresources/AsyncStorageIdlingResourceSpec.kt
rename to detox/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/AsyncStorageIdlingResourceSpec.kt
diff --git a/detox/android/detox/src/test/java/com/wix/detox/reactnative/idlingresources/SerialExecutorReflectedSpec.kt b/detox/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/SerialExecutorReflectedSpec.kt
similarity index 100%
rename from detox/android/detox/src/test/java/com/wix/detox/reactnative/idlingresources/SerialExecutorReflectedSpec.kt
rename to detox/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/SerialExecutorReflectedSpec.kt
diff --git a/detox/android/detox/src/test/java/com/wix/detox/reactnative/idlingresources/timers/DefaultIdleInterrogationStrategySpec.kt b/detox/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/timers/DefaultIdleInterrogationStrategySpec.kt
similarity index 100%
rename from detox/android/detox/src/test/java/com/wix/detox/reactnative/idlingresources/timers/DefaultIdleInterrogationStrategySpec.kt
rename to detox/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/timers/DefaultIdleInterrogationStrategySpec.kt
diff --git a/detox/android/detox/src/test/java/com/wix/detox/reactnative/idlingresources/timers/DelegatedIdleInterrogationStrategySpec.kt b/detox/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/timers/DelegatedIdleInterrogationStrategySpec.kt
similarity index 100%
rename from detox/android/detox/src/test/java/com/wix/detox/reactnative/idlingresources/timers/DelegatedIdleInterrogationStrategySpec.kt
rename to detox/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/timers/DelegatedIdleInterrogationStrategySpec.kt
diff --git a/detox/android/detox/src/test/java/com/wix/detox/reactnative/idlingresources/timers/TimersIdlingResourceSpec.kt b/detox/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/timers/TimersIdlingResourceSpec.kt
similarity index 100%
rename from detox/android/detox/src/test/java/com/wix/detox/reactnative/idlingresources/timers/TimersIdlingResourceSpec.kt
rename to detox/android/detox/src/testFull/java/com/wix/detox/reactnative/idlingresources/timers/TimersIdlingResourceSpec.kt
diff --git a/detox/android/detox/src/test/java/com/wix/invoke/JsonParserTest.java b/detox/android/detox/src/testFull/java/com/wix/invoke/JsonParserTest.java
similarity index 100%
rename from detox/android/detox/src/test/java/com/wix/invoke/JsonParserTest.java
rename to detox/android/detox/src/testFull/java/com/wix/invoke/JsonParserTest.java
diff --git a/detox/android/detox/src/test/java/com/wix/invoke/MethodInvocationTest.java b/detox/android/detox/src/testFull/java/com/wix/invoke/MethodInvocationTest.java
similarity index 100%
rename from detox/android/detox/src/test/java/com/wix/invoke/MethodInvocationTest.java
rename to detox/android/detox/src/testFull/java/com/wix/invoke/MethodInvocationTest.java
diff --git a/detox/android/detox/src/test/java/com/wix/invoke/TestUtils.java b/detox/android/detox/src/testFull/java/com/wix/invoke/TestUtils.java
similarity index 100%
rename from detox/android/detox/src/test/java/com/wix/invoke/TestUtils.java
rename to detox/android/detox/src/testFull/java/com/wix/invoke/TestUtils.java
diff --git a/detox/android/detox/src/test/java/com/wix/invoke/types/InvocationTest.java b/detox/android/detox/src/testFull/java/com/wix/invoke/types/InvocationTest.java
similarity index 100%
rename from detox/android/detox/src/test/java/com/wix/invoke/types/InvocationTest.java
rename to detox/android/detox/src/testFull/java/com/wix/invoke/types/InvocationTest.java
diff --git a/detox/android/detox/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker b/detox/android/detox/src/testFull/resources/mockito-extensions/org.mockito.plugins.MockMaker
similarity index 100%
rename from detox/android/detox/src/test/resources/mockito-extensions/org.mockito.plugins.MockMaker
rename to detox/android/detox/src/testFull/resources/mockito-extensions/org.mockito.plugins.MockMaker
diff --git a/detox/android/detox/src/test/resources/robolectric.properties b/detox/android/detox/src/testFull/resources/robolectric.properties
similarity index 100%
rename from detox/android/detox/src/test/resources/robolectric.properties
rename to detox/android/detox/src/testFull/resources/robolectric.properties
diff --git a/detox/detox-native/README.md b/detox/detox-native/README.md
new file mode 100644
index 000000000..f4580a3f9
--- /dev/null
+++ b/detox/detox-native/README.md
@@ -0,0 +1,112 @@
+<p align="center">
+	<img alt="Detox" width=380 src="https://raw.githubusercontent.com/wix/Detox/master/docs/img/DetoxLogo.png"/>
+</p>
+<h1 align="center">
+  Detox (Native)
+</h1>
+<p align="center">
+  <b>Gray box end-to-end testing and automation library for mobile apps.</b>
+</p>
+
+**Detox-Native** is a subsidiary of the [Detox](https://github.com/wix/Detox) project. It is a work-in-progress, experimental initiative to bring all of Detox' under-the-hood magic for mobile app developers, typically writing UI tests using Google and Apple's native go-to frameworks (e.g. Espresso, EarlGrey, XCTest).
+
+**At the moment, the focus of the project is strictly on the Android platform.**
+
+## Android
+
+On Android, the project mostly aims to be an improvement over what we've found to be shortcomings in `Espresso`'s ability to produce stable and reliable UI tests. However, it also aims at offering additional interesting features.
+
+**If you find Espresso unstable / unreliable, or are looking for some additional features, give `Detox-Native` a try!**
+
+### Features Set
+
+Below are a few examples of what Detox offers for Android, at the moment (more to come, we hope!).
+
+#### Tap-Action Improvement
+
+Detox offers a tap-action that is essentially equivalent to Espresso's `ViewActions.click()` . However, it aims to perform the tap in a more robust way, that would not result in undesired long-taps, on occasions (as with Espresso's `click()`).
+
+Usage example:
+
+```kotlin
+onView(withId(R.id.fab)).perform(DetoxViewActions.tap())
+```
+
+#### Double-Tap Improvement
+
+Detox offers a double-tap gesture action equivalent to Espresso's `ViewActions.doubleClick()`. However, the implementation makes double-tapping very reliable, to the point where it would be very unlikely that the gesture would be registered as two separate taps (i.e. and would then not be caught by a crafted double-tap gesture handler in the app).
+
+Usage example:
+
+```kotlin
+onView(withId(R.id.knockKnock)).perform(DetoxViewActions.doubleTap())
+```
+
+#### Multi-tap Gesture
+
+Detox can inject a series of as many taps as you like, in a reliable way. In fact, `tap()` and `doubleTap()` a mere convience methods for using `multiTap(1)` and `multiTap(2)`, respectively.
+
+Usage example:
+
+```kotlin
+onView(withId(R.id.easterEgg)).perform(DetoxViewActions.multiTap(5))
+```
+
+#### Take View Screenshots!
+
+Detox can take screenshots of views, including all child-views in the view-hierarchy. Example of a resulted bitmap:
+
+![Announcement View](../../docs/img/element-screenshot-view.png)
+
+This can be very useful for screenshot-based snapshot tests, using external tools such as `applitools eyes`. It is a better approach than doing so with screenshots of the entire screen, as those include varying elements such as battery level, and time. Read more about it in our [Screenshots guide](../../docs/APIRef.Screenshots.md#element-level-screenshots-android-only).
+
+Detox can provide the result screenshot as a bitmap, a byte-array, or a Base64-Encoded string (based on the raw byte-array). The byte-array approach is especially useful when using external services such as `applitools`, because this is normally the way the image can be uploaded there.
+
+Usage example:
+
+```kotlin
+var bitmap: Bitmap?
+var raw: ByteArray?
+var base64: String?
+onView(withId(R.id.announcement)).perform(DetoxViewActions.takeScreenshot().also { action ->
+	action.getResult()?.let {
+		bitmap = it.asBitmap()
+		raw = it.asRawBytes()
+		base64 = it.asBase64String()
+	}
+})
+```
+
+> To-do: add info about saving the image to a file.
+
+### Installation
+
+In your app's `build.gradle` - Add `Detox` as an android-test implementation dependency:
+
+```groovy
+dependencies {
+  // ...  
+  androidTestImplementation 'com.wix:detox:0.1.0'
+}
+```
+
+In your root-project's `build.gradle` - be sure to add `mavenCentral()` as an artifacts repository:
+
+```groovy
+buildscript {
+  repositories {
+    // ...
+    mavenCentral()
+  }
+}
+```
+
+
+
+> Note: Detox indirectly specifies Espresso and related dependencies - so best if you remove your own specification of them:
+>
+> ```diff
+> -  androidTestImplementation 'androidx.test.ext:junit:1.1.1'
+> -  androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0
+> ```
+
diff --git a/detox/package.json b/detox/package.json
index 2a2b932fc..b5a9940fa 100644
--- a/detox/package.json
+++ b/detox/package.json
@@ -1,7 +1,7 @@
 {
   "name": "detox",
   "description": "E2E tests and automation for mobile",
-  "version": "18.7.0",
+  "version": "18.7.1",
   "bin": {
     "detox": "local-cli/cli.js"
   },
diff --git a/detox/src/Detox.js b/detox/src/Detox.js
index cec32bbc7..fff602d37 100644
--- a/detox/src/Detox.js
+++ b/detox/src/Detox.js
@@ -148,7 +148,8 @@ class Detox {
     await this._client.connect();
 
     const invocationManager = new InvocationManager(this._client);
-    const deviceDriver = driverRegistry.resolve(this._deviceConfig.type, {
+    const DeviceDriverImpl = driverRegistry.resolve(this._deviceConfig.type);
+    const deviceDriver = new DeviceDriverImpl({
       client: this._client,
       invocationManager,
       emitter: this._eventEmitter,
diff --git a/detox/src/configuration/composeDeviceConfig.js b/detox/src/configuration/composeDeviceConfig.js
index 71ee65fbd..782d9b880 100644
--- a/detox/src/configuration/composeDeviceConfig.js
+++ b/detox/src/configuration/composeDeviceConfig.js
@@ -1,4 +1,5 @@
 const _ = require('lodash');
+const driverRegistry = require('../devices/DriverRegistry').default;
 
 /**
  * @param {DetoxConfigErrorComposer} opts.errorComposer
@@ -94,6 +95,11 @@ function validateDeviceConfig({ deviceConfig, errorComposer, deviceAlias }) {
     throw errorComposer.missingDeviceType(deviceAlias);
   }
 
+  const DriverClass = _.attempt(() => driverRegistry.resolve(deviceConfig.type));
+  if (_.isError(DriverClass)) {
+    throw errorComposer.invalidDeviceType(deviceAlias, deviceConfig, DriverClass);
+  }
+
   if (deviceConfig.utilBinaryPaths) {
     if (!Array.isArray(deviceConfig.utilBinaryPaths)) {
       throw errorComposer.malformedUtilBinaryPaths(deviceAlias);
diff --git a/detox/src/devices/DriverRegistry.js b/detox/src/devices/DriverRegistry.js
index 21e544a14..e9cb72863 100644
--- a/detox/src/devices/DriverRegistry.js
+++ b/detox/src/devices/DriverRegistry.js
@@ -5,22 +5,18 @@ class DriverRegistry {
     this.deviceClasses = deviceClasses;
   }
 
-  resolve(deviceType, opts) {
+  resolve(deviceType) {
     let DeviceDriverClass = this.deviceClasses[deviceType];
 
     if (!DeviceDriverClass) {
-      try {
-        DeviceDriverClass = resolveModuleFromPath(deviceType).DriverClass;
-      } catch (e) {
-        // noop, if we don't find a module to require, we'll hit the unsupported error below
-      }
-    }
+      DeviceDriverClass = resolveModuleFromPath(deviceType).DriverClass;
 
-    if (!DeviceDriverClass) {
-      throw new Error(`'${deviceType}' is not supported`);
+      if (!DeviceDriverClass) {
+        throw new Error(`The custom driver '${deviceType}' does not export DriverClass property`);
+      }
     }
 
-    return new DeviceDriverClass(opts);
+    return DeviceDriverClass;
   }
 }
 
diff --git a/detox/src/errors/DetoxConfigErrorComposer.js b/detox/src/errors/DetoxConfigErrorComposer.js
index 6f9ddcd77..c760ed005 100644
--- a/detox/src/errors/DetoxConfigErrorComposer.js
+++ b/detox/src/errors/DetoxConfigErrorComposer.js
@@ -253,6 +253,22 @@ Examine your Detox config${this._atPath()}`,
     });
   }
 
+  invalidDeviceType(deviceAlias, deviceConfig, innerError) {
+    return new DetoxConfigError({
+      message: `Invalid device type ${J(deviceConfig.type)} inside your configuration.`,
+      hint: `Did you mean to use one of these?
+${hintConfigurations(deviceAppTypes)}
+
+P.S. If you intended to use a third-party driver, please resolve this error:
+
+${innerError.message}
+
+Please check your Detox config${this._atPath()}`,
+      debugInfo: this._focusOnDeviceConfig(deviceAlias, this._ensureProperty('type')),
+      inspectOptions: { depth: 3 },
+    });
+  }
+
   malformedUtilBinaryPaths(deviceAlias) {
     return new DetoxConfigError({
       message: `Invalid type of "utilBinaryPaths" inside the device configuration.`
diff --git a/docs/APIRef.DeviceObjectAPI.md b/docs/APIRef.DeviceObjectAPI.md
index 8b929d3f6..ce5456f61 100644
--- a/docs/APIRef.DeviceObjectAPI.md
+++ b/docs/APIRef.DeviceObjectAPI.md
@@ -319,7 +319,7 @@ Check out Detox's [own test suite.](../detox/test/e2e/06.device-orientation.test
 
 ### `device.setLocation(lat, lon)` **iOS Only**
 
-> Note: `setLocation` is dependent on [fbsimctl](https://github.com/facebook/idb/tree/master/fbsimctl). If `fbsimctl` is not installed, the command will fail, asking for it to be installed.
+> Note: `setLocation` is dependent on [fbsimctl](https://github.com/facebook/idb/tree/4b7929480c3c0f158f33f78a5b802c1d0e7030d2/fbsimctl) which [is now deprecated](https://github.com/wix/Detox/issues/1371). If `fbsimctl` is not installed, the command will fail, asking for it to be installed.
 
 Sets the simulator location to the given latitude and longitude.
 
diff --git a/docs/Guide.Jest.md b/docs/Guide.Jest.md
index 5c1efb5e5..94d98af29 100644
--- a/docs/Guide.Jest.md
+++ b/docs/Guide.Jest.md
@@ -68,7 +68,7 @@ A typical Detox configuration in `.detoxrc.json` file looks like:
   "runnerConfig": "e2e/config.json",
   "devices": {
     "simulator": {
-      "type": "ios.simulator"
+      "type": "ios.simulator",
       "device": {
         "type": "iPhone 12 Pro Max"
       }
diff --git a/docs/Introduction.Android.md b/docs/Introduction.Android.md
index 087ce6144..173ab676f 100644
--- a/docs/Introduction.Android.md
+++ b/docs/Introduction.Android.md
@@ -377,6 +377,7 @@ android {
       // ...
       testBuildType System.getProperty('testBuildType', 'debug')  // This will later be used to control the test apk build type
       testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
+      missingDimensionStrategy 'detox', 'full'
   }
 }
 ```
diff --git a/examples/demo-native-android/package.json b/examples/demo-native-android/package.json
index 77f2521a4..86b792ca6 100644
--- a/examples/demo-native-android/package.json
+++ b/examples/demo-native-android/package.json
@@ -1,6 +1,6 @@
 {
   "name": "detox-demo-native-android",
-  "version": "18.7.0",
+  "version": "18.7.1",
   "private": true,
   "scripts": {
     "packager": "react-native start",
@@ -8,7 +8,7 @@
     "e2e": "mocha e2e --opts ./e2e/mocha.opts"
   },
   "devDependencies": {
-    "detox": "^18.7.0",
+    "detox": "^18.7.1",
     "mocha": "^6.1.3"
   },
   "detox": {}
diff --git a/examples/demo-native-ios/package.json b/examples/demo-native-ios/package.json
index 9d8823eca..0f6fc8170 100644
--- a/examples/demo-native-ios/package.json
+++ b/examples/demo-native-ios/package.json
@@ -1,9 +1,9 @@
 {
   "name": "detox-demo-native-ios",
-  "version": "18.7.0",
+  "version": "18.7.1",
   "private": true,
   "devDependencies": {
-    "detox": "^18.7.0",
+    "detox": "^18.7.1",
     "mocha": "^6.1.3"
   },
   "detox": {
diff --git a/examples/demo-react-native-detox-instruments/package.json b/examples/demo-react-native-detox-instruments/package.json
index 24a5a5cce..8e42528b4 100644
--- a/examples/demo-react-native-detox-instruments/package.json
+++ b/examples/demo-react-native-detox-instruments/package.json
@@ -1,10 +1,10 @@
 {
   "name": "demo-react-native-detox-instruments",
-  "version": "18.7.0",
+  "version": "18.7.1",
   "private": true,
   "scripts": {},
   "devDependencies": {
-    "detox": "^18.7.0",
+    "detox": "^18.7.1",
     "mocha": "6.x.x"
   },
   "detox": {
diff --git a/examples/demo-react-native-jest/package.json b/examples/demo-react-native-jest/package.json
index 473cd3462..15bceac5d 100644
--- a/examples/demo-react-native-jest/package.json
+++ b/examples/demo-react-native-jest/package.json
@@ -1,6 +1,6 @@
 {
   "name": "demo-react-native-jest",
-  "version": "18.7.0",
+  "version": "18.7.1",
   "private": true,
   "scripts": {
     "test:ios-release": "detox test --configuration ios.sim.release -l verbose",
@@ -10,7 +10,7 @@
   },
   "devDependencies": {
     "@types/jest": "^26.0.19",
-    "detox": "^18.7.0",
+    "detox": "^18.7.1",
     "jest": "^26.5.0",
     "jest-circus": "^26.5.2",
     "sanitize-filename": "^1.6.1",
diff --git a/examples/demo-react-native/package.json b/examples/demo-react-native/package.json
index bc8c0f57e..cebda7d0a 100644
--- a/examples/demo-react-native/package.json
+++ b/examples/demo-react-native/package.json
@@ -1,6 +1,6 @@
 {
   "name": "example",
-  "version": "18.7.0",
+  "version": "18.7.1",
   "private": true,
   "scripts": {
     "start": "react-native start",
@@ -25,7 +25,7 @@
   },
   "devDependencies": {
     "@types/mocha": "^8.2.0",
-    "detox": "^18.7.0",
+    "detox": "^18.7.1",
     "mocha": "^6.1.3",
     "ts-node": "^9.1.1",
     "typescript": "^4.1.3"
diff --git a/generation/index.js b/generation/index.js
index 98e17c98a..1d6a7cbc4 100755
--- a/generation/index.js
+++ b/generation/index.js
@@ -38,18 +38,18 @@ function createAndroidFiles() {
   return {
     ...downloadedAndroidFilesMap,
     ...downloadedEspressoFilesMap,
-    '../detox/android/detox/src/main/java/com/wix/detox/espresso/DetoxAction.java': '../detox/src/android/espressoapi/DetoxAction.js',
-    '../detox/android/detox/src/main/java/com/wix/detox/espresso/DetoxAssertion.java': '../detox/src/android/espressoapi/DetoxAssertion.js',
-    '../detox/android/detox/src/main/java/com/wix/detox/espresso/DetoxViewActions.java': '../detox/src/android/espressoapi/DetoxViewActions.js',
-    '../detox/android/detox/src/main/java/com/wix/detox/espresso/DetoxMatcher.java': '../detox/src/android/espressoapi/DetoxMatcher.js',
-    '../detox/android/detox/src/main/java/com/wix/detox/Detox.java': '../detox/src/android/espressoapi/Detox.js',
-    '../detox/android/detox/src/main/java/com/wix/detox/espresso/EspressoDetox.java': '../detox/src/android/espressoapi/EspressoDetox.js',
-    '../detox/android/detox/src/main/java/com/wix/detox/uiautomator/UiAutomator.java': '../detox/src/android/espressoapi/UIAutomator.js',
-    '../detox/android/detox/src/main/java/com/wix/detox/espresso/web/EspressoWebDetox.java': '../detox/src/android/espressoapi/web/EspressoWebDetox.js',
-    '../detox/android/detox/src/main/java/com/wix/detox/espresso/web/DetoxWebAtomMatcher.java': '../detox/src/android/espressoapi/web/DetoxWebAtomMatcher.js',
-    '../detox/android/detox/src/main/java/com/wix/detox/espresso/web/WebViewElement.java': '../detox/src/android/espressoapi/web/WebViewElement.js',
-    '../detox/android/detox/src/main/java/com/wix/detox/espresso/web/WebElement.java': '../detox/src/android/espressoapi/web/WebElement.js',
-    '../detox/android/detox/src/main/java/com/wix/detox/espresso/web/WebExpect.java': '../detox/src/android/espressoapi/web/WebExpect.js'
+    '../detox/android/detox/src/full/java/com/wix/detox/espresso/DetoxAction.java': '../detox/src/android/espressoapi/DetoxAction.js',
+    '../detox/android/detox/src/full/java/com/wix/detox/espresso/DetoxAssertion.java': '../detox/src/android/espressoapi/DetoxAssertion.js',
+    '../detox/android/detox/src/full/java/com/wix/detox/espresso/DetoxViewActions.java': '../detox/src/android/espressoapi/DetoxViewActions.js',
+    '../detox/android/detox/src/full/java/com/wix/detox/espresso/DetoxMatcher.java': '../detox/src/android/espressoapi/DetoxMatcher.js',
+    '../detox/android/detox/src/full/java/com/wix/detox/Detox.java': '../detox/src/android/espressoapi/Detox.js',
+    '../detox/android/detox/src/full/java/com/wix/detox/espresso/EspressoDetox.java': '../detox/src/android/espressoapi/EspressoDetox.js',
+    '../detox/android/detox/src/full/java/com/wix/detox/uiautomator/UiAutomator.java': '../detox/src/android/espressoapi/UIAutomator.js',
+    '../detox/android/detox/src/full/java/com/wix/detox/espresso/web/EspressoWebDetox.java': '../detox/src/android/espressoapi/web/EspressoWebDetox.js',
+    '../detox/android/detox/src/full/java/com/wix/detox/espresso/web/DetoxWebAtomMatcher.java': '../detox/src/android/espressoapi/web/DetoxWebAtomMatcher.js',
+    '../detox/android/detox/src/full/java/com/wix/detox/espresso/web/WebViewElement.java': '../detox/src/android/espressoapi/web/WebViewElement.js',
+    '../detox/android/detox/src/full/java/com/wix/detox/espresso/web/WebElement.java': '../detox/src/android/espressoapi/web/WebElement.js',
+    '../detox/android/detox/src/full/java/com/wix/detox/espresso/web/WebExpect.java': '../detox/src/android/espressoapi/web/WebExpect.js'
   };
 }
 
diff --git a/generation/package.json b/generation/package.json
index c11ab74e5..cb0a1607c 100644
--- a/generation/package.json
+++ b/generation/package.json
@@ -1,6 +1,6 @@
 {
 	"name": "generation",
-	"version": "18.7.0",
+	"version": "18.7.1",
 	"description": "Generate wrapper code for native dependencies",
 	"main": "index.js",
 	"private": true,
diff --git a/lerna.json b/lerna.json
index b00ec521b..82b27fe1d 100644
--- a/lerna.json
+++ b/lerna.json
@@ -13,7 +13,7 @@
     "generation",
     "."
   ],
-  "version": "18.7.0",
+  "version": "18.7.1",
   "npmClient": "npm",
   "command": {
     "publish": {
diff --git a/package.json b/package.json
index 4af33c802..df1410b3b 100644
--- a/package.json
+++ b/package.json
@@ -19,5 +19,5 @@
     "semver": "5.x.x",
     "shell-utils": "1.x.x"
   },
-  "version": "18.7.0"
+  "version": "18.7.1"
 }


Test patch:
diff --git a/detox/android/detox/src/androidTest/java/com/wix/detox/ExampleInstrumentedTest.java b/detox/android/detox/src/androidTest/java/com/wix/detox/ExampleInstrumentedTest.java
deleted file mode 100644
index c5b8ff1cb..000000000
--- a/detox/android/detox/src/androidTest/java/com/wix/detox/ExampleInstrumentedTest.java
+++ /dev/null
@@ -1,27 +0,0 @@
-package com.wix.detox;
-
-import android.content.Context;
-
-import org.junit.Test;
-import org.junit.runner.RunWith;
-
-import androidx.test.platform.app.InstrumentationRegistry;
-import androidx.test.ext.junit.runners.AndroidJUnit4;
-
-import static org.junit.Assert.*;
-
-/**
- * Instrumentation test, which will execute on an Android device.
- *
- * @see <a href="http://d.android.com/tools/testing">Testing documentation</a>
- */
-@RunWith(AndroidJUnit4.class)
-public class ExampleInstrumentedTest {
-    @Test
-    public void useAppContext() throws Exception {
-        // Context of the app under test.
-        Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
-
-        assertEquals("com.wix.detox", appContext.getPackageName());
-    }
-}
diff --git a/detox/android/detox/src/main/java/com/wix/detox/DetoxANRHandler.kt b/detox/android/detox/src/full/java/com/wix/detox/DetoxANRHandler.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/DetoxANRHandler.kt
rename to detox/android/detox/src/full/java/com/wix/detox/DetoxANRHandler.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/DetoxActionHandlers.kt b/detox/android/detox/src/full/java/com/wix/detox/DetoxActionHandlers.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/DetoxActionHandlers.kt
rename to detox/android/detox/src/full/java/com/wix/detox/DetoxActionHandlers.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/DetoxCrashHandler.kt b/detox/android/detox/src/full/java/com/wix/detox/DetoxCrashHandler.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/DetoxCrashHandler.kt
rename to detox/android/detox/src/full/java/com/wix/detox/DetoxCrashHandler.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/DetoxJUnitRunner.java b/detox/android/detox/src/full/java/com/wix/detox/DetoxJUnitRunner.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/DetoxJUnitRunner.java
rename to detox/android/detox/src/full/java/com/wix/detox/DetoxJUnitRunner.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/DetoxManager.java b/detox/android/detox/src/full/java/com/wix/detox/DetoxManager.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/DetoxManager.java
rename to detox/android/detox/src/full/java/com/wix/detox/DetoxManager.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/LaunchArgs.java b/detox/android/detox/src/full/java/com/wix/detox/LaunchArgs.java
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/LaunchArgs.java
rename to detox/android/detox/src/full/java/com/wix/detox/LaunchArgs.java
diff --git a/detox/android/detox/src/main/java/com/wix/detox/LaunchIntentsFactory.kt b/detox/android/detox/src/full/java/com/wix/detox/LaunchIntentsFactory.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/LaunchIntentsFactory.kt
rename to detox/android/detox/src/full/java/com/wix/detox/LaunchIntentsFactory.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/NotificationDataParser.kt b/detox/android/detox/src/full/java/com/wix/detox/NotificationDataParser.kt
similarity index 100%
rename from detox/android/detox/src/main/java/com/wix/detox/NotificationDataParser.kt
rename to detox/android/detox/src/full/java/com/wix/detox/NotificationDataParser.kt
diff --git a/detox/android/detox/src/main/java/com/wix/detox/TestEngineFacade.kt b/detox/android/detox/src/full/java/com/wix/detox/TestEngineFacade.kt
similarity index 87%
rename from detox/android/detox/src/main/java/com/wix/detox/TestEngineFacade.kt
rename to detox/android/detox/src/full/java/com/wix/detox/TestEngineFacade.kt
index 847904eef..16a40833f 100644
--- a/detox/android/detox/src/main/java/com/wix/detox/TestEngineFacade.kt
+++ b/detox/android/detox/src/full/java/com/wix/detox/TestEngineFacade.kt
@@ -4,13 +4,14 @@ import android.content.Context
 import android.util.Log
 import androidx.test.espresso.Espresso
 import androidx.test.espresso.IdlingResource
+import com.wix.detox.common.DetoxLog.Companion.LOG_TAG
 import com.wix.detox.espresso.EspressoDetox
 import com.wix.detox.espresso.UiAutomatorHelper
 import com.wix.detox.reactnative.ReactNativeExtension
 
 class TestEngineFacade {
     fun awaitIdle(): Unit? = Espresso.onIdle() {
-        Log.i(Detox.LOG_TAG, "Wait is over: app is now idle!")
+        Log.i(LOG_TAG, "Wait is over: app is now idle!")
         null
     }
     fun syncIdle() = UiAutomatorHelper.espressoSync() // TODO Check whether this can be replaced with #awaitIdle()
diff --git a/detox/android/detox/src/test/java/com/wix/detox/DetoxActionHandlersSpec.kt b/detox/android/detox/src/testFull/java/com/wix/detox/DetoxActionHandlersSpec.kt
similarity index 100%
rename from detox/android/detox/src/test/java/com/wix/detox/DetoxActionHandlersSpec.kt
rename to detox/android/detox/src/testFull/java/com/wix/detox/DetoxActionHandlersSpec.kt
diff --git a/detox/android/detox/src/test/java/com/wix/detox/UTHelpers.kt b/detox/android/detox/src/testFull/java/com/wix/detox/UTHelpers.kt
similarity index 100%
rename from detox/android/detox/src/test/java/com/wix/detox/UTHelpers.kt
rename to detox/android/detox/src/testFull/java/com/wix/detox/UTHelpers.kt
diff --git a/detox/android/detox/src/test/java/com/wix/detox/common/JsonConverterTest.kt b/detox/android/detox/src/testFull/java/com/wix/detox/common/JsonConverterTest.kt
similarity index 100%
rename from detox/android/detox/src/test/java/com/wix/detox/common/JsonConverterTest.kt
rename to detox/android/detox/src/testFull/java/com/wix/detox/common/JsonConverterTest.kt
diff --git a/detox/android/detox/src/test/java/com/wix/detox/common/TapEventsSpec.kt b/detox/android/detox/src/testFull/java/com/wix/detox/common/TapEventsSpec.kt
similarity index 97%
rename from detox/android/detox/src/test/java/com/wix/detox/common/TapEventsSpec.kt
rename to detox/android/detox/src/testFull/java/com/wix/detox/common/TapEventsSpec.kt
index 252d67992..def9a295e 100644
--- a/detox/android/detox/src/test/java/com/wix/detox/common/TapEventsSpec.kt
+++ b/detox/android/detox/src/testFull/java/com/wix/detox/common/TapEventsSpec.kt
@@ -2,8 +2,8 @@ package com.wix.detox.common
 
 import android.view.MotionEvent
 import com.nhaarman.mockitokotlin2.*
-import com.wix.detox.espresso.common.MotionEvents
-import com.wix.detox.espresso.common.TapEvents
+import com.wix.detox.espresso.action.common.MotionEvents
+import com.wix.detox.espresso.action.common.TapEvents
 import org.assertj.core.api.Assertions.assertThat
 import org.spekframework.spek2.Spek
 import org.spekframework.spek2.style.specification.describe
diff --git a/detox/android/detox/src/test/java/com/wix/detox/common/collect/PairsIteratorSpec.kt b/detox/android/detox/src/testFull/java/com/wix/detox/common/collect/PairsIteratorSpec.kt
similarity index 100%
rename from detox/android/detox/src/test/java/com/wix/detox/common/collect/PairsIteratorSpec.kt
rename to detox/android/detox/src/testFull/java/com/wix/detox/common/collect/PairsIteratorSpec.kt
diff --git a/detox/android/detox/src/test/java/com/wix/detox/common/proxy/MethodsSpySpec.kt b/detox/android/detox/src/testFull/java/com/wix/detox/common/proxy/MethodsSpySpec.kt
similarity index 100%
rename from detox/android/detox/src/test/java/com/wix/detox/common/proxy/MethodsSpySpec.kt
rename to detox/android/detox/src/testFull/java/com/wix/detox/common/proxy/MethodsSpySpec.kt
diff --git a/detox/android/detox/src/test/java/com/wix/detox/espresso/action/DetoxMultiTapSpec.kt b/detox/android/detox/src/testFull/java/com/wix/detox/espresso/action/DetoxMultiTapSpec.kt
similarity index 98%
rename from detox/android/detox/src/test/java/com/wix/detox/espresso/action/DetoxMultiTapSpec.kt
rename to detox/android/detox/src/testFull/java/com/wix/detox/espresso/action/DetoxMultiTapSpec.kt
index 5d92b010d..3bd5c4512 100644
--- a/detox/android/detox/src/test/java/com/wix/detox/espresso/action/DetoxMultiTapSpec.kt
+++ b/detox/android/detox/src/testFull/java/com/wix/detox/espresso/action/DetoxMultiTapSpec.kt
@@ -4,11 +4,10 @@ import android.view.MotionEvent
 import androidx.test.espresso.UiController
 import androidx.test.espresso.action.Tapper
 import com.nhaarman.mockitokotlin2.*
-import com.wix.detox.common.DetoxErrors.DetoxIllegalStateException
 import com.wix.detox.common.DetoxLog
 import com.wix.detox.common.proxy.CallInfo
 import com.wix.detox.espresso.UiControllerSpy
-import com.wix.detox.espresso.common.TapEvents
+import com.wix.detox.espresso.action.common.TapEvents
 import org.assertj.core.api.Assertions.assertThat
 import org.spekframework.spek2.Spek
 import org.spekframework.spek2.style.specification.describe
diff --git a/detox/android/detox/src/test/java/com/wix/detox/espresso/scroll/DetoxSwipeSpec.kt b/detox/android/detox/src/testFull/java/com/wix/detox/espresso/scroll/DetoxSwipeSpec.kt
similarity index 100%
rename from detox/android/detox/src/test/java/com/wix/detox/espresso/scroll/DetoxSwipeSpec.kt
rename to detox/android/detox/src/testFull/java/com/wix/detox/espresso/scroll/DetoxSwipeSpec.kt
diff --git a/detox/android/detox/src/test/java/com/wix/detox/espresso/scroll/FlinglessSwiperSpec.kt b/detox/android/detox/src/testFull/java/com/wix/detox/espresso/scroll/FlinglessSwiperSpec.kt
similarity index 99%
rename from detox/android/detox/src/test/java/com/wix/detox/espresso/scroll/FlinglessSwiperSpec.kt
rename to detox/android/detox/src/testFull/java/com/wix/detox/espresso/scroll/FlinglessSwiperSpec.kt
index 95dc99c34..ba6a24ca8 100644
--- a/detox/android/detox/src/test/java/com/wix/detox/espresso/scroll/FlinglessSwiperSpec.kt
+++ b/detox/android/detox/src/testFull/java/com/wix/detox/espresso/scroll/FlinglessSwiperSpec.kt
@@ -4,7 +4,7 @@ import android.view.MotionEvent
 import android.view.ViewConfiguration
 import androidx.test.espresso.UiController
 import com.nhaarman.mockitokotlin2.*
-import com.wix.detox.espresso.common.MotionEvents
+import com.wix.detox.espresso.action.common.MotionEvents
 import org.assertj.core.api.Assertions.assertThat
 import org.spekframework.spek2.Spek
 import org.spekframework.spek2.style.specification.describe
diff --git a/detox/android/detox/src/test/java/com/wix/detox/espresso/scroll/SwipeHelperSpec.kt b/detox/android/detox/src/testFull/java/com/wix/detox/espresso/scroll/SwipeHelperSpec.kt
similarity index 99%
rename from detox/android/detox/src/test/java/com/wix/detox/espresso/scroll/SwipeHelperSpec.kt
rename to detox/android/detox/src/testFull/java/com/wix/detox/espresso/scroll/SwipeHelperSpec.kt
index 31e175a29..f469ca6bc 100644
--- a/detox/android/detox/src/test/java/com/wix/detox/espresso/scroll/SwipeHelperSpec.kt
+++ b/detox/android/detox/src/testFull/java/com/wix/detox/espresso/scroll/SwipeHelperSpec.kt
@@ -8,7 +8,8 @@ import androidx.test.espresso.ViewAction
 import androidx.test.espresso.action.*
 import com.nhaarman.mockitokotlin2.mock
 import com.nhaarman.mockitokotlin2.whenever
-import com.wix.detox.espresso.common.annot.*
+import com.wix.detox.action.common.*
+import com.wix.detox.espresso.common.*
 import org.junit.Before
 import org.junit.Test
 import org.junit.runner.RunWith
diff --git a/detox/android/detox/src/test/java/com/wix/detox/espresso/utils/Vector2DSpec.kt b/detox/android/detox/src/testFull/java/com/wix/detox/espresso/utils/Vector2DSpec.kt
similarity index 98%
rename from detox/android/detox/src/test/java/com/wix/detox/espresso/utils/Vector2DSpec.kt
rename to detox/android/detox/src/testFull/java/com/wix/detox/espresso/utils/Vector2DSpec.kt
index 4dbda2135..1eae5e1a7 100644
--- a/detox/android/detox/src/test/java/com/wix/detox/espresso/utils/Vector2DSpec.kt
+++ b/detox/android/detox/src/testFull/java/com/wix/detox/espresso/utils/Vector2DSpec.kt
@@ -1,6 +1,7 @@
 package com.wix.detox.espresso.utils
 
-import com.wix.detox.espresso.common.annot.*
+import com.wix.detox.action.common.*
+import com.wix.detox.espresso.common.*
 import org.spekframework.spek2.Spek
 import org.spekframework.spek2.style.specification.describe
 import kotlin.test.assertEquals
diff --git a/detox/local-cli/test.test.js b/detox/local-cli/test.test.js
index 3f4ed5569..5f6d6d23e 100644
--- a/detox/local-cli/test.test.js
+++ b/detox/local-cli/test.test.js
@@ -217,8 +217,7 @@ describe('CLI', () => {
     });
 
     test('should omit --grep --invert for custom platforms', async () => {
-      const customDriver = `module.exports = class CustomDriver {};`
-      singleConfig().type = tempfile('.js', customDriver);
+      singleConfig().type = tempfile('.js', aCustomDriverModule());
 
       await run();
       expect(cliCall().command).not.toContain(' --invert ');
@@ -494,8 +493,7 @@ describe('CLI', () => {
     });
 
     test('should omit --testNamePattern for custom platforms', async () => {
-      const customDriver = `module.exports = class CustomDriver {};`
-      singleConfig().type = tempfile('.js', customDriver);
+      singleConfig().type = tempfile('.js', aCustomDriverModule());
 
       await run();
       expect(cliCall().command).not.toContain('--testNamePattern');
@@ -781,4 +779,8 @@ describe('CLI', () => {
   function quote(s, q = isInCMD() ? `"` : `'`) {
     return q + s + q;
   }
+
+  function aCustomDriverModule() {
+    return `class DriverClass {}; module.exports = { DriverClass }`;
+  }
 });
diff --git a/detox/src/Detox.test.js b/detox/src/Detox.test.js
index b56ceae0a..37bea2293 100644
--- a/detox/src/Detox.test.js
+++ b/detox/src/Detox.test.js
@@ -107,14 +107,7 @@ describe('Detox', () => {
         expect(client().connect).toHaveBeenCalled());
 
       it('should resolve a device driver from the registry', () =>
-        expect(FakeDriverRegistry.default.resolve).toHaveBeenCalledWith(
-          detoxConfig.deviceConfig.type,
-          {
-            client: client(),
-            invocationManager: invocationManager(),
-            emitter: expect.anything(),
-          }
-        ));
+        expect(FakeDriverRegistry.default.resolve).toHaveBeenCalledWith(detoxConfig.deviceConfig.type));
 
       it('should resolve matchers implementation', () => {
         const { emitter } = Device.mock.calls[0][0];
diff --git a/detox/src/configuration/composeDeviceConfig.test.js b/detox/src/configuration/composeDeviceConfig.test.js
index e24d67544..41873fa40 100644
--- a/detox/src/configuration/composeDeviceConfig.test.js
+++ b/detox/src/configuration/composeDeviceConfig.test.js
@@ -12,12 +12,18 @@ describe('composeDeviceConfig', () => {
   let globalConfig;
   /** @type {DetoxConfigErrorComposer} */
   let errorComposer;
+  /** @type {DriverRegistry} */
+  let driverRegistry;
 
   beforeEach(() => {
-    composeDeviceConfig = require('./composeDeviceConfig');
+    jest.mock('../devices/DriverRegistry', () => {
+      const DriverRegistry = jest.requireActual('../devices/DriverRegistry');
+      driverRegistry = DriverRegistry.default;
+      return DriverRegistry;
+    });
+
     cliConfig = {};
     localConfig = {};
-
     globalConfig = {
       configurations: {
         someConfig: localConfig,
@@ -27,6 +33,8 @@ describe('composeDeviceConfig', () => {
     errorComposer = new DetoxConfigErrorComposer()
       .setDetoxConfig(globalConfig)
       .setConfigurationName('someConfig');
+
+    composeDeviceConfig = require('./composeDeviceConfig');
   });
 
   const compose = () => composeDeviceConfig({
@@ -72,6 +80,7 @@ describe('composeDeviceConfig', () => {
 
       beforeEach(() => {
         Object.assign(localConfig, values);
+        driverRegistry.resolve = () => (class SomeDriver {});
       });
 
       it('should take it as is, for backward compatibility', () => {
@@ -230,6 +239,18 @@ describe('composeDeviceConfig', () => {
       });
     });
 
+    it('should throw if the device config has invalid type', () => {
+      const someError = new Error('Some error');
+      driverRegistry.resolve = () => { throw someError };
+
+      localConfig.device = { type: 'android.apk' };
+      expect(compose).toThrow(errorComposer.invalidDeviceType(
+        undefined,
+        localConfig.device,
+        someError
+      ));
+    });
+
     describe('missing device matcher properties', () => {
       it.each([
         [['type', 'name', 'id'], 'ios.simulator'],
diff --git a/detox/src/devices/DriverRegistry.test.js b/detox/src/devices/DriverRegistry.test.js
index 832ab28f4..99fa12f3e 100644
--- a/detox/src/devices/DriverRegistry.test.js
+++ b/detox/src/devices/DriverRegistry.test.js
@@ -6,15 +6,10 @@ jest.mock('../utils/resolveModuleFromPath');
 
 describe('DriverRegistry', () => {
   let DriverRegistry;
-  let registry, opts;
+  let registry;
 
   beforeEach(() => {
     DriverRegistry = require('./DriverRegistry');
-
-    opts = {
-      client: { whatever: Math.random() },
-      emitter: { anything: Math.random() },
-    };
   });
 
   describe('by default', () => {
@@ -24,34 +19,30 @@ describe('DriverRegistry', () => {
 
     it('should resolve "ios.none" to IosDriver', () => {
       const IosDriver = require('./drivers/ios/IosDriver');
-      const driver = registry.resolve('ios.none', opts);
+      const ResolvedDriver = registry.resolve('ios.none');
 
-      expect(driver).toBeInstanceOf(IosDriver);
-      expect(IosDriver).toHaveBeenCalledWith(opts);
+      expect(ResolvedDriver).toBe(IosDriver);
     });
 
     it('should resolve "ios.simulator" to SimulatorDriver', () => {
       const SimulatorDriver = require('./drivers/ios/SimulatorDriver');
-      const driver = registry.resolve('ios.simulator', opts);
+      const ResolvedDriver = registry.resolve('ios.simulator');
 
-      expect(driver).toBeInstanceOf(SimulatorDriver);
-      expect(SimulatorDriver).toHaveBeenCalledWith(opts);
+      expect(ResolvedDriver).toBe(SimulatorDriver);
     });
 
     it('should resolve "android.attached" to AttachedAndroidDriver', () => {
       const AttachedAndroidDriver = require('./drivers/android/attached/AttachedAndroidDriver');
-      const driver = registry.resolve('android.attached', opts);
+      const ResolvedDriver = registry.resolve('android.attached');
 
-      expect(driver).toBeInstanceOf(AttachedAndroidDriver);
-      expect(AttachedAndroidDriver).toHaveBeenCalledWith(opts);
+      expect(ResolvedDriver).toBe(AttachedAndroidDriver);
     });
 
     it('should resolve "android.emulator" to EmulatorDriver', () => {
       const EmulatorDriver = require('./drivers/android/emulator/EmulatorDriver');
-      const driver = registry.resolve('android.emulator', opts);
+      const ResolvedDriver = registry.resolve('android.emulator');
 
-      expect(driver).toBeInstanceOf(EmulatorDriver);
-      expect(EmulatorDriver).toHaveBeenCalledWith(opts);
+      expect(ResolvedDriver).toBe(EmulatorDriver);
     });
 
     it('should try to resolve unknown driver as a node.js dependency', () => {
@@ -62,15 +53,22 @@ describe('DriverRegistry', () => {
       });
 
       const FakeDriver = require('./drivers/__mocks__/FakeDriver');
-      const driver = registry.resolve('fake-driver', opts);
+      const ResolvedDriver = registry.resolve('fake-driver');
+
+      expect(ResolvedDriver).toBe(FakeDriver);
+    });
+
+    it('should throw an error if a custom driver does not export DriverClass property', () => {
+      require('../utils/resolveModuleFromPath').mockImplementation(() => {
+        return require('./drivers/__mocks__/FakeDriver');
+      });
 
-      expect(driver).toBeInstanceOf(FakeDriver);
-      expect(driver.constructorArgs).toEqual([opts]);
+      expect(() => registry.resolve('fake-driver')).toThrowError(/does not export DriverClass/);
     });
 
     it('should throw errors if it cannot resolve a driver', () => {
-      expect(() => registry.resolve('imaginary.driver', opts))
-        .toThrowError(/imaginary.driver.*not supported/);
+      require('../utils/resolveModuleFromPath').mockImplementation(() => { throw new Error('BAD IDEA'); });
+      expect(() => registry.resolve('imaginary.driver')).toThrowError('BAD IDEA');
     });
   });
 
@@ -78,10 +76,9 @@ describe('DriverRegistry', () => {
     it('should be extensible', () => {
       const FakeDriver101 = require('./drivers/__mocks__/FakeDriver');
       const registry = new DriverRegistry({ FakeDriver101 });
-      const driver = registry.resolve('FakeDriver101', opts);
+      const driver = registry.resolve('FakeDriver101');
 
-      expect(driver).toBeInstanceOf(FakeDriver101);
-      expect(driver.constructorArgs).toEqual([opts]);
+      expect(driver).toBe(FakeDriver101);
     });
   });
 });
diff --git a/detox/src/errors/DetoxConfigErrorComposer.test.js b/detox/src/errors/DetoxConfigErrorComposer.test.js
index 372b41ad2..6610ce122 100644
--- a/detox/src/errors/DetoxConfigErrorComposer.test.js
+++ b/detox/src/errors/DetoxConfigErrorComposer.test.js
@@ -222,6 +222,30 @@ describe('DetoxConfigErrorComposer', () => {
       });
     });
 
+    describe('.invalidDeviceType', () => {
+      beforeEach(() => {
+        build = (deviceConfig, alias) => {
+          // eslint-disable-next-line node/no-missing-require
+          const err = _.attempt(() => require('android.apk'));
+          return builder.invalidDeviceType(alias, deviceConfig, err);
+        };
+      });
+
+      it('should create an error for inlined configuration', () => {
+        const deviceConfig = config.configurations.inlined.device;
+        deviceConfig.type = 'android.apk';
+        builder.setConfigurationName('inlined');
+        expect(build(deviceConfig)).toMatchSnapshot();
+      });
+
+      it('should create an error for aliased configuration', () => {
+        const deviceConfig = config.devices.aDevice;
+        deviceConfig.type = 'android.apk';
+        builder.setConfigurationName('aliased');
+        expect(build(deviceConfig, 'aDevice')).toMatchSnapshot();
+      });
+    });
+
     describe('.missingDeviceMatcherProperties', () => {
       beforeEach(() => {
         build = (alias) => builder.missingDeviceMatcherProperties(alias, ['foo', 'bar']);
diff --git a/detox/src/errors/__snapshots__/DetoxConfigErrorComposer.test.js.snap b/detox/src/errors/__snapshots__/DetoxConfigErrorComposer.test.js.snap
index 20245517c..da2fa0b1a 100644
--- a/detox/src/errors/__snapshots__/DetoxConfigErrorComposer.test.js.snap
+++ b/detox/src/errors/__snapshots__/DetoxConfigErrorComposer.test.js.snap
@@ -557,6 +557,64 @@ Examine your Detox config at path:
 /home/detox/myproject/.detoxrc.json]
 `;
 
+exports[`DetoxConfigErrorComposer (from composeDeviceConfig) .invalidDeviceType should create an error for aliased configuration 1`] = `
+[DetoxConfigError: Invalid device type "android.apk" inside your configuration.
+
+HINT: Did you mean to use one of these?
+* ios.simulator
+* ios.none
+* android.attached
+* android.emulator
+* android.genycloud
+
+P.S. If you intended to use a third-party driver, please resolve this error:
+
+Cannot find module 'android.apk' from 'src/errors/DetoxConfigErrorComposer.test.js'
+
+Please check your Detox config at path:
+/home/detox/myproject/.detoxrc.json
+
+{
+  devices: {
+    aDevice: {
+      type: 'android.apk',
+      device: {
+        type: 'iPhone 12'
+      }
+    }
+  }
+}]
+`;
+
+exports[`DetoxConfigErrorComposer (from composeDeviceConfig) .invalidDeviceType should create an error for inlined configuration 1`] = `
+[DetoxConfigError: Invalid device type "android.apk" inside your configuration.
+
+HINT: Did you mean to use one of these?
+* ios.simulator
+* ios.none
+* android.attached
+* android.emulator
+* android.genycloud
+
+P.S. If you intended to use a third-party driver, please resolve this error:
+
+Cannot find module 'android.apk' from 'src/errors/DetoxConfigErrorComposer.test.js'
+
+Please check your Detox config at path:
+/home/detox/myproject/.detoxrc.json
+
+{
+  configurations: {
+    inlined: {
+      device: {
+        type: 'android.apk',
+        device: [Object]
+      }
+    }
+  }
+}]
+`;
+
 exports[`DetoxConfigErrorComposer (from composeDeviceConfig) .malformedUtilBinaryPaths should create an error for aliased configuration 1`] = `
 [DetoxConfigError: Invalid type of "utilBinaryPaths" inside the device configuration. Expected an array of strings.
 
diff --git a/detox/test/android/app/build.gradle b/detox/test/android/app/build.gradle
index 380389470..28930a945 100644
--- a/detox/test/android/app/build.gradle
+++ b/detox/test/android/app/build.gradle
@@ -33,6 +33,8 @@ android {
                 'detoxSessionId': 'test'
         ]
         */
+
+        missingDimensionStrategy 'detox', 'full'
     }
     splits {
         abi {
diff --git a/detox/test/package.json b/detox/test/package.json
index e6edb8479..489cd7e02 100644
--- a/detox/test/package.json
+++ b/detox/test/package.json
@@ -1,6 +1,6 @@
 {
   "name": "detox-test",
-  "version": "18.7.0",
+  "version": "18.7.1",
   "private": true,
   "engines": {
     "node": ">=8.3.0"
@@ -35,7 +35,7 @@
   "devDependencies": {
     "@babel/core": "^7.8.7",
     "@types/node": "^14.14.20",
-    "detox": "^18.7.0",
+    "detox": "^18.7.1",
     "dtslint": "^4.0.6",
     "express": "^4.15.3",
     "jest": "^26.5.0",