Replace verbose @Provider with a private @Binds

The original version of the dagger code used a Provider so that the
private SensitiveContentCoordinatorImpl class was not exposed as part of
the public API signature (which would cause a compilation error).

This change utilizes a quirk with Dagger Module "includes" where you are
able to include a private Module inside of a public one. This private
module is able to use the symbols private to the Kotlin file (in this
case, SensitiveContentCoordinatorImpl).

The downside here is that the tests have become slightly more verbose.

Test: atest SensitiveContentCoordinatorTest
Change-Id: I06d87e68e5b40f432bc39d1015b54c03f141fc4d
This commit is contained in:
Steve Elliott
2022-02-10 11:27:03 -05:00
parent badac481dc
commit 3c56125692
4 changed files with 75 additions and 32 deletions

View File

@@ -21,8 +21,9 @@ import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.util.ListenerSet
import com.android.systemui.util.concurrency.DelayableExecutor
import dagger.Binds
import dagger.Module
import dagger.Provides
import javax.inject.Inject
/**
* Choreographs evaluation resulting from multiple asynchronous sources. Specifically, it exposes
@@ -46,22 +47,21 @@ interface NotifPipelineChoreographer {
fun removeOnEvalListener(onEvalListener: Runnable)
}
@Module(includes = [PrivateModule::class])
object NotifPipelineChoreographerModule
@Module
object NotifPipelineChoreographerModule {
@Provides
@JvmStatic
@SysUISingleton
fun provideChoreographer(
choreographer: Choreographer,
@Main mainExecutor: DelayableExecutor
): NotifPipelineChoreographer = NotifPipelineChoreographerImpl(choreographer, mainExecutor)
private interface PrivateModule {
@Binds
fun bindChoreographer(impl: NotifPipelineChoreographerImpl): NotifPipelineChoreographer
}
private const val TIMEOUT_MS: Long = 100
private class NotifPipelineChoreographerImpl(
@SysUISingleton
private class NotifPipelineChoreographerImpl @Inject constructor(
private val viewChoreographer: Choreographer,
private val executor: DelayableExecutor
@Main private val executor: DelayableExecutor
) : NotifPipelineChoreographer {
private val listeners = ListenerSet<Runnable>()

View File

@@ -30,29 +30,24 @@ import com.android.systemui.statusbar.notification.collection.coordinator.dagger
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator
import com.android.systemui.statusbar.policy.KeyguardStateController
import dagger.Binds
import dagger.Module
import dagger.Provides
import javax.inject.Inject
@Module(includes = [PrivateModule::class])
interface SensitiveContentCoordinatorModule
@Module
object SensitiveContentCoordinatorModule {
@Provides
@JvmStatic
@CoordinatorScope
fun provideCoordinator(
dynamicPrivacyController: DynamicPrivacyController,
lockscreenUserManager: NotificationLockscreenUserManager,
keyguardUpdateMonitor: KeyguardUpdateMonitor,
statusBarStateController: StatusBarStateController,
keyguardStateController: KeyguardStateController
): SensitiveContentCoordinator =
SensitiveContentCoordinatorImpl(dynamicPrivacyController, lockscreenUserManager,
keyguardUpdateMonitor, statusBarStateController, keyguardStateController)
private interface PrivateModule {
@Binds
fun bindCoordinator(impl: SensitiveContentCoordinatorImpl): SensitiveContentCoordinator
}
/** Coordinates re-inflation and post-processing of sensitive notification content. */
interface SensitiveContentCoordinator : Coordinator
private class SensitiveContentCoordinatorImpl(
@CoordinatorScope
private class SensitiveContentCoordinatorImpl @Inject constructor(
private val dynamicPrivacyController: DynamicPrivacyController,
private val lockscreenUserManager: NotificationLockscreenUserManager,
private val keyguardUpdateMonitor: KeyguardUpdateMonitor,

View File

@@ -20,10 +20,14 @@ import android.testing.AndroidTestingRunner
import android.view.Choreographer
import androidx.test.filters.SmallTest
import com.android.systemui.SysuiTestCase
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Main
import com.android.systemui.util.concurrency.DelayableExecutor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.withArgCaptor
import dagger.BindsInstance
import dagger.Component
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.RunWith
@@ -41,8 +45,10 @@ class NotifPipelineChoreographerTest : SysuiTestCase() {
whenever(it.executeDelayed(any(), anyLong())).thenReturn(timeoueSubscription)
}
val pipelineChoreographer: NotifPipelineChoreographer = NotifPipelineChoreographerModule
.provideChoreographer(viewChoreographer, executor)
val pipelineChoreographer: NotifPipelineChoreographer =
DaggerNotifPipelineChoreographerTestComponent.factory()
.create(viewChoreographer, executor)
.choreographer
@Test
fun scheduleThenEvalFrameCallback() {
@@ -97,4 +103,19 @@ class NotifPipelineChoreographerTest : SysuiTestCase() {
verify(viewChoreographer).removeFrameCallback(frameCallback)
verify(timeoueSubscription).run()
}
}
@SysUISingleton
@Component(modules = [NotifPipelineChoreographerModule::class])
interface NotifPipelineChoreographerTestComponent {
val choreographer: NotifPipelineChoreographer
@Component.Factory
interface Factory {
fun create(
@BindsInstance viewChoreographer: Choreographer,
@BindsInstance @Main executor: DelayableExecutor
): NotifPipelineChoreographerTestComponent
}
}

View File

@@ -28,13 +28,16 @@ import com.android.systemui.statusbar.notification.DynamicPrivacyController
import com.android.systemui.statusbar.notification.collection.ListEntry
import com.android.systemui.statusbar.notification.collection.NotifPipeline
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.collection.coordinator.dagger.CoordinatorScope
import com.android.systemui.statusbar.notification.collection.listbuilder.OnBeforeRenderListListener
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Invalidator
import com.android.systemui.statusbar.notification.collection.listbuilder.pluggable.Pluggable
import com.android.systemui.statusbar.policy.KeyguardStateController
import com.android.systemui.util.mockito.withArgCaptor
import com.android.systemui.util.mockito.any
import com.android.systemui.util.mockito.mock
import com.android.systemui.util.mockito.withArgCaptor
import dagger.BindsInstance
import dagger.Component
import org.junit.Test
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
@@ -50,9 +53,16 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() {
val statusBarStateController: StatusBarStateController = mock()
val keyguardStateController: KeyguardStateController = mock()
val coordinator: SensitiveContentCoordinator = SensitiveContentCoordinatorModule
.provideCoordinator(dynamicPrivacyController, lockscreenUserManager,
keyguardUpdateMonitor, statusBarStateController, keyguardStateController)
val coordinator: SensitiveContentCoordinator =
DaggerTestSensitiveContentCoordinatorComponent
.factory()
.create(
dynamicPrivacyController,
lockscreenUserManager,
keyguardUpdateMonitor,
statusBarStateController,
keyguardStateController)
.coordinator
@Test
fun onDynamicPrivacyChanged_invokeInvalidationListener() {
@@ -238,4 +248,21 @@ class SensitiveContentCoordinatorTest : SysuiTestCase() {
override fun getRepresentativeEntry(): NotificationEntry = mockEntry
}
}
}
@CoordinatorScope
@Component(modules = [SensitiveContentCoordinatorModule::class])
interface TestSensitiveContentCoordinatorComponent {
val coordinator: SensitiveContentCoordinator
@Component.Factory
interface Factory {
fun create(
@BindsInstance dynamicPrivacyController: DynamicPrivacyController,
@BindsInstance lockscreenUserManager: NotificationLockscreenUserManager,
@BindsInstance keyguardUpdateMonitor: KeyguardUpdateMonitor,
@BindsInstance statusBarStateController: StatusBarStateController,
@BindsInstance keyguardStateController: KeyguardStateController
): TestSensitiveContentCoordinatorComponent
}
}