Integrate ViewTreeViewModelStoreOwner into Activity+Fragment

Ensure that ComponentActivity and Fragment return
the correct result from ViewTreeViewModelStoreOwner.get()

Test: updated Activity and Fragment tests
Change-Id: I29203201d1bdc7a6fba0a16e062d02563ba6bef1
diff --git a/activity/activity-ktx/build.gradle b/activity/activity-ktx/build.gradle
index ce1eb88..c728b82 100644
--- a/activity/activity-ktx/build.gradle
+++ b/activity/activity-ktx/build.gradle
@@ -38,10 +38,10 @@
     api("androidx.core:core-ktx:1.1.0") {
         because 'Mirror activity dependency graph for -ktx artifacts'
     }
-    api("androidx.lifecycle:lifecycle-runtime-ktx:2.3.0-alpha01") {
+    api(project(":lifecycle:lifecycle-runtime-ktx")) {
         because 'Mirror activity dependency graph for -ktx artifacts'
     }
-    api("androidx.lifecycle:lifecycle-viewmodel-ktx:2.3.0-alpha01")
+    api(project(":lifecycle:lifecycle-viewmodel-ktx"))
     api(KOTLIN_STDLIB)
 
     androidTestImplementation(project(":lifecycle:lifecycle-runtime-testing"))
diff --git a/activity/activity/build.gradle b/activity/activity/build.gradle
index 6571d19..327871c 100644
--- a/activity/activity/build.gradle
+++ b/activity/activity/build.gradle
@@ -23,10 +23,10 @@
     api("androidx.annotation:annotation:1.1.0")
     implementation("androidx.collection:collection:1.0.0")
     api("androidx.core:core:1.1.0")
-    api("androidx.lifecycle:lifecycle-runtime:2.3.0-alpha01")
-    api("androidx.lifecycle:lifecycle-viewmodel:2.3.0-alpha01")
+    api(project(":lifecycle:lifecycle-runtime"))
+    api(project(":lifecycle:lifecycle-viewmodel"))
     api("androidx.savedstate:savedstate:1.0.0")
-    api("androidx.lifecycle:lifecycle-viewmodel-savedstate:2.3.0-alpha01")
+    api(project(":lifecycle:lifecycle-viewmodel-savedstate"))
 
     androidTestImplementation(project(":lifecycle:lifecycle-runtime-testing"))
     androidTestImplementation(KOTLIN_STDLIB)
diff --git a/activity/activity/src/androidTest/java/androidx/activity/ContentViewTest.kt b/activity/activity/src/androidTest/java/androidx/activity/ContentViewTest.kt
index 356b6da..1ca8f2c 100644
--- a/activity/activity/src/androidTest/java/androidx/activity/ContentViewTest.kt
+++ b/activity/activity/src/androidTest/java/androidx/activity/ContentViewTest.kt
@@ -22,6 +22,7 @@
 import android.widget.TextView
 import androidx.activity.test.R
 import androidx.lifecycle.ViewTreeLifecycleOwner
+import androidx.lifecycle.ViewTreeViewModelStoreOwner
 import androidx.test.core.app.ActivityScenario
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
@@ -45,7 +46,7 @@
     }
 
     @Test
-    fun testViewTreeLifecycleOwnerInflation() {
+    fun testViewTreeInflation() {
         with(ActivityScenario.launch(ContentViewActivity::class.java)) {
             val inflatedTextView: TextView = withActivity { findViewById(R.id.inflated_text_view) }
 
@@ -53,12 +54,15 @@
                 assertWithMessage("inflated view has correct ViewTreeLifecycleOwner")
                     .that(ViewTreeLifecycleOwner.get(inflatedTextView))
                     .isSameInstanceAs(this@withActivity)
+                assertWithMessage("inflated view has correct ViewTreeViewModelStoreOwner")
+                    .that(ViewTreeViewModelStoreOwner.get(inflatedTextView))
+                    .isSameInstanceAs(this@withActivity)
             }
         }
     }
 
     @Test
