Use reflection name for Worker and ViewModel multibinding keys.

Worker factories search for an assisted factory based on the
reflection name of the class and not its canonical name,
e.g. TopClass$NestedWorker vs TopClass.NestedWorker. This
changes fixes the generated multibinding key (@StringKey) so that
the reflection name is used and nested Worker classes get
instantiated by Hilt. Furthermore to keep the keys consistent,
this change updates HiltViewModelFactory to also use the
reflection name.

Bug: 160524718
Test: Hilt Worker and ViewModel test apps.
Change-Id: I3f9255c2e8601fbf7cb2c0160c4e6aae2fe6c58f
diff --git a/hilt/hilt-compiler/src/main/kotlin/androidx/hilt/lifecycle/ViewModelGenerator.kt b/hilt/hilt-compiler/src/main/kotlin/androidx/hilt/lifecycle/ViewModelGenerator.kt
index 07da0e6..42444c6 100644
--- a/hilt/hilt-compiler/src/main/kotlin/androidx/hilt/lifecycle/ViewModelGenerator.kt
+++ b/hilt/hilt-compiler/src/main/kotlin/androidx/hilt/lifecycle/ViewModelGenerator.kt
@@ -105,7 +105,7 @@
                     .addAnnotation(ClassNames.INTO_MAP)
                     .addAnnotation(
                         AnnotationSpec.builder(ClassNames.STRING_KEY)
-                            .addMember("value", S, injectedViewModel.className.canonicalName())
+                            .addMember("value", S, injectedViewModel.className.reflectionName())
                             .build())
                     .addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC)
                     .returns(
diff --git a/hilt/hilt-compiler/src/main/kotlin/androidx/hilt/work/WorkerGenerator.kt b/hilt/hilt-compiler/src/main/kotlin/androidx/hilt/work/WorkerGenerator.kt
index ce6c538..fae2357 100644
--- a/hilt/hilt-compiler/src/main/kotlin/androidx/hilt/work/WorkerGenerator.kt
+++ b/hilt/hilt-compiler/src/main/kotlin/androidx/hilt/work/WorkerGenerator.kt
@@ -105,7 +105,7 @@
                     .addAnnotation(ClassNames.INTO_MAP)
                     .addAnnotation(
                         AnnotationSpec.builder(ClassNames.STRING_KEY)
-                            .addMember("value", S, injectedWorker.className.canonicalName())
+                            .addMember("value", S, injectedWorker.className.reflectionName())
                             .build())
                     .addModifiers(Modifier.ABSTRACT, Modifier.PUBLIC)
                     .returns(
diff --git a/hilt/hilt-compiler/src/test/kotlin/androidx/hilt/lifecycle/ViewModelGeneratorTest.kt b/hilt/hilt-compiler/src/test/kotlin/androidx/hilt/lifecycle/ViewModelGeneratorTest.kt
index 711bb2c..2711070 100644
--- a/hilt/hilt-compiler/src/test/kotlin/androidx/hilt/lifecycle/ViewModelGeneratorTest.kt
+++ b/hilt/hilt-compiler/src/test/kotlin/androidx/hilt/lifecycle/ViewModelGeneratorTest.kt
@@ -448,7 +448,7 @@
         public interface Outer_InnerViewModel_HiltModule {
             @Binds
             @IntoMap
-            @StringKey("androidx.hilt.lifecycle.test.Outer.InnerViewModel")
+            @StringKey("androidx.hilt.lifecycle.test.Outer${'$'}InnerViewModel")
             ViewModelAssistedFactory<? extends ViewModel> bind(
                     Outer_InnerViewModel_AssistedFactory factory)
         }
diff --git a/hilt/hilt-lifecycle-viewmodel/src/main/java/androidx/hilt/lifecycle/HiltViewModelFactory.java b/hilt/hilt-lifecycle-viewmodel/src/main/java/androidx/hilt/lifecycle/HiltViewModelFactory.java
index 305ed6a..86398c0 100644
--- a/hilt/hilt-lifecycle-viewmodel/src/main/java/androidx/hilt/lifecycle/HiltViewModelFactory.java
+++ b/hilt/hilt-lifecycle-viewmodel/src/main/java/androidx/hilt/lifecycle/HiltViewModelFactory.java
@@ -64,7 +64,7 @@
     protected <T extends ViewModel> T create(@NonNull String key, @NonNull Class<T> modelClass,
             @NonNull SavedStateHandle handle) {
         Provider<ViewModelAssistedFactory<? extends ViewModel>> factoryProvider =
-                mViewModelFactories.get(modelClass.getCanonicalName());
+                mViewModelFactories.get(modelClass.getName());
         if (factoryProvider == null) {
             // Delegate to factory that will attempt to reflectively construct the ViewModel.
             // A prefixed key is used to avoid collisions since the
diff --git a/hilt/integration-tests/viewmodelapp/src/androidTest/java/androidx/hilt/integration/viewmodelapp/ActivityInjectionTest.kt b/hilt/integration-tests/viewmodelapp/src/androidTest/java/androidx/hilt/integration/viewmodelapp/ActivityInjectionTest.kt
index 1dd56a5..f7a9c11 100644
--- a/hilt/integration-tests/viewmodelapp/src/androidTest/java/androidx/hilt/integration/viewmodelapp/ActivityInjectionTest.kt
+++ b/hilt/integration-tests/viewmodelapp/src/androidTest/java/androidx/hilt/integration/viewmodelapp/ActivityInjectionTest.kt
@@ -48,6 +48,7 @@
                 assertThat(activity.myAndroidViewModel).isNotNull()
                 assertThat(activity.myViewModel).isNotNull()
                 assertThat(activity.myInjectedViewModel).isNotNull()
+                assertThat(activity.myNestedInjectedViewModel).isNotNull()
             }
         }
     }
@@ -57,5 +58,6 @@
         val myAndroidViewModel by viewModels<MyAndroidViewModel>()
         val myViewModel by viewModels<MyViewModel>()
         val myInjectedViewModel by viewModels<MyInjectedViewModel>()
+        val myNestedInjectedViewModel by viewModels<TopClass.MyNestedInjectedViewModel>()
     }
 }
