Loading packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/events/PrivacyDotViewControllerTest.kt +3 −3 Original line number Diff line number Diff line Loading @@ -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) } Loading Loading @@ -307,7 +307,7 @@ class PrivacyDotViewControllerTest : SysuiTestCase() { newTopLeftView, newTopRightView, newBottomLeftView, newBottomRightView newBottomRightView, ) assertThat((newBottomRightView.layoutParams as FrameLayout.LayoutParams).gravity) Loading packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt +83 −35 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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() Loading @@ -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( Loading Loading @@ -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 Loading @@ -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() Loading @@ -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 Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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 && Loading Loading @@ -457,7 +487,7 @@ constructor( landscapeRect = right, upsideDownRect = bottom, paddingTop = paddingTop, layoutRtl = rtl layoutRtl = rtl, ) } } Loading Loading @@ -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) { Loading @@ -553,7 +583,7 @@ constructor( nextViewState = nextViewState.copy( systemPrivacyEventIsActive = true, contentDescription = contentDescr contentDescription = contentDescr, ) } Loading Loading @@ -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 } } Loading Loading @@ -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 Loading @@ -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) } } packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt +2 −3 Original line number Diff line number Diff line Loading @@ -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() Loading packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.kt +2 −1 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/window/FakeStatusBarWindowControllerFactory.kt +1 −1 Original line number Diff line number Diff line Loading @@ -24,6 +24,6 @@ class FakeStatusBarWindowControllerFactory : StatusBarWindowController.Factory { override fun create( context: Context, viewCaptureAwareWindowManager: ViewCaptureAwareWindowManager, statusBarConfigurationController: StatusBarConfigurationController statusBarConfigurationController: StatusBarConfigurationController, ) = FakeStatusBarWindowController() } Loading
packages/SystemUI/multivalentTests/src/com/android/systemui/statusbar/events/PrivacyDotViewControllerTest.kt +3 −3 Original line number Diff line number Diff line Loading @@ -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) } Loading Loading @@ -307,7 +307,7 @@ class PrivacyDotViewControllerTest : SysuiTestCase() { newTopLeftView, newTopRightView, newBottomLeftView, newBottomRightView newBottomRightView, ) assertThat((newBottomRightView.layoutParams as FrameLayout.LayoutParams).gravity) Loading
packages/SystemUI/src/com/android/systemui/statusbar/events/PrivacyDotViewController.kt +83 −35 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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() Loading @@ -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( Loading Loading @@ -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 Loading @@ -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() Loading @@ -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 Loading @@ -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 Loading Loading @@ -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 Loading Loading @@ -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 && Loading Loading @@ -457,7 +487,7 @@ constructor( landscapeRect = right, upsideDownRect = bottom, paddingTop = paddingTop, layoutRtl = rtl layoutRtl = rtl, ) } } Loading Loading @@ -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) { Loading @@ -553,7 +583,7 @@ constructor( nextViewState = nextViewState.copy( systemPrivacyEventIsActive = true, contentDescription = contentDescr contentDescription = contentDescr, ) } Loading Loading @@ -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 } } Loading Loading @@ -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 Loading @@ -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) } }
packages/SystemUI/src/com/android/systemui/statusbar/phone/ConfigurationControllerImpl.kt +2 −3 Original line number Diff line number Diff line Loading @@ -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() Loading
packages/SystemUI/src/com/android/systemui/statusbar/phone/dagger/StatusBarPhoneModule.kt +2 −1 Original line number Diff line number Diff line Loading @@ -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 Loading @@ -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 Loading
packages/SystemUI/tests/utils/src/com/android/systemui/statusbar/window/FakeStatusBarWindowControllerFactory.kt +1 −1 Original line number Diff line number Diff line Loading @@ -24,6 +24,6 @@ class FakeStatusBarWindowControllerFactory : StatusBarWindowController.Factory { override fun create( context: Context, viewCaptureAwareWindowManager: ViewCaptureAwareWindowManager, statusBarConfigurationController: StatusBarConfigurationController statusBarConfigurationController: StatusBarConfigurationController, ) = FakeStatusBarWindowController() }