Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 3d454fb1 authored by Chris Göllner's avatar Chris Göllner
Browse files

Prepare PrivacyDotViewController for multiple displays

- Split interface and impl
- Turn it into an @AssistedInject class

Test: Build
Test: N/A No behavior changes
Flag: EXEMPT no behavior changes
Bug: 362720432
Change-Id: Icb3c493b92e172253d79e8b568b46a73938722fe
parent 547b29d6
Loading
Loading
Loading
Loading
+3 −3
Original line number Diff line number Diff line
@@ -70,14 +70,14 @@ class PrivacyDotViewControllerTest : SysuiTestCase() {
        }

    private fun createController() =
        PrivacyDotViewController(
        PrivacyDotViewControllerImpl(
                executor,
                testScope.backgroundScope,
                statusBarStateController,
                configurationController,
                contentInsetsProvider,
                animationScheduler = mock<SystemStatusAnimationScheduler>(),
                shadeInteractor = null
                shadeInteractor = null,
            )
            .also { it.setUiExecutor(executor) }

@@ -307,7 +307,7 @@ class PrivacyDotViewControllerTest : SysuiTestCase() {
            newTopLeftView,
            newTopRightView,
            newBottomLeftView,
            newBottomRightView
            newBottomRightView,
        )

        assertThat((newBottomRightView.layoutParams as FrameLayout.LayoutParams).gravity)
+83 −35
Original line number Diff line number Diff line
@@ -44,8 +44,12 @@ import com.android.systemui.util.leak.RotationUtils.ROTATION_NONE
import com.android.systemui.util.leak.RotationUtils.ROTATION_SEASCAPE
import com.android.systemui.util.leak.RotationUtils.ROTATION_UPSIDE_DOWN
import com.android.systemui.util.leak.RotationUtils.Rotation
import dagger.Module
import dagger.Provides
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import java.util.concurrent.Executor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.launch

@@ -63,26 +67,57 @@ import kotlinx.coroutines.launch
 * NOTE: any operation that modifies views directly must run on the provided executor, because these
 * views are owned by ScreenDecorations and it runs in its own thread
 */
@SysUISingleton
open class PrivacyDotViewController
@Inject
interface PrivacyDotViewController {

    // Only can be modified on @UiThread
    var currentViewState: ViewState

    var showingListener: ShowingListener?

    fun setUiExecutor(e: DelayableExecutor)

    fun getUiExecutor(): DelayableExecutor?

    @UiThread fun setNewRotation(rot: Int)

    @UiThread fun hideDotView(dot: View, animate: Boolean)

    @UiThread fun showDotView(dot: View, animate: Boolean)

    // Update the gravity and margins of the privacy views
    @UiThread fun updateRotations(rotation: Int, paddingTop: Int)

    @UiThread fun setCornerSizes(state: ViewState)

    fun initialize(topLeft: View, topRight: View, bottomLeft: View, bottomRight: View)

    @UiThread fun updateDotView(state: ViewState)

    interface ShowingListener {
        fun onPrivacyDotShown(v: View?)

        fun onPrivacyDotHidden(v: View?)
    }
}

open class PrivacyDotViewControllerImpl
@AssistedInject
constructor(
    @Main private val mainExecutor: Executor,
    @Application scope: CoroutineScope,
    @Assisted scope: CoroutineScope,
    private val stateController: StatusBarStateController,
    private val configurationController: ConfigurationController,
    private val contentInsetsProvider: StatusBarContentInsetsProvider,
    @Assisted private val configurationController: ConfigurationController,
    @Assisted private val contentInsetsProvider: StatusBarContentInsetsProvider,
    private val animationScheduler: SystemStatusAnimationScheduler,
    shadeInteractor: ShadeInteractor?
) {
    shadeInteractor: ShadeInteractor?,
) : PrivacyDotViewController {
    private lateinit var tl: View
    private lateinit var tr: View
    private lateinit var bl: View
    private lateinit var br: View

    // Only can be modified on @UiThread
    var currentViewState: ViewState = ViewState()
        get() = field
    override var currentViewState: ViewState = ViewState()

    @GuardedBy("lock")
    private var nextViewState: ViewState = currentViewState.copy()
@@ -100,11 +135,7 @@ constructor(
    private val views: Sequence<View>
        get() = if (!this::tl.isInitialized) sequenceOf() else sequenceOf(tl, tr, br, bl)

    var showingListener: ShowingListener? = null
        set(value) {
            field = value
        }
        get() = field
    override var showingListener: PrivacyDotViewController.ShowingListener? = null

    init {
        contentInsetsProvider.addCallback(
@@ -153,16 +184,16 @@ constructor(
        }
    }

    fun setUiExecutor(e: DelayableExecutor) {
    override fun setUiExecutor(e: DelayableExecutor) {
        uiExecutor = e
    }

    fun getUiExecutor(): DelayableExecutor? {
    override fun getUiExecutor(): DelayableExecutor? {
        return uiExecutor
    }

    @UiThread
    fun setNewRotation(rot: Int) {
    override fun setNewRotation(rot: Int) {
        dlog("updateRotation: $rot")

        val isRtl: Boolean
@@ -187,13 +218,13 @@ constructor(
                    rotation = rot,
                    paddingTop = paddingTop,
                    designatedCorner = newCorner,
                    cornerIndex = index
                    cornerIndex = index,
                )
        }
    }

    @UiThread
    fun hideDotView(dot: View, animate: Boolean) {
    override fun hideDotView(dot: View, animate: Boolean) {
        dot.clearAnimation()
        if (animate) {
            dot.animate()
@@ -212,7 +243,7 @@ constructor(
    }

    @UiThread
    fun showDotView(dot: View, animate: Boolean) {
    override fun showDotView(dot: View, animate: Boolean) {
        dot.clearAnimation()
        if (animate) {
            dot.visibility = View.VISIBLE
@@ -229,9 +260,8 @@ constructor(
        showingListener?.onPrivacyDotShown(dot)
    }

    // Update the gravity and margins of the privacy views
    @UiThread
    open fun updateRotations(rotation: Int, paddingTop: Int) {
    override fun updateRotations(rotation: Int, paddingTop: Int) {
        // To keep a view in the corner, its gravity is always the description of its current corner
        // Therefore, just figure out which view is in which corner. This turns out to be something
        // like (myCorner - rot) mod 4, where topLeft = 0, topRight = 1, etc. and portrait = 0, and
@@ -262,7 +292,7 @@ constructor(
    }

    @UiThread
    open fun setCornerSizes(state: ViewState) {
    override fun setCornerSizes(state: ViewState) {
        // StatusBarContentInsetsProvider can tell us the location of the privacy indicator dot
        // in every rotation. The only thing we need to check is rtl
        val rtl = state.layoutRtl
@@ -415,7 +445,7 @@ constructor(
        }
    }

    fun initialize(topLeft: View, topRight: View, bottomLeft: View, bottomRight: View) {
    override fun initialize(topLeft: View, topRight: View, bottomLeft: View, bottomRight: View) {
        if (
            this::tl.isInitialized &&
                this::tr.isInitialized &&
@@ -457,7 +487,7 @@ constructor(
                    landscapeRect = right,
                    upsideDownRect = bottom,
                    paddingTop = paddingTop,
                    layoutRtl = rtl
                    layoutRtl = rtl,
                )
        }
    }
@@ -533,7 +563,7 @@ constructor(
    }

    @UiThread
    open fun updateDotView(state: ViewState) {
    override fun updateDotView(state: ViewState) {
        val shouldShow = state.shouldShowDot()
        if (shouldShow != currentViewState.shouldShowDot()) {
            if (shouldShow && state.designatedCorner != null) {
@@ -553,7 +583,7 @@ constructor(
                    nextViewState =
                        nextViewState.copy(
                            systemPrivacyEventIsActive = true,
                            contentDescription = contentDescr
                            contentDescription = contentDescr,
                        )
                }

@@ -595,15 +625,18 @@ constructor(
                    seascapeRect = rects[0],
                    portraitRect = rects[1],
                    landscapeRect = rects[2],
                    upsideDownRect = rects[3]
                    upsideDownRect = rects[3],
                )
        }
    }

    interface ShowingListener {
        fun onPrivacyDotShown(v: View?)

        fun onPrivacyDotHidden(v: View?)
    @AssistedFactory
    interface Factory {
        fun create(
            scope: CoroutineScope,
            configurationController: ConfigurationController,
            contentInsetsProvider: StatusBarContentInsetsProvider,
        ): PrivacyDotViewControllerImpl
    }
}

@@ -662,7 +695,7 @@ data class ViewState(
    val paddingTop: Int = 0,
    val cornerIndex: Int = -1,
    val designatedCorner: View? = null,
    val contentDescription: String? = null
    val contentDescription: String? = null,
) {
    fun shouldShowDot(): Boolean {
        return systemPrivacyEventIsActive && !shadeExpanded && !qsExpanded
@@ -687,3 +720,18 @@ data class ViewState(
        }
    }
}

@Module
object PrivacyDotViewControllerModule {

    @Provides
    @SysUISingleton
    fun controller(
        factory: PrivacyDotViewControllerImpl.Factory,
        @Application scope: CoroutineScope,
        configurationController: ConfigurationController,
        contentInsetsProvider: StatusBarContentInsetsProvider,
    ): PrivacyDotViewController {
        return factory.create(scope, configurationController, contentInsetsProvider)
    }
}
+2 −3
Original line number Diff line number Diff line
@@ -29,9 +29,8 @@ import dagger.assisted.AssistedInject

class ConfigurationControllerImpl
@AssistedInject
constructor(
    @Assisted private val context: Context,
) : ConfigurationController, StatusBarConfigurationController {
constructor(@Assisted private val context: Context) :
    ConfigurationController, StatusBarConfigurationController {

    private val listeners: MutableList<ConfigurationListener> = ArrayList()
    private val lastConfig = Configuration()
+2 −1
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ import com.android.systemui.statusbar.core.StatusBarInitializerStore
import com.android.systemui.statusbar.core.StatusBarOrchestrator
import com.android.systemui.statusbar.core.StatusBarSimpleFragment
import com.android.systemui.statusbar.data.repository.StatusBarModeRepositoryStore
import com.android.systemui.statusbar.events.PrivacyDotViewControllerModule
import com.android.systemui.statusbar.phone.CentralSurfacesCommandQueueCallbacks
import com.android.systemui.statusbar.window.StatusBarWindowControllerStore
import com.android.systemui.statusbar.window.data.repository.StatusBarWindowStateRepositoryStore
@@ -45,7 +46,7 @@ import dagger.multibindings.IntoMap
import kotlinx.coroutines.CoroutineScope

/** Similar in purpose to [StatusBarModule], but scoped only to phones */
@Module
@Module(includes = [PrivacyDotViewControllerModule::class])
interface StatusBarPhoneModule {

    @Binds
+1 −1
Original line number Diff line number Diff line
@@ -24,6 +24,6 @@ class FakeStatusBarWindowControllerFactory : StatusBarWindowController.Factory {
    override fun create(
        context: Context,
        viewCaptureAwareWindowManager: ViewCaptureAwareWindowManager,
        statusBarConfigurationController: StatusBarConfigurationController
        statusBarConfigurationController: StatusBarConfigurationController,
    ) = FakeStatusBarWindowController()
}