Merge "Add a fragment-testing-manifest artifact." into androidx-main
diff --git a/fragment/fragment-testing-manifest-lint/OWNERS b/fragment/fragment-testing-manifest-lint/OWNERS
new file mode 100644
index 0000000..80569a3
--- /dev/null
+++ b/fragment/fragment-testing-manifest-lint/OWNERS
@@ -0,0 +1 @@
[email protected]
diff --git a/fragment/fragment-testing-manifest-lint/build.gradle b/fragment/fragment-testing-manifest-lint/build.gradle
new file mode 100644
index 0000000..afa4705
--- /dev/null
+++ b/fragment/fragment-testing-manifest-lint/build.gradle
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import androidx.build.LibraryType
+
+plugins {
+    id("AndroidXPlugin")
+    id("kotlin")
+}
+
+dependencies {
+    compileOnly(libs.androidLintMinApi)
+    compileOnly(libs.kotlinStdlib)
+
+    testImplementation(libs.kotlinStdlib)
+    testImplementation(libs.androidLint)
+    testImplementation(libs.androidLintTests)
+    testImplementation(libs.junit)
+    testImplementation(libs.truth)
+}
+
+androidx {
+    name = "Android Fragment-Testing-Manifest Lint Checks"
+    type = LibraryType.LINT
+    mavenGroup = LibraryGroups.FRAGMENT
+    inceptionYear = "2022"
+    description = "Lint Checks for the Fragment Testing Manifest module"
+}
diff --git a/fragment/fragment-testing-manifest-lint/src/main/java/androidx/fragment/testing/manifest/lint/FragmentTestingManifestIssueRegistry.kt b/fragment/fragment-testing-manifest-lint/src/main/java/androidx/fragment/testing/manifest/lint/FragmentTestingManifestIssueRegistry.kt
new file mode 100644
index 0000000..7ce1350
--- /dev/null
+++ b/fragment/fragment-testing-manifest-lint/src/main/java/androidx/fragment/testing/manifest/lint/FragmentTestingManifestIssueRegistry.kt
@@ -0,0 +1,33 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.fragment.testing.manifest.lint
+
+import com.android.tools.lint.client.api.IssueRegistry
+import com.android.tools.lint.client.api.Vendor
+import com.android.tools.lint.detector.api.CURRENT_API
+
+@Suppress("UnstableApiUsage")
+class FragmentTestingManifestIssueRegistry : IssueRegistry() {
+    override val api = 13
+    override val minApi = CURRENT_API
+    override val issues get() = listOf(GradleConfigurationDetector.ISSUE)
+    override val vendor = Vendor(
+        feedbackUrl = "https://issuetracker.google.com/issues/new?component=460964",
+        identifier = "androidx.fragment.testing.manifest",
+        vendorName = "Android Open Source Project",
+    )
+}
diff --git a/fragment/fragment-testing-manifest-lint/src/main/java/androidx/fragment/testing/manifest/lint/GradleConfigurationDetector.kt b/fragment/fragment-testing-manifest-lint/src/main/java/androidx/fragment/testing/manifest/lint/GradleConfigurationDetector.kt
new file mode 100644
index 0000000..c493e4f
--- /dev/null
+++ b/fragment/fragment-testing-manifest-lint/src/main/java/androidx/fragment/testing/manifest/lint/GradleConfigurationDetector.kt
@@ -0,0 +1,94 @@
+/*
+ * Copyright 2019 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.fragment.testing.manifest.lint
+
+import com.android.tools.lint.detector.api.Category
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.GradleContext
+import com.android.tools.lint.detector.api.GradleScanner
+import com.android.tools.lint.detector.api.Implementation
+import com.android.tools.lint.detector.api.Issue
+import com.android.tools.lint.detector.api.Scope
+import com.android.tools.lint.detector.api.Severity
+
+/**
+ * Lint check for ensuring that the Fragment Testing library is included using the correct
+ * debugImplementation configuration.
+ */
+class GradleConfigurationDetector : Detector(), GradleScanner {
+    companion object {
+        val ISSUE = Issue.create(
+            id = "FragmentGradleConfiguration",
+            briefDescription = "Include the fragment-testing-manifest library using the " +
+                "debugImplementation configuration.",
+            explanation = """The fragment-testing-manifest library defines an EmptyActivity\
+                used when using FragmentScenario. Howver, it only needs to be present in testing\
+                configurations therefore use this dependency with the debugImplementation\
+                configuration.""",
+            category = Category.CORRECTNESS,
+            severity = Severity.ERROR,
+            implementation = Implementation(
+                GradleConfigurationDetector::class.java, Scope.GRADLE_SCOPE
+            ),
+            androidSpecific = true
+        ).addMoreInfo("https://d.android.com/training/basics/fragments/testing#configure")
+    }
+
+    override fun checkDslPropertyAssignment(
+        context: GradleContext,
+        property: String,
+        value: String,
+        parent: String,
+        parentParent: String?,
+        valueCookie: Any,
+        statementCookie: Any
+    ) {
+        // Remove enclosing quotes and check starting string to ensure only instances that
+        // result in the fragment-testing library being imported are checked.
+        // Non-string values cannot be resolved so invalid imports via functions, variables, etc.
+        // will not be detected.
+        val library = getStringLiteralValue(value)
+        if (library.startsWith("androidx.fragment:fragment-testing-manifest") &&
+            property != "debugImplementation"
+        ) {
+            context.report(
+                ISSUE, statementCookie, context.getLocation(statementCookie),
+                "Replace with debugImplementation.",
+                fix().replace()
+                    .text(property)
+                    .with("debugImplementation")
+                    .build()
+            )
+        }
+    }
+
+    /**
+     * Extracts the string value from the DSL value by removing surrounding quotes.
+     *
+     * Returns an empty string if [value] is not a string literal.
+     */
+    private fun getStringLiteralValue(value: String): String {
+        if (value.length > 2 && (
+            value.startsWith("'") && value.endsWith("'") ||
+                value.startsWith("\"") && value.endsWith("\"")
+            )
+        ) {
+            return value.substring(1, value.length - 1)
+        }
+        return ""
+    }
+}
diff --git a/fragment/fragment-testing-manifest-lint/src/main/resources/META-INF/services/com.android.tools.lint.client.api.IssueRegistry b/fragment/fragment-testing-manifest-lint/src/main/resources/META-INF/services/com.android.tools.lint.client.api.IssueRegistry
new file mode 100644
index 0000000..910866a
--- /dev/null
+++ b/fragment/fragment-testing-manifest-lint/src/main/resources/META-INF/services/com.android.tools.lint.client.api.IssueRegistry
@@ -0,0 +1 @@
+androidx.fragment.testing.manifest.lint.FragmentTestingManifestIssueRegistry
diff --git a/fragment/fragment-testing-manifest-lint/src/test/java/androidx/fragment/testing/manifest/lint/ApiLintVersionsTest.kt b/fragment/fragment-testing-manifest-lint/src/test/java/androidx/fragment/testing/manifest/lint/ApiLintVersionsTest.kt
new file mode 100644
index 0000000..bc638dd
--- /dev/null
+++ b/fragment/fragment-testing-manifest-lint/src/test/java/androidx/fragment/testing/manifest/lint/ApiLintVersionsTest.kt
@@ -0,0 +1,40 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.fragment.testing.manifest.lint
+
+import com.android.tools.lint.client.api.LintClient
+import com.android.tools.lint.detector.api.CURRENT_API
+import com.google.common.truth.Truth.assertThat
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class ApiLintVersionsTest {
+
+    @Test
+    fun versionsCheck() {
+        LintClient.clientName = LintClient.CLIENT_UNIT_TESTS
+
+        val registry = FragmentTestingManifestIssueRegistry()
+        // we hardcode version registry.api to the version that is used to run tests
+        assertThat(registry.api).isEqualTo(CURRENT_API)
+        // Intentionally fails in IDE, because we use different API version in
+        // studio and command line
+        assertThat(registry.minApi).isEqualTo(10)
+    }
+}
diff --git a/fragment/fragment-testing-manifest-lint/src/test/java/androidx/fragment/testing/manifest/lint/GradleConfigurationDetectorTest.kt b/fragment/fragment-testing-manifest-lint/src/test/java/androidx/fragment/testing/manifest/lint/GradleConfigurationDetectorTest.kt
new file mode 100644
index 0000000..3980f47
--- /dev/null
+++ b/fragment/fragment-testing-manifest-lint/src/test/java/androidx/fragment/testing/manifest/lint/GradleConfigurationDetectorTest.kt
@@ -0,0 +1,80 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.fragment.testing.manifest.lint
+
+import com.android.tools.lint.checks.infrastructure.LintDetectorTest
+import com.android.tools.lint.detector.api.Detector
+import com.android.tools.lint.detector.api.Issue
+import org.junit.Test
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+
+@RunWith(JUnit4::class)
+class GradleConfigurationDetectorTest : LintDetectorTest() {
+    override fun getDetector(): Detector = GradleConfigurationDetector()
+
+    override fun getIssues(): MutableList<Issue> = mutableListOf(GradleConfigurationDetector.ISSUE)
+
+    @Test
+    fun expectPass() {
+        lint().files(
+            gradle(
+                "build.gradle",
+                """
+                dependencies {
+                    debugImplementation("androidx.fragment:fragment-testing-manifest:1.2.0-beta02")
+                }
+            """
+            ).indented()
+        )
+            .run()
+            .expectClean()
+    }
+
+    @Test
+    fun expectFail() {
+        lint().files(
+            gradle(
+                "build.gradle",
+                """
+                dependencies {
+                    androidTestImplementation("androidx.fragment:fragment-testing-manifest:1.2.0-beta02")
+                }
+            """
+            ).indented()
+        )
+            .run()
+            .expect(
+                """
+                build.gradle:2: Error: Replace with debugImplementation. [FragmentGradleConfiguration]
+                    androidTestImplementation("androidx.fragment:fragment-testing-manifest:1.2.0-beta02")
+                    ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+                1 errors, 0 warnings
+                """.trimIndent()
+            )
+            .checkFix(
+                null,
+                gradle(
+                    """
+                dependencies {
+                    debugImplementation("androidx.fragment:fragment-testing-manifest:1.2.0-beta02")
+                }
+            """
+                ).indented()
+            )
+    }
+}
diff --git a/fragment/fragment-testing-manifest/api/current.txt b/fragment/fragment-testing-manifest/api/current.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/fragment/fragment-testing-manifest/api/current.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/fragment/fragment-testing-manifest/api/public_plus_experimental_current.txt b/fragment/fragment-testing-manifest/api/public_plus_experimental_current.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/fragment/fragment-testing-manifest/api/public_plus_experimental_current.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/fragment/fragment-testing-manifest/api/res-current.txt b/fragment/fragment-testing-manifest/api/res-current.txt
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/fragment/fragment-testing-manifest/api/res-current.txt
diff --git a/fragment/fragment-testing-manifest/api/restricted_current.txt b/fragment/fragment-testing-manifest/api/restricted_current.txt
new file mode 100644
index 0000000..e6f50d0
--- /dev/null
+++ b/fragment/fragment-testing-manifest/api/restricted_current.txt
@@ -0,0 +1 @@
+// Signature format: 4.0
diff --git a/fragment/fragment-testing-manifest/build.gradle b/fragment/fragment-testing-manifest/build.gradle
new file mode 100644
index 0000000..55210b93
--- /dev/null
+++ b/fragment/fragment-testing-manifest/build.gradle
@@ -0,0 +1,51 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+import androidx.build.LibraryType
+import org.jetbrains.kotlin.gradle.tasks.KotlinCompile
+
+plugins {
+    id("AndroidXPlugin")
+    id("com.android.library")
+    id("kotlin-android")
+}
+
+dependencies {
+    api(project(":fragment:fragment-ktx"))
+    api(libs.kotlinStdlib)
+
+    lintPublish(project(":fragment:fragment-testing-manifest-lint"))
+}
+
+androidx {
+    name = "Fragment Testing Manifest dependency"
+    type = LibraryType.PUBLISHED_TEST_LIBRARY
+    mavenGroup = LibraryGroups.FRAGMENT
+    inceptionYear = "2022"
+    description = "Fragment testing library that should be added as a debugImplementation dependency to add properties to the debug manifest necessary for testing an application"
+}
+
+android {
+    namespace "androidx.fragment.testing.manifest"
+}
+
+tasks.withType(KotlinCompile).configureEach {
+    kotlinOptions {
+        freeCompilerArgs += [
+                "-Xjvm-default=all",
+        ]
+    }
+}
diff --git a/fragment/fragment-testing-manifest/src/main/AndroidManifest.xml b/fragment/fragment-testing-manifest/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..cbbd7bc5
--- /dev/null
+++ b/fragment/fragment-testing-manifest/src/main/AndroidManifest.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  ~ Copyright 2018 The Android Open Source Project
+  ~
+  ~ Licensed under the Apache License, Version 2.0 (the "License");
+  ~ you may not use this file except in compliance with the License.
+  ~ You may obtain a copy of the License at
+  ~
+  ~      http://www.apache.org/licenses/LICENSE-2.0
+  ~
+  ~ Unless required by applicable law or agreed to in writing, software
+  ~ distributed under the License is distributed on an "AS IS" BASIS,
+  ~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  ~ See the License for the specific language governing permissions and
+  ~ limitations under the License.
+-->
+<manifest xmlns:android="http://schemas.android.com/apk/res/android"
+          xmlns:tools="http://schemas.android.com/tools">
+    <uses-permission android:name="android.permission.REORDER_TASKS" />
+    <application>
+        <activity
+                android:name="androidx.fragment.app.testing.EmptyFragmentActivity"
+                android:theme="@style/FragmentScenarioEmptyFragmentActivityTheme"
+                android:taskAffinity=""
+                android:multiprocess="true"
+                android:exported="true">
+            <intent-filter>
+                <action android:name="android.intent.action.MAIN" />
+            </intent-filter>
+        </activity>
+    </application>
+</manifest>
diff --git a/fragment/fragment-testing-manifest/src/main/java/androidx/fragment/app/testing/EmptyFragmentActivity.kt b/fragment/fragment-testing-manifest/src/main/java/androidx/fragment/app/testing/EmptyFragmentActivity.kt
new file mode 100644
index 0000000..c1d6c7b
--- /dev/null
+++ b/fragment/fragment-testing-manifest/src/main/java/androidx/fragment/app/testing/EmptyFragmentActivity.kt
@@ -0,0 +1,56 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.fragment.app.testing
+
+import android.annotation.SuppressLint
+import android.os.Bundle
+import androidx.annotation.RestrictTo
+import androidx.fragment.app.FragmentActivity
+import androidx.fragment.testing.manifest.R
+
+/**
+ * An empty activity inheriting FragmentActivity. This Activity is used to host Fragment in
+ * FragmentScenario.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+class EmptyFragmentActivity : FragmentActivity() {
+    @SuppressLint("RestrictedApi")
+    override fun onCreate(savedInstanceState: Bundle?) {
+        setTheme(
+            intent.getIntExtra(
+                THEME_EXTRAS_BUNDLE_KEY,
+                R.style.FragmentScenarioEmptyFragmentActivityTheme
+            )
+        )
+
+        // Checks if we have a custom FragmentFactory and set it.
+        val factory = FragmentFactoryHolderViewModel.getInstance(this).fragmentFactory
+        if (factory != null) {
+            supportFragmentManager.fragmentFactory = factory
+        }
+
+        // FragmentFactory needs to be set before calling the super.onCreate, otherwise the
+        // Activity crashes when it is recreating and there is a fragment which has no
+        // default constructor.
+        super.onCreate(savedInstanceState)
+    }
+
+    companion object {
+        const val THEME_EXTRAS_BUNDLE_KEY = "androidx.fragment.app.testing.FragmentScenario" +
+            ".EmptyFragmentActivity.THEME_EXTRAS_BUNDLE_KEY"
+    }
+}
\ No newline at end of file
diff --git a/fragment/fragment-testing-manifest/src/main/java/androidx/fragment/app/testing/FragmentFactoryHolderViewModel.kt b/fragment/fragment-testing-manifest/src/main/java/androidx/fragment/app/testing/FragmentFactoryHolderViewModel.kt
new file mode 100644
index 0000000..00840ca
--- /dev/null
+++ b/fragment/fragment-testing-manifest/src/main/java/androidx/fragment/app/testing/FragmentFactoryHolderViewModel.kt
@@ -0,0 +1,55 @@
+/*
+ * Copyright 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.fragment.app.testing
+
+import androidx.activity.viewModels
+import androidx.annotation.RestrictTo
+import androidx.fragment.app.FragmentActivity
+import androidx.fragment.app.FragmentFactory
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+
+/**
+ * A view-model to hold a fragment factory.
+ */
+@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
+class FragmentFactoryHolderViewModel : ViewModel() {
+    var fragmentFactory: FragmentFactory? = null
+
+    override fun onCleared() {
+        super.onCleared()
+        fragmentFactory = null
+    }
+
+    companion object {
+        @Suppress("MemberVisibilityCanBePrivate")
+        internal val FACTORY: ViewModelProvider.Factory =
+            object : ViewModelProvider.Factory {
+                @Suppress("UNCHECKED_CAST")
+                override fun <T : ViewModel> create(modelClass: Class<T>): T {
+                    val viewModel =
+                        FragmentFactoryHolderViewModel()
+                    return viewModel as T
+                }
+            }
+
+        fun getInstance(activity: FragmentActivity): FragmentFactoryHolderViewModel {
+            val viewModel: FragmentFactoryHolderViewModel by activity.viewModels { FACTORY }
+            return viewModel
+        }
+    }
+}
\ No newline at end of file
diff --git a/fragment/fragment-testing/src/main/res/values/styles.xml b/fragment/fragment-testing-manifest/src/main/res/values/styles.xml
similarity index 100%
rename from fragment/fragment-testing/src/main/res/values/styles.xml
rename to fragment/fragment-testing-manifest/src/main/res/values/styles.xml
diff --git a/fragment/fragment-testing/build.gradle b/fragment/fragment-testing/build.gradle
index 2d36b95..919eb6c 100644
--- a/fragment/fragment-testing/build.gradle
+++ b/fragment/fragment-testing/build.gradle
@@ -27,6 +27,7 @@
     api(project(":fragment:fragment-ktx"))
     api(libs.testCore)
     api(libs.kotlinStdlib)
