Merge "[Ongoing Call] Add an option to disable tapping the chip while in immersive mode." into sc-v2-dev
This commit is contained in:
committed by
Android (Google) Code Review
commit
6db6e348df
@@ -48,6 +48,8 @@
|
|||||||
|
|
||||||
<bool name="flag_ongoing_call_in_immersive">false</bool>
|
<bool name="flag_ongoing_call_in_immersive">false</bool>
|
||||||
|
|
||||||
|
<bool name="flag_ongoing_call_in_immersive_chip_tap">true</bool>
|
||||||
|
|
||||||
<bool name="flag_smartspace">false</bool>
|
<bool name="flag_smartspace">false</bool>
|
||||||
|
|
||||||
<bool name="flag_smartspace_deduping">true</bool>
|
<bool name="flag_smartspace_deduping">true</bool>
|
||||||
|
|||||||
@@ -166,6 +166,11 @@ public class FeatureFlags {
|
|||||||
&& mFlagReader.isEnabled(R.bool.flag_ongoing_call_in_immersive);
|
&& mFlagReader.isEnabled(R.bool.flag_ongoing_call_in_immersive);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean isOngoingCallInImmersiveChipTapEnabled() {
|
||||||
|
return isOngoingCallInImmersiveEnabled()
|
||||||
|
&& mFlagReader.isEnabled(R.bool.flag_ongoing_call_in_immersive_chip_tap);
|
||||||
|
}
|
||||||
|
|
||||||
public boolean isSmartspaceEnabled() {
|
public boolean isSmartspaceEnabled() {
|
||||||
return mFlagReader.isEnabled(R.bool.flag_smartspace);
|
return mFlagReader.isEnabled(R.bool.flag_smartspace);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -257,7 +257,8 @@ public interface StatusBarDependenciesModule {
|
|||||||
OngoingCallLogger logger,
|
OngoingCallLogger logger,
|
||||||
DumpManager dumpManager,
|
DumpManager dumpManager,
|
||||||
StatusBarWindowController statusBarWindowController,
|
StatusBarWindowController statusBarWindowController,
|
||||||
SwipeStatusBarAwayGestureHandler swipeStatusBarAwayGestureHandler) {
|
SwipeStatusBarAwayGestureHandler swipeStatusBarAwayGestureHandler,
|
||||||
|
StatusBarStateController statusBarStateController) {
|
||||||
Optional<StatusBarWindowController> windowController =
|
Optional<StatusBarWindowController> windowController =
|
||||||
featureFlags.isOngoingCallInImmersiveEnabled()
|
featureFlags.isOngoingCallInImmersiveEnabled()
|
||||||
? Optional.of(statusBarWindowController)
|
? Optional.of(statusBarWindowController)
|
||||||
@@ -277,8 +278,8 @@ public interface StatusBarDependenciesModule {
|
|||||||
logger,
|
logger,
|
||||||
dumpManager,
|
dumpManager,
|
||||||
windowController,
|
windowController,
|
||||||
gestureHandler
|
gestureHandler,
|
||||||
);
|
statusBarStateController);
|
||||||
ongoingCallController.init();
|
ongoingCallController.init();
|
||||||
return ongoingCallController;
|
return ongoingCallController;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ import com.android.systemui.dagger.qualifiers.Main
|
|||||||
import com.android.systemui.dump.DumpManager
|
import com.android.systemui.dump.DumpManager
|
||||||
import com.android.systemui.plugins.ActivityStarter
|
import com.android.systemui.plugins.ActivityStarter
|
||||||
import com.android.systemui.flags.FeatureFlags
|
import com.android.systemui.flags.FeatureFlags
|
||||||
|
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
||||||
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
|
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
|
||||||
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
|
import com.android.systemui.statusbar.notification.collection.notifcollection.NotifCollectionListener
|
||||||
@@ -61,8 +62,10 @@ class OngoingCallController @Inject constructor(
|
|||||||
private val dumpManager: DumpManager,
|
private val dumpManager: DumpManager,
|
||||||
private val statusBarWindowController: Optional<StatusBarWindowController>,
|
private val statusBarWindowController: Optional<StatusBarWindowController>,
|
||||||
private val swipeStatusBarAwayGestureHandler: Optional<SwipeStatusBarAwayGestureHandler>,
|
private val swipeStatusBarAwayGestureHandler: Optional<SwipeStatusBarAwayGestureHandler>,
|
||||||
|
private val statusBarStateController: StatusBarStateController,
|
||||||
) : CallbackController<OngoingCallListener>, Dumpable {
|
) : CallbackController<OngoingCallListener>, Dumpable {
|
||||||
|
|
||||||
|
private var isFullscreen: Boolean = false
|
||||||
/** Non-null if there's an active call notification. */
|
/** Non-null if there's an active call notification. */
|
||||||
private var callNotificationInfo: CallNotificationInfo? = null
|
private var callNotificationInfo: CallNotificationInfo? = null
|
||||||
/** True if the application managing the call is visible to the user. */
|
/** True if the application managing the call is visible to the user. */
|
||||||
@@ -124,6 +127,7 @@ class OngoingCallController @Inject constructor(
|
|||||||
dumpManager.registerDumpable(this)
|
dumpManager.registerDumpable(this)
|
||||||
if (featureFlags.isOngoingCallStatusBarChipEnabled) {
|
if (featureFlags.isOngoingCallStatusBarChipEnabled) {
|
||||||
notifCollection.addCollectionListener(notifListener)
|
notifCollection.addCollectionListener(notifListener)
|
||||||
|
statusBarStateController.addCallback(statusBarStateListener)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -177,10 +181,8 @@ class OngoingCallController @Inject constructor(
|
|||||||
|
|
||||||
val currentChipView = chipView
|
val currentChipView = chipView
|
||||||
val timeView = currentChipView?.getTimeView()
|
val timeView = currentChipView?.getTimeView()
|
||||||
val backgroundView =
|
|
||||||
currentChipView?.findViewById<View>(R.id.ongoing_call_chip_background)
|
|
||||||
|
|
||||||
if (currentChipView != null && timeView != null && backgroundView != null) {
|
if (currentChipView != null && timeView != null) {
|
||||||
if (currentCallNotificationInfo.hasValidStartTime()) {
|
if (currentCallNotificationInfo.hasValidStartTime()) {
|
||||||
timeView.setShouldHideText(false)
|
timeView.setShouldHideText(false)
|
||||||
timeView.base = currentCallNotificationInfo.callStartTime -
|
timeView.base = currentCallNotificationInfo.callStartTime -
|
||||||
@@ -191,19 +193,8 @@ class OngoingCallController @Inject constructor(
|
|||||||
timeView.setShouldHideText(true)
|
timeView.setShouldHideText(true)
|
||||||
timeView.stop()
|
timeView.stop()
|
||||||
}
|
}
|
||||||
|
updateChipClickListener()
|
||||||
|
|
||||||
currentCallNotificationInfo.intent?.let { intent ->
|
|
||||||
currentChipView.setOnClickListener {
|
|
||||||
logger.logChipClicked()
|
|
||||||
activityStarter.postStartActivityDismissingKeyguard(
|
|
||||||
intent,
|
|
||||||
0,
|
|
||||||
ActivityLaunchAnimator.Controller.fromView(
|
|
||||||
backgroundView,
|
|
||||||
InteractionJankMonitor.CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
setUpUidObserver(currentCallNotificationInfo)
|
setUpUidObserver(currentCallNotificationInfo)
|
||||||
if (!currentCallNotificationInfo.statusBarSwipedAway) {
|
if (!currentCallNotificationInfo.statusBarSwipedAway) {
|
||||||
statusBarWindowController.ifPresent {
|
statusBarWindowController.ifPresent {
|
||||||
@@ -227,6 +218,30 @@ class OngoingCallController @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun updateChipClickListener() {
|
||||||
|
if (callNotificationInfo == null) { return }
|
||||||
|
if (isFullscreen && !featureFlags.isOngoingCallInImmersiveChipTapEnabled) {
|
||||||
|
chipView?.setOnClickListener(null)
|
||||||
|
} else {
|
||||||
|
val currentChipView = chipView
|
||||||
|
val backgroundView =
|
||||||
|
currentChipView?.findViewById<View>(R.id.ongoing_call_chip_background)
|
||||||
|
val intent = callNotificationInfo?.intent
|
||||||
|
if (currentChipView != null && backgroundView != null && intent != null) {
|
||||||
|
currentChipView.setOnClickListener {
|
||||||
|
logger.logChipClicked()
|
||||||
|
activityStarter.postStartActivityDismissingKeyguard(
|
||||||
|
intent,
|
||||||
|
0,
|
||||||
|
ActivityLaunchAnimator.Controller.fromView(
|
||||||
|
backgroundView,
|
||||||
|
InteractionJankMonitor.CUJ_STATUS_BAR_APP_LAUNCH_FROM_CALL_CHIP)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets up an [IUidObserver] to monitor the status of the application managing the ongoing call.
|
* Sets up an [IUidObserver] to monitor the status of the application managing the ongoing call.
|
||||||
*/
|
*/
|
||||||
@@ -315,6 +330,13 @@ class OngoingCallController @Inject constructor(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private val statusBarStateListener = object : StatusBarStateController.StateListener {
|
||||||
|
override fun onFullscreenStateChanged(isFullscreen: Boolean) {
|
||||||
|
this@OngoingCallController.isFullscreen = isFullscreen
|
||||||
|
updateChipClickListener()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private data class CallNotificationInfo(
|
private data class CallNotificationInfo(
|
||||||
val key: String,
|
val key: String,
|
||||||
val callStartTime: Long,
|
val callStartTime: Long,
|
||||||
|
|||||||
@@ -36,6 +36,7 @@ import com.android.systemui.SysuiTestCase
|
|||||||
import com.android.systemui.dump.DumpManager
|
import com.android.systemui.dump.DumpManager
|
||||||
import com.android.systemui.plugins.ActivityStarter
|
import com.android.systemui.plugins.ActivityStarter
|
||||||
import com.android.systemui.flags.FeatureFlags
|
import com.android.systemui.flags.FeatureFlags
|
||||||
|
import com.android.systemui.plugins.statusbar.StatusBarStateController
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
import com.android.systemui.statusbar.notification.collection.NotificationEntry
|
||||||
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
|
import com.android.systemui.statusbar.notification.collection.NotificationEntryBuilder
|
||||||
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
|
import com.android.systemui.statusbar.notification.collection.notifcollection.CommonNotifCollection
|
||||||
@@ -82,11 +83,13 @@ class OngoingCallControllerTest : SysuiTestCase() {
|
|||||||
private lateinit var controller: OngoingCallController
|
private lateinit var controller: OngoingCallController
|
||||||
private lateinit var notifCollectionListener: NotifCollectionListener
|
private lateinit var notifCollectionListener: NotifCollectionListener
|
||||||
|
|
||||||
|
@Mock private lateinit var mockFeatureFlags: FeatureFlags
|
||||||
@Mock private lateinit var mockSwipeStatusBarAwayGestureHandler: SwipeStatusBarAwayGestureHandler
|
@Mock private lateinit var mockSwipeStatusBarAwayGestureHandler: SwipeStatusBarAwayGestureHandler
|
||||||
@Mock private lateinit var mockOngoingCallListener: OngoingCallListener
|
@Mock private lateinit var mockOngoingCallListener: OngoingCallListener
|
||||||
@Mock private lateinit var mockActivityStarter: ActivityStarter
|
@Mock private lateinit var mockActivityStarter: ActivityStarter
|
||||||
@Mock private lateinit var mockIActivityManager: IActivityManager
|
@Mock private lateinit var mockIActivityManager: IActivityManager
|
||||||
@Mock private lateinit var mockStatusBarWindowController: StatusBarWindowController
|
@Mock private lateinit var mockStatusBarWindowController: StatusBarWindowController
|
||||||
|
@Mock private lateinit var mockStatusBarStateController: StatusBarStateController
|
||||||
|
|
||||||
private lateinit var chipView: View
|
private lateinit var chipView: View
|
||||||
|
|
||||||
@@ -98,13 +101,12 @@ class OngoingCallControllerTest : SysuiTestCase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
MockitoAnnotations.initMocks(this)
|
MockitoAnnotations.initMocks(this)
|
||||||
val featureFlags = mock(FeatureFlags::class.java)
|
`when`(mockFeatureFlags.isOngoingCallStatusBarChipEnabled).thenReturn(true)
|
||||||
`when`(featureFlags.isOngoingCallStatusBarChipEnabled).thenReturn(true)
|
|
||||||
val notificationCollection = mock(CommonNotifCollection::class.java)
|
val notificationCollection = mock(CommonNotifCollection::class.java)
|
||||||
|
|
||||||
controller = OngoingCallController(
|
controller = OngoingCallController(
|
||||||
notificationCollection,
|
notificationCollection,
|
||||||
featureFlags,
|
mockFeatureFlags,
|
||||||
clock,
|
clock,
|
||||||
mockActivityStarter,
|
mockActivityStarter,
|
||||||
mainExecutor,
|
mainExecutor,
|
||||||
@@ -113,6 +115,7 @@ class OngoingCallControllerTest : SysuiTestCase() {
|
|||||||
DumpManager(),
|
DumpManager(),
|
||||||
Optional.of(mockStatusBarWindowController),
|
Optional.of(mockStatusBarWindowController),
|
||||||
Optional.of(mockSwipeStatusBarAwayGestureHandler),
|
Optional.of(mockSwipeStatusBarAwayGestureHandler),
|
||||||
|
mockStatusBarStateController,
|
||||||
)
|
)
|
||||||
controller.init()
|
controller.init()
|
||||||
controller.addCallback(mockOngoingCallListener)
|
controller.addCallback(mockOngoingCallListener)
|
||||||
@@ -455,6 +458,56 @@ class OngoingCallControllerTest : SysuiTestCase() {
|
|||||||
// Other tests for notifyChipVisibilityChanged are in [OngoingCallLogger], since
|
// Other tests for notifyChipVisibilityChanged are in [OngoingCallLogger], since
|
||||||
// [OngoingCallController.notifyChipVisibilityChanged] just delegates to that class.
|
// [OngoingCallController.notifyChipVisibilityChanged] just delegates to that class.
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun callNotificationAdded_chipIsClickable() {
|
||||||
|
notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
|
||||||
|
|
||||||
|
assertThat(chipView.hasOnClickListeners()).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun fullscreenIsTrue_thenCallNotificationAdded_chipNotClickable() {
|
||||||
|
`when`(mockFeatureFlags.isOngoingCallInImmersiveChipTapEnabled).thenReturn(false)
|
||||||
|
|
||||||
|
getStateListener().onFullscreenStateChanged(/* isFullscreen= */ true)
|
||||||
|
notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
|
||||||
|
|
||||||
|
assertThat(chipView.hasOnClickListeners()).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun callNotificationAdded_thenFullscreenIsTrue_chipNotClickable() {
|
||||||
|
`when`(mockFeatureFlags.isOngoingCallInImmersiveChipTapEnabled).thenReturn(false)
|
||||||
|
|
||||||
|
notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
|
||||||
|
getStateListener().onFullscreenStateChanged(/* isFullscreen= */ true)
|
||||||
|
|
||||||
|
assertThat(chipView.hasOnClickListeners()).isFalse()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun fullscreenChangesToFalse_chipClickable() {
|
||||||
|
`when`(mockFeatureFlags.isOngoingCallInImmersiveChipTapEnabled).thenReturn(false)
|
||||||
|
|
||||||
|
notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
|
||||||
|
// First, update to true
|
||||||
|
getStateListener().onFullscreenStateChanged(/* isFullscreen= */ true)
|
||||||
|
// Then, update to false
|
||||||
|
getStateListener().onFullscreenStateChanged(/* isFullscreen= */ false)
|
||||||
|
|
||||||
|
assertThat(chipView.hasOnClickListeners()).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun fullscreenIsTrue_butChipClickInImmersiveEnabled_chipClickable() {
|
||||||
|
`when`(mockFeatureFlags.isOngoingCallInImmersiveChipTapEnabled).thenReturn(true)
|
||||||
|
|
||||||
|
notifCollectionListener.onEntryUpdated(createOngoingCallNotifEntry())
|
||||||
|
getStateListener().onFullscreenStateChanged(/* isFullscreen= */ true)
|
||||||
|
|
||||||
|
assertThat(chipView.hasOnClickListeners()).isTrue()
|
||||||
|
}
|
||||||
|
|
||||||
private fun createOngoingCallNotifEntry() = createCallNotifEntry(ongoingCallStyle)
|
private fun createOngoingCallNotifEntry() = createCallNotifEntry(ongoingCallStyle)
|
||||||
|
|
||||||
private fun createScreeningCallNotifEntry() = createCallNotifEntry(screeningCallStyle)
|
private fun createScreeningCallNotifEntry() = createCallNotifEntry(screeningCallStyle)
|
||||||
@@ -479,6 +532,13 @@ class OngoingCallControllerTest : SysuiTestCase() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun createNotCallNotifEntry() = NotificationEntryBuilder().build()
|
private fun createNotCallNotifEntry() = NotificationEntryBuilder().build()
|
||||||
|
|
||||||
|
private fun getStateListener(): StatusBarStateController.StateListener {
|
||||||
|
val statusBarStateListenerCaptor = ArgumentCaptor.forClass(
|
||||||
|
StatusBarStateController.StateListener::class.java)
|
||||||
|
verify(mockStatusBarStateController).addCallback(statusBarStateListenerCaptor.capture())
|
||||||
|
return statusBarStateListenerCaptor.value!!
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private val person = Person.Builder().setName("name").build()
|
private val person = Person.Builder().setName("name").build()
|
||||||
|
|||||||
Reference in New Issue
Block a user