Merge "Send AGSA the dismiss intent when user dismisses the recommendation card or the reactivated media player (during the recommendation active session)." into sc-qpr1-dev am: 72afe9d682

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

Change-Id: Id61dee95069461cc66c81f63e9446df171b80a91
This commit is contained in:
Cecilia Hong
2021-09-20 16:23:54 +00:00
committed by Automerger Merge Worker
6 changed files with 67 additions and 8 deletions

View File

@@ -75,6 +75,8 @@ public class MediaControlPanel {
private static final String TAG = "MediaControlPanel"; private static final String TAG = "MediaControlPanel";
private static final float DISABLED_ALPHA = 0.38f; private static final float DISABLED_ALPHA = 0.38f;
private static final String EXPORTED_SMARTSPACE_TRAMPOLINE_ACTIVITY_NAME = "com.google"
+ ".android.apps.gsa.staticplugins.opa.smartspace.ExportedSmartspaceTrampolineActivity";
private static final String EXTRAS_SMARTSPACE_INTENT = private static final String EXTRAS_SMARTSPACE_INTENT =
"com.google.android.apps.gsa.smartspace.extra.SMARTSPACE_INTENT"; "com.google.android.apps.gsa.smartspace.extra.SMARTSPACE_INTENT";
private static final int MEDIA_RECOMMENDATION_ITEMS_PER_ROW = 3; private static final int MEDIA_RECOMMENDATION_ITEMS_PER_ROW = 3;
@@ -627,6 +629,22 @@ public class MediaControlPanel {
closeGuts(); closeGuts();
mMediaDataManagerLazy.get().dismissSmartspaceRecommendation( mMediaDataManagerLazy.get().dismissSmartspaceRecommendation(
data.getTargetId(), MediaViewController.GUTS_ANIMATION_DURATION + 100L); data.getTargetId(), MediaViewController.GUTS_ANIMATION_DURATION + 100L);
Intent dismissIntent = data.getDismissIntent();
if (dismissIntent == null) {
Log.w(TAG, "Cannot create dismiss action click action: "
+ "extras missing dismiss_intent.");
return;
}
if (dismissIntent.getComponent() != null
&& dismissIntent.getComponent().getClassName()
.equals(EXPORTED_SMARTSPACE_TRAMPOLINE_ACTIVITY_NAME)) {
// Dismiss the card Smartspace data through Smartspace trampoline activity.
mContext.startActivity(dismissIntent);
} else {
mContext.sendBroadcast(dismissIntent);
}
}); });
mController = null; mController = null;

View File