+    api(project(":fragment:fragment-testing-manifest"))
     androidTestImplementation(libs.kotlinStdlib)
     androidTestImplementation(libs.espressoCore)
     androidTestImplementation(libs.testExtJunit)
diff --git a/fragment/fragment-testing/src/main/AndroidManifest.xml b/fragment/fragment-testing/src/main/AndroidManifest.xml
index 9b9e0e1a..9968c17 100644
--- a/fragment/fragment-testing/src/main/AndroidManifest.xml
+++ b/fragment/fragment-testing/src/main/AndroidManifest.xml
@@ -18,17 +18,7 @@
           xmlns:tools="http://schemas.android.com/tools">
     <!-- TODO: Remove this override after androidx.test:core lowers the level -->
     <uses-sdk tools:overrideLibrary="androidx.test.core" />
-    <uses-permission android:name="android.permission.REORDER_TASKS" />
     <application>
-        <activity
-                android:name="androidx.fragment.app.testing.FragmentScenario$EmptyFragmentActivity"
-                android:theme="@style/FragmentScenarioEmptyFragmentActivityTheme"
-                android:taskAffinity=""
-                android:multiprocess="true"
-                android:exported="true">
-            <intent-filter>
-                <action android:name="android.intent.action.MAIN" />
-            </intent-filter>
-        </activity>
+
     </application>
 </manifest>