-    fun testViewTreeLifecycleAttachment() {
+    fun testViewTreeAttachment() {
         runAttachTest("setContentView view only") { setContentView(it) }
         runAttachTest("setContentView with LayoutParams") {
             setContentView(it, ViewGroup.LayoutParams(WRAP_CONTENT, WRAP_CONTENT))
@@ -76,19 +80,23 @@
             withActivity {
                 val view = View(this)
 
-                var attachedResult: Any? = "did not attach"
+                var attachedLifecycleOwner: Any? = "did not attach"
+                var attachedViewModelStoreOwner: Any? = "did not attach"
                 view.addOnAttachStateChangeListener(object : View.OnAttachStateChangeListener {
                     override fun onViewDetachedFromWindow(v: View?) {
                         // Do nothing
                     }
 
                     override fun onViewAttachedToWindow(v: View?) {
-                        attachedResult = ViewTreeLifecycleOwner.get(view)
+                        attachedLifecycleOwner = ViewTreeLifecycleOwner.get(view)
+                        attachedViewModelStoreOwner = ViewTreeViewModelStoreOwner.get(view)
                     }
                 })
                 attach(view)
                 assertWithMessage("$message: ViewTreeLifecycleOwner was set correctly")
-                    .that(attachedResult).isSameInstanceAs(this)
+                    .that(attachedLifecycleOwner).isSameInstanceAs(this)
+                assertWithMessage("$message: ViewTreeViewModelStoreOwner was set correctly")
+                    .that(attachedViewModelStoreOwner).isSameInstanceAs(this)
             }
         }
     }
diff --git a/activity/activity/src/main/java/androidx/activity/ComponentActivity.java b/activity/activity/src/main/java/androidx/activity/ComponentActivity.java
index 58b8ab1..6620d21 100644
--- a/activity/activity/src/main/java/androidx/activity/ComponentActivity.java
+++ b/activity/activity/src/main/java/androidx/activity/ComponentActivity.java
@@ -67,6 +67,7 @@
 import androidx.lifecycle.ViewModelStore;
 import androidx.lifecycle.ViewModelStoreOwner;
 import androidx.lifecycle.ViewTreeLifecycleOwner;
+import androidx.lifecycle.ViewTreeViewModelStoreOwner;
 import androidx.savedstate.SavedStateRegistry;
 import androidx.savedstate.SavedStateRegistryController;
 import androidx.savedstate.SavedStateRegistryOwner;
@@ -354,6 +355,7 @@
         // Set the VTLO before setting the content view so that the inflation process
         // and attach listeners will see it already present
         ViewTreeLifecycleOwner.set(getWindow().getDecorView(), this);
+        ViewTreeViewModelStoreOwner.set(getWindow().getDecorView(), this);
         super.setContentView(layoutResID);
     }
 
@@ -362,6 +364,7 @@
         // Set the VTLO before setting the content view so that attach listeners
         // will see it already present
         ViewTreeLifecycleOwner.set(getWindow().getDecorView(), this);
+        ViewTreeViewModelStoreOwner.set(getWindow().getDecorView(), this);
         super.setContentView(view);
     }
 
@@ -372,6 +375,7 @@
         // Set the VTLO before setting the content view so that attach listeners
         // will see it already present
         ViewTreeLifecycleOwner.set(getWindow().getDecorView(), this);
+        ViewTreeViewModelStoreOwner.set(getWindow().getDecorView(), this);
         super.setContentView(view, params);
     }
 
@@ -382,6 +386,7 @@
         // Set the VTLO before setting the content view so that attach listeners
         // will see it already present.
         ViewTreeLifecycleOwner.set(getWindow().getDecorView(), this);
+        ViewTreeViewModelStoreOwner.set(getWindow().getDecorView(), this);
         super.addContentView(view, params);
     }
 
diff --git a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentViewLifecycleTest.kt b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentViewLifecycleTest.kt
index 9d2a203..9362743 100644
--- a/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentViewLifecycleTest.kt
+++ b/fragment/fragment/src/androidTest/java/androidx/fragment/app/FragmentViewLifecycleTest.kt
@@ -29,6 +29,7 @@
 import androidx.lifecycle.MutableLiveData
 import androidx.lifecycle.Observer
 import androidx.lifecycle.ViewTreeLifecycleOwner
+import androidx.lifecycle.ViewTreeViewModelStoreOwner
 import androidx.test.annotation.UiThreadTest
 import androidx.test.ext.junit.runners.AndroidJUnit4
 import androidx.test.filters.LargeTest
@@ -244,18 +245,18 @@
     }
 
     /**
-     * Test that the ViewTreeLifecycleOwner for a fragment's view is the fragment's own
-     * viewLifecycleOwner.
+     * Test that the ViewTree get() methods for a fragment's view work correctly.
      */
     @Test
-    fun testFragmentViewTreeLifecycleOwner() {
+    fun testFragmentViewTree() {
         val activity = activityRule.activity
         val fm = activity.supportFragmentManager
 
-        val fragment = ViewTreeLifecycleOwnerCheckFragment()
+        val fragment = ViewTreeCheckFragment()
 
         var observedLifecycleOwner: Any? = "not set"
         var observedTreeLifecycleOwner: Any? = "not set"
+        var observedTreeViewModelStoreOwner: Any? = "not set"
 
         val latch = CountDownLatch(1)
         activity.runOnUiThread {
@@ -266,6 +267,9 @@
 
                 observedLifecycleOwner = owner
                 observedTreeLifecycleOwner = fragment.view?.let { ViewTreeLifecycleOwner.get(it) }
+                observedTreeViewModelStoreOwner = fragment.view?.let {
+                    ViewTreeViewModelStoreOwner.get(it)
+                }
             }
 
             fm.beginTransaction().add(R.id.content, fragment).commitNow()
@@ -277,11 +281,19 @@
         assertWithMessage("ViewTreeLifecycleOwner should match viewLifecycleOwner after commitNow")
             .that(ViewTreeLifecycleOwner.get(fragment.view ?: error("no fragment view created")))
             .isSameInstanceAs(fragment.viewLifecycleOwner)
+        assertWithMessage("ViewTreeViewModelStoreOwner should match fragment after commitNow")
+            .that(ViewTreeViewModelStoreOwner.get(fragment.view
+                ?: error("no fragment view created")))
+            .isSameInstanceAs(fragment)
 
         assertWithMessage("ViewTreeLifecycleOwner should match viewLifecycleOwner in " +
                 "viewLifecycleOwnerLiveData observer")
             .that(observedTreeLifecycleOwner)
             .isSameInstanceAs(fragment.viewLifecycleOwner)
+        assertWithMessage("ViewTreeViewModelStoreOwner should match fragment in " +
+                "viewLifecycleOwnerLiveData observer")
+            .that(observedTreeViewModelStoreOwner)
+            .isSameInstanceAs(fragment)
 
         assertWithMessage("ViewTreeLifecycleOwner should match observed LifecycleOwner in " +
                 "viewLifecycleOwnerLiveData observer")
@@ -292,10 +304,15 @@
                 "onViewCreated")
             .that(fragment.onViewCreatedLifecycleOwner)
             .isSameInstanceAs(fragment.viewLifecycleOwner)
+        assertWithMessage("ViewTreeViewModelStoreOwner should match fragment in " +
+                "onViewCreated")
+            .that(fragment.onViewCreatedViewModelStoreOwner)
+            .isSameInstanceAs(fragment)
     }
 
-    class ViewTreeLifecycleOwnerCheckFragment : Fragment() {
+    class ViewTreeCheckFragment : Fragment() {
         var onViewCreatedLifecycleOwner: Any? = "not set"
+        var onViewCreatedViewModelStoreOwner: Any? = "not set"
 
         override fun onCreateView(
             inflater: LayoutInflater,
@@ -305,6 +322,7 @@
 
         override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
             onViewCreatedLifecycleOwner = ViewTreeLifecycleOwner.get(view)
+            onViewCreatedViewModelStoreOwner = ViewTreeViewModelStoreOwner.get(view)
         }
     }
 
diff --git a/fragment/fragment/src/main/java/androidx/fragment/app/Fragment.java b/fragment/fragment/src/main/java/androidx/fragment/app/Fragment.java
index 2d594f9..0da7ba0 100644
--- a/fragment/fragment/src/main/java/androidx/fragment/app/Fragment.java
+++ b/fragment/fragment/src/main/java/androidx/fragment/app/Fragment.java
@@ -84,6 +84,7 @@
 import androidx.lifecycle.ViewModelStore;
 import androidx.lifecycle.ViewModelStoreOwner;
 import androidx.lifecycle.ViewTreeLifecycleOwner;
+import androidx.lifecycle.ViewTreeViewModelStoreOwner;
 import androidx.loader.app.LoaderManager;
 import androidx.savedstate.SavedStateRegistry;
 import androidx.savedstate.SavedStateRegistryController;
@@ -2894,8 +2895,9 @@
             mViewLifecycleOwner.initialize();
             // Tell the fragment's new view about it before we tell anyone listening
             // to mViewLifecycleOwnerLiveData and before onViewCreated, so that calls to
-            // ViewTreeLifecycleOwner.get() return something meaningful
+            // ViewTree get() methods return something meaningful
             ViewTreeLifecycleOwner.set(mView, mViewLifecycleOwner);
+            ViewTreeViewModelStoreOwner.set(mView, this);
             // Then inform any Observers of the new LifecycleOwner
             mViewLifecycleOwnerLiveData.setValue(mViewLifecycleOwner);
         } else {