Merge "Populate additional fields for smartspace logging" into sc-qpr1-dev am: bff78358ad
Original change: https://googleplex-android-review.googlesource.com/c/platform/frameworks/base/+/15590965 Change-Id: I782a36d32b978cc91ee6438adf7ec191c32e928e
This commit is contained in:
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user