Merge "[CS] Move LkscrnShadeTransitionCtlr to ShadeInteractor#isShadeEnabled." into udc-qpr-dev am: ed7bbe1fc3 am: 59ed13f73d

Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/23791305

Change-Id: I4582397bc6256ebcf267aa2c8b4d15b3b074c354
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Caitlin Shkuratov
2023-06-28 13:44:21 +00:00
committed by Automerger Merge Worker
9 changed files with 89 additions and 62 deletions

View File

@@ -17,38 +17,52 @@
package com.android.systemui.shade.domain.interactor
import com.android.systemui.dagger.SysUISingleton
import com.android.systemui.dagger.qualifiers.Application
import com.android.systemui.keyguard.data.repository.KeyguardRepository
import com.android.systemui.statusbar.disableflags.data.repository.DisableFlagsRepository
import com.android.systemui.statusbar.pipeline.mobile.data.repository.UserSetupRepository
import com.android.systemui.statusbar.policy.DeviceProvisionedController
import com.android.systemui.user.domain.interactor.UserInteractor
import javax.inject.Inject
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
/** Business logic for shade interactions. */
@SysUISingleton
class ShadeInteractor
@Inject
constructor(
@Application scope: CoroutineScope,
disableFlagsRepository: DisableFlagsRepository,
keyguardRepository: KeyguardRepository,
userSetupRepository: UserSetupRepository,
deviceProvisionedController: DeviceProvisionedController,
userInteractor: UserInteractor,
) {
/** Emits true if the shade is currently allowed and false otherwise. */
val isShadeEnabled: StateFlow<Boolean> =
disableFlagsRepository.disableFlags
.map { it.isShadeEnabled() }
.stateIn(scope, SharingStarted.Eagerly, initialValue = false)
/** Emits true if the shade can be expanded from QQS to QS and false otherwise. */
val isExpandToQsEnabled: Flow<Boolean> =
combine(
disableFlagsRepository.disableFlags,
isShadeEnabled,
keyguardRepository.isDozing,
userSetupRepository.isUserSetupFlow,
) { disableFlags, isDozing, isUserSetup ->
) { disableFlags, isShadeEnabled, isDozing, isUserSetup ->
deviceProvisionedController.isDeviceProvisioned &&
// Disallow QS during setup if it's a simple user switcher. (The user intends to
// use the lock screen user switcher, QS is not needed.)
(isUserSetup || !userInteractor.isSimpleUserSwitcher) &&
disableFlags.isShadeEnabled() &&
isShadeEnabled &&
disableFlags.isQuickSettingsEnabled() &&
!isDozing
}

View File

@@ -32,6 +32,7 @@ import com.android.systemui.plugins.statusbar.StatusBarStateController
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.shade.ShadeViewController
import com.android.systemui.shade.data.repository.ShadeRepository
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.notification.collection.NotificationEntry
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.ExpandableView
@@ -76,6 +77,7 @@ class LockscreenShadeTransitionController @Inject constructor(
dumpManager: DumpManager,
qsTransitionControllerFactory: LockscreenShadeQsTransitionController.Factory,
private val shadeRepository: ShadeRepository,
private val shadeInteractor: ShadeInteractor,
private val powerInteractor: PowerInteractor,
) : Dumpable {
private var pulseHeight: Float = 0f
@@ -558,7 +560,7 @@ class LockscreenShadeTransitionController @Inject constructor(
animationHandler: ((Long) -> Unit)? = null,
cancelAction: Runnable? = null
) {
if (centralSurfaces.isShadeDisabled) {
if (!shadeInteractor.isShadeEnabled.value) {
cancelAction?.run()
logger.logShadeDisabledOnGoToLockedShade()
return

View File

@@ -203,8 +203,6 @@ public interface CentralSurfaces extends Dumpable, LifecycleOwner {
int getStatusBarHeight();
boolean isShadeDisabled();
boolean isLaunchingActivityOverLockscreen();
void onKeyguardViewManagerStatesUpdated();
@@ -380,14 +378,6 @@ public interface CentralSurfaces extends Dumpable, LifecycleOwner {
void resendMessage(Object msg);
int getDisabled1();
void setDisabled1(int disabled);
int getDisabled2();
void setDisabled2(int disabled);
void setLastCameraLaunchSource(int source);
void setLaunchCameraOnFinishedGoingToSleep(boolean launch);

View File

@@ -111,6 +111,9 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba
private static final VibrationAttributes HARDWARE_FEEDBACK_VIBRATION_ATTRIBUTES =
VibrationAttributes.createForUsage(VibrationAttributes.USAGE_HARDWARE_FEEDBACK);
private int mDisabled1;
private int mDisabled2;
@Inject
CentralSurfacesCommandQueueCallbacks(
CentralSurfaces centralSurfaces,
@@ -256,22 +259,14 @@ public class CentralSurfacesCommandQueueCallbacks implements CommandQueue.Callba
return;
}
int state2BeforeAdjustment = state2;
state2 = mRemoteInputQuickSettingsDisabler.adjustDisableFlags(state2);
Log.d(CentralSurfaces.TAG,
mDisableFlagsLogger.getDisableFlagsString(
/* new= */ new DisableFlagsLogger.DisableState(
state1, state2BeforeAdjustment),
/* newStateAfterLocalModification= */ new DisableFlagsLogger.DisableState(
state1, state2)));
final int old1 = mCentralSurfaces.getDisabled1();
final int old1 = mDisabled1;
final int diff1 = state1 ^ old1;
mCentralSurfaces.setDisabled1(state1);
mDisabled1 = state1;
final int old2 = mCentralSurfaces.getDisabled2();
state2 = mRemoteInputQuickSettingsDisabler.adjustDisableFlags(state2);
final int old2 = mDisabled2;
final int diff2 = state2 ^ old2;
mCentralSurfaces.setDisabled2(state2);
mDisabled2 = state2;
if ((diff1 & StatusBarManager.DISABLE_EXPAND) != 0) {
if ((state1 & StatusBarManager.DISABLE_EXPAND) != 0) {

View File

@@ -361,26 +361,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
mMessageRouter.sendMessage(msg);
}
@Override
public int getDisabled1() {
return mDisabled1;
}
@Override
public void setDisabled1(int disabled) {
mDisabled1 = disabled;
}
@Override
public int getDisabled2() {
return mDisabled2;
}
@Override
public void setDisabled2(int disabled) {
mDisabled2 = disabled;
}
@Override
public void setLastCameraLaunchSource(int source) {
mLastCameraLaunchSource = source;
@@ -527,11 +507,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
private CentralSurfacesComponent mCentralSurfacesComponent;
// Flags for disabling the status bar
// Two variables because the first one evidently ran out of room for new flags.
private int mDisabled1 = 0;
private int mDisabled2 = 0;
/**
* This keeps track of whether we have (or haven't) registered the predictive back callback.
* Since we can have visible -> visible transitions, we need to avoid
@@ -1721,11 +1696,6 @@ public class CentralSurfacesImpl implements CoreStartable, CentralSurfaces {
return mStatusBarWindowController.getStatusBarHeight();
}
@Override
public boolean isShadeDisabled() {
return (mDisabled2 & StatusBarManager.DISABLE2_NOTIFICATION_SHADE) != 0;
}
private void updateReportRejectedTouchVisibility() {
if (mReportRejectedTouch == null) {
return;

View File

@@ -169,6 +169,7 @@ public class QuickSettingsControllerBaseTest extends SysuiTestCase {
when(mDeviceProvisionedController.isDeviceProvisioned()).thenReturn(true);
mShadeInteractor =
new ShadeInteractor(
mTestScope.getBackgroundScope(),
mDisableFlagsRepository,
mKeyguardRepository,
new FakeUserSetupRepository(),

View File

@@ -117,6 +117,7 @@ class ShadeInteractorTest : SysuiTestCase() {
)
underTest =
ShadeInteractor(
testScope.backgroundScope,
disableFlagsRepository,
keyguardRepository,
userSetupRepository,
@@ -125,6 +126,20 @@ class ShadeInteractorTest : SysuiTestCase() {
)
}
@Test
fun isShadeEnabled_matchesDisableFlagsRepo() =
testScope.runTest {
val actual by collectLastValue(underTest.isShadeEnabled)
disableFlagsRepository.disableFlags.value =
DisableFlagsModel(disable2 = DISABLE2_NOTIFICATION_SHADE)
assertThat(actual).isFalse()
disableFlagsRepository.disableFlags.value = DisableFlagsModel(disable2 = DISABLE2_NONE)
assertThat(actual).isTrue()
}
@Test
fun isExpandToQsEnabled_deviceNotProvisioned_false() =
testScope.runTest {

View File

@@ -1,5 +1,6 @@
package com.android.systemui.statusbar
import android.app.StatusBarManager.DISABLE2_NOTIFICATION_SHADE
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import android.testing.TestableLooper.RunWithLooper
@@ -11,6 +12,7 @@ import com.android.systemui.classifier.FalsingCollector
import com.android.systemui.classifier.FalsingCollectorFake
import com.android.systemui.dump.DumpManager
import com.android.systemui.keyguard.WakefulnessLifecycle
import com.android.systemui.keyguard.data.repository.FakeKeyguardRepository
import com.android.systemui.media.controls.ui.MediaHierarchyManager
import com.android.systemui.plugins.ActivityStarter
import com.android.systemui.plugins.FalsingManager
@@ -19,6 +21,9 @@ import com.android.systemui.power.data.repository.FakePowerRepository
import com.android.systemui.power.domain.interactor.PowerInteractor
import com.android.systemui.shade.ShadeViewController
import com.android.systemui.shade.data.repository.FakeShadeRepository
import com.android.systemui.shade.domain.interactor.ShadeInteractor
import com.android.systemui.statusbar.disableflags.data.model.DisableFlagsModel
import com.android.systemui.statusbar.disableflags.data.repository.FakeDisableFlagsRepository
import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow
import com.android.systemui.statusbar.notification.row.NotificationTestHelper
import com.android.systemui.statusbar.notification.stack.AmbientState
@@ -28,8 +33,13 @@ import com.android.systemui.statusbar.phone.CentralSurfaces
import com.android.systemui.statusbar.phone.KeyguardBypassController
import com.android.systemui.statusbar.phone.LSShadeTransitionLogger
import com.android.systemui.statusbar.phone.ScrimController
import com.android.systemui.statusbar.pipeline.mobile.data.repository.FakeUserSetupRepository
import com.android.systemui.statusbar.policy.FakeConfigurationController
import com.android.systemui.util.mockito.mock
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.test.StandardTestDispatcher
import kotlinx.coroutines.test.TestScope
import kotlinx.coroutines.test.runCurrent
import org.junit.After
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNotNull
@@ -60,8 +70,11 @@ private fun <T> anyObject(): T {
@SmallTest
@RunWithLooper(setAsMainLooper = true)
@RunWith(AndroidTestingRunner::class)
@OptIn(ExperimentalCoroutinesApi::class)
class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
private val testScope = TestScope(StandardTestDispatcher())
lateinit var transitionController: LockscreenShadeTransitionController
lateinit var row: ExpandableNotificationRow
@Mock lateinit var statusbarStateController: SysuiStatusBarStateController
@@ -87,6 +100,15 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
@Mock lateinit var qsTransitionController: LockscreenShadeQsTransitionController
@Mock lateinit var activityStarter: ActivityStarter
@Mock lateinit var transitionControllerCallback: LockscreenShadeTransitionController.Callback
private val disableFlagsRepository = FakeDisableFlagsRepository()
private val shadeInteractor = ShadeInteractor(
testScope.backgroundScope,
disableFlagsRepository,
keyguardRepository = FakeKeyguardRepository(),
userSetupRepository = FakeUserSetupRepository(),
deviceProvisionedController = mock(),
userInteractor = mock(),
)
private val powerInteractor = PowerInteractor(
FakePowerRepository(),
FalsingCollectorFake(),
@@ -99,6 +121,10 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
@Before
fun setup() {
// By default, have the shade enabled
disableFlagsRepository.disableFlags.value = DisableFlagsModel()
testScope.runCurrent()
val helper = NotificationTestHelper(
mContext,
mDependency,
@@ -139,6 +165,7 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
qsTransitionControllerFactory = { qsTransitionController },
activityStarter = activityStarter,
shadeRepository = FakeShadeRepository(),
shadeInteractor = shadeInteractor,
powerInteractor = powerInteractor,
)
transitionController.addCallback(transitionControllerCallback)
@@ -214,7 +241,10 @@ class LockscreenShadeTransitionControllerTest : SysuiTestCase() {
@Test
fun testDontGoWhenShadeDisabled() {
whenever(mCentralSurfaces.isShadeDisabled).thenReturn(true)
disableFlagsRepository.disableFlags.value = DisableFlagsModel(
disable2 = DISABLE2_NOTIFICATION_SHADE,
)
testScope.runCurrent()
transitionController.goToLockedShade(null)
verify(statusbarStateController, never()).setState(anyInt())
}

View File

@@ -20,6 +20,7 @@ import static android.view.Display.DEFAULT_DISPLAY;
import static org.mockito.ArgumentMatchers.anyInt;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyZeroInteractions;
import static org.mockito.Mockito.when;
@@ -144,23 +145,32 @@ public class CentralSurfacesCommandQueueCallbacksTest extends SysuiTestCase {
@Test
public void testDisableNotificationShade() {
when(mCentralSurfaces.getDisabled1()).thenReturn(StatusBarManager.DISABLE_NONE);
when(mCentralSurfaces.getDisabled2()).thenReturn(StatusBarManager.DISABLE_NONE);
// Start with nothing disabled
mSbcqCallbacks.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_NONE,
StatusBarManager.DISABLE2_NONE, false);
when(mCommandQueue.panelsEnabled()).thenReturn(false);
// WHEN the new disable flags have the shade disabled
mSbcqCallbacks.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_NONE,
StatusBarManager.DISABLE2_NOTIFICATION_SHADE, false);
// THEN the shade is collapsed
verify(mShadeController).animateCollapseShade();
}
@Test
public void testEnableNotificationShade() {
when(mCentralSurfaces.getDisabled1()).thenReturn(StatusBarManager.DISABLE_NONE);
when(mCentralSurfaces.getDisabled2())
.thenReturn(StatusBarManager.DISABLE2_NOTIFICATION_SHADE);
// Start with the shade disabled
mSbcqCallbacks.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_NONE,
StatusBarManager.DISABLE2_NOTIFICATION_SHADE, false);
reset(mShadeController);
when(mCommandQueue.panelsEnabled()).thenReturn(true);
// WHEN the new disable flags have the shade enabled
mSbcqCallbacks.disable(DEFAULT_DISPLAY, StatusBarManager.DISABLE_NONE,
StatusBarManager.DISABLE2_NONE, false);
// THEN the shade is not collapsed
verify(mShadeController, never()).animateCollapseShade();
}