From 9027bda01f030669d78b9f8314de390716998cd0 Mon Sep 17 00:00:00 2001 From: Lucas Dupin Date: Tue, 28 May 2019 14:34:47 -0700 Subject: [PATCH] Fix stale media metadata Checking if the metadata object is the same is not enough, we must check if the fields are also the same, otherwise we can skip events. It's also necessary to wait for a while before removing the media, otherwise animation would be janky. Test: adb shell input keyevent 87 Fixes: 133378688 Change-Id: I7847c8e435f35f4ab596f2aa2cc9296f06d5df26 --- .../keyguard/KeyguardSliceProvider.java | 63 ++++++++++++++----- 1 file changed, 47 insertions(+), 16 deletions(-) diff --git a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java index 35b8d203cbe28..d4c73668d0ed1 100644 --- a/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java +++ b/packages/SystemUI/src/com/android/systemui/keyguard/KeyguardSliceProvider.java @@ -56,6 +56,8 @@ import com.android.systemui.statusbar.policy.NextAlarmController; import com.android.systemui.statusbar.policy.NextAlarmControllerImpl; import com.android.systemui.statusbar.policy.ZenModeController; import com.android.systemui.statusbar.policy.ZenModeControllerImpl; +import com.android.systemui.util.wakelock.SettableWakeLock; +import com.android.systemui.util.wakelock.WakeLock; import java.util.Date; import java.util.HashSet; @@ -101,6 +103,8 @@ public class KeyguardSliceProvider extends SliceProvider implements private final Handler mHandler; private final AlarmManager.OnAlarmListener mUpdateNextAlarm = this::updateNextAlarm; private final HashSet mMediaInvisibleStates; + private final Object mMediaToken = new Object(); + private SettableWakeLock mMediaWakeLock; private ZenModeController mZenModeController; private String mDatePattern; private DateFormat mDateFormat; @@ -114,7 +118,8 @@ public class KeyguardSliceProvider extends SliceProvider implements private PendingIntent mPendingIntent; protected NotificationMediaManager mMediaManager; private StatusBarStateController mStatusBarStateController; - protected MediaMetadata mMediaMetaData; + private CharSequence mMediaTitle; + private CharSequence mMediaArtist; protected boolean mDozing; private boolean mMediaIsVisible; @@ -218,24 +223,18 @@ public class KeyguardSliceProvider extends SliceProvider implements } protected boolean needsMediaLocked() { - return mMediaMetaData != null && mMediaIsVisible && mDozing; + return !TextUtils.isEmpty(mMediaTitle) && mMediaIsVisible && mDozing; } protected void addMediaLocked(ListBuilder listBuilder) { - if (mMediaMetaData == null) { + if (TextUtils.isEmpty(mMediaTitle)) { return; } + listBuilder.setHeader(new ListBuilder.HeaderBuilder(mHeaderUri).setTitle(mMediaTitle)); - CharSequence title = mMediaMetaData.getText(MediaMetadata.METADATA_KEY_TITLE); - if (TextUtils.isEmpty(title)) { - title = getContext().getResources().getString(R.string.music_controls_no_title); - } - listBuilder.setHeader(new ListBuilder.HeaderBuilder(mHeaderUri).setTitle(title)); - - CharSequence album = mMediaMetaData.getText(MediaMetadata.METADATA_KEY_ARTIST); - if (!TextUtils.isEmpty(album)) { + if (!TextUtils.isEmpty(mMediaArtist)) { RowBuilder albumBuilder = new RowBuilder(mMediaUri); - albumBuilder.setTitle(album); + albumBuilder.setTitle(mMediaArtist); Icon mediaIcon = mMediaManager == null ? null : mMediaManager.getMediaIcon(); IconCompat mediaIconCompat = mediaIcon == null ? null @@ -306,6 +305,8 @@ public class KeyguardSliceProvider extends SliceProvider implements mZenModeController.addCallback(this); mDatePattern = getContext().getString(R.string.system_ui_aod_date_pattern); mPendingIntent = PendingIntent.getActivity(getContext(), 0, new Intent(), 0); + mMediaWakeLock = new SettableWakeLock(WakeLock.createPartial(getContext(), "media"), + "media"); KeyguardSliceProvider.sInstance = this; registerClockUpdate(); updateClockLocked(); @@ -425,12 +426,42 @@ public class KeyguardSliceProvider extends SliceProvider implements public void onMetadataOrStateChanged(MediaMetadata metadata, @PlaybackState.State int state) { synchronized (this) { boolean nextVisible = !mMediaInvisibleStates.contains(state); - if (nextVisible == mMediaIsVisible && metadata == mMediaMetaData) { - return; + mHandler.removeCallbacksAndMessages(mMediaToken); + if (mMediaIsVisible && !nextVisible) { + // We need to delay this event for a few millis when stopping to avoid jank in the + // animation. The media app might not send its update when buffering, and the slice + // would end up without a header for 0.5 second. + mMediaWakeLock.setAcquired(true); + mHandler.postDelayed(() -> { + updateMediaStateLocked(metadata, state); + mMediaWakeLock.setAcquired(false); + }, mMediaToken, 2000); + } else { + mMediaWakeLock.setAcquired(false); + updateMediaStateLocked(metadata, state); } - mMediaMetaData = metadata; - mMediaIsVisible = nextVisible; } + } + + private void updateMediaStateLocked(MediaMetadata metadata, @PlaybackState.State int state) { + boolean nextVisible = !mMediaInvisibleStates.contains(state); + CharSequence title = null; + if (metadata != null) { + title = metadata.getText(MediaMetadata.METADATA_KEY_TITLE); + if (TextUtils.isEmpty(title)) { + title = getContext().getResources().getString(R.string.music_controls_no_title); + } + } + CharSequence artist = metadata == null ? null : metadata.getText( + MediaMetadata.METADATA_KEY_ARTIST); + + if (nextVisible == mMediaIsVisible && TextUtils.equals(title, mMediaTitle) + && TextUtils.equals(artist, mMediaArtist)) { + return; + } + mMediaTitle = title; + mMediaArtist = artist; + mMediaIsVisible = nextVisible; notifyChange(); }