summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArnaud Berry <arnaudberry@google.com>2023-12-20 15:53:13 -0800
committerArnaud Berry <arnaudberry@google.com>2023-12-21 12:54:25 -0800
commit595d15cd3506f6bb82d960f6878c665fba428ff1 (patch)
tree575c1688a4632d3b46fc33752e875908804936b9
parent28ef1a8a4ad976fd044a6b5c089d5104c93ff75b (diff)
downloadMedia-595d15cd3506f6bb82d960f6878c665fba428ff1.tar.gz
Improve anaylitics for the playback queue
Fixes: 317269148 Fixes: 317277338 Test: manual with TestMediaApp and gradle Change-Id: Ia7ebd7c8e5735f1c9bac73a492bfa1941fee00cb
-rw-r--r--src/com/android/car/media/AnalyticsHelper.java19
-rw-r--r--src/com/android/car/media/BrowseViewController.java13
-rw-r--r--src/com/android/car/media/MediaActivity.java6
-rw-r--r--src/com/android/car/media/MediaActivityController.java15
-rw-r--r--src/com/android/car/media/NowPlayingController.java9
-rw-r--r--src/com/android/car/media/PlaybackQueueController.java61
6 files changed, 84 insertions, 39 deletions
diff --git a/src/com/android/car/media/AnalyticsHelper.java b/src/com/android/car/media/AnalyticsHelper.java
index bb94fa9..4d0b86a 100644
--- a/src/com/android/car/media/AnalyticsHelper.java
+++ b/src/com/android/car/media/AnalyticsHelper.java
@@ -19,7 +19,7 @@ package com.android.car.media;
import static androidx.car.app.mediaextensions.analytics.event.AnalyticsEvent.VIEW_ACTION_HIDE;
import static androidx.car.app.mediaextensions.analytics.event.AnalyticsEvent.VIEW_ACTION_MODE_NONE;
import static androidx.car.app.mediaextensions.analytics.event.AnalyticsEvent.VIEW_ACTION_MODE_SCROLL;
-import static androidx.car.app.mediaextensions.analytics.event.AnalyticsEvent.VIEW_COMPONENT_BROWSE_LIST;
+import static androidx.car.app.mediaextensions.analytics.event.AnalyticsEvent.VIEW_ACTION_SHOW;
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
import androidx.annotation.OptIn;
@@ -42,20 +42,20 @@ public class AnalyticsHelper {
* @return the currently visible items.
*/
public static List<String> sendVisibleItemsInc(
+ @AnalyticsEvent.ViewComponent int viewComp,
MediaItemsRepository repo, MediaItemMetadata parentItem, List<String> prevItems,
List<MediaItemMetadata> items, int currFirst, int currLast, boolean fromScroll) {
- //Handle empty list by hiding previous and returning empty.
+ // Handle empty list by hiding previous and returning empty.
if (items.isEmpty() && !prevItems.isEmpty()) {
repo.getAnalyticsManager().sendVisibleItemsEvents(
- parentItem != null ? parentItem.getId() : null,
- VIEW_COMPONENT_BROWSE_LIST, VIEW_ACTION_HIDE,
+ parentItem != null ? parentItem.getId() : null, viewComp, VIEW_ACTION_HIDE,
fromScroll ? VIEW_ACTION_MODE_SCROLL : VIEW_ACTION_MODE_NONE,
new ArrayList<>(prevItems));
return List.of();
}
- //If for any reason there are no visible items or error state
+ // If for any reason there are no visible items or error state
// we have nothing to show, hide prev
if (currFirst == NO_POSITION
|| currLast == NO_POSITION
@@ -64,8 +64,7 @@ public class AnalyticsHelper {
if (!prevItems.isEmpty()) {
repo.getAnalyticsManager().sendVisibleItemsEvents(
- parentItem != null ? parentItem.getId() : null,
- VIEW_COMPONENT_BROWSE_LIST, VIEW_ACTION_HIDE,
+ parentItem != null ? parentItem.getId() : null, viewComp, VIEW_ACTION_HIDE,
fromScroll ? VIEW_ACTION_MODE_SCROLL : VIEW_ACTION_MODE_NONE,
new ArrayList<>(prevItems));
}
@@ -91,15 +90,13 @@ public class AnalyticsHelper {
if (!delta.isEmpty()) {
repo.getAnalyticsManager().sendVisibleItemsEvents(
- parentItem != null ? parentItem.getId() : null,
- VIEW_COMPONENT_BROWSE_LIST, VIEW_ACTION_HIDE,
+ parentItem != null ? parentItem.getId() : null, viewComp, VIEW_ACTION_HIDE,
fromScroll ? VIEW_ACTION_MODE_SCROLL : VIEW_ACTION_MODE_NONE,
new ArrayList<>(delta));
}
if (!deltaNew.isEmpty()) {
repo.getAnalyticsManager().sendVisibleItemsEvents(
- parentItem != null ? parentItem.getId() : null,
- VIEW_COMPONENT_BROWSE_LIST, AnalyticsEvent.VIEW_ACTION_SHOW,
+ parentItem != null ? parentItem.getId() : null, viewComp, VIEW_ACTION_SHOW,
fromScroll ? VIEW_ACTION_MODE_SCROLL : VIEW_ACTION_MODE_NONE,
new ArrayList<>(deltaNew));
}
diff --git a/src/com/android/car/media/BrowseViewController.java b/src/com/android/car/media/BrowseViewController.java
index 9215576..75bf306 100644
--- a/src/com/android/car/media/BrowseViewController.java
+++ b/src/com/android/car/media/BrowseViewController.java
@@ -21,6 +21,7 @@ import static android.car.media.CarMediaManager.MEDIA_SOURCE_MODE_PLAYBACK;
import static androidx.car.app.mediaextensions.analytics.event.AnalyticsEvent.VIEW_ACTION_HIDE;
import static androidx.car.app.mediaextensions.analytics.event.AnalyticsEvent.VIEW_ACTION_SHOW;
+import static androidx.car.app.mediaextensions.analytics.event.AnalyticsEvent.VIEW_COMPONENT_BROWSE_LIST;
import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
import static com.android.car.apps.common.util.ViewUtils.removeFromParent;
@@ -164,7 +165,7 @@ public class BrowseViewController {
protected void onPlayableItemClicked(@NonNull MediaItemMetadata item) {
if (item.getId() != null) {
mMediaRepo.getAnalyticsManager().sendMediaClickedEvent(item.getId(),
- AnalyticsEvent.VIEW_COMPONENT_BROWSE_LIST);
+ VIEW_COMPONENT_BROWSE_LIST);
}
mCallbacks.onPlayableItemClicked(item);
}
@@ -173,7 +174,7 @@ public class BrowseViewController {
protected void onBrowsableItemClicked(@NonNull MediaItemMetadata item) {
if (item.getId() != null) {
mMediaRepo.getAnalyticsManager().sendMediaClickedEvent(item.getId(),
- AnalyticsEvent.VIEW_COMPONENT_BROWSE_LIST);
+ VIEW_COMPONENT_BROWSE_LIST);
}
mCallbacks.goToMediaItem(item);
}
@@ -218,7 +219,7 @@ public class BrowseViewController {
.collect(Collectors.toCollection(ArrayList::new));
mMediaRepo.getAnalyticsManager().sendVisibleItemsEvents(
- parentId, AnalyticsEvent.VIEW_COMPONENT_BROWSE_LIST,
+ parentId, VIEW_COMPONENT_BROWSE_LIST,
isShown ? AnalyticsEvent.VIEW_ACTION_SHOW : AnalyticsEvent.VIEW_ACTION_HIDE,
AnalyticsEvent.VIEW_ACTION_MODE_NONE, itemsSublist);
}
@@ -546,9 +547,9 @@ public class BrowseViewController {
&& mMediaItems.getValue().getData() != null) {
int currFirst = mLimitedBrowseAdapter.findFirstVisibleItemIndex();
int currLast = mLimitedBrowseAdapter.findLastVisibleItemIndex(true);
- mPrevVisible = AnalyticsHelper.sendVisibleItemsInc(mMediaRepo, mParentItem,
- mPrevVisible, mMediaItems.getValue().getData(), currFirst, currLast,
- fromScroll);
+ mPrevVisible = AnalyticsHelper.sendVisibleItemsInc(VIEW_COMPONENT_BROWSE_LIST,
+ mMediaRepo, mParentItem, mPrevVisible, mMediaItems.getValue().getData(),
+ currFirst, currLast, fromScroll);
}
}
diff --git a/src/com/android/car/media/MediaActivity.java b/src/com/android/car/media/MediaActivity.java
index 7e71326..3ef4d4b 100644
--- a/src/com/android/car/media/MediaActivity.java
+++ b/src/com/android/car/media/MediaActivity.java
@@ -610,6 +610,7 @@ public class MediaActivity extends FragmentActivity implements MediaActivityCont
VIEW_COMPONENT_BROWSE_LIST, VIEW_ACTION_HIDE);
break;
case PLAYBACK:
+ mMediaActivityController.onNpvActualVisibilityChanged(false);
getMediaItemsRepository().getAnalyticsManager().sendViewChangedEvent(
VIEW_COMPONENT_PLAYBACK, VIEW_ACTION_HIDE);
break;
@@ -632,7 +633,10 @@ public class MediaActivity extends FragmentActivity implements MediaActivityCont
mPlaybackContainer.setY(0);
mPlaybackContainer.setAlpha(0f);
ViewUtils.hideViewAnimated(mErrorContainer, fadeOutDuration);
- ViewUtils.showViewAnimated(mPlaybackContainer, mFadeDuration);
+ // Reporting the view as visible at the end of the animation gives a chance for the
+ // new queue to be loaded and avoids reporting the old queue as visible.
+ ViewUtils.showViewAnimated(mPlaybackContainer, mFadeDuration,
+ view -> mMediaActivityController.onNpvActualVisibilityChanged(true));
ViewUtils.hideViewAnimated(mBrowseContainer, fadeOutDuration);
getMediaItemsRepository().getAnalyticsManager().sendViewChangedEvent(
VIEW_COMPONENT_PLAYBACK, VIEW_ACTION_SHOW);
diff --git a/src/com/android/car/media/MediaActivityController.java b/src/com/android/car/media/MediaActivityController.java
index a1442f0..827118a 100644
--- a/src/com/android/car/media/MediaActivityController.java
+++ b/src/com/android/car/media/MediaActivityController.java
@@ -20,6 +20,7 @@ import static android.car.media.CarMediaManager.MEDIA_SOURCE_MODE_BROWSE;
import static android.car.media.CarMediaManager.MEDIA_SOURCE_MODE_PLAYBACK;
import static android.view.accessibility.AccessibilityNodeInfo.ACTION_FOCUS;
+import static androidx.car.app.mediaextensions.analytics.event.AnalyticsEvent.VIEW_COMPONENT_BROWSE_LIST;
import static androidx.car.app.mediaextensions.analytics.event.AnalyticsEvent.VIEW_COMPONENT_BROWSE_TABS;
import static com.android.car.apps.common.util.ViewUtils.showHideViewAnimated;
@@ -168,9 +169,9 @@ public class MediaActivityController extends ViewControllerBase {
(LimitedBrowseAdapter) toolbarSearchResultsView.getAdapter();
int currFirst = limitedBrowseAdapter.findFirstVisibleItemIndex();
int currLast = limitedBrowseAdapter.findLastVisibleItemIndex(canKeyboardCover);
- mPrevVisible = AnalyticsHelper.sendVisibleItemsInc(mediaItemsRepository, null,
- mPrevVisible, limitedBrowseAdapter.getItems(), currFirst, currLast,
- fromScroll);
+ mPrevVisible = AnalyticsHelper.sendVisibleItemsInc(VIEW_COMPONENT_BROWSE_LIST,
+ mediaItemsRepository, null, mPrevVisible, limitedBrowseAdapter.getItems(),
+ currFirst, currLast, fromScroll);
}
};
}
@@ -353,6 +354,14 @@ public class MediaActivityController extends ViewControllerBase {
mNowPlayingController.setListener(mNowPlayingListener);
}
+ /**
+ * Tells the Now Playing View controller what is actually happening to its view, so that it
+ * can be considered hidden right when a hiding animation starts.
+ */
+ public void onNpvActualVisibilityChanged(boolean isShown) {
+ mNowPlayingController.onActualVisibilityChanged(isShown);
+ }
+
private BrowseViewController recreateController(BrowseStack.BrowseEntry entry) {
switch (entry.mType) {
case TREE_ROOT:
diff --git a/src/com/android/car/media/NowPlayingController.java b/src/com/android/car/media/NowPlayingController.java
index eccaf2e..66eb7cf 100644
--- a/src/com/android/car/media/NowPlayingController.java
+++ b/src/com/android/car/media/NowPlayingController.java
@@ -245,6 +245,14 @@ public class NowPlayingController {
});
}
+ /**
+ * Tells the controller what is actually happening to its view, so that it can be
+ * considered hidden right when a hiding animation starts.
+ */
+ public void onActualVisibilityChanged(boolean isShown) {
+ mPlaybackQueueController.onActualVisibilityChanged(isShown && mQueueIsVisible);
+ }
+
private void initPlaybackControls(PlaybackControlsActionBar playbackControls) {
mPlaybackControls = playbackControls;
mPlaybackControls.setModel(mPlaybackViewModel, getActivity());
@@ -358,6 +366,7 @@ public class NowPlayingController {
if (mQueueIsVisible != visible) {
mQueueIsVisible = visible;
+ mPlaybackQueueController.onActualVisibilityChanged(mQueueIsVisible);
if (mQueueIsVisible) {
ViewUtils.showViewsAnimated(mViewsToShowWhenQueueIsVisible, mFadeDuration);
ViewUtils.hideViewsAnimated(mViewsToHideWhenQueueIsVisible, mFadeDuration);
diff --git a/src/com/android/car/media/PlaybackQueueController.java b/src/com/android/car/media/PlaybackQueueController.java
index defc404..538c44e 100644
--- a/src/com/android/car/media/PlaybackQueueController.java
+++ b/src/com/android/car/media/PlaybackQueueController.java
@@ -16,6 +16,9 @@
package com.android.car.media;
+import static androidx.car.app.mediaextensions.analytics.event.AnalyticsEvent.VIEW_COMPONENT_QUEUE_LIST;
+import static androidx.recyclerview.widget.RecyclerView.NO_POSITION;
+
import static com.android.car.ui.recyclerview.RangeFilter.INVALID_INDEX;
import android.content.Context;
@@ -66,22 +69,24 @@ public class PlaybackQueueController {
private static final String TAG = "PlaybackQueueController";
- private Callbacks mCallbacks;
- private LifeCycleObserverUxrContentLimiter mUxrContentLimiter;
- private PlaybackViewModel mPlaybackViewModel;
- private MediaItemsRepository mMediaItemsRepository;
+ private final Callbacks mCallbacks;
+ private final LifeCycleObserverUxrContentLimiter mUxrContentLimiter;
+ private final PlaybackViewModel mPlaybackViewModel;
+ private final MediaItemsRepository mMediaItemsRepository;
private QueueItemsAdapter mQueueAdapter;
- private CarUiRecyclerView mQueue;
+ private boolean mIsActuallyVisible = false;
+ private List<String> mPrevVisibleItems = new ArrayList<>();
+ private final CarUiRecyclerView mQueue;
private PlaybackQueueCallback mPlaybackQueueCallback;
private DefaultItemAnimator mItemAnimator;
private PlaybackViewModel.PlaybackController mController;
private Long mActiveQueueItemId;
- private boolean mShowTimeForActiveQueueItem;
- private boolean mShowIconForActiveQueueItem;
- private boolean mShowThumbnailForQueueItem;
- private boolean mShowSubtitleForQueueItem;
+ private final boolean mShowTimeForActiveQueueItem;
+ private final boolean mShowIconForActiveQueueItem;
+ private final boolean mShowThumbnailForQueueItem;
+ private final boolean mShowSubtitleForQueueItem;
/**
* The callbacks used to communicate the user interactions to the queue fragment listeners.
@@ -510,6 +515,31 @@ public class PlaybackQueueController {
mPlaybackQueueCallback = callback;
}
+ /**
+ * Tells the controller what is actually happening to its view, so that it can be
+ * considered hidden right when a hiding animation starts.
+ */
+ public void onActualVisibilityChanged(boolean isVisible) {
+ if (mIsActuallyVisible != isVisible) {
+ mIsActuallyVisible = isVisible;
+ sendVisibleItemsIncremental(isVisible, false);
+ }
+ }
+
+ private void sendVisibleItemsIncremental(boolean isShown, boolean fromScroll) {
+ if (isShown) {
+ int currFirst = mQueueAdapter.findFirstVisibleItemIndex();
+ int currLast = mQueueAdapter.findLastVisibleItemIndex();
+ mPrevVisibleItems = AnalyticsHelper.sendVisibleItemsInc(VIEW_COMPONENT_QUEUE_LIST,
+ mMediaItemsRepository, null, mPrevVisibleItems, mQueueAdapter.mQueueItems,
+ currFirst, currLast, fromScroll);
+ } else {
+ mPrevVisibleItems = AnalyticsHelper.sendVisibleItemsInc(VIEW_COMPONENT_QUEUE_LIST,
+ mMediaItemsRepository, null, mPrevVisibleItems, mQueueAdapter.mQueueItems,
+ NO_POSITION, NO_POSITION, false);
+ }
+ }
+
private void initQueue() {
int decorationHeight = getActivity().getResources().getDimensionPixelSize(
@@ -534,24 +564,16 @@ public class PlaybackQueueController {
});
mQueue.setAdapter(mQueueAdapter);
mQueue.addOnScrollListener(new CarUiRecyclerView.OnScrollListener() {
- List<String> mPrevVisible = new ArrayList<>();
@Override
public void onScrolled(CarUiRecyclerView recyclerView, int dx, int dy) {
//dx and dy are 0 when items in RV change or layout is requested. We should
// use this to trigger querying what is visible.
- sendScrollEvent(dx != 0 || dy != 0);
+ sendVisibleItemsIncremental(true, (dx != 0 || dy != 0));
}
@Override
public void onScrollStateChanged(CarUiRecyclerView recyclerView, int newState) {}
-
- private void sendScrollEvent(boolean fromScroll) {
- int currFirst = mQueueAdapter.findFirstVisibleItemIndex();
- int currLast = mQueueAdapter.findLastVisibleItemIndex();
- mPrevVisible = AnalyticsHelper.sendVisibleItemsInc(mMediaItemsRepository, null,
- mPrevVisible, mQueueAdapter.mQueueItems, currFirst, currLast, fromScroll);
- }
});
// Disable item changed animation.
mItemAnimator = new DefaultItemAnimator();
@@ -570,6 +592,9 @@ public class PlaybackQueueController {
void setQueue(List<MediaItemMetadata> queueItems) {
mQueueAdapter.setItems(queueItems);
+ if (mIsActuallyVisible) {
+ sendVisibleItemsIncremental(/* visible */ true, /* fromScroll */ false);
+ }
}
private void onQueueItemClicked(MediaItemMetadata item) {