@@ -16,6 +16,7 @@
package com.android.systemui.media package com.android.systemui.media
import android.content.Context
import android.os.SystemProperties import android.os.SystemProperties
import android.util.Log import android.util.Log
import com.android.internal.annotations.VisibleForTesting import com.android.internal.annotations.VisibleForTesting
@@ -32,6 +33,8 @@ import kotlin.collections.LinkedHashMap
private const val TAG = "MediaDataFilter" private const val TAG = "MediaDataFilter"
private const val DEBUG = true private const val DEBUG = true
private const val EXPORTED_SMARTSPACE_TRAMPOLINE_ACTIVITY_NAME = ("com.google" +
".android.apps.gsa.staticplugins.opa.smartspace.ExportedSmartspaceTrampolineActivity")
private const val RESUMABLE_MEDIA_MAX_AGE_SECONDS_KEY = "resumable_media_max_age_seconds" private const val RESUMABLE_MEDIA_MAX_AGE_SECONDS_KEY = "resumable_media_max_age_seconds"
/** /**
@@ -51,6 +54,7 @@ internal val SMARTSPACE_MAX_AGE = SystemProperties
* background users (e.g. timeouts). * background users (e.g. timeouts).
*/ */
class MediaDataFilter @Inject constructor( class MediaDataFilter @Inject constructor(
private val context: Context,
private val broadcastDispatcher: BroadcastDispatcher, private val broadcastDispatcher: BroadcastDispatcher,
private val mediaResumeListener: MediaResumeListener, private val mediaResumeListener: MediaResumeListener,
private val lockscreenUserManager: NotificationLockscreenUserManager, private val lockscreenUserManager: NotificationLockscreenUserManager,
@@ -229,6 +233,18 @@ class MediaDataFilter @Inject constructor(
mediaDataManager.setTimedOut(it, timedOut = true, forceUpdate = true) mediaDataManager.setTimedOut(it, timedOut = true, forceUpdate = true)
} }
if (smartspaceMediaData.isActive) { if (smartspaceMediaData.isActive) {
val dismissIntent = smartspaceMediaData.dismissIntent
if (dismissIntent == null) {
Log.w(TAG, "Cannot create dismiss action click action: " +
"extras missing dismiss_intent.")
} else if (dismissIntent.getComponent() != null &&
dismissIntent.getComponent().getClassName()
== EXPORTED_SMARTSPACE_TRAMPOLINE_ACTIVITY_NAME) {
// Dismiss the card Smartspace data through Smartspace trampoline activity.
context.startActivity(dismissIntent)
} else {
context.sendBroadcast(dismissIntent)
}
smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA.copy( smartspaceMediaData = EMPTY_SMARTSPACE_MEDIA_DATA.copy(
targetId = smartspaceMediaData.targetId, isValid = smartspaceMediaData.isValid) targetId = smartspaceMediaData.targetId, isValid = smartspaceMediaData.isValid)
} }

View File

@@ -76,12 +76,13 @@ private val ART_URIS = arrayOf(
private const val TAG = "MediaDataManager" private const val TAG = "MediaDataManager"
private const val DEBUG = true private const val DEBUG = true
private const val EXTRAS_SMARTSPACE_DISMISS_INTENT_KEY = "dismiss_intent"
private val LOADING = MediaData(-1, false, 0, null, null, null, null, null, private val LOADING = MediaData(-1, false, 0, null, null, null, null, null,
emptyList(), emptyList(), "INVALID", null, null, null, true, null) emptyList(), emptyList(), "INVALID", null, null, null, true, null)
@VisibleForTesting @VisibleForTesting
internal val EMPTY_SMARTSPACE_MEDIA_DATA = SmartspaceMediaData("INVALID", false, false, internal val EMPTY_SMARTSPACE_MEDIA_DATA = SmartspaceMediaData("INVALID", false, false,
"INVALID", null, emptyList(), 0) "INVALID", null, emptyList(), null, 0)
fun isMediaNotification(sbn: StatusBarNotification): Boolean { fun isMediaNotification(sbn: StatusBarNotification): Boolean {
if (!sbn.notification.hasMediaSession()) { if (!sbn.notification.hasMediaSession()) {
@@ -883,12 +884,22 @@ class MediaDataManager(
target: SmartspaceTarget, target: SmartspaceTarget,
isActive: Boolean isActive: Boolean
): SmartspaceMediaData { ): SmartspaceMediaData {
var dismissIntent: Intent? = null
if (target.baseAction != null && target.baseAction.extras != null) {
dismissIntent = target
.baseAction
.extras
.getParcelable(EXTRAS_SMARTSPACE_DISMISS_INTENT_KEY) as Intent
}
packageName(target)?.let { packageName(target)?.let {
return SmartspaceMediaData(target.smartspaceTargetId, isActive, true, it, return SmartspaceMediaData(target.smartspaceTargetId, isActive, true, it,
target.baseAction, target.iconGrid, 0) target.baseAction, target.iconGrid,
dismissIntent, 0)
} }
return EMPTY_SMARTSPACE_MEDIA_DATA return EMPTY_SMARTSPACE_MEDIA_DATA
.copy(targetId = target.smartspaceTargetId, isActive = isActive) .copy(targetId = target.smartspaceTargetId,
isActive = isActive,
dismissIntent = dismissIntent)
} }
private fun packageName(target: SmartspaceTarget): String? { private fun packageName(target: SmartspaceTarget): String? {

View File

@@ -17,6 +17,7 @@
package com.android.systemui.media package com.android.systemui.media
import android.app.smartspace.SmartspaceAction import android.app.smartspace.SmartspaceAction
import android.content.Intent
/** State of a Smartspace media recommendations view. */ /** State of a Smartspace media recommendations view. */
data class SmartspaceMediaData( data class SmartspaceMediaData(
@@ -44,6 +45,10 @@ data class SmartspaceMediaData(
* List of media recommendations. * List of media recommendations.
*/ */
val recommendations: List<SmartspaceAction>, val recommendations: List<SmartspaceAction>,
/**
* Intent for the user's initiated dismissal.
*/
val dismissIntent: Intent?,
/** /**
* View's background color. * View's background color.
*/ */

View File

@@ -86,7 +86,7 @@ class MediaDataFilterTest : SysuiTestCase() {
@Before @Before
fun setup() { fun setup() {
MockitoAnnotations.initMocks(this) MockitoAnnotations.initMocks(this)
mediaDataFilter = MediaDataFilter(broadcastDispatcher, mediaResumeListener, mediaDataFilter = MediaDataFilter(context, broadcastDispatcher, mediaResumeListener,
lockscreenUserManager, executor, clock) lockscreenUserManager, executor, clock)
mediaDataFilter.mediaDataManager = mediaDataManager mediaDataFilter.mediaDataManager = mediaDataManager
mediaDataFilter.addListener(listener) mediaDataFilter.addListener(listener)

View File

@@ -4,6 +4,7 @@ import android.app.Notification.MediaStyle
import android.app.PendingIntent import android.app.PendingIntent
import android.app.smartspace.SmartspaceAction import android.app.smartspace.SmartspaceAction
import android.app.smartspace.SmartspaceTarget import android.app.smartspace.SmartspaceTarget
import android.content.Intent
import android.graphics.Bitmap import android.graphics.Bitmap
import android.media.MediaDescription import android.media.MediaDescription
import android.media.MediaMetadata import android.media.MediaMetadata
@@ -51,6 +52,7 @@ private const val APP_NAME = "SystemUI"
private const val SESSION_ARTIST = "artist" private const val SESSION_ARTIST = "artist"
private const val SESSION_TITLE = "title" private const val SESSION_TITLE = "title"
private const val USER_ID = 0 private const val USER_ID = 0
private val DISMISS_INTENT = Intent().apply { action = "dismiss" }
private fun <T> anyObject(): T { private fun <T> anyObject(): T {
return Mockito.anyObject<T>() return Mockito.anyObject<T>()
@@ -83,6 +85,7 @@ class MediaDataManagerTest : SysuiTestCase() {
lateinit var smartspaceMediaDataProvider: SmartspaceMediaDataProvider lateinit var smartspaceMediaDataProvider: SmartspaceMediaDataProvider
@Mock lateinit var mediaSmartspaceTarget: SmartspaceTarget @Mock lateinit var mediaSmartspaceTarget: SmartspaceTarget
@Mock private lateinit var mediaRecommendationItem: SmartspaceAction @Mock private lateinit var mediaRecommendationItem: SmartspaceAction
@Mock private lateinit var mediaSmartspaceBaseAction: SmartspaceAction
lateinit var mediaDataManager: MediaDataManager lateinit var mediaDataManager: MediaDataManager
lateinit var mediaNotification: StatusBarNotification lateinit var mediaNotification: StatusBarNotification
@Captor lateinit var mediaDataCaptor: ArgumentCaptor<MediaData> @Captor lateinit var mediaDataCaptor: ArgumentCaptor<MediaData>
@@ -146,8 +149,12 @@ class MediaDataManagerTest : SysuiTestCase() {
// treat mediaSessionBasedFilter as a listener for testing. // treat mediaSessionBasedFilter as a listener for testing.
listener = mediaSessionBasedFilter listener = mediaSessionBasedFilter
val recommendationExtras = Bundle() val recommendationExtras = Bundle().apply {
recommendationExtras.putString("package_name", PACKAGE_NAME) putString("package_name", PACKAGE_NAME)
putParcelable("dismiss_intent", DISMISS_INTENT)
}
whenever(mediaSmartspaceBaseAction.extras).thenReturn(recommendationExtras)
whenever(mediaSmartspaceTarget.baseAction).thenReturn(mediaSmartspaceBaseAction)
whenever(mediaRecommendationItem.extras).thenReturn(recommendationExtras) whenever(mediaRecommendationItem.extras).thenReturn(recommendationExtras)
whenever(mediaSmartspaceTarget.smartspaceTargetId).thenReturn(KEY_MEDIA_SMARTSPACE) whenever(mediaSmartspaceTarget.smartspaceTargetId).thenReturn(KEY_MEDIA_SMARTSPACE)
whenever(mediaSmartspaceTarget.featureType).thenReturn(SmartspaceTarget.FEATURE_MEDIA) whenever(mediaSmartspaceTarget.featureType).thenReturn(SmartspaceTarget.FEATURE_MEDIA)
@@ -380,7 +387,8 @@ class MediaDataManagerTest : SysuiTestCase() {
verify(listener).onSmartspaceMediaDataLoaded( verify(listener).onSmartspaceMediaDataLoaded(
eq(KEY_MEDIA_SMARTSPACE), eq(KEY_MEDIA_SMARTSPACE),
eq(SmartspaceMediaData(KEY_MEDIA_SMARTSPACE, true /* isActive */, true /*isValid */, eq(SmartspaceMediaData(KEY_MEDIA_SMARTSPACE, true /* isActive */, true /*isValid */,
PACKAGE_NAME, null, listOf(mediaRecommendationItem), 0)), PACKAGE_NAME, mediaSmartspaceBaseAction, listOf(mediaRecommendationItem),
DISMISS_INTENT, 0)),
eq(false)) eq(false))
} }
@@ -391,7 +399,8 @@ class MediaDataManagerTest : SysuiTestCase() {
verify(listener).onSmartspaceMediaDataLoaded( verify(listener).onSmartspaceMediaDataLoaded(
eq(KEY_MEDIA_SMARTSPACE), eq(KEY_MEDIA_SMARTSPACE),
eq(EMPTY_SMARTSPACE_MEDIA_DATA eq(EMPTY_SMARTSPACE_MEDIA_DATA
.copy(targetId = KEY_MEDIA_SMARTSPACE, isActive = true, isValid = false)), .copy(targetId = KEY_MEDIA_SMARTSPACE, isActive = true,
isValid = false, dismissIntent = DISMISS_INTENT)),
eq(false)) eq(false))
} }