summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt103
-rw-r--r--packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java57
2 files changed, 122 insertions, 38 deletions
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
index 2facf3dedd18..db5dbb0263c8 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt
@@ -212,14 +212,32 @@ class MediaCarouselController @Inject constructor(
isSsReactivated: Boolean
) {
if (addOrUpdatePlayer(key, oldKey, data)) {
+ // Log card received if a new resumable media card is added
MediaPlayerData.getMediaPlayer(key)?.let {
logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED
it.mInstanceId,
+ it.mUid,
/* isRecommendationCard */ false,
it.surfaceForSmartspaceLogging,
rank = MediaPlayerData.getMediaPlayerIndex(key))
}
}
+ if (isSsReactivated) {
+ // If resumable media is reactivated by headphone connection, update instance
+ // id for each card and log a receive event.
+ MediaPlayerData.players().forEachIndexed { index, it ->
+ if (it.recommendationViewHolder == null) {
+ it.mInstanceId = SmallHash.hash(it.mUid +
+ systemClock.currentTimeMillis().toInt())
+ logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED
+ it.mInstanceId,
+ it.mUid,
+ /* isRecommendationCard */ false,
+ it.surfaceForSmartspaceLogging,
+ rank = index)
+ }
+ }
+ }
if (mediaCarouselScrollHandler.visibleToUser &&
isSsReactivated && !mediaCarouselScrollHandler.qsExpanded) {
// It could happen that reactived media player isn't visible to user because
@@ -252,6 +270,7 @@ class MediaCarouselController @Inject constructor(
MediaPlayerData.getMediaPlayer(key)?.let {
logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED
it.mInstanceId,
+ it.mUid,
/* isRecommendationCard */ true,
it.surfaceForSmartspaceLogging,
rank = MediaPlayerData.getMediaPlayerIndex(key))
@@ -261,6 +280,7 @@ class MediaCarouselController @Inject constructor(
MediaPlayerData.getMediaPlayerIndex(key)) {
logSmartspaceCardReported(800, // SMARTSPACE_CARD_SEEN
it.mInstanceId,
+ it.mUid,
/* isRecommendationCard */ true,
it.surfaceForSmartspaceLogging)
}
@@ -339,9 +359,9 @@ class MediaCarouselController @Inject constructor(
if (activeMediaIndex != -1) {
previousVisiblePlayerKey?.let {
val previousVisibleIndex = MediaPlayerData.playerKeys()
- .indexOfFirst { key -> it == key }
+ .indexOfFirst { key -> it == key }
mediaCarouselScrollHandler
- .scrollToPlayer(previousVisibleIndex, activeMediaIndex)
+ .scrollToPlayer(previousVisibleIndex, activeMediaIndex)
} ?: {
mediaCarouselScrollHandler.scrollToPlayer(destIndex = activeMediaIndex)
}
@@ -355,11 +375,11 @@ class MediaCarouselController @Inject constructor(
MediaPlayerData.moveIfExists(oldKey, key)
val existingPlayer = MediaPlayerData.getMediaPlayer(key)
val curVisibleMediaKey = MediaPlayerData.playerKeys()
- .elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex)
+ .elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex)
if (existingPlayer == null) {
var newPlayer = mediaControlPanelFactory.get()
newPlayer.attachPlayer(
- PlayerViewHolder.create(LayoutInflater.from(context), mediaContent))
+ PlayerViewHolder.create(LayoutInflater.from(context), mediaContent))
newPlayer.mediaViewController.sizeChangedListener = this::updateCarouselDimensions
val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.WRAP_CONTENT)
@@ -407,14 +427,14 @@ class MediaCarouselController @Inject constructor(
var newRecs = mediaControlPanelFactory.get()
newRecs.attachRecommendation(
- RecommendationViewHolder.create(LayoutInflater.from(context), mediaContent))
+ RecommendationViewHolder.create(LayoutInflater.from(context), mediaContent))
newRecs.mediaViewController.sizeChangedListener = this::updateCarouselDimensions
val lp = LinearLayout.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
- ViewGroup.LayoutParams.WRAP_CONTENT)
+ ViewGroup.LayoutParams.WRAP_CONTENT)
newRecs.recommendationViewHolder?.recommendations?.setLayoutParams(lp)
newRecs.bindRecommendation(data.copy(backgroundColor = bgColor))
val curVisibleMediaKey = MediaPlayerData.playerKeys()
- .elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex)
+ .elementAtOrNull(mediaCarouselScrollHandler.visibleMediaIndex)
MediaPlayerData.addMediaRecommendation(key, data, newRecs, shouldPrioritize, systemClock)
updatePlayerToState(newRecs, noAnimation = true)
reorderAllPlayers(curVisibleMediaKey)
@@ -462,7 +482,7 @@ class MediaCarouselController @Inject constructor(
removePlayer(key, dismissMediaData = false, dismissRecommendation = false)
smartspaceMediaData?.let {
addSmartspaceMediaRecommendations(
- it.targetId, it, MediaPlayerData.shouldPrioritizeSs)
+ it.targetId, it, MediaPlayerData.shouldPrioritizeSs)
}
} else {
removePlayer(key, dismissMediaData = false, dismissRecommendation = false)
@@ -585,7 +605,7 @@ class MediaCarouselController @Inject constructor(
?: endShowsActive
if (currentlyShowingOnlyActive != endShowsActive ||
((currentTransitionProgress != 1.0f && currentTransitionProgress != 0.0f) &&
- startShowsActive != endShowsActive)) {
+ startShowsActive != endShowsActive)) {
// Whenever we're transitioning from between differing states or the endstate differs
// we reset the translation
currentlyShowingOnlyActive = endShowsActive
@@ -696,23 +716,43 @@ class MediaCarouselController @Inject constructor(
}
logSmartspaceCardReported(800, // SMARTSPACE_CARD_SEEN
mediaControlPanel.mInstanceId,
+ mediaControlPanel.mUid,
isRecommendationCard,
mediaControlPanel.surfaceForSmartspaceLogging)
}
}
@JvmOverloads
+ /**
+ * Log Smartspace events
+ *
+ * @param eventId UI event id (e.g. 800 for SMARTSPACE_CARD_SEEN)
+ * @param instanceId id to uniquely identify a card, e.g. each headphone generates a new
+ * instanceId
+ * @param uid uid for the application that media comes from
+ * @param isRecommendationCard whether the card is media recommendation
+ * @param surface which display surface the media card is on (e.g. lockscreen, shade)
+ * @param interactedSubcardRank the rank for interacted media item for recommendation card, -1
+ * for tapping on card but not on any media item, 0 for first media item, 1 for second, etc.
+ * @param interactedSubcardCardinality how many media items were shown to the user when there
+ * is user interaction
+ * @param rank the rank for media card in the media carousel, starting from 0
+ *
+ */
fun logSmartspaceCardReported(
eventId: Int,
instanceId: Int,
+ uid: Int,
isRecommendationCard: Boolean,
surface: Int,
+ interactedSubcardRank: Int = 0,
+ interactedSubcardCardinality: Int = 0,
rank: Int = mediaCarouselScrollHandler.visibleMediaIndex
) {
// Only log media resume card when Smartspace data is available
if (!isRecommendationCard &&
- !mediaManager.smartspaceMediaData.isActive &&
- MediaPlayerData.smartspaceMediaData == null) {
+ !mediaManager.smartspaceMediaData.isActive &&
+ MediaPlayerData.smartspaceMediaData == null) {
return
}
@@ -720,13 +760,20 @@ class MediaCarouselController @Inject constructor(
SysUiStatsLog.write(SysUiStatsLog.SMARTSPACE_CARD_REPORTED,
eventId,
instanceId,
- if (isRecommendationCard)
- SysUiStatsLog.SMART_SPACE_CARD_REPORTED__CARD_TYPE__HEADPHONE_MEDIA_RECOMMENDATIONS
- else
- SysUiStatsLog.SMART_SPACE_CARD_REPORTED__CARD_TYPE__HEADPHONE_RESUME_MEDIA,
+ // Deprecated, replaced with AiAi feature type so we don't need to create logging
+ // card type for each new feature.
+ SysUiStatsLog.SMART_SPACE_CARD_REPORTED__CARD_TYPE__UNKNOWN_CARD,
surface,
rank,
- mediaContent.getChildCount())
+ mediaContent.getChildCount(),
+ if (isRecommendationCard)
+ 15 // MEDIA_RECOMMENDATION
+ else
+ 31, // MEDIA_RESUME
+ uid,
+ interactedSubcardRank,
+ interactedSubcardCardinality
+ )
/* ktlint-disable max-line-length */
}
@@ -738,18 +785,20 @@ class MediaCarouselController @Inject constructor(
if (!recommendation.isEmpty()) {
logSmartspaceCardReported(761, // SMARTSPACE_CARD_DISMISS
recommendation.get(0).mInstanceId,
+ recommendation.get(0).mUid,
true,
recommendation.get(0).surfaceForSmartspaceLogging,
- /* rank */-1)
+ rank = -1)
} else {
val visibleMediaIndex = mediaCarouselScrollHandler.visibleMediaIndex
if (MediaPlayerData.players().size > visibleMediaIndex) {
val player = MediaPlayerData.players().elementAt(visibleMediaIndex)
logSmartspaceCardReported(761, // SMARTSPACE_CARD_DISMISS
player.mInstanceId,
- false,
+ player.mUid,
+ false,
player.surfaceForSmartspaceLogging,
- /* rank */-1)
+ rank = -1)
}
}
mediaManager.onSwipeToDismiss()
@@ -768,7 +817,7 @@ class MediaCarouselController @Inject constructor(
@VisibleForTesting
internal object MediaPlayerData {
private val EMPTY = 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)
// Whether should prioritize Smartspace card.
internal var shouldPrioritizeSs: Boolean = false
private set
@@ -776,18 +825,18 @@ internal object MediaPlayerData {
private set
data class MediaSortKey(
- // Whether the item represents a Smartspace media recommendation.
+ // Whether the item represents a Smartspace media recommendation.
val isSsMediaRec: Boolean,
val data: MediaData,
val updateTime: Long = 0
)
private val comparator =
- compareByDescending<MediaSortKey> { it.data.isPlaying }
- .thenByDescending { if (shouldPrioritizeSs) it.isSsMediaRec else !it.isSsMediaRec }
- .thenByDescending { it.data.isLocalSession }
- .thenByDescending { !it.data.resumption }
- .thenByDescending { it.updateTime }
+ compareByDescending<MediaSortKey> { it.data.isPlaying }
+ .thenByDescending { if (shouldPrioritizeSs) it.isSsMediaRec else !it.isSsMediaRec }
+ .thenByDescending { it.data.isLocalSession }
+ .thenByDescending { !it.data.resumption }
+ .thenByDescending { it.updateTime }
private val mediaPlayers = TreeMap<MediaSortKey, MediaControlPanel>(comparator)
private val mediaData: MutableMap<String, MediaSortKey> = mutableMapOf()
@@ -888,4 +937,4 @@ internal object MediaPlayerData {
}
return false
}
-}
+} \ No newline at end of file
diff --git a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
index 15a70831b2f9..afe9e5a6ee95 100644
--- a/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
+++ b/packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java
@@ -33,6 +33,7 @@ import android.graphics.drawable.Icon;
import android.media.session.MediaController;
import android.media.session.MediaSession;
import android.media.session.PlaybackState;
+import android.os.Process;
import android.text.Layout;
import android.util.Log;
import android.view.View;
@@ -111,6 +112,9 @@ public class MediaControlPanel {
private int mAlbumArtSize;
// Instance id for logging purpose.
protected int mInstanceId = -1;
+ // Uid for the media app.
+ protected int mUid = Process.INVALID_UID;
+ private int mSmartspaceMediaItemsCount;
private MediaCarouselController mMediaCarouselController;
private final MediaOutputDialogFactory mMediaOutputDialogFactory;
@@ -266,7 +270,13 @@ public class MediaControlPanel {
}
mKey = key;
MediaSession.Token token = data.getToken();
- mInstanceId = SmallHash.hash(data.getPackageName());
+ PackageManager packageManager = mContext.getPackageManager();
+ try {
+ mUid = packageManager.getApplicationInfo(data.getPackageName(), 0 /* flags */).uid;
+ } catch (PackageManager.NameNotFoundException e) {
+ Log.e(TAG, "Unable to look up package name", e);
+ }
+ mInstanceId = SmallHash.hash(mUid);
mBackgroundColor = data.getBackgroundColor();
if (mToken == null || !mToken.equals(token)) {
@@ -531,10 +541,11 @@ public class MediaControlPanel {
}
// Set up recommendation card's header.
- ApplicationInfo applicationInfo = null;
+ ApplicationInfo applicationInfo;
try {
applicationInfo = mContext.getPackageManager()
.getApplicationInfo(data.getPackageName(), 0 /* flags */);
+ mUid = applicationInfo.uid;
} catch (PackageManager.NameNotFoundException e) {
Log.w(TAG, "Fail to get media recommendation's app info", e);
return;
@@ -553,7 +564,8 @@ public class MediaControlPanel {
headerTitleText.setText(appLabel);
}
// Set up media rec card's tap action if applicable.
- setSmartspaceRecItemOnClickListener(recommendationCard, data.getCardAction());
+ setSmartspaceRecItemOnClickListener(recommendationCard, data.getCardAction(),
+ /* interactedSubcardRank */ -1);
// Set up media rec card's accessibility label.
recommendationCard.setContentDescription(
mContext.getString(R.string.controls_media_smartspace_rec_description, appLabel));
@@ -567,7 +579,8 @@ public class MediaControlPanel {
ConstraintSet collapsedSet = mMediaViewController.getCollapsedLayout();
int mediaRecommendationNum = Math.min(mediaRecommendationList.size(),
MEDIA_RECOMMENDATION_MAX_NUM);
- for (int itemIndex = 0, uiComponentIndex = 0;
+ int uiComponentIndex = 0;
+ for (int itemIndex = 0;
itemIndex < mediaRecommendationNum && uiComponentIndex < mediaRecommendationNum;
itemIndex++) {
SmartspaceAction recommendation = mediaRecommendationList.get(itemIndex);
@@ -582,7 +595,8 @@ public class MediaControlPanel {
// Set up the media item's click listener if applicable.
ViewGroup mediaCoverContainer = mediaCoverContainers.get(uiComponentIndex);
- setSmartspaceRecItemOnClickListener(mediaCoverContainer, recommendation);
+ setSmartspaceRecItemOnClickListener(mediaCoverContainer, recommendation,
+ uiComponentIndex);
// Set up the accessibility label for the media item.
String artistName = recommendation.getExtras()
@@ -614,10 +628,10 @@ public class MediaControlPanel {
mediaCoverItemsResIds.get(uiComponentIndex), true);
setVisibleAndAlpha(expandedSet,
mediaCoverContainersResIds.get(uiComponentIndex), true);
-
uiComponentIndex++;
}
+ mSmartspaceMediaItemsCount = uiComponentIndex;
// Set up long press to show guts setting panel.
mRecommendationViewHolder.getDismiss().setOnClickListener(v -> {
logSmartspaceCardReported(761, // SMARTSPACE_CARD_DISMISS
@@ -750,7 +764,8 @@ public class MediaControlPanel {
private void setSmartspaceRecItemOnClickListener(
@NonNull View view,
- @NonNull SmartspaceAction action) {
+ @NonNull SmartspaceAction action,
+ int interactedSubcardRank) {
if (view == null || action == null || action.getIntent() == null
|| action.getIntent().getExtras() == null) {
Log.e(TAG, "No tap action can be set up");
@@ -758,9 +773,10 @@ public class MediaControlPanel {
}
view.setOnClickListener(v -> {
- // When media recommendation card is shown, it will always be the top card.
logSmartspaceCardReported(760, // SMARTSPACE_CARD_CLICK
- /* isRecommendationCard */ true);
+ /* isRecommendationCard */ true,
+ interactedSubcardRank,
+ getSmartspaceSubCardCardinality());
if (shouldSmartspaceRecItemOpenInForeground(action)) {
// Request to unlock the device if the activity needs to be opened in foreground.
@@ -818,9 +834,28 @@ public class MediaControlPanel {
}
private void logSmartspaceCardReported(int eventId, boolean isRecommendationCard) {
+ logSmartspaceCardReported(eventId, isRecommendationCard,
+ /* interactedSubcardRank */ 0,
+ /* interactedSubcardCardinality */ 0);
+ }
+
+ private void logSmartspaceCardReported(int eventId, boolean isRecommendationCard,
+ int interactedSubcardRank, int interactedSubcardCardinality) {
mMediaCarouselController.logSmartspaceCardReported(eventId,
mInstanceId,
+ mUid,
isRecommendationCard,
- getSurfaceForSmartspaceLogging());
+ getSurfaceForSmartspaceLogging(),
+ interactedSubcardRank,
+ interactedSubcardCardinality);
+ }
+
+ private int getSmartspaceSubCardCardinality() {
+ if (!mMediaCarouselController.getMediaCarouselScrollHandler().getQsExpanded()
+ && mSmartspaceMediaItemsCount > 3) {
+ return 3;
+ }
+
+ return mSmartspaceMediaItemsCount;
}
-}
+} \ No newline at end of file