Loading packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt +20 −12 Original line number Original line Diff line number Diff line Loading @@ -12,6 +12,7 @@ import android.view.View import android.view.ViewGroup import android.view.ViewGroup import android.widget.LinearLayout import android.widget.LinearLayout import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting import com.android.internal.logging.InstanceId import com.android.systemui.Dumpable import com.android.systemui.Dumpable import com.android.systemui.R import com.android.systemui.R import com.android.systemui.classifier.FalsingCollector import com.android.systemui.classifier.FalsingCollector Loading Loading @@ -59,7 +60,7 @@ class MediaCarouselController @Inject constructor( falsingCollector: FalsingCollector, falsingCollector: FalsingCollector, falsingManager: FalsingManager, falsingManager: FalsingManager, dumpManager: DumpManager, dumpManager: DumpManager, private val mediaFlags: MediaFlags private val logger: MediaUiEventLogger ) : Dumpable { ) : Dumpable { /** /** * The current width of the carousel * The current width of the carousel Loading Loading @@ -119,7 +120,9 @@ class MediaCarouselController @Inject constructor( private val mediaCarousel: MediaScrollView private val mediaCarousel: MediaScrollView val mediaCarouselScrollHandler: MediaCarouselScrollHandler val mediaCarouselScrollHandler: MediaCarouselScrollHandler val mediaFrame: ViewGroup val mediaFrame: ViewGroup private lateinit var settingsButton: View @VisibleForTesting lateinit var settingsButton: View private set private val mediaContent: ViewGroup private val mediaContent: ViewGroup private val pageIndicator: PageIndicator private val pageIndicator: PageIndicator private val visualStabilityCallback: OnReorderingAllowedListener private val visualStabilityCallback: OnReorderingAllowedListener Loading Loading @@ -183,7 +186,8 @@ class MediaCarouselController @Inject constructor( pageIndicator = mediaFrame.requireViewById(R.id.media_page_indicator) pageIndicator = mediaFrame.requireViewById(R.id.media_page_indicator) mediaCarouselScrollHandler = MediaCarouselScrollHandler(mediaCarousel, pageIndicator, mediaCarouselScrollHandler = MediaCarouselScrollHandler(mediaCarousel, pageIndicator, executor, this::onSwipeToDismiss, this::updatePageIndicatorLocation, executor, this::onSwipeToDismiss, this::updatePageIndicatorLocation, this::closeGuts, falsingCollector, falsingManager, this::logSmartspaceImpression) this::closeGuts, falsingCollector, falsingManager, this::logSmartspaceImpression, logger) isRtl = context.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL isRtl = context.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL inflateSettingsButton() inflateSettingsButton() mediaContent = mediaCarousel.requireViewById(R.id.media_carousel) mediaContent = mediaCarousel.requireViewById(R.id.media_carousel) Loading Loading @@ -220,7 +224,7 @@ class MediaCarouselController @Inject constructor( MediaPlayerData.getMediaPlayer(key)?.let { MediaPlayerData.getMediaPlayer(key)?.let { /* ktlint-disable max-line-length */ /* ktlint-disable max-line-length */ logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED it.mInstanceId, it.mSmartspaceId, it.mUid, it.mUid, /* isRecommendationCard */ false, /* isRecommendationCard */ false, intArrayOf( intArrayOf( Loading @@ -239,12 +243,12 @@ class MediaCarouselController @Inject constructor( // resume card is ranked first // resume card is ranked first MediaPlayerData.players().forEachIndexed { index, it -> MediaPlayerData.players().forEachIndexed { index, it -> if (it.recommendationViewHolder == null) { if (it.recommendationViewHolder == null) { it.mInstanceId = SmallHash.hash(it.mUid + it.mSmartspaceId = SmallHash.hash(it.mUid + systemClock.currentTimeMillis().toInt()) systemClock.currentTimeMillis().toInt()) it.mIsImpressed = false it.mIsImpressed = false /* ktlint-disable max-line-length */ /* ktlint-disable max-line-length */ logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED it.mInstanceId, it.mSmartspaceId, it.mUid, it.mUid, /* isRecommendationCard */ false, /* isRecommendationCard */ false, intArrayOf( intArrayOf( Loading Loading @@ -291,12 +295,12 @@ class MediaCarouselController @Inject constructor( // recommendation card is valid and ranked first // recommendation card is valid and ranked first MediaPlayerData.players().forEachIndexed { index, it -> MediaPlayerData.players().forEachIndexed { index, it -> if (it.recommendationViewHolder == null) { if (it.recommendationViewHolder == null) { it.mInstanceId = SmallHash.hash(it.mUid + it.mSmartspaceId = SmallHash.hash(it.mUid + systemClock.currentTimeMillis().toInt()) systemClock.currentTimeMillis().toInt()) it.mIsImpressed = false it.mIsImpressed = false /* ktlint-disable max-line-length */ /* ktlint-disable max-line-length */ logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED it.mInstanceId, it.mSmartspaceId, it.mUid, it.mUid, /* isRecommendationCard */ false, /* isRecommendationCard */ false, intArrayOf( intArrayOf( Loading @@ -312,7 +316,7 @@ class MediaCarouselController @Inject constructor( MediaPlayerData.getMediaPlayer(key)?.let { MediaPlayerData.getMediaPlayer(key)?.let { /* ktlint-disable max-line-length */ /* ktlint-disable max-line-length */ logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED it.mInstanceId, it.mSmartspaceId, it.mUid, it.mUid, /* isRecommendationCard */ true, /* isRecommendationCard */ true, intArrayOf( intArrayOf( Loading Loading @@ -369,6 +373,7 @@ class MediaCarouselController @Inject constructor( mediaFrame.addView(settingsButton) mediaFrame.addView(settingsButton) mediaCarouselScrollHandler.onSettingsButtonUpdated(settings) mediaCarouselScrollHandler.onSettingsButtonUpdated(settings) settingsButton.setOnClickListener { settingsButton.setOnClickListener { logger.logCarouselSettings() activityStarter.startActivity(settingsIntent, true /* dismissShade */) activityStarter.startActivity(settingsIntent, true /* dismissShade */) } } } } Loading Loading @@ -752,7 +757,7 @@ class MediaCarouselController @Inject constructor( return return } } logSmartspaceCardReported(800, // SMARTSPACE_CARD_SEEN logSmartspaceCardReported(800, // SMARTSPACE_CARD_SEEN mediaControlPanel.mInstanceId, mediaControlPanel.mSmartspaceId, mediaControlPanel.mUid, mediaControlPanel.mUid, isRecommendationCard, isRecommendationCard, intArrayOf(mediaControlPanel.surfaceForSmartspaceLogging)) intArrayOf(mediaControlPanel.surfaceForSmartspaceLogging)) Loading Loading @@ -836,7 +841,7 @@ class MediaCarouselController @Inject constructor( index, it -> index, it -> if (it.mIsImpressed) { if (it.mIsImpressed) { logSmartspaceCardReported(SMARTSPACE_CARD_DISMISS_EVENT, logSmartspaceCardReported(SMARTSPACE_CARD_DISMISS_EVENT, it.mInstanceId, it.mSmartspaceId, it.mUid, it.mUid, it.recommendationViewHolder != null, it.recommendationViewHolder != null, intArrayOf(it.surfaceForSmartspaceLogging), intArrayOf(it.surfaceForSmartspaceLogging), Loading @@ -846,6 +851,7 @@ class MediaCarouselController @Inject constructor( it.mIsImpressed = false it.mIsImpressed = false } } } } logger.logSwipeDismiss() mediaManager.onSwipeToDismiss() mediaManager.onSwipeToDismiss() } } Loading Loading @@ -881,7 +887,9 @@ internal object MediaPlayerData { clickIntent = null, clickIntent = null, device = null, device = null, active = true, active = true, resumeAction = null) resumeAction = null, instanceId = InstanceId.fakeInstanceId(-1), appUid = -1) // Whether should prioritize Smartspace card. // Whether should prioritize Smartspace card. internal var shouldPrioritizeSs: Boolean = false internal var shouldPrioritizeSs: Boolean = false private set private set Loading packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt +4 −2 Original line number Original line Diff line number Diff line Loading @@ -57,12 +57,13 @@ class MediaCarouselScrollHandler( private val scrollView: MediaScrollView, private val scrollView: MediaScrollView, private val pageIndicator: PageIndicator, private val pageIndicator: PageIndicator, private val mainExecutor: DelayableExecutor, private val mainExecutor: DelayableExecutor, private val dismissCallback: () -> Unit, val dismissCallback: () -> Unit, private var translationChangedListener: () -> Unit, private var translationChangedListener: () -> Unit, private val closeGuts: (immediate: Boolean) -> Unit, private val closeGuts: (immediate: Boolean) -> Unit, private val falsingCollector: FalsingCollector, private val falsingCollector: FalsingCollector, private val falsingManager: FalsingManager, private val falsingManager: FalsingManager, private val logSmartspaceImpression: (Boolean) -> Unit private val logSmartspaceImpression: (Boolean) -> Unit, private val logger: MediaUiEventLogger ) { ) { /** /** * Is the view in RTL * Is the view in RTL Loading Loading @@ -476,6 +477,7 @@ class MediaCarouselScrollHandler( visibleMediaIndex = newIndex visibleMediaIndex = newIndex if (oldIndex != visibleMediaIndex && visibleToUser) { if (oldIndex != visibleMediaIndex && visibleToUser) { logSmartspaceImpression(qsExpanded) logSmartspaceImpression(qsExpanded) logger.logMediaCarouselPage(newIndex) } } closeGuts(false) closeGuts(false) updatePlayerVisibilities() updatePlayerVisibilities() Loading packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +25 −16 Original line number Original line Diff line number Diff line Loading @@ -53,6 +53,7 @@ import androidx.annotation.UiThread; import androidx.constraintlayout.widget.ConstraintSet; import androidx.constraintlayout.widget.ConstraintSet; import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.logging.InstanceId; import com.android.settingslib.widget.AdaptiveIcon; import com.android.settingslib.widget.AdaptiveIcon; import com.android.systemui.R; import com.android.systemui.R; import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.animation.ActivityLaunchAnimator; Loading Loading @@ -131,8 +132,6 @@ public class MediaControlPanel { private MediaController mController; private MediaController mController; private Lazy<MediaDataManager> mMediaDataManagerLazy; private Lazy<MediaDataManager> mMediaDataManagerLazy; private int mBackgroundColor; private int mBackgroundColor; // Instance id for logging purpose. protected int mInstanceId = -1; // Uid for the media app. // Uid for the media app. protected int mUid = Process.INVALID_UID; protected int mUid = Process.INVALID_UID; private int mSmartspaceMediaItemsCount; private int mSmartspaceMediaItemsCount; Loading @@ -140,9 +139,13 @@ public class MediaControlPanel { private final MediaOutputDialogFactory mMediaOutputDialogFactory; private final MediaOutputDialogFactory mMediaOutputDialogFactory; private final FalsingManager mFalsingManager; private final FalsingManager mFalsingManager; // Used for swipe-to-dismiss logging. // Used for logging. protected boolean mIsImpressed = false; protected boolean mIsImpressed = false; private SystemClock mSystemClock; private SystemClock mSystemClock; private MediaUiEventLogger mLogger; private InstanceId mInstanceId; protected int mSmartspaceId = -1; private String mPackageName; /** /** * Initialize a new control panel * Initialize a new control panel Loading @@ -157,7 +160,7 @@ public class MediaControlPanel { Lazy<MediaDataManager> lazyMediaDataManager, Lazy<MediaDataManager> lazyMediaDataManager, MediaOutputDialogFactory mediaOutputDialogFactory, MediaOutputDialogFactory mediaOutputDialogFactory, MediaCarouselController mediaCarouselController, MediaCarouselController mediaCarouselController, FalsingManager falsingManager, SystemClock systemClock) { FalsingManager falsingManager, SystemClock systemClock, MediaUiEventLogger logger) { mContext = context; mContext = context; mBackgroundExecutor = backgroundExecutor; mBackgroundExecutor = backgroundExecutor; mActivityStarter = activityStarter; mActivityStarter = activityStarter; Loading @@ -169,8 +172,12 @@ public class MediaControlPanel { mMediaCarouselController = mediaCarouselController; mMediaCarouselController = mediaCarouselController; mFalsingManager = falsingManager; mFalsingManager = falsingManager; mSystemClock = systemClock; mSystemClock = systemClock; mLogger = logger; mSeekBarViewModel.setLogSmartspaceClick(() -> { mSeekBarViewModel.setLogSeek(() -> { if (mPackageName != null && mInstanceId != null) { mLogger.logSeek(mUid, mPackageName, mInstanceId); } logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT, logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT, /* isRecommendationCard */ false); /* isRecommendationCard */ false); return Unit.INSTANCE; return Unit.INSTANCE; Loading Loading @@ -261,6 +268,7 @@ public class MediaControlPanel { }); }); vh.getSettings().setOnClickListener(v -> { vh.getSettings().setOnClickListener(v -> { if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { mLogger.logLongPressSettings(mUid, mPackageName, mInstanceId); mActivityStarter.startActivity(SETTINGS_INTENT, true /* dismissShade */); mActivityStarter.startActivity(SETTINGS_INTENT, true /* dismissShade */); } } }); }); Loading Loading @@ -301,16 +309,13 @@ public class MediaControlPanel { } } mKey = key; mKey = key; MediaSession.Token token = data.getToken(); MediaSession.Token token = data.getToken(); PackageManager packageManager = mContext.getPackageManager(); mPackageName = data.getPackageName(); try { mUid = data.getAppUid(); mUid = packageManager.getApplicationInfo(data.getPackageName(), 0 /* flags */).uid; } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, "Unable to look up package name", e); } // Only assigns instance id if it's unassigned. // Only assigns instance id if it's unassigned. if (mInstanceId == -1) { if (mSmartspaceId == -1) { mInstanceId = SmallHash.hash(mUid + (int) mSystemClock.currentTimeMillis()); mSmartspaceId = SmallHash.hash(mUid + (int) mSystemClock.currentTimeMillis()); } } mInstanceId = data.getInstanceId(); mBackgroundColor = data.getBackgroundColor(); mBackgroundColor = data.getBackgroundColor(); if (mToken == null || !mToken.equals(token)) { if (mToken == null || !mToken.equals(token)) { Loading Loading @@ -401,6 +406,7 @@ public class MediaControlPanel { if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { return; return; } } mLogger.logOpenOutputSwitcher(mUid, mPackageName, mInstanceId); if (device.getIntent() != null) { if (device.getIntent() != null) { if (device.getIntent().isActivity()) { if (device.getIntent().isActivity()) { mActivityStarter.startActivity( mActivityStarter.startActivity( Loading @@ -413,7 +419,7 @@ public class MediaControlPanel { } } } } } else { } else { mMediaOutputDialogFactory.create(data.getPackageName(), true, mMediaOutputDialogFactory.create(mPackageName, true, mMediaViewHolder.getSeamlessButton()); mMediaViewHolder.getSeamlessButton()); } } }); }); Loading @@ -437,6 +443,7 @@ public class MediaControlPanel { logSmartspaceCardReported(SMARTSPACE_CARD_DISMISS_EVENT, logSmartspaceCardReported(SMARTSPACE_CARD_DISMISS_EVENT, /* isRecommendationCard */ false); /* isRecommendationCard */ false); mLogger.logLongPressDismiss(mUid, mPackageName, mInstanceId); if (mKey != null) { if (mKey != null) { closeGuts(); closeGuts(); Loading Loading @@ -675,6 +682,7 @@ public class MediaControlPanel { button.setEnabled(true); button.setEnabled(true); button.setOnClickListener(v -> { button.setOnClickListener(v -> { if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { mLogger.logTapAction(button.getId(), mUid, mPackageName, mInstanceId); logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT, logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT, /* isRecommendationCard */ false); /* isRecommendationCard */ false); action.run(); action.run(); Loading Loading @@ -794,7 +802,7 @@ public class MediaControlPanel { return; return; } } mInstanceId = SmallHash.hash(data.getTargetId()); mSmartspaceId = SmallHash.hash(data.getTargetId()); mBackgroundColor = data.getBackgroundColor(); mBackgroundColor = data.getBackgroundColor(); TransitionLayout recommendationCard = mRecommendationViewHolder.getRecommendations(); TransitionLayout recommendationCard = mRecommendationViewHolder.getRecommendations(); recommendationCard.setBackgroundTintList(ColorStateList.valueOf(mBackgroundColor)); recommendationCard.setBackgroundTintList(ColorStateList.valueOf(mBackgroundColor)); Loading Loading @@ -976,6 +984,7 @@ public class MediaControlPanel { mRecommendationViewHolder.marquee(true, mMediaViewController.GUTS_ANIMATION_DURATION); mRecommendationViewHolder.marquee(true, mMediaViewController.GUTS_ANIMATION_DURATION); } } mMediaViewController.openGuts(); mMediaViewController.openGuts(); mLogger.logLongPressOpen(mUid, mPackageName, mInstanceId); } } /** /** Loading Loading @@ -1138,7 +1147,7 @@ public class MediaControlPanel { private void logSmartspaceCardReported(int eventId, boolean isRecommendationCard, private void logSmartspaceCardReported(int eventId, boolean isRecommendationCard, int interactedSubcardRank, int interactedSubcardCardinality) { int interactedSubcardRank, int interactedSubcardCardinality) { mMediaCarouselController.logSmartspaceCardReported(eventId, mMediaCarouselController.logSmartspaceCardReported(eventId, mInstanceId, mSmartspaceId, mUid, mUid, isRecommendationCard, isRecommendationCard, new int[]{getSurfaceForSmartspaceLogging()}, new int[]{getSurfaceForSmartspaceLogging()}, Loading packages/SystemUI/src/com/android/systemui/media/MediaData.kt +12 −1 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.app.PendingIntent import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable import android.graphics.drawable.Icon import android.graphics.drawable.Icon import android.media.session.MediaSession import android.media.session.MediaSession import com.android.internal.logging.InstanceId import com.android.systemui.R import com.android.systemui.R /** State of a media view. */ /** State of a media view. */ Loading Loading @@ -115,7 +116,17 @@ data class MediaData( /** /** * Timestamp when this player was last active. * Timestamp when this player was last active. */ */ var lastActive: Long = 0L var lastActive: Long = 0L, /** * Instance ID for logging purposes */ val instanceId: InstanceId, /** * The UID of the app, used for logging */ val appUid: Int ) { ) { companion object { companion object { /** Media is playing on the local device */ /** Media is playing on the local device */ Loading packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +75 −15 Original line number Original line Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.content.ContentResolver import android.content.Context import android.content.Context import android.content.Intent import android.content.Intent import android.content.IntentFilter import android.content.IntentFilter import android.content.pm.PackageManager import android.graphics.Bitmap import android.graphics.Bitmap import android.graphics.ImageDecoder import android.graphics.ImageDecoder import android.graphics.drawable.Icon import android.graphics.drawable.Icon Loading @@ -37,6 +38,7 @@ import android.media.session.MediaSession import android.media.session.PlaybackState import android.media.session.PlaybackState import android.net.Uri import android.net.Uri import android.os.Parcelable import android.os.Parcelable import android.os.Process import android.os.UserHandle import android.os.UserHandle import android.provider.Settings import android.provider.Settings import android.service.notification.StatusBarNotification import android.service.notification.StatusBarNotification Loading @@ -44,6 +46,7 @@ import android.text.TextUtils import android.util.Log import android.util.Log import androidx.media.utils.MediaConstants import androidx.media.utils.MediaConstants import com.android.internal.annotations.VisibleForTesting import com.android.internal.annotations.VisibleForTesting import com.android.internal.logging.InstanceId import com.android.systemui.Dumpable import com.android.systemui.Dumpable import com.android.systemui.R import com.android.systemui.R import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.broadcast.BroadcastDispatcher Loading Loading @@ -94,7 +97,9 @@ private val LOADING = MediaData( clickIntent = null, clickIntent = null, device = null, device = null, active = true, active = true, resumeAction = null) resumeAction = null, instanceId = InstanceId.fakeInstanceId(-1), appUid = Process.INVALID_UID) @VisibleForTesting @VisibleForTesting internal val EMPTY_SMARTSPACE_MEDIA_DATA = SmartspaceMediaData("INVALID", false, false, internal val EMPTY_SMARTSPACE_MEDIA_DATA = SmartspaceMediaData("INVALID", false, false, Loading Loading @@ -138,7 +143,8 @@ class MediaDataManager( private val useQsMediaPlayer: Boolean, private val useQsMediaPlayer: Boolean, private val systemClock: SystemClock, private val systemClock: SystemClock, private val tunerService: TunerService, private val tunerService: TunerService, private val mediaFlags: MediaFlags private val mediaFlags: MediaFlags, private val logger: MediaUiEventLogger ) : Dumpable, BcSmartspaceDataPlugin.SmartspaceTargetListener { ) : Dumpable, BcSmartspaceDataPlugin.SmartspaceTargetListener { companion object { companion object { Loading Loading @@ -202,12 +208,13 @@ class MediaDataManager( smartspaceMediaDataProvider: SmartspaceMediaDataProvider, smartspaceMediaDataProvider: SmartspaceMediaDataProvider, clock: SystemClock, clock: SystemClock, tunerService: TunerService, tunerService: TunerService, mediaFlags: MediaFlags mediaFlags: MediaFlags, logger: MediaUiEventLogger ) : this(context, backgroundExecutor, foregroundExecutor, mediaControllerFactory, ) : this(context, backgroundExecutor, foregroundExecutor, mediaControllerFactory, broadcastDispatcher, dumpManager, mediaTimeoutListener, mediaResumeListener, broadcastDispatcher, dumpManager, mediaTimeoutListener, mediaResumeListener, mediaSessionBasedFilter, mediaDeviceManager, mediaDataCombineLatest, mediaDataFilter, mediaSessionBasedFilter, mediaDeviceManager, mediaDataCombineLatest, mediaDataFilter, activityStarter, smartspaceMediaDataProvider, Utils.useMediaResumption(context), activityStarter, smartspaceMediaDataProvider, Utils.useMediaResumption(context), Utils.useQsMediaPlayer(context), clock, tunerService, mediaFlags) Utils.useQsMediaPlayer(context), clock, tunerService, mediaFlags, logger) private val appChangeReceiver = object : BroadcastReceiver() { private val appChangeReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) { Loading Loading @@ -298,17 +305,24 @@ class MediaDataManager( fun onNotificationAdded(key: String, sbn: StatusBarNotification) { fun onNotificationAdded(key: String, sbn: StatusBarNotification) { if (useQsMediaPlayer && isMediaNotification(sbn)) { if (useQsMediaPlayer && isMediaNotification(sbn)) { var logEvent = false Assert.isMainThread() Assert.isMainThread() val oldKey = findExistingEntry(key, sbn.packageName) val oldKey = findExistingEntry(key, sbn.packageName) if (oldKey == null) { if (oldKey == null) { val temp = LOADING.copy(packageName = sbn.packageName) val instanceId = logger.getNewInstanceId() val temp = LOADING.copy( packageName = sbn.packageName, instanceId = instanceId ) mediaEntries.put(key, temp) mediaEntries.put(key, temp) logEvent = true } else if (oldKey != key) { } else if (oldKey != key) { // Move to new key // Resume -> active conversion; move to new key val oldData = mediaEntries.remove(oldKey)!! val oldData = mediaEntries.remove(oldKey)!! logEvent = true mediaEntries.put(key, oldData) mediaEntries.put(key, oldData) } } loadMediaData(key, sbn, oldKey) loadMediaData(key, sbn, oldKey, logEvent) } else { } else { onNotificationRemoved(key) onNotificationRemoved(key) } } Loading Loading @@ -340,9 +354,23 @@ class MediaDataManager( ) { ) { // Resume controls don't have a notification key, so store by package name instead // Resume controls don't have a notification key, so store by package name instead if (!mediaEntries.containsKey(packageName)) { if (!mediaEntries.containsKey(packageName)) { val resumeData = LOADING.copy(packageName = packageName, resumeAction = action, val instanceId = logger.getNewInstanceId() hasCheckedForResume = true) val appUid = try { context.packageManager.getApplicationInfo(packageName, 0)?.uid!! } catch (e: PackageManager.NameNotFoundException) { Log.w(TAG, "Could not get app UID for $packageName", e) Process.INVALID_UID } val resumeData = LOADING.copy( packageName = packageName, resumeAction = action, hasCheckedForResume = true, instanceId = instanceId, appUid = appUid ) mediaEntries.put(packageName, resumeData) mediaEntries.put(packageName, resumeData) logger.logResumeMediaAdded(appUid, packageName, instanceId) } } backgroundExecutor.execute { backgroundExecutor.execute { loadMediaDataInBgForResumption(userId, desc, action, token, appName, appIntent, loadMediaDataInBgForResumption(userId, desc, action, token, appName, appIntent, Loading @@ -368,10 +396,11 @@ class MediaDataManager( private fun loadMediaData( private fun loadMediaData( key: String, key: String, sbn: StatusBarNotification, sbn: StatusBarNotification, oldKey: String? oldKey: String?, logEvent: Boolean = false ) { ) { backgroundExecutor.execute { backgroundExecutor.execute { loadMediaDataInBg(key, sbn, oldKey) loadMediaDataInBg(key, sbn, oldKey, logEvent) } } } } Loading Loading @@ -449,6 +478,10 @@ class MediaDataManager( */ */ internal fun setTimedOut(key: String, timedOut: Boolean, forceUpdate: Boolean = false) { internal fun setTimedOut(key: String, timedOut: Boolean, forceUpdate: Boolean = false) { mediaEntries[key]?.let { mediaEntries[key]?.let { if (timedOut && !forceUpdate) { // Only log this event when media expires on its own logger.logMediaTimeout(it.appUid, it.packageName, it.instanceId) } if (it.active == !timedOut && !forceUpdate) { if (it.active == !timedOut && !forceUpdate) { if (it.resumption) { if (it.resumption) { if (DEBUG) Log.d(TAG, "timing out resume player $key") if (DEBUG) Log.d(TAG, "timing out resume player $key") Loading @@ -463,7 +496,9 @@ class MediaDataManager( } } private fun removeEntry(key: String) { private fun removeEntry(key: String) { mediaEntries.remove(key) mediaEntries.remove(key)?.let { logger.logMediaRemoved(it.appUid, it.packageName, it.instanceId) } notifyMediaDataRemoved(key) notifyMediaDataRemoved(key) } } Loading Loading @@ -537,6 +572,10 @@ class MediaDataManager( null null } } val currentEntry = mediaEntries.get(packageName) val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId() val appUid = currentEntry?.appUid ?: Process.INVALID_UID val mediaAction = getResumeMediaAction(resumeAction) val mediaAction = getResumeMediaAction(resumeAction) val lastActive = systemClock.elapsedRealtime() val lastActive = systemClock.elapsedRealtime() foregroundExecutor.execute { foregroundExecutor.execute { Loading @@ -545,14 +584,16 @@ class MediaDataManager( MediaButton(playOrPause = mediaAction), packageName, token, appIntent, MediaButton(playOrPause = mediaAction), packageName, token, appIntent, device = null, active = false, device = null, active = false, resumeAction = resumeAction, resumption = true, notificationKey = packageName, resumeAction = resumeAction, resumption = true, notificationKey = packageName, hasCheckedForResume = true, lastActive = lastActive)) hasCheckedForResume = true, lastActive = lastActive, instanceId = instanceId, appUid = appUid)) } } } } private fun loadMediaDataInBg( private fun loadMediaDataInBg( key: String, key: String, sbn: StatusBarNotification, sbn: StatusBarNotification, oldKey: String? oldKey: String?, logEvent: Boolean = false ) { ) { val token = sbn.notification.extras.getParcelable(Notification.EXTRA_MEDIA_SESSION) val token = sbn.notification.extras.getParcelable(Notification.EXTRA_MEDIA_SESSION) as MediaSession.Token? as MediaSession.Token? Loading Loading @@ -636,6 +677,22 @@ class MediaDataManager( MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL) MediaData.PLAYBACK_LOCAL MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL) MediaData.PLAYBACK_LOCAL else MediaData.PLAYBACK_CAST_LOCAL else MediaData.PLAYBACK_CAST_LOCAL val isPlaying = mediaController.playbackState?.let { isPlayingState(it.state) } ?: null val isPlaying = mediaController.playbackState?.let { isPlayingState(it.state) } ?: null val currentEntry = mediaEntries.get(key) val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId() val appUid = try { context.packageManager.getApplicationInfo(sbn.packageName, 0)?.uid!! } catch (e: PackageManager.NameNotFoundException) { Log.w(TAG, "Could not get app UID for ${sbn.packageName}", e) Process.INVALID_UID } if (logEvent) { logger.logActiveMediaAdded(appUid, sbn.packageName, instanceId, playbackLocation) } else if (playbackLocation != currentEntry?.playbackLocation) { logger.logPlaybackLocationChange(appUid, sbn.packageName, instanceId, playbackLocation) } val lastActive = systemClock.elapsedRealtime() val lastActive = systemClock.elapsedRealtime() foregroundExecutor.execute { foregroundExecutor.execute { val resumeAction: Runnable? = mediaEntries[key]?.resumeAction val resumeAction: Runnable? = mediaEntries[key]?.resumeAction Loading @@ -647,7 +704,7 @@ class MediaDataManager( active, resumeAction = resumeAction, playbackLocation = playbackLocation, active, resumeAction = resumeAction, playbackLocation = playbackLocation, notificationKey = key, hasCheckedForResume = hasCheckedForResume, notificationKey = key, hasCheckedForResume = hasCheckedForResume, isPlaying = isPlaying, isClearable = sbn.isClearable(), isPlaying = isPlaying, isClearable = sbn.isClearable(), lastActive = lastActive)) lastActive = lastActive, instanceId = instanceId, appUid = appUid)) } } } } Loading Loading @@ -989,10 +1046,12 @@ class MediaDataManager( notifyMediaDataRemoved(key) notifyMediaDataRemoved(key) notifyMediaDataLoaded(pkg, pkg, updated) notifyMediaDataLoaded(pkg, pkg, updated) } } logger.logActiveConvertedToResume(updated.appUid, pkg, updated.instanceId) return return } } if (removed != null) { if (removed != null) { notifyMediaDataRemoved(key) notifyMediaDataRemoved(key) logger.logMediaRemoved(removed.appUid, removed.packageName, removed.instanceId) } } } } Loading @@ -1009,6 +1068,7 @@ class MediaDataManager( filtered.forEach { filtered.forEach { mediaEntries.remove(it.key) mediaEntries.remove(it.key) notifyMediaDataRemoved(it.key) notifyMediaDataRemoved(it.key) logger.logMediaRemoved(it.value.appUid, it.value.packageName, it.value.instanceId) } } } } } } Loading Loading
packages/SystemUI/src/com/android/systemui/media/MediaCarouselController.kt +20 −12 Original line number Original line Diff line number Diff line Loading @@ -12,6 +12,7 @@ import android.view.View import android.view.ViewGroup import android.view.ViewGroup import android.widget.LinearLayout import android.widget.LinearLayout import androidx.annotation.VisibleForTesting import androidx.annotation.VisibleForTesting import com.android.internal.logging.InstanceId import com.android.systemui.Dumpable import com.android.systemui.Dumpable import com.android.systemui.R import com.android.systemui.R import com.android.systemui.classifier.FalsingCollector import com.android.systemui.classifier.FalsingCollector Loading Loading @@ -59,7 +60,7 @@ class MediaCarouselController @Inject constructor( falsingCollector: FalsingCollector, falsingCollector: FalsingCollector, falsingManager: FalsingManager, falsingManager: FalsingManager, dumpManager: DumpManager, dumpManager: DumpManager, private val mediaFlags: MediaFlags private val logger: MediaUiEventLogger ) : Dumpable { ) : Dumpable { /** /** * The current width of the carousel * The current width of the carousel Loading Loading @@ -119,7 +120,9 @@ class MediaCarouselController @Inject constructor( private val mediaCarousel: MediaScrollView private val mediaCarousel: MediaScrollView val mediaCarouselScrollHandler: MediaCarouselScrollHandler val mediaCarouselScrollHandler: MediaCarouselScrollHandler val mediaFrame: ViewGroup val mediaFrame: ViewGroup private lateinit var settingsButton: View @VisibleForTesting lateinit var settingsButton: View private set private val mediaContent: ViewGroup private val mediaContent: ViewGroup private val pageIndicator: PageIndicator private val pageIndicator: PageIndicator private val visualStabilityCallback: OnReorderingAllowedListener private val visualStabilityCallback: OnReorderingAllowedListener Loading Loading @@ -183,7 +186,8 @@ class MediaCarouselController @Inject constructor( pageIndicator = mediaFrame.requireViewById(R.id.media_page_indicator) pageIndicator = mediaFrame.requireViewById(R.id.media_page_indicator) mediaCarouselScrollHandler = MediaCarouselScrollHandler(mediaCarousel, pageIndicator, mediaCarouselScrollHandler = MediaCarouselScrollHandler(mediaCarousel, pageIndicator, executor, this::onSwipeToDismiss, this::updatePageIndicatorLocation, executor, this::onSwipeToDismiss, this::updatePageIndicatorLocation, this::closeGuts, falsingCollector, falsingManager, this::logSmartspaceImpression) this::closeGuts, falsingCollector, falsingManager, this::logSmartspaceImpression, logger) isRtl = context.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL isRtl = context.resources.configuration.layoutDirection == View.LAYOUT_DIRECTION_RTL inflateSettingsButton() inflateSettingsButton() mediaContent = mediaCarousel.requireViewById(R.id.media_carousel) mediaContent = mediaCarousel.requireViewById(R.id.media_carousel) Loading Loading @@ -220,7 +224,7 @@ class MediaCarouselController @Inject constructor( MediaPlayerData.getMediaPlayer(key)?.let { MediaPlayerData.getMediaPlayer(key)?.let { /* ktlint-disable max-line-length */ /* ktlint-disable max-line-length */ logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED it.mInstanceId, it.mSmartspaceId, it.mUid, it.mUid, /* isRecommendationCard */ false, /* isRecommendationCard */ false, intArrayOf( intArrayOf( Loading @@ -239,12 +243,12 @@ class MediaCarouselController @Inject constructor( // resume card is ranked first // resume card is ranked first MediaPlayerData.players().forEachIndexed { index, it -> MediaPlayerData.players().forEachIndexed { index, it -> if (it.recommendationViewHolder == null) { if (it.recommendationViewHolder == null) { it.mInstanceId = SmallHash.hash(it.mUid + it.mSmartspaceId = SmallHash.hash(it.mUid + systemClock.currentTimeMillis().toInt()) systemClock.currentTimeMillis().toInt()) it.mIsImpressed = false it.mIsImpressed = false /* ktlint-disable max-line-length */ /* ktlint-disable max-line-length */ logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED it.mInstanceId, it.mSmartspaceId, it.mUid, it.mUid, /* isRecommendationCard */ false, /* isRecommendationCard */ false, intArrayOf( intArrayOf( Loading Loading @@ -291,12 +295,12 @@ class MediaCarouselController @Inject constructor( // recommendation card is valid and ranked first // recommendation card is valid and ranked first MediaPlayerData.players().forEachIndexed { index, it -> MediaPlayerData.players().forEachIndexed { index, it -> if (it.recommendationViewHolder == null) { if (it.recommendationViewHolder == null) { it.mInstanceId = SmallHash.hash(it.mUid + it.mSmartspaceId = SmallHash.hash(it.mUid + systemClock.currentTimeMillis().toInt()) systemClock.currentTimeMillis().toInt()) it.mIsImpressed = false it.mIsImpressed = false /* ktlint-disable max-line-length */ /* ktlint-disable max-line-length */ logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED it.mInstanceId, it.mSmartspaceId, it.mUid, it.mUid, /* isRecommendationCard */ false, /* isRecommendationCard */ false, intArrayOf( intArrayOf( Loading @@ -312,7 +316,7 @@ class MediaCarouselController @Inject constructor( MediaPlayerData.getMediaPlayer(key)?.let { MediaPlayerData.getMediaPlayer(key)?.let { /* ktlint-disable max-line-length */ /* ktlint-disable max-line-length */ logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED logSmartspaceCardReported(759, // SMARTSPACE_CARD_RECEIVED it.mInstanceId, it.mSmartspaceId, it.mUid, it.mUid, /* isRecommendationCard */ true, /* isRecommendationCard */ true, intArrayOf( intArrayOf( Loading Loading @@ -369,6 +373,7 @@ class MediaCarouselController @Inject constructor( mediaFrame.addView(settingsButton) mediaFrame.addView(settingsButton) mediaCarouselScrollHandler.onSettingsButtonUpdated(settings) mediaCarouselScrollHandler.onSettingsButtonUpdated(settings) settingsButton.setOnClickListener { settingsButton.setOnClickListener { logger.logCarouselSettings() activityStarter.startActivity(settingsIntent, true /* dismissShade */) activityStarter.startActivity(settingsIntent, true /* dismissShade */) } } } } Loading Loading @@ -752,7 +757,7 @@ class MediaCarouselController @Inject constructor( return return } } logSmartspaceCardReported(800, // SMARTSPACE_CARD_SEEN logSmartspaceCardReported(800, // SMARTSPACE_CARD_SEEN mediaControlPanel.mInstanceId, mediaControlPanel.mSmartspaceId, mediaControlPanel.mUid, mediaControlPanel.mUid, isRecommendationCard, isRecommendationCard, intArrayOf(mediaControlPanel.surfaceForSmartspaceLogging)) intArrayOf(mediaControlPanel.surfaceForSmartspaceLogging)) Loading Loading @@ -836,7 +841,7 @@ class MediaCarouselController @Inject constructor( index, it -> index, it -> if (it.mIsImpressed) { if (it.mIsImpressed) { logSmartspaceCardReported(SMARTSPACE_CARD_DISMISS_EVENT, logSmartspaceCardReported(SMARTSPACE_CARD_DISMISS_EVENT, it.mInstanceId, it.mSmartspaceId, it.mUid, it.mUid, it.recommendationViewHolder != null, it.recommendationViewHolder != null, intArrayOf(it.surfaceForSmartspaceLogging), intArrayOf(it.surfaceForSmartspaceLogging), Loading @@ -846,6 +851,7 @@ class MediaCarouselController @Inject constructor( it.mIsImpressed = false it.mIsImpressed = false } } } } logger.logSwipeDismiss() mediaManager.onSwipeToDismiss() mediaManager.onSwipeToDismiss() } } Loading Loading @@ -881,7 +887,9 @@ internal object MediaPlayerData { clickIntent = null, clickIntent = null, device = null, device = null, active = true, active = true, resumeAction = null) resumeAction = null, instanceId = InstanceId.fakeInstanceId(-1), appUid = -1) // Whether should prioritize Smartspace card. // Whether should prioritize Smartspace card. internal var shouldPrioritizeSs: Boolean = false internal var shouldPrioritizeSs: Boolean = false private set private set Loading
packages/SystemUI/src/com/android/systemui/media/MediaCarouselScrollHandler.kt +4 −2 Original line number Original line Diff line number Diff line Loading @@ -57,12 +57,13 @@ class MediaCarouselScrollHandler( private val scrollView: MediaScrollView, private val scrollView: MediaScrollView, private val pageIndicator: PageIndicator, private val pageIndicator: PageIndicator, private val mainExecutor: DelayableExecutor, private val mainExecutor: DelayableExecutor, private val dismissCallback: () -> Unit, val dismissCallback: () -> Unit, private var translationChangedListener: () -> Unit, private var translationChangedListener: () -> Unit, private val closeGuts: (immediate: Boolean) -> Unit, private val closeGuts: (immediate: Boolean) -> Unit, private val falsingCollector: FalsingCollector, private val falsingCollector: FalsingCollector, private val falsingManager: FalsingManager, private val falsingManager: FalsingManager, private val logSmartspaceImpression: (Boolean) -> Unit private val logSmartspaceImpression: (Boolean) -> Unit, private val logger: MediaUiEventLogger ) { ) { /** /** * Is the view in RTL * Is the view in RTL Loading Loading @@ -476,6 +477,7 @@ class MediaCarouselScrollHandler( visibleMediaIndex = newIndex visibleMediaIndex = newIndex if (oldIndex != visibleMediaIndex && visibleToUser) { if (oldIndex != visibleMediaIndex && visibleToUser) { logSmartspaceImpression(qsExpanded) logSmartspaceImpression(qsExpanded) logger.logMediaCarouselPage(newIndex) } } closeGuts(false) closeGuts(false) updatePlayerVisibilities() updatePlayerVisibilities() Loading
packages/SystemUI/src/com/android/systemui/media/MediaControlPanel.java +25 −16 Original line number Original line Diff line number Diff line Loading @@ -53,6 +53,7 @@ import androidx.annotation.UiThread; import androidx.constraintlayout.widget.ConstraintSet; import androidx.constraintlayout.widget.ConstraintSet; import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.jank.InteractionJankMonitor; import com.android.internal.logging.InstanceId; import com.android.settingslib.widget.AdaptiveIcon; import com.android.settingslib.widget.AdaptiveIcon; import com.android.systemui.R; import com.android.systemui.R; import com.android.systemui.animation.ActivityLaunchAnimator; import com.android.systemui.animation.ActivityLaunchAnimator; Loading Loading @@ -131,8 +132,6 @@ public class MediaControlPanel { private MediaController mController; private MediaController mController; private Lazy<MediaDataManager> mMediaDataManagerLazy; private Lazy<MediaDataManager> mMediaDataManagerLazy; private int mBackgroundColor; private int mBackgroundColor; // Instance id for logging purpose. protected int mInstanceId = -1; // Uid for the media app. // Uid for the media app. protected int mUid = Process.INVALID_UID; protected int mUid = Process.INVALID_UID; private int mSmartspaceMediaItemsCount; private int mSmartspaceMediaItemsCount; Loading @@ -140,9 +139,13 @@ public class MediaControlPanel { private final MediaOutputDialogFactory mMediaOutputDialogFactory; private final MediaOutputDialogFactory mMediaOutputDialogFactory; private final FalsingManager mFalsingManager; private final FalsingManager mFalsingManager; // Used for swipe-to-dismiss logging. // Used for logging. protected boolean mIsImpressed = false; protected boolean mIsImpressed = false; private SystemClock mSystemClock; private SystemClock mSystemClock; private MediaUiEventLogger mLogger; private InstanceId mInstanceId; protected int mSmartspaceId = -1; private String mPackageName; /** /** * Initialize a new control panel * Initialize a new control panel Loading @@ -157,7 +160,7 @@ public class MediaControlPanel { Lazy<MediaDataManager> lazyMediaDataManager, Lazy<MediaDataManager> lazyMediaDataManager, MediaOutputDialogFactory mediaOutputDialogFactory, MediaOutputDialogFactory mediaOutputDialogFactory, MediaCarouselController mediaCarouselController, MediaCarouselController mediaCarouselController, FalsingManager falsingManager, SystemClock systemClock) { FalsingManager falsingManager, SystemClock systemClock, MediaUiEventLogger logger) { mContext = context; mContext = context; mBackgroundExecutor = backgroundExecutor; mBackgroundExecutor = backgroundExecutor; mActivityStarter = activityStarter; mActivityStarter = activityStarter; Loading @@ -169,8 +172,12 @@ public class MediaControlPanel { mMediaCarouselController = mediaCarouselController; mMediaCarouselController = mediaCarouselController; mFalsingManager = falsingManager; mFalsingManager = falsingManager; mSystemClock = systemClock; mSystemClock = systemClock; mLogger = logger; mSeekBarViewModel.setLogSmartspaceClick(() -> { mSeekBarViewModel.setLogSeek(() -> { if (mPackageName != null && mInstanceId != null) { mLogger.logSeek(mUid, mPackageName, mInstanceId); } logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT, logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT, /* isRecommendationCard */ false); /* isRecommendationCard */ false); return Unit.INSTANCE; return Unit.INSTANCE; Loading Loading @@ -261,6 +268,7 @@ public class MediaControlPanel { }); }); vh.getSettings().setOnClickListener(v -> { vh.getSettings().setOnClickListener(v -> { if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { mLogger.logLongPressSettings(mUid, mPackageName, mInstanceId); mActivityStarter.startActivity(SETTINGS_INTENT, true /* dismissShade */); mActivityStarter.startActivity(SETTINGS_INTENT, true /* dismissShade */); } } }); }); Loading Loading @@ -301,16 +309,13 @@ public class MediaControlPanel { } } mKey = key; mKey = key; MediaSession.Token token = data.getToken(); MediaSession.Token token = data.getToken(); PackageManager packageManager = mContext.getPackageManager(); mPackageName = data.getPackageName(); try { mUid = data.getAppUid(); mUid = packageManager.getApplicationInfo(data.getPackageName(), 0 /* flags */).uid; } catch (PackageManager.NameNotFoundException e) { Log.e(TAG, "Unable to look up package name", e); } // Only assigns instance id if it's unassigned. // Only assigns instance id if it's unassigned. if (mInstanceId == -1) { if (mSmartspaceId == -1) { mInstanceId = SmallHash.hash(mUid + (int) mSystemClock.currentTimeMillis()); mSmartspaceId = SmallHash.hash(mUid + (int) mSystemClock.currentTimeMillis()); } } mInstanceId = data.getInstanceId(); mBackgroundColor = data.getBackgroundColor(); mBackgroundColor = data.getBackgroundColor(); if (mToken == null || !mToken.equals(token)) { if (mToken == null || !mToken.equals(token)) { Loading Loading @@ -401,6 +406,7 @@ public class MediaControlPanel { if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { if (mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { return; return; } } mLogger.logOpenOutputSwitcher(mUid, mPackageName, mInstanceId); if (device.getIntent() != null) { if (device.getIntent() != null) { if (device.getIntent().isActivity()) { if (device.getIntent().isActivity()) { mActivityStarter.startActivity( mActivityStarter.startActivity( Loading @@ -413,7 +419,7 @@ public class MediaControlPanel { } } } } } else { } else { mMediaOutputDialogFactory.create(data.getPackageName(), true, mMediaOutputDialogFactory.create(mPackageName, true, mMediaViewHolder.getSeamlessButton()); mMediaViewHolder.getSeamlessButton()); } } }); }); Loading @@ -437,6 +443,7 @@ public class MediaControlPanel { logSmartspaceCardReported(SMARTSPACE_CARD_DISMISS_EVENT, logSmartspaceCardReported(SMARTSPACE_CARD_DISMISS_EVENT, /* isRecommendationCard */ false); /* isRecommendationCard */ false); mLogger.logLongPressDismiss(mUid, mPackageName, mInstanceId); if (mKey != null) { if (mKey != null) { closeGuts(); closeGuts(); Loading Loading @@ -675,6 +682,7 @@ public class MediaControlPanel { button.setEnabled(true); button.setEnabled(true); button.setOnClickListener(v -> { button.setOnClickListener(v -> { if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { if (!mFalsingManager.isFalseTap(FalsingManager.LOW_PENALTY)) { mLogger.logTapAction(button.getId(), mUid, mPackageName, mInstanceId); logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT, logSmartspaceCardReported(SMARTSPACE_CARD_CLICK_EVENT, /* isRecommendationCard */ false); /* isRecommendationCard */ false); action.run(); action.run(); Loading Loading @@ -794,7 +802,7 @@ public class MediaControlPanel { return; return; } } mInstanceId = SmallHash.hash(data.getTargetId()); mSmartspaceId = SmallHash.hash(data.getTargetId()); mBackgroundColor = data.getBackgroundColor(); mBackgroundColor = data.getBackgroundColor(); TransitionLayout recommendationCard = mRecommendationViewHolder.getRecommendations(); TransitionLayout recommendationCard = mRecommendationViewHolder.getRecommendations(); recommendationCard.setBackgroundTintList(ColorStateList.valueOf(mBackgroundColor)); recommendationCard.setBackgroundTintList(ColorStateList.valueOf(mBackgroundColor)); Loading Loading @@ -976,6 +984,7 @@ public class MediaControlPanel { mRecommendationViewHolder.marquee(true, mMediaViewController.GUTS_ANIMATION_DURATION); mRecommendationViewHolder.marquee(true, mMediaViewController.GUTS_ANIMATION_DURATION); } } mMediaViewController.openGuts(); mMediaViewController.openGuts(); mLogger.logLongPressOpen(mUid, mPackageName, mInstanceId); } } /** /** Loading Loading @@ -1138,7 +1147,7 @@ public class MediaControlPanel { private void logSmartspaceCardReported(int eventId, boolean isRecommendationCard, private void logSmartspaceCardReported(int eventId, boolean isRecommendationCard, int interactedSubcardRank, int interactedSubcardCardinality) { int interactedSubcardRank, int interactedSubcardCardinality) { mMediaCarouselController.logSmartspaceCardReported(eventId, mMediaCarouselController.logSmartspaceCardReported(eventId, mInstanceId, mSmartspaceId, mUid, mUid, isRecommendationCard, isRecommendationCard, new int[]{getSurfaceForSmartspaceLogging()}, new int[]{getSurfaceForSmartspaceLogging()}, Loading
packages/SystemUI/src/com/android/systemui/media/MediaData.kt +12 −1 Original line number Original line Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.app.PendingIntent import android.graphics.drawable.Drawable import android.graphics.drawable.Drawable import android.graphics.drawable.Icon import android.graphics.drawable.Icon import android.media.session.MediaSession import android.media.session.MediaSession import com.android.internal.logging.InstanceId import com.android.systemui.R import com.android.systemui.R /** State of a media view. */ /** State of a media view. */ Loading Loading @@ -115,7 +116,17 @@ data class MediaData( /** /** * Timestamp when this player was last active. * Timestamp when this player was last active. */ */ var lastActive: Long = 0L var lastActive: Long = 0L, /** * Instance ID for logging purposes */ val instanceId: InstanceId, /** * The UID of the app, used for logging */ val appUid: Int ) { ) { companion object { companion object { /** Media is playing on the local device */ /** Media is playing on the local device */ Loading
packages/SystemUI/src/com/android/systemui/media/MediaDataManager.kt +75 −15 Original line number Original line Diff line number Diff line Loading @@ -27,6 +27,7 @@ import android.content.ContentResolver import android.content.Context import android.content.Context import android.content.Intent import android.content.Intent import android.content.IntentFilter import android.content.IntentFilter import android.content.pm.PackageManager import android.graphics.Bitmap import android.graphics.Bitmap import android.graphics.ImageDecoder import android.graphics.ImageDecoder import android.graphics.drawable.Icon import android.graphics.drawable.Icon Loading @@ -37,6 +38,7 @@ import android.media.session.MediaSession import android.media.session.PlaybackState import android.media.session.PlaybackState import android.net.Uri import android.net.Uri import android.os.Parcelable import android.os.Parcelable import android.os.Process import android.os.UserHandle import android.os.UserHandle import android.provider.Settings import android.provider.Settings import android.service.notification.StatusBarNotification import android.service.notification.StatusBarNotification Loading @@ -44,6 +46,7 @@ import android.text.TextUtils import android.util.Log import android.util.Log import androidx.media.utils.MediaConstants import androidx.media.utils.MediaConstants import com.android.internal.annotations.VisibleForTesting import com.android.internal.annotations.VisibleForTesting import com.android.internal.logging.InstanceId import com.android.systemui.Dumpable import com.android.systemui.Dumpable import com.android.systemui.R import com.android.systemui.R import com.android.systemui.broadcast.BroadcastDispatcher import com.android.systemui.broadcast.BroadcastDispatcher Loading Loading @@ -94,7 +97,9 @@ private val LOADING = MediaData( clickIntent = null, clickIntent = null, device = null, device = null, active = true, active = true, resumeAction = null) resumeAction = null, instanceId = InstanceId.fakeInstanceId(-1), appUid = Process.INVALID_UID) @VisibleForTesting @VisibleForTesting internal val EMPTY_SMARTSPACE_MEDIA_DATA = SmartspaceMediaData("INVALID", false, false, internal val EMPTY_SMARTSPACE_MEDIA_DATA = SmartspaceMediaData("INVALID", false, false, Loading Loading @@ -138,7 +143,8 @@ class MediaDataManager( private val useQsMediaPlayer: Boolean, private val useQsMediaPlayer: Boolean, private val systemClock: SystemClock, private val systemClock: SystemClock, private val tunerService: TunerService, private val tunerService: TunerService, private val mediaFlags: MediaFlags private val mediaFlags: MediaFlags, private val logger: MediaUiEventLogger ) : Dumpable, BcSmartspaceDataPlugin.SmartspaceTargetListener { ) : Dumpable, BcSmartspaceDataPlugin.SmartspaceTargetListener { companion object { companion object { Loading Loading @@ -202,12 +208,13 @@ class MediaDataManager( smartspaceMediaDataProvider: SmartspaceMediaDataProvider, smartspaceMediaDataProvider: SmartspaceMediaDataProvider, clock: SystemClock, clock: SystemClock, tunerService: TunerService, tunerService: TunerService, mediaFlags: MediaFlags mediaFlags: MediaFlags, logger: MediaUiEventLogger ) : this(context, backgroundExecutor, foregroundExecutor, mediaControllerFactory, ) : this(context, backgroundExecutor, foregroundExecutor, mediaControllerFactory, broadcastDispatcher, dumpManager, mediaTimeoutListener, mediaResumeListener, broadcastDispatcher, dumpManager, mediaTimeoutListener, mediaResumeListener, mediaSessionBasedFilter, mediaDeviceManager, mediaDataCombineLatest, mediaDataFilter, mediaSessionBasedFilter, mediaDeviceManager, mediaDataCombineLatest, mediaDataFilter, activityStarter, smartspaceMediaDataProvider, Utils.useMediaResumption(context), activityStarter, smartspaceMediaDataProvider, Utils.useMediaResumption(context), Utils.useQsMediaPlayer(context), clock, tunerService, mediaFlags) Utils.useQsMediaPlayer(context), clock, tunerService, mediaFlags, logger) private val appChangeReceiver = object : BroadcastReceiver() { private val appChangeReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context, intent: Intent) { override fun onReceive(context: Context, intent: Intent) { Loading Loading @@ -298,17 +305,24 @@ class MediaDataManager( fun onNotificationAdded(key: String, sbn: StatusBarNotification) { fun onNotificationAdded(key: String, sbn: StatusBarNotification) { if (useQsMediaPlayer && isMediaNotification(sbn)) { if (useQsMediaPlayer && isMediaNotification(sbn)) { var logEvent = false Assert.isMainThread() Assert.isMainThread() val oldKey = findExistingEntry(key, sbn.packageName) val oldKey = findExistingEntry(key, sbn.packageName) if (oldKey == null) { if (oldKey == null) { val temp = LOADING.copy(packageName = sbn.packageName) val instanceId = logger.getNewInstanceId() val temp = LOADING.copy( packageName = sbn.packageName, instanceId = instanceId ) mediaEntries.put(key, temp) mediaEntries.put(key, temp) logEvent = true } else if (oldKey != key) { } else if (oldKey != key) { // Move to new key // Resume -> active conversion; move to new key val oldData = mediaEntries.remove(oldKey)!! val oldData = mediaEntries.remove(oldKey)!! logEvent = true mediaEntries.put(key, oldData) mediaEntries.put(key, oldData) } } loadMediaData(key, sbn, oldKey) loadMediaData(key, sbn, oldKey, logEvent) } else { } else { onNotificationRemoved(key) onNotificationRemoved(key) } } Loading Loading @@ -340,9 +354,23 @@ class MediaDataManager( ) { ) { // Resume controls don't have a notification key, so store by package name instead // Resume controls don't have a notification key, so store by package name instead if (!mediaEntries.containsKey(packageName)) { if (!mediaEntries.containsKey(packageName)) { val resumeData = LOADING.copy(packageName = packageName, resumeAction = action, val instanceId = logger.getNewInstanceId() hasCheckedForResume = true) val appUid = try { context.packageManager.getApplicationInfo(packageName, 0)?.uid!! } catch (e: PackageManager.NameNotFoundException) { Log.w(TAG, "Could not get app UID for $packageName", e) Process.INVALID_UID } val resumeData = LOADING.copy( packageName = packageName, resumeAction = action, hasCheckedForResume = true, instanceId = instanceId, appUid = appUid ) mediaEntries.put(packageName, resumeData) mediaEntries.put(packageName, resumeData) logger.logResumeMediaAdded(appUid, packageName, instanceId) } } backgroundExecutor.execute { backgroundExecutor.execute { loadMediaDataInBgForResumption(userId, desc, action, token, appName, appIntent, loadMediaDataInBgForResumption(userId, desc, action, token, appName, appIntent, Loading @@ -368,10 +396,11 @@ class MediaDataManager( private fun loadMediaData( private fun loadMediaData( key: String, key: String, sbn: StatusBarNotification, sbn: StatusBarNotification, oldKey: String? oldKey: String?, logEvent: Boolean = false ) { ) { backgroundExecutor.execute { backgroundExecutor.execute { loadMediaDataInBg(key, sbn, oldKey) loadMediaDataInBg(key, sbn, oldKey, logEvent) } } } } Loading Loading @@ -449,6 +478,10 @@ class MediaDataManager( */ */ internal fun setTimedOut(key: String, timedOut: Boolean, forceUpdate: Boolean = false) { internal fun setTimedOut(key: String, timedOut: Boolean, forceUpdate: Boolean = false) { mediaEntries[key]?.let { mediaEntries[key]?.let { if (timedOut && !forceUpdate) { // Only log this event when media expires on its own logger.logMediaTimeout(it.appUid, it.packageName, it.instanceId) } if (it.active == !timedOut && !forceUpdate) { if (it.active == !timedOut && !forceUpdate) { if (it.resumption) { if (it.resumption) { if (DEBUG) Log.d(TAG, "timing out resume player $key") if (DEBUG) Log.d(TAG, "timing out resume player $key") Loading @@ -463,7 +496,9 @@ class MediaDataManager( } } private fun removeEntry(key: String) { private fun removeEntry(key: String) { mediaEntries.remove(key) mediaEntries.remove(key)?.let { logger.logMediaRemoved(it.appUid, it.packageName, it.instanceId) } notifyMediaDataRemoved(key) notifyMediaDataRemoved(key) } } Loading Loading @@ -537,6 +572,10 @@ class MediaDataManager( null null } } val currentEntry = mediaEntries.get(packageName) val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId() val appUid = currentEntry?.appUid ?: Process.INVALID_UID val mediaAction = getResumeMediaAction(resumeAction) val mediaAction = getResumeMediaAction(resumeAction) val lastActive = systemClock.elapsedRealtime() val lastActive = systemClock.elapsedRealtime() foregroundExecutor.execute { foregroundExecutor.execute { Loading @@ -545,14 +584,16 @@ class MediaDataManager( MediaButton(playOrPause = mediaAction), packageName, token, appIntent, MediaButton(playOrPause = mediaAction), packageName, token, appIntent, device = null, active = false, device = null, active = false, resumeAction = resumeAction, resumption = true, notificationKey = packageName, resumeAction = resumeAction, resumption = true, notificationKey = packageName, hasCheckedForResume = true, lastActive = lastActive)) hasCheckedForResume = true, lastActive = lastActive, instanceId = instanceId, appUid = appUid)) } } } } private fun loadMediaDataInBg( private fun loadMediaDataInBg( key: String, key: String, sbn: StatusBarNotification, sbn: StatusBarNotification, oldKey: String? oldKey: String?, logEvent: Boolean = false ) { ) { val token = sbn.notification.extras.getParcelable(Notification.EXTRA_MEDIA_SESSION) val token = sbn.notification.extras.getParcelable(Notification.EXTRA_MEDIA_SESSION) as MediaSession.Token? as MediaSession.Token? Loading Loading @@ -636,6 +677,22 @@ class MediaDataManager( MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL) MediaData.PLAYBACK_LOCAL MediaController.PlaybackInfo.PLAYBACK_TYPE_LOCAL) MediaData.PLAYBACK_LOCAL else MediaData.PLAYBACK_CAST_LOCAL else MediaData.PLAYBACK_CAST_LOCAL val isPlaying = mediaController.playbackState?.let { isPlayingState(it.state) } ?: null val isPlaying = mediaController.playbackState?.let { isPlayingState(it.state) } ?: null val currentEntry = mediaEntries.get(key) val instanceId = currentEntry?.instanceId ?: logger.getNewInstanceId() val appUid = try { context.packageManager.getApplicationInfo(sbn.packageName, 0)?.uid!! } catch (e: PackageManager.NameNotFoundException) { Log.w(TAG, "Could not get app UID for ${sbn.packageName}", e) Process.INVALID_UID } if (logEvent) { logger.logActiveMediaAdded(appUid, sbn.packageName, instanceId, playbackLocation) } else if (playbackLocation != currentEntry?.playbackLocation) { logger.logPlaybackLocationChange(appUid, sbn.packageName, instanceId, playbackLocation) } val lastActive = systemClock.elapsedRealtime() val lastActive = systemClock.elapsedRealtime() foregroundExecutor.execute { foregroundExecutor.execute { val resumeAction: Runnable? = mediaEntries[key]?.resumeAction val resumeAction: Runnable? = mediaEntries[key]?.resumeAction Loading @@ -647,7 +704,7 @@ class MediaDataManager( active, resumeAction = resumeAction, playbackLocation = playbackLocation, active, resumeAction = resumeAction, playbackLocation = playbackLocation, notificationKey = key, hasCheckedForResume = hasCheckedForResume, notificationKey = key, hasCheckedForResume = hasCheckedForResume, isPlaying = isPlaying, isClearable = sbn.isClearable(), isPlaying = isPlaying, isClearable = sbn.isClearable(), lastActive = lastActive)) lastActive = lastActive, instanceId = instanceId, appUid = appUid)) } } } } Loading Loading @@ -989,10 +1046,12 @@ class MediaDataManager( notifyMediaDataRemoved(key) notifyMediaDataRemoved(key) notifyMediaDataLoaded(pkg, pkg, updated) notifyMediaDataLoaded(pkg, pkg, updated) } } logger.logActiveConvertedToResume(updated.appUid, pkg, updated.instanceId) return return } } if (removed != null) { if (removed != null) { notifyMediaDataRemoved(key) notifyMediaDataRemoved(key) logger.logMediaRemoved(removed.appUid, removed.packageName, removed.instanceId) } } } } Loading @@ -1009,6 +1068,7 @@ class MediaDataManager( filtered.forEach { filtered.forEach { mediaEntries.remove(it.key) mediaEntries.remove(it.key) notifyMediaDataRemoved(it.key) notifyMediaDataRemoved(it.key) logger.logMediaRemoved(it.value.appUid, it.value.packageName, it.value.instanceId) } } } } } } Loading