Merge "Tapping dream media chip opens media instead of UMO if flag is set." into tm-qpr-dev am: b18a6841d9

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

Change-Id: I665f6a4089ab9c376fdd96ebba087892654b4c6f
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
This commit is contained in:
Xiaowen Lei
2022-09-26 16:30:51 +00:00
committed by Automerger Merge Worker
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.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.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.util.Log;
import android.view.View; import android.view.View;
import com.android.systemui.ActivityIntentHelper;
import com.android.systemui.dreams.DreamOverlayStateController; import com.android.systemui.dreams.DreamOverlayStateController;
import com.android.systemui.dreams.complication.dagger.DreamMediaEntryComplicationComponent; 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.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 com.android.systemui.util.ViewController;
import javax.inject.Inject; import javax.inject.Inject;
@@ -87,6 +95,15 @@ public class DreamMediaEntryComplication implements Complication {
private final DreamOverlayStateController mDreamOverlayStateController; private final DreamOverlayStateController mDreamOverlayStateController;
private final MediaDreamComplication mMediaComplication; 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; private boolean mMediaComplicationAdded;
@@ -94,15 +111,28 @@ public class DreamMediaEntryComplication implements Complication {
DreamMediaEntryViewController( DreamMediaEntryViewController(
@Named(DREAM_MEDIA_ENTRY_VIEW) View view, @Named(DREAM_MEDIA_ENTRY_VIEW) View view,
DreamOverlayStateController dreamOverlayStateController, DreamOverlayStateController dreamOverlayStateController,
MediaDreamComplication mediaComplication) { MediaDreamComplication mediaComplication,
MediaCarouselController mediaCarouselController,
ActivityStarter activityStarter,
ActivityIntentHelper activityIntentHelper,
KeyguardStateController keyguardStateController,
NotificationLockscreenUserManager lockscreenUserManager,
FeatureFlags featureFlags) {
super(view); super(view);
mDreamOverlayStateController = dreamOverlayStateController; mDreamOverlayStateController = dreamOverlayStateController;
mMediaComplication = mediaComplication; mMediaComplication = mediaComplication;
mMediaCarouselController = mediaCarouselController;
mActivityStarter = activityStarter;
mActivityIntentHelper = activityIntentHelper;
mKeyguardStateController = keyguardStateController;
mLockscreenUserManager = lockscreenUserManager;
mFeatureFlags = featureFlags;
mView.setOnClickListener(this::onClickMediaEntry); mView.setOnClickListener(this::onClickMediaEntry);
} }
@Override @Override
protected void onViewAttached() { protected void onViewAttached() {
mIsTapToOpenEnabled = mFeatureFlags.isEnabled(DREAM_MEDIA_TAP_TO_OPEN);
} }
@Override @Override
@@ -113,6 +143,31 @@ public class DreamMediaEntryComplication implements Complication {
private void onClickMediaEntry(View v) { private void onClickMediaEntry(View v) {
if (DEBUG) Log.d(TAG, "media entry complication tapped"); 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) { if (!mMediaComplicationAdded) {
addMediaComplication(); addMediaComplication();
} else { } else {

View File

@@ -200,7 +200,8 @@ public class Flags {
public static final UnreleasedFlag MEDIA_SESSION_ACTIONS = new UnreleasedFlag(901); 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_NEARBY_DEVICES = new ReleasedFlag(903);
public static final ReleasedFlag MEDIA_MUTE_AWAIT = new ReleasedFlag(904); 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 // 1000 - dock
public static final ReleasedFlag SIMULATE_DOCK_THROUGH_CHARGING = public static final ReleasedFlag SIMULATE_DOCK_THROUGH_CHARGING =

View File

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

View File

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

View File

@@ -16,17 +16,28 @@
package com.android.systemui.dreams.complication; 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.AndroidTestingRunner;
import android.testing.TestableLooper; import android.testing.TestableLooper;
import android.view.View; import android.view.View;
import androidx.test.filters.SmallTest; import androidx.test.filters.SmallTest;
import com.android.systemui.ActivityIntentHelper;
import com.android.systemui.SysuiTestCase; import com.android.systemui.SysuiTestCase;
import com.android.systemui.dreams.DreamOverlayStateController; 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.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.Before;
import org.junit.Test; import org.junit.Test;
@@ -48,21 +59,52 @@ public class DreamMediaEntryComplicationTest extends SysuiTestCase {
@Mock @Mock
private MediaDreamComplication mMediaComplication; 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 @Before
public void setup() { public void setup() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
when(mFeatureFlags.isEnabled(DREAM_MEDIA_TAP_TO_OPEN)).thenReturn(false);
} }
/** /**
* Ensures clicking media entry chip adds/removes media complication. * Ensures clicking media entry chip adds/removes media complication.
*/ */
@Test @Test
public void testClick() { public void testClickToOpenUMO() {
final DreamMediaEntryComplication.DreamMediaEntryViewController viewController = final DreamMediaEntryComplication.DreamMediaEntryViewController viewController =
new DreamMediaEntryComplication.DreamMediaEntryViewController( new DreamMediaEntryComplication.DreamMediaEntryViewController(
mView, mView,
mDreamOverlayStateController, mDreamOverlayStateController,
mMediaComplication); mMediaComplication,
mMediaCarouselController,
mActivityStarter,
mActivityIntentHelper,
mKeyguardStateController,
mLockscreenUserManager,
mFeatureFlags);
final ArgumentCaptor<View.OnClickListener> clickListenerCaptor = final ArgumentCaptor<View.OnClickListener> clickListenerCaptor =
ArgumentCaptor.forClass(View.OnClickListener.class); ArgumentCaptor.forClass(View.OnClickListener.class);
@@ -85,10 +127,90 @@ public class DreamMediaEntryComplicationTest extends SysuiTestCase {
new DreamMediaEntryComplication.DreamMediaEntryViewController( new DreamMediaEntryComplication.DreamMediaEntryViewController(
mView, mView,
mDreamOverlayStateController, mDreamOverlayStateController,
mMediaComplication); mMediaComplication,
mMediaCarouselController,
mActivityStarter,
mActivityIntentHelper,
mKeyguardStateController,
mLockscreenUserManager,
mFeatureFlags);
viewController.onViewDetached(); viewController.onViewDetached();
verify(mView).setSelected(false); verify(mView).setSelected(false);
verify(mDreamOverlayStateController).removeComplication(mMediaComplication); 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 package com.android.systemui.media
import android.app.PendingIntent
import android.testing.AndroidTestingRunner import android.testing.AndroidTestingRunner
import android.testing.TestableLooper import android.testing.TestableLooper
import androidx.test.filters.SmallTest import androidx.test.filters.SmallTest
@@ -43,6 +44,7 @@ import org.junit.runner.RunWith
import org.mockito.ArgumentCaptor import org.mockito.ArgumentCaptor
import org.mockito.Captor import org.mockito.Captor
import org.mockito.Mock import org.mockito.Mock
import org.mockito.Mockito.mock
import org.mockito.Mockito.verify import org.mockito.Mockito.verify
import org.mockito.Mockito.verifyNoMoreInteractions import org.mockito.Mockito.verifyNoMoreInteractions
import org.mockito.Mockito.`when` as whenever import org.mockito.Mockito.`when` as whenever
@@ -366,7 +368,7 @@ class MediaCarouselControllerTest : SysuiTestCase() {
playerIndex, playerIndex,
mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex mediaCarouselController.mediaCarouselScrollHandler.visibleMediaIndex
) )
assertEquals( playerIndex, 0) assertEquals(playerIndex, 0)
// Replaying the same media player one more time. // Replaying the same media player one more time.
// And check that the card stays in its position. // And check that the card stays in its position.
@@ -402,4 +404,44 @@ class MediaCarouselControllerTest : SysuiTestCase() {
visualStabilityCallback.value.onReorderingAllowed() visualStabilityCallback.value.onReorderingAllowed()
assertEquals(true, result) 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; 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.AdditionalMatchers.not;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
@@ -68,7 +68,7 @@ public class MediaDreamSentinelTest extends SysuiTestCase {
public void setup() { public void setup() {
MockitoAnnotations.initMocks(this); MockitoAnnotations.initMocks(this);
when(mFeatureFlags.isEnabled(MEDIA_DREAM_COMPLICATION)).thenReturn(true); when(mFeatureFlags.isEnabled(DREAM_MEDIA_COMPLICATION)).thenReturn(true);
} }
@Test @Test
@@ -137,7 +137,7 @@ public class MediaDreamSentinelTest extends SysuiTestCase {
@Test @Test
public void testOnMediaDataLoaded_mediaComplicationDisabled_doesNotAddComplication() { 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, final MediaDreamSentinel sentinel = new MediaDreamSentinel(mContext, mMediaDataManager,
mDreamOverlayStateController, mMediaEntryComplication, mFeatureFlags); mDreamOverlayStateController, mMediaEntryComplication, mFeatureFlags);