\ No newline at end of file
diff --git a/fragment/fragment-testing/src/main/java/androidx/fragment/app/testing/FragmentScenario.kt b/fragment/fragment-testing/src/main/java/androidx/fragment/app/testing/FragmentScenario.kt
index f32df12..b90929fe 100644
--- a/fragment/fragment-testing/src/main/java/androidx/fragment/app/testing/FragmentScenario.kt
+++ b/fragment/fragment-testing/src/main/java/androidx/fragment/app/testing/FragmentScenario.kt
@@ -20,7 +20,6 @@
 import android.content.ComponentName
 import android.content.Intent
 import android.os.Bundle
-import androidx.activity.viewModels
 import androidx.annotation.IdRes
 import androidx.annotation.StyleRes
 import androidx.fragment.app.Fragment
@@ -28,10 +27,8 @@
 import androidx.fragment.app.FragmentFactory
 import androidx.fragment.app.commitNow
 import androidx.fragment.app.testing.FragmentScenario.Companion.launch
-import androidx.fragment.testing.R
+import androidx.fragment.testing.manifest.R
 import androidx.lifecycle.Lifecycle
-import androidx.lifecycle.ViewModel
-import androidx.lifecycle.ViewModelProvider
 import androidx.test.core.app.ActivityScenario
 import androidx.test.core.app.ApplicationProvider
 import java.io.Closeable
