Skip to content

Commit 5c2e7f9

Browse files
authored
Delay subcomponent generation (duckduckgo#2132)
Task/Issue URL: https://app.asana.com/0/1202552961248957/1202710479869519/f ### Description See the [asana task](https://app.asana.com/0/1202552961248957/1202710479869519/f) for full context and explanation ### Steps to test this PR - [x] install from this branch - [x] smoke tests for app and AppTP - [x] filter logcat by `TrackerBlockingVpnService\$startVpn` - [x] install from develop - [x] enable AppTP (it should be disabled before) - [x] record the logcat - [x] install from this branch - [x] enable AppTP (it should be disabled before) - [x] verify the logcat is the same
1 parent 9b997bf commit 5c2e7f9

File tree

11 files changed

+60
-28
lines changed

11 files changed

+60
-28
lines changed

anvil/anvil-compiler/src/main/java/com/duckduckgo/anvil/compiler/ContributesSubComponentCodeGenerator.kt

Lines changed: 36 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ package com.duckduckgo.anvil.compiler
1818

1919
import com.duckduckgo.anvil.annotations.InjectWith
2020
import com.google.auto.service.AutoService
21+
import com.squareup.anvil.annotations.ContributesSubcomponent
2122
import com.squareup.anvil.annotations.ContributesTo
2223
import com.squareup.anvil.annotations.ExperimentalAnvilApi
2324
import com.squareup.anvil.annotations.MergeSubcomponent
@@ -30,6 +31,7 @@ import com.squareup.anvil.compiler.internal.reference.classAndInnerClassReferenc
3031
import com.squareup.kotlinpoet.*
3132
import com.squareup.kotlinpoet.ParameterizedTypeName.Companion.parameterizedBy
3233
import dagger.Binds
34+
import dagger.BindsInstance
3335
import dagger.Subcomponent
3436
import dagger.multibindings.ClassKey
3537
import dagger.multibindings.IntoMap
@@ -73,16 +75,27 @@ class ContributesSubComponentCodeGenerator : CodeGenerator {
7375
.builder(singleInstanceAnnotationFqName.asClassName(module)).addMember("scope = %T::class", scope.asClassName())
7476
.build()
7577
)
76-
.addAnnotation(AnnotationSpec.builder(MergeSubcomponent::class).addMember("scope = %T::class", scope.asClassName()).build())
78+
.addAnnotation(scope.fqName.subComponentAnnotation(module))
7779
.addSuperinterface(duckduckgoAndroidInjectorFqName.asClassName(module).parameterizedBy(vmClass.asClassName()))
7880
.addType(
7981
TypeSpec.interfaceBuilder("Factory")
8082
.addSuperinterface(
8183
duckduckgoAndroidInjectorFqName.asClassName(module)
8284
.nestedClass("Factory")
83-
.parameterizedBy(vmClass.asClassName())
85+
.parameterizedBy(vmClass.asClassName(), FqName(subcomponentFactoryClassName).asClassName(module))
86+
)
87+
.addAnnotation(scope.fqName.subComponentFactoryAnnotation(module))
88+
.addFunction(
89+
// This function should follow the [AndroidInjector.Factory.create] signature
90+
FunSpec.builder("create")
91+
.addModifiers(KModifier.OVERRIDE)
92+
.addModifiers(KModifier.ABSTRACT)
93+
.addParameter(
94+
ParameterSpec.builder("instance", vmClass.asClassName()).addAnnotation(BindsInstance::class).build()
95+
)
96+
.returns(FqName(subcomponentFactoryClassName).asClassName(module))
97+
.build()
8498
)
85-
.addAnnotation(AnnotationSpec.builder(Subcomponent.Factory::class).build())
8699
.build()
87100
)
88101
.addType(generateParentComponentInterface(vmClass, codeGenDir, module))
@@ -144,7 +157,7 @@ class ContributesSubComponentCodeGenerator : CodeGenerator {
144157
AnnotationSpec.builder(ClassKey::class).addMember("%T::class", bindingClassKey.asClassName(module)).build()
145158
)
146159
.addModifiers(KModifier.ABSTRACT)
147-
.returns(duckduckgoAndroidInjectorFqName.asClassName(module).nestedClass("Factory").parameterizedBy(STAR))
160+
.returns(duckduckgoAndroidInjectorFqName.asClassName(module).nestedClass("Factory").parameterizedBy(STAR, STAR))
148161
.build()
149162
)
150163
.build()
@@ -155,6 +168,25 @@ class ContributesSubComponentCodeGenerator : CodeGenerator {
155168

156169
}
157170

