Tapping dream media chip opens media instead of UMO if flag is set.

Bug: 242613318
Test: manual
Test: atest DreamMediaEntryComplicationTest
Test: atest MediaCarouselControllerTest
Test: atest MediaDreamSentinelTest
Change-Id: I94ad877e8042b7969eab92ad988fba7a0f62eab4
This commit is contained in:
Xiaowen Lei
2022-09-14 20:09:42 +00:00
parent bb103d52d6
commit 49eed100b4
7 changed files with 238 additions and 12 deletions

View File

@@ -18,13 +18,21 @@ package com.android.systemui.dreams.complication;
import static com.android.systemui.dreams.complication.dagger.DreamMediaEntryComplicationComponent.DreamMediaEntryModule.DREAM_MEDIA_ENTRY_VIEW;
import static com.android.systemui.dreams.complication.dagger.RegisteredComplicationsModule.DREAM_MEDIA_ENTRY_LAYOUT_PARAMS;
import static com.android.systemui.flags.Flags.DREAM_MEDIA_TAP_TO_OPEN;
import android.app.PendingIntent;
import android.util.Log;
import android.view.View;
import com.android.systemui.ActivityIntentHelper;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dreams.complication.dagger.DreamMediaEntryComplicationComponent;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.media.MediaCarouselController;
import com.android.systemui.media.dream.MediaDreamComplication;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import com.android.systemui.util.ViewController;
import javax.inject.Inject;
@@ -87,6 +95,15 @@ public class DreamMediaEntryComplication implements Complication {
private final DreamOverlayStateController mDreamOverlayStateController;
private final MediaDreamComplication mMediaComplication;
private final MediaCarouselController mMediaCarouselController;
private final ActivityStarter mActivityStarter;
private final ActivityIntentHelper mActivityIntentHelper;
private final KeyguardStateController mKeyguardStateController;
private final NotificationLockscreenUserManager mLockscreenUserManager;
private final FeatureFlags mFeatureFlags;
private boolean mIsTapToOpenEnabled;
private boolean mMediaComplicationAdded;
@@ -94,15 +111,28 @@ public class DreamMediaEntryComplication implements Complication {
DreamMediaEntryViewController(
@Named(DREAM_MEDIA_ENTRY_VIEW) View view,
DreamOverlayStateController dreamOverlayStateController,
MediaDreamComplication mediaComplication) {
MediaDreamComplication mediaComplication,
MediaCarouselController mediaCarouselController,
ActivityStarter activityStarter,
ActivityIntentHelper activityIntentHelper,
KeyguardStateController keyguardStateController,
NotificationLockscreenUserManager lockscreenUserManager,
FeatureFlags featureFlags) {
super(view);
mDreamOverlayStateController = dreamOverlayStateController;
mMediaComplication = mediaComplication;
mMediaCarouselController = mediaCarouselController;
mActivityStarter = activityStarter;
mActivityIntentHelper = activityIntentHelper;
mKeyguardStateController = keyguardStateController;
mLockscreenUserManager = lockscreenUserManager;
mFeatureFlags = featureFlags;
mView.setOnClickListener(this::onClickMediaEntry);
}
@Override
protected void onViewAttached() {
mIsTapToOpenEnabled = mFeatureFlags.isEnabled(DREAM_MEDIA_TAP_TO_OPEN);
}
@Override
@@ -113,6 +143,31 @@ public class DreamMediaEntryComplication implements Complication {
private void onClickMediaEntry(View v) {
if (DEBUG) Log.d(TAG, "media entry complication tapped");
if (mIsTapToOpenEnabled) {
final PendingIntent clickIntent =
mMediaCarouselController.getCurrentVisibleMediaContentIntent();
if (clickIntent == null) {
return;
}
// See StatusBarNotificationActivityStarter#onNotificationClicked
final boolean showOverLockscreen = mKeyguardStateController.isShowing()
&& mActivityIntentHelper.wouldShowOverLockscreen(clickIntent.getIntent(),
mLockscreenUserManager.getCurrentUserId());
if (showOverLockscreen) {
mActivityStarter.startActivity(clickIntent.getIntent(),
/* dismissShade */ true,
/* animationController */ null,
/* showOverLockscreenWhenLocked */ true);
} else {
mActivityStarter.postStartActivityDismissingKeyguard(clickIntent, null);
}
return;
}
if (!mMediaComplicationAdded) {
addMediaComplication();
} else {

View File

@@ -196,7 +196,8 @@ public class Flags {
public static final UnreleasedFlag MEDIA_SESSION_ACTIONS = new UnreleasedFlag(901);
public static final ReleasedFlag MEDIA_NEARBY_DEVICES = new ReleasedFlag(903);
public static final ReleasedFlag MEDIA_MUTE_AWAIT = new ReleasedFlag(904);
public static final UnreleasedFlag MEDIA_DREAM_COMPLICATION = new UnreleasedFlag(905);
public static final UnreleasedFlag DREAM_MEDIA_COMPLICATION = new UnreleasedFlag(905);
public static final UnreleasedFlag DREAM_MEDIA_TAP_TO_OPEN = new UnreleasedFlag(906);
// 1000 - dock
public static final ReleasedFlag SIMULATE_DOCK_THROUGH_CHARGING =

View File

@@ -1,5 +1,6 @@
package com.android.systemui.media
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.content.res.ColorStateList
@@ -945,6 +946,11 @@ class MediaCarouselController @Inject constructor(
mediaManager.onSwipeToDismiss()
}
fun getCurrentVisibleMediaContentIntent(): PendingIntent? {
return MediaPlayerData.playerKeys()
.elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex)?.data?.clickIntent
}
override fun dump(pw: PrintWriter, args: Array<out String>) {
pw.apply {
println("keysNeedRemoval: $keysNeedRemoval")

View File

@@ -16,7 +16,7 @@
package com.android.systemui.media.dream;
import static com.android.systemui.flags.Flags.MEDIA_DREAM_COMPLICATION;
import static com.android.systemui.flags.Flags.DREAM_MEDIA_COMPLICATION;
import android.content.Context;
import android.util.Log;
@@ -77,7 +77,7 @@ public class MediaDreamSentinel extends CoreStartable {
public void onMediaDataLoaded(@NonNull String key, @Nullable String oldKey,
@NonNull MediaData data, boolean immediately, int receivedSmartspaceCardLatency,
boolean isSsReactivated) {
if (!mFeatureFlags.isEnabled(MEDIA_DREAM_COMPLICATION)) {
if (!mFeatureFlags.isEnabled(DREAM_MEDIA_COMPLICATION)) {
return;
}

View File

@@ -16,17 +16,28 @@
package com.android.systemui.dreams.complication;
import static org.mockito.Mockito.verify;
import static com.android.systemui.flags.Flags.DREAM_MEDIA_TAP_TO_OPEN;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
import android.app.PendingIntent;
import android.content.Intent;
import android.testing.AndroidTestingRunner;
import android.testing.TestableLooper;
import android.view.View;
import androidx.test.filters.SmallTest;
import com.android.systemui.ActivityIntentHelper;
import com.android.systemui.SysuiTestCase;
import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.flags.FeatureFlags;
import com.android.systemui.media.MediaCarouselController;
import com.android.systemui.media.dream.MediaDreamComplication;
import com.android.systemui.plugins.ActivityStarter;
import com.android.systemui.statusbar.NotificationLockscreenUserManager;
import com.android.systemui.statusbar.policy.KeyguardStateController;
import org.junit.Before;
import org.junit.Test;
@@ -48,21 +59,52 @@ public class DreamMediaEntryComplicationTest extends SysuiTestCase {
@Mock
private MediaDreamComplication mMediaComplication;
@Mock
private MediaCarouselController mMediaCarouselController;
@Mock
private ActivityStarter mActivityStarter;
@Mock
private ActivityIntentHelper mActivityIntentHelper;
@Mock
private KeyguardStateController mKeyguardStateController;
@Mock
private NotificationLockscreenUserManager mLockscreenUserManager;
@Mock
private FeatureFlags mFeatureFlags;
@Mock
private PendingIntent mPendingIntent;
private final Intent mIntent = new Intent("android.test.TEST_ACTION");
private final Integer mCurrentUserId = 99;
@Before
public void setup() {
MockitoAnnotations.initMocks(this);
when(mFeatureFlags.isEnabled(DREAM_MEDIA_TAP_TO_OPEN)).thenReturn(false);
}
/**
* Ensures clicking media entry chip adds/removes media complication.
*/
@Test
public void testClick() {
public void testClickToOpenUMO() {
final DreamMediaEntryComplication.DreamMediaEntryViewController viewController =
new DreamMediaEntryComplication.DreamMediaEntryViewController(
mView,
mDreamOverlayStateController,
mMediaComplication);
mMediaComplication,
mMediaCarouselController,
mActivityStarter,
mActivityIntentHelper,
mKeyguardStateController,
mLockscreenUserManager,
mFeatureFlags);
final ArgumentCaptor<View.OnClickListener> clickListenerCaptor =
ArgumentCaptor.forClass(View.OnClickListener.class);
@@ -85,10 +127,90 @@ public class DreamMediaEntryComplicationTest extends SysuiTestCase {
new DreamMediaEntryComplication.DreamMediaEntryViewController(
mView,
mDreamOverlayStateController,
mMediaComplication);
mMediaComplication,
mMediaCarouselController,
mActivityStarter,
mActivityIntentHelper,
mKeyguardStateController,
mLockscreenUserManager,
mFeatureFlags);
viewController.onViewDetached();
verify(mView).setSelected(false);
verify(mDreamOverlayStateController).removeComplication(mMediaComplication);
}
/**
* Ensures clicking media entry chip opens media when flag is set.
*/
@Test
public void testClickToOpenMediaOverLockscreen() {
when(mFeatureFlags.isEnabled(DREAM_MEDIA_TAP_TO_OPEN)).thenReturn(true);
when(mMediaCarouselController.getCurrentVisibleMediaContentIntent()).thenReturn(
mPendingIntent);
when(mKeyguardStateController.isShowing()).thenReturn(true);
when(mPendingIntent.getIntent()).thenReturn(mIntent);
when(mLockscreenUserManager.getCurrentUserId()).thenReturn(mCurrentUserId);
final DreamMediaEntryComplication.DreamMediaEntryViewController viewController =
new DreamMediaEntryComplication.DreamMediaEntryViewController(
mView,
mDreamOverlayStateController,
mMediaComplication,
mMediaCarouselController,
mActivityStarter,
mActivityIntentHelper,
mKeyguardStateController,
mLockscreenUserManager,
mFeatureFlags);
viewController.onViewAttached();
final ArgumentCaptor<View.OnClickListener> clickListenerCaptor =
ArgumentCaptor.forClass(View.OnClickListener.class);
verify(mView).setOnClickListener(clickListenerCaptor.capture());
when(mActivityIntentHelper.wouldShowOverLockscreen(mIntent, mCurrentUserId)).thenReturn(
true);
clickListenerCaptor.getValue().onClick(mView);
verify(mActivityStarter).startActivity(mIntent, true, null, true);
}
/**
* Ensures clicking media entry chip opens media when flag is set.
*/
@Test
public void testClickToOpenMediaDismissingLockscreen() {
when(mFeatureFlags.isEnabled(DREAM_MEDIA_TAP_TO_OPEN)).thenReturn(true);
when(mMediaCarouselController.getCurrentVisibleMediaContentIntent()).thenReturn(
mPendingIntent);
when(mKeyguardStateController.isShowing()).thenReturn(true);
when(mPendingIntent.getIntent()).thenReturn(mIntent);
when(mLockscreenUserManager.getCurrentUserId()).thenReturn(mCurrentUserId);
final DreamMediaEntryComplication.DreamMediaEntryViewController viewController =
new DreamMediaEntryComplication.DreamMediaEntryViewController(
mView,
mDreamOverlayStateController,
mMediaComplication,
mMediaCarouselController,
mActivityStarter,
mActivityIntentHelper,
mKeyguardStateController,
mLockscreenUserManager,
mFeatureFlags);
viewController.onViewAttached();
final ArgumentCaptor<View.OnClickListener> clickListenerCaptor =
ArgumentCaptor.forClass(View.OnClickListener.class);
verify(mView).setOnClickListener(clickListenerCaptor.capture());
when(mActivityIntentHelper.wouldShowOverLockscreen(mIntent, mCurrentUserId)).thenReturn(
false);
clickListenerCaptor.getValue().onClick(mView);
verify(mActivityStarter).postStartActivityDismissingKeyguard(mPendingIntent, null);
}
}

View File

@@ -16,6 +16,7 @@
package com.android.systemui.media
import android.app.PendingIntent
import android.testing.AndroidTestingRunner
import android.testing.TestableLooper
import androidx.test.filters.SmallTest
@@ -43,6 +44,7 @@ import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor
import org.mockito.Captor
import org.mockito.Mock
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.Mockito.`when` as whenever
@@ -366,7 +368,7 @@ class MediaCarouselControllerTest : SysuiTestCase() {
playerIndex,
mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex
)
assertEquals( playerIndex, 0)
assertEquals(playerIndex, 0)
// Replaying the same media player one more time.
// And check that the card stays in its position.
@@ -402,4 +404,44 @@ class MediaCarouselControllerTest : SysuiTestCase() {
visualStabilityCallback.value.onReorderingAllowed()
assertEquals(true, result)
}
@Test
fun testGetCurrentVisibleMediaContentIntent() {
val clickIntent1 = mock(PendingIntent::class.java)
val player1 = Triple("player1",
DATA.copy(clickIntent = clickIntent1),
1000L)
clock.setCurrentTimeMillis(player1.third)
MediaPlayerData.addMediaPlayer(player1.first,
player1.second.copy(notificationKey = player1.first),
panel, clock, isSsReactivated = false)
assertEquals(mediaCarouselController.getCurrentVisibleMediaContentIntent(), clickIntent1)
val clickIntent2 = mock(PendingIntent::class.java)
val player2 = Triple("player2",
DATA.copy(clickIntent = clickIntent2),
2000L)
clock.setCurrentTimeMillis(player2.third)
MediaPlayerData.addMediaPlayer(player2.first,
player2.second.copy(notificationKey = player2.first),
panel, clock, isSsReactivated = false)
// mediaCarouselScrollHandler.visibleMediaIndex is unchanged (= 0), and the new player is
// added to the front because it was active more recently.
assertEquals(mediaCarouselController.getCurrentVisibleMediaContentIntent(), clickIntent2)
val clickIntent3 = mock(PendingIntent::class.java)
val player3 = Triple("player3",
DATA.copy(clickIntent = clickIntent3),
500L)
clock.setCurrentTimeMillis(player3.third)
MediaPlayerData.addMediaPlayer(player3.first,
player3.second.copy(notificationKey = player3.first),
panel, clock, isSsReactivated = false)
// mediaCarouselScrollHandler.visibleMediaIndex is unchanged (= 0), and the new player is
// added to the end because it was active less recently.
assertEquals(mediaCarouselController.getCurrentVisibleMediaContentIntent(), clickIntent2)
}
}

View File

@@ -16,7 +16,7 @@
package com.android.systemui.media.dream;
import static com.android.systemui.flags.Flags.MEDIA_DREAM_COMPLICATION;
import static com.android.systemui.flags.Flags.DREAM_MEDIA_COMPLICATION;
import static org.mockito.AdditionalMatchers.not;
import static org.mockito.ArgumentMatchers.any;
@@ -68,7 +68,7 @@ public class MediaDreamSentinelTest extends SysuiTestCase {
public void setup() {
MockitoAnnotations.initMocks(this);
when(mFeatureFlags.isEnabled(MEDIA_DREAM_COMPLICATION)).thenReturn(true);
when(mFeatureFlags.isEnabled(DREAM_MEDIA_COMPLICATION)).thenReturn(true);
}
@Test
@@ -137,7 +137,7 @@ public class MediaDreamSentinelTest extends SysuiTestCase {
@Test
public void testOnMediaDataLoaded_mediaComplicationDisabled_doesNotAddComplication() {
when(mFeatureFlags.isEnabled(MEDIA_DREAM_COMPLICATION)).thenReturn(false);
when(mFeatureFlags.isEnabled(DREAM_MEDIA_COMPLICATION)).thenReturn(false);
final MediaDreamSentinel sentinel = new MediaDreamSentinel(mContext, mMediaDataManager,
mDreamOverlayStateController, mMediaEntryComplication, mFeatureFlags);