@@ -239,68 +236,6 @@
 ) : Closeable {
 
     /**
-     * An empty activity inheriting FragmentActivity. This Activity is used to host Fragment in
-     * FragmentScenario.
-     */
-    internal class EmptyFragmentActivity : FragmentActivity() {
-        @SuppressLint("RestrictedApi")
-        override fun onCreate(savedInstanceState: Bundle?) {
-            setTheme(
-                intent.getIntExtra(
-                    THEME_EXTRAS_BUNDLE_KEY,
-                    R.style.FragmentScenarioEmptyFragmentActivityTheme
-                )
-            )
-
-            // Checks if we have a custom FragmentFactory and set it.
-            val factory = FragmentFactoryHolderViewModel.getInstance(this).fragmentFactory
-            if (factory != null) {
-                supportFragmentManager.fragmentFactory = factory
-            }
-
-            // FragmentFactory needs to be set before calling the super.onCreate, otherwise the
-            // Activity crashes when it is recreating and there is a fragment which has no
-            // default constructor.
-            super.onCreate(savedInstanceState)
-        }
-
-        companion object {
-            const val THEME_EXTRAS_BUNDLE_KEY = "androidx.fragment.app.testing.FragmentScenario" +
-                ".EmptyFragmentActivity.THEME_EXTRAS_BUNDLE_KEY"
-        }
-    }
-
-    /**
-     * A view-model to hold a fragment factory.
-     */
-    internal class FragmentFactoryHolderViewModel : ViewModel() {
-        var fragmentFactory: FragmentFactory? = null
-
-        override fun onCleared() {
-            super.onCleared()
-            fragmentFactory = null
-        }
-
-        companion object {
-            @Suppress("MemberVisibilityCanBePrivate")
-            internal val FACTORY: ViewModelProvider.Factory =
-                object : ViewModelProvider.Factory {
-                    @Suppress("UNCHECKED_CAST")
-                    override fun <T : ViewModel> create(modelClass: Class<T>): T {
-                        val viewModel =
-                            FragmentFactoryHolderViewModel()
-                        return viewModel as T
-                    }
-                }
-
-            fun getInstance(activity: FragmentActivity): FragmentFactoryHolderViewModel {
-                val viewModel: FragmentFactoryHolderViewModel by activity.viewModels { FACTORY }
-                return viewModel
-            }
-        }
-    }
-
-    /**
      * Moves Fragment state to a new state.
      *
      *  If a new state and current state are the same, this method does nothing. It accepts
diff --git a/fragment/integration-tests/testapp/build.gradle b/fragment/integration-tests/testapp/build.gradle
index f49848c..17004dc 100644
--- a/fragment/integration-tests/testapp/build.gradle
+++ b/fragment/integration-tests/testapp/build.gradle
@@ -37,6 +37,13 @@
     implementation(project(":fragment:fragment-ktx"))
     implementation("androidx.transition:transition:1.3.0")
     implementation("androidx.recyclerview:recyclerview:1.1.0")
+    debugImplementation(project(":fragment:fragment-testing-manifest"))
+
+    androidTestImplementation(project(":fragment:fragment-testing"))
+    androidTestImplementation(libs.testExtJunit)
+    androidTestImplementation(libs.testRunner)
+    androidTestImplementation(libs.truth)
+    androidTestImplementation(libs.espressoCore)
 }
 
 tasks["check"].dependsOn(tasks["connectedCheck"])
diff --git a/fragment/integration-tests/testapp/src/androidTest/java/androidx/fragment/testapp/SimpleFragmentTest.kt b/fragment/integration-tests/testapp/src/androidTest/java/androidx/fragment/testapp/SimpleFragmentTest.kt
new file mode 100644
index 0000000..5ef3ea4
--- /dev/null
+++ b/fragment/integration-tests/testapp/src/androidTest/java/androidx/fragment/testapp/SimpleFragmentTest.kt
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2022 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.fragment.testapp
+
+import androidx.fragment.app.testing.launchFragment
+import androidx.test.ext.junit.runners.AndroidJUnit4
+import androidx.test.filters.LargeTest
+import org.junit.Test
+import org.junit.runner.RunWith
+
+/**
+ * Simple integration test to verify FragmentScenario behavior in an app module.
+ */
+@RunWith(AndroidJUnit4::class)
+@LargeTest
+class SimpleFragmentTest {
+    @Test
+    fun fragmentScenario() {
+        with(launchFragment<SimpleFragment>()) {
+        }
+    }
+}
diff --git a/fragment/integration-tests/testapp/src/main/java/androidx/fragment/testapp/SimpleFragment.kt b/fragment/integration-tests/testapp/src/main/java/androidx/fragment/testapp/SimpleFragment.kt
new file mode 100644
index 0000000..00c06ea
--- /dev/null
+++ b/fragment/integration-tests/testapp/src/main/java/androidx/fragment/testapp/SimpleFragment.kt
@@ -0,0 +1,21 @@
+/*
+ * Copyright 2020 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package androidx.fragment.testapp
+
+import androidx.fragment.app.Fragment
+
+class SimpleFragment : Fragment(R.layout.simple_fragment)
diff --git a/fragment/integration-tests/testapp/src/main/res/layout/simple_fragment.xml b/fragment/integration-tests/testapp/src/main/res/layout/simple_fragment.xml
new file mode 100644
index 0000000..17e99b5
--- /dev/null
+++ b/fragment/integration-tests/testapp/src/main/res/layout/simple_fragment.xml
@@ -0,0 +1,28 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+  Copyright 2022 The Android Open Source Project
+
+  Licensed under the Apache License, Version 2.0 (the "License");
+  you may not use this file except in compliance with the License.
+  You may obtain a copy of the License at
+
+       http://www.apache.org/licenses/LICENSE-2.0
+
+  Unless required by applicable law or agreed to in writing, software
+  distributed under the License is distributed on an "AS IS" BASIS,
+  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+  See the License for the specific language governing permissions and
+  limitations under the License.
+  -->
+
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:orientation="vertical"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent">
+
+    <TextView
+        android:id="@+id/textView"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:text="TextView" />
+</LinearLayout>
diff --git a/settings.gradle b/settings.gradle
index aa8e498..2a444ec 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -653,6 +653,8 @@
 includeProject(":fragment:fragment-lint", [BuildType.MAIN, BuildType.FLAN, BuildType.WEAR])
 includeProject(":fragment:fragment-testing", [BuildType.MAIN, BuildType.FLAN])
 includeProject(":fragment:fragment-testing-lint", [BuildType.MAIN, BuildType.FLAN])
+includeProject(":fragment:fragment-testing-manifest", [BuildType.MAIN, BuildType.FLAN])
+includeProject(":fragment:fragment-testing-manifest-lint", [BuildType.MAIN, BuildType.FLAN])
 includeProject(":fragment:fragment-truth", [BuildType.MAIN, BuildType.FLAN])
 includeProject(":fragment:integration-tests:testapp", [BuildType.MAIN, BuildType.FLAN])
 includeProject(":glance:glance", [BuildType.GLANCE])