171+
private fun FqName.subComponentAnnotation(module: ModuleDescriptor): AnnotationSpec {
172+
return if (this == vpnScopeFqName) {
173+
AnnotationSpec.builder(ContributesSubcomponent::class)
174+
.addMember("scope = %T::class", this.asClassName(module))
175+
.addMember("parentScope = %T::class", getParentScope(module).asClassName(module))
176+
.build()
177+
} else {
178+
AnnotationSpec.builder(MergeSubcomponent::class).addMember("scope = %T::class", this.asClassName(module)).build()
179+
}
180+
}
181+
182+
private fun FqName.subComponentFactoryAnnotation(module: ModuleDescriptor): AnnotationSpec {
183+
return if (this == vpnScopeFqName) {
184+
AnnotationSpec.builder(ContributesSubcomponent.Factory::class).build()
185+
} else {
186+
AnnotationSpec.builder(Subcomponent.Factory::class).build()
187+
}
188+
}
189+
158190
private fun FqName.getParentScope(module: ModuleDescriptor): FqName {
159191
return when (this.asClassName(module)) {
160192
activityScopeFqName.asClassName(module) -> appScopeFqName

app/src/internal/java/com/duckduckgo/app/di.component/VpnInternalSettingsActivityComponent.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import dagger.multibindings.IntoMap
3737
)
3838
interface VpnInternalSettingsActivityComponent : AndroidInjector<VpnInternalSettingsActivity> {
3939
@Subcomponent.Factory
40-
interface Factory : AndroidInjector.Factory<VpnInternalSettingsActivity>
40+
interface Factory : AndroidInjector.Factory<VpnInternalSettingsActivity, VpnInternalSettingsActivityComponent>
4141
}
4242

4343
@ContributesTo(AppScope::class)
@@ -51,5 +51,5 @@ abstract class VpnInternalSettingsActivityBindingModule {
5151
@Binds
5252
@IntoMap
5353
@ClassKey(VpnInternalSettingsActivity::class)
54-
abstract fun VpnInternalSettingsActivityComponent.Factory.bind(): AndroidInjector.Factory<*>
54+
abstract fun VpnInternalSettingsActivityComponent.Factory.bind(): AndroidInjector.Factory<*, *>
5555
}

app/src/main/java/com/duckduckgo/app/global/DuckDuckGoApplication.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ open class DuckDuckGoApplication : HasDaggerInjector, Application() {
6464
lateinit var appCoroutineScope: CoroutineScope
6565

6666
@Inject
67-
lateinit var injectorFactoryMap: DaggerMap<Class<*>, AndroidInjector.Factory<*>>
67+
lateinit var injectorFactoryMap: DaggerMap<Class<*>, AndroidInjector.Factory<*, *>>
6868

6969
private val processDetector = ProcessDetector()
7070

@@ -211,7 +211,7 @@ open class DuckDuckGoApplication : HasDaggerInjector, Application() {
211211
*
212212
* This method will return the [AndroidInjector.Factory] for the given key passed in as parameter.
213213
*/
214-
override fun daggerFactoryFor(key: Class<*>): AndroidInjector.Factory<*> {
214+
override fun daggerFactoryFor(key: Class<*>): AndroidInjector.Factory<*, *> {
215215
return injectorFactoryMap[key]
216216
?: throw RuntimeException(
217217
"""

bandwidth/bandwidth-impl/src/main/java/com/duckduckgo/bandwidth/impl/AppTpBandwidthCollector.kt

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ import com.duckduckgo.app.global.DispatcherProvider
2121
import com.duckduckgo.app.statistics.pixels.Pixel
2222
import com.duckduckgo.app.utils.ConflatedJob
2323
import com.duckduckgo.bandwidth.impl.BandwidthPixelName.APPTP_BANDWIDTH
24-
import com.duckduckgo.di.scopes.AppScope
24+
import com.duckduckgo.di.scopes.VpnScope
2525
import com.duckduckgo.mobile.android.vpn.service.VpnServiceCallbacks
2626
import com.duckduckgo.mobile.android.vpn.state.VpnStateMonitor.VpnStopReason
2727
import com.squareup.anvil.annotations.ContributesMultibinding
@@ -32,10 +32,10 @@ import java.util.concurrent.TimeUnit
3232
import javax.inject.Inject
3333

3434
@ContributesMultibinding(
35-
scope = AppScope::class,
35+
scope = VpnScope::class,
3636
boundType = VpnServiceCallbacks::class
3737
)
38-
@SingleInstanceIn(AppScope::class)
38+
@SingleInstanceIn(VpnScope::class)
3939
class AppTpBandwidthCollector @Inject constructor(
4040
private val context: Context,
4141
private val bandwidthRepository: BandwidthRepository,

di/src/main/java/dagger/android/AndroidInjector.kt

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ interface HasDaggerInjector {
3333
* 1. creating the dagger component
3434
* 2. inject the dependencies in the Android type (eg. Activity)
3535
*/
36-
fun daggerFactoryFor(key: Class<*>): AndroidInjector.Factory<*>
36+
fun daggerFactoryFor(key: Class<*>): AndroidInjector.Factory<*, *>
3737
}
3838

3939
interface AndroidInjector<T> {
@@ -45,12 +45,12 @@ interface AndroidInjector<T> {
4545
*
4646
* @param <T> the concrete type to be injected
4747
*/
48-
interface Factory<T> {
48+
interface Factory<T, SubComponentType : AndroidInjector<T>> {
4949
/**
5050
* Creates an {@link AndroidInjector} for {@code instance}. This should be the same instance
5151
* that will be passed to {@link #inject(Object)}.
5252
*/
53-
fun create(@BindsInstance instance: T): AndroidInjector<T>
53+
fun create(@BindsInstance instance: T): SubComponentType
5454
}
5555

5656
companion object {
@@ -61,13 +61,13 @@ interface AndroidInjector<T> {
6161
* 2. Use the factory to create the dagger component that relates to an Android type, eg. Activity
6262
* 3. Inject any dependency requested by the Android type
6363
*/
64-
inline fun <reified T> inject(
64+
inline fun <reified T, R : AndroidInjector<T>> inject(
6565
injector: Any,
6666
instance: T,
6767
mapKey: Class<*>? = null
6868
) {
6969
if ((injector is HasDaggerInjector)) {
70-
(injector.daggerFactoryFor(mapKey ?: instance!!::class.java) as Factory<T>)
70+
(injector.daggerFactoryFor(mapKey ?: instance!!::class.java) as Factory<T, R>)
7171
.create(instance)
7272
.inject(instance)
7373
} else {

di/src/main/java/dagger/android/DaggerActivity.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -22,9 +22,9 @@ import javax.inject.Inject
2222

2323
abstract class DaggerActivity : AppCompatActivity(), HasDaggerInjector {
2424
@Inject
25-
lateinit var injectorFactoryMap: DaggerMap<Class<*>, AndroidInjector.Factory<*>>
25+
lateinit var injectorFactoryMap: DaggerMap<Class<*>, AndroidInjector.Factory<*, *>>
2626

27-
override fun daggerFactoryFor(key: Class<*>): AndroidInjector.Factory<*> {
27+
override fun daggerFactoryFor(key: Class<*>): AndroidInjector.Factory<*, *> {
2828
return injectorFactoryMap[key]
2929
?: throw RuntimeException(
3030
"""

vpn-internal/src/main/java/com/duckduckgo/vpn/internal/feature/logs/DebugLoggingReceiver.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ package com.duckduckgo.vpn.internal.feature.logs
1818

1919
import android.content.Context
2020
import android.content.Intent
21-
import com.duckduckgo.di.scopes.AppScope
21+
import com.duckduckgo.di.scopes.VpnScope
2222
import com.duckduckgo.mobile.android.vpn.service.VpnServiceCallbacks
2323
import com.duckduckgo.mobile.android.vpn.state.VpnStateMonitor.VpnStopReason
2424
import com.duckduckgo.vpn.internal.feature.InternalFeatureReceiver
@@ -59,7 +59,7 @@ class DebugLoggingReceiver(
5959
}
6060
}
6161

62-
@ContributesMultibinding(AppScope::class)
62+
@ContributesMultibinding(VpnScope::class)
6363
class DebugLoggingReceiverRegister @Inject constructor(
6464
private val context: Context
6565
) : VpnServiceCallbacks {

vpn-internal/src/main/java/com/duckduckgo/vpn/internal/feature/remote/VpnRemoteFeatureReceiver.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ package com.duckduckgo.vpn.internal.feature.remote
3535
import android.content.Context
3636
import android.content.Intent
3737
import com.duckduckgo.app.global.DispatcherProvider
38-
import com.duckduckgo.di.scopes.AppScope
38+
import com.duckduckgo.di.scopes.VpnScope
3939
import com.duckduckgo.mobile.android.vpn.feature.*
4040
import com.duckduckgo.mobile.android.vpn.service.VpnServiceCallbacks
4141
import com.duckduckgo.mobile.android.vpn.state.VpnStateMonitor.VpnStopReason
@@ -89,7 +89,7 @@ class VpnRemoteFeatureReceiver(
8989
}
9090
}
9191

92-
@ContributesMultibinding(AppScope::class)
92+
@ContributesMultibinding(VpnScope::class)
9393
class VpnRemoteFeatureReceiverRegister @Inject constructor(
9494
private val context: Context,
9595
private val appTpFeatureConfig: AppTpFeatureConfig,

vpn-internal/src/main/java/com/duckduckgo/vpn/internal/feature/rules/ExceptionRulesDebugReceiver.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ import android.content.BroadcastReceiver
2020
import android.content.Context
2121
import android.content.Intent
2222
import android.content.IntentFilter
23-
import com.duckduckgo.di.scopes.AppScope
23+
import com.duckduckgo.di.scopes.VpnScope
2424
import com.duckduckgo.mobile.android.vpn.service.VpnServiceCallbacks
2525
import com.duckduckgo.mobile.android.vpn.state.VpnStateMonitor.VpnStopReason
2626
import com.duckduckgo.mobile.android.vpn.trackers.AppTrackerExceptionRule
@@ -72,7 +72,7 @@ class ExceptionRulesDebugReceiver(
7272
}
7373
}
7474

75-
@ContributesMultibinding(AppScope::class)
75+
@ContributesMultibinding(VpnScope::class)
7676
class ExceptionRulesDebugReceiverRegister @Inject constructor(
7777
private val context: Context,
7878
private val exclusionRulesRepository: ExclusionRulesRepository,

vpn-internal/src/main/java/com/duckduckgo/vpn/internal/feature/trackers/DeleteTrackersDebugReceiver.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ package com.duckduckgo.vpn.internal.feature.trackers
1919
import android.content.Context
2020
import android.content.Intent
2121
import com.duckduckgo.app.di.AppCoroutineScope
22-
import com.duckduckgo.di.scopes.AppScope
22+
import com.duckduckgo.di.scopes.VpnScope
2323
import com.duckduckgo.mobile.android.vpn.service.VpnServiceCallbacks
2424
import com.duckduckgo.mobile.android.vpn.state.VpnStateMonitor.VpnStopReason
2525
import com.duckduckgo.mobile.android.vpn.store.VpnDatabase
@@ -50,7 +50,7 @@ class DeleteTrackersDebugReceiver(
5050
}
5151
}
5252

53-
@ContributesMultibinding(AppScope::class)
53+
@ContributesMultibinding(VpnScope::class)
5454
class DeleteTrackersDebugReceiverRegister @Inject constructor(
5555
private val context: Context,
5656
private val vpnDatabase: VpnDatabase,

0 commit comments

Comments
 (0)