\ No newline at end of file
diff --git a/hilt/integration-tests/viewmodelapp/src/androidTest/java/androidx/hilt/integration/viewmodelapp/MyViewModels.kt b/hilt/integration-tests/viewmodelapp/src/androidTest/java/androidx/hilt/integration/viewmodelapp/MyViewModels.kt
index 7253fd4..4284828 100644
--- a/hilt/integration-tests/viewmodelapp/src/androidTest/java/androidx/hilt/integration/viewmodelapp/MyViewModels.kt
+++ b/hilt/integration-tests/viewmodelapp/src/androidTest/java/androidx/hilt/integration/viewmodelapp/MyViewModels.kt
@@ -26,4 +26,9 @@
 class MyViewModel() : ViewModel()
 
 @Suppress("UNUSED_PARAMETER")
-class MyInjectedViewModel @ViewModelInject constructor(foo: Foo) : ViewModel()
\ No newline at end of file
+class MyInjectedViewModel @ViewModelInject constructor(foo: Foo) : ViewModel()
+
+object TopClass {
+    @Suppress("UNUSED_PARAMETER")
+    class MyNestedInjectedViewModel @ViewModelInject constructor(foo: Foo) : ViewModel()
+}
\ No newline at end of file
diff --git a/hilt/integration-tests/workerapp/src/androidTest/java/androidx/hilt/integration/workerapp/SimpleTest.kt b/hilt/integration-tests/workerapp/src/androidTest/java/androidx/hilt/integration/workerapp/SimpleTest.kt
index 08eaa65..477c46b 100644
--- a/hilt/integration-tests/workerapp/src/androidTest/java/androidx/hilt/integration/workerapp/SimpleTest.kt
+++ b/hilt/integration-tests/workerapp/src/androidTest/java/androidx/hilt/integration/workerapp/SimpleTest.kt
@@ -73,4 +73,14 @@
             assertThat(result).isEqualTo(ListenableWorker.Result.success())
         }
     }
+
+    @Test
+    fun testNestedWorkerInject() {
+        val context = InstrumentationRegistry.getInstrumentation().targetContext
+        val worker = TestListenableWorkerBuilder<TopClass.NestedWorker>(context).apply {
+            setWorkerFactory(hiltWorkerFactory)
+        }.build()
+        val result = worker.doWork()
+        assertThat(result).isEqualTo(ListenableWorker.Result.success())
+    }
 }
\ No newline at end of file
diff --git a/hilt/integration-tests/workerapp/src/main/java/androidx/hilt/integration/workerapp/SimpleWorker.kt b/hilt/integration-tests/workerapp/src/main/java/androidx/hilt/integration/workerapp/SimpleWorker.kt
index 9c7e3ab..cc4c474 100644
--- a/hilt/integration-tests/workerapp/src/main/java/androidx/hilt/integration/workerapp/SimpleWorker.kt
+++ b/hilt/integration-tests/workerapp/src/main/java/androidx/hilt/integration/workerapp/SimpleWorker.kt
@@ -47,6 +47,16 @@
     }
 }
 
+object TopClass {
+    class NestedWorker @WorkerInject constructor(
+        @Assisted context: Context,
+        @Assisted params: WorkerParameters,
+        private val logger: MyLogger
+    ) : Worker(context, params) {
+        override fun doWork() = Result.success()
+    }
+}
+
 class MyLogger @Inject constructor() {
     fun log(s: String) {
         Log.i("MyLogger", s)