Merge changes from topic "media_delete_intent_rvc_qpr2" into rvc-qpr-dev

* changes:
  Notifications starting paused shall still be subject to timeout.
  Disable player's "Dismiss" button when notification is not dismissible.
  Media player attempts to dismiss notifications when players removed.
This commit is contained in:
Jeff DeCew
2020-10-19 20:58:00 +00:00
committed by Android (Google) Code Review
6 changed files with 58 additions and 9 deletions

View File

@@ -2820,6 +2820,8 @@
<string name="controls_media_title">Media</string>
<!-- Explanation for closing controls associated with a specific media session [CHAR_LIMIT=NONE] -->
<string name="controls_media_close_session">Hide the current session.</string>
<!-- Explanation that controls associated with a specific media session are active [CHAR_LIMIT=NONE] -->
<string name="controls_media_active_session">Current session cannot be hidden.</string>
<!-- Label for a button that will hide media controls [CHAR_LIMIT=30] -->
<string name="controls_media_dismiss_button">Dismiss</string>
<!-- Label for button to resume media playback [CHAR_LIMIT=NONE] -->

View File

@@ -359,7 +359,15 @@ public class MediaControlPanel {
final MediaController controller = getController();
mBackgroundExecutor.execute(() -> mSeekBarViewModel.updateController(controller));
// Guts label
boolean isDismissible = data.isClearable();
mViewHolder.getSettingsText().setText(isDismissible
? R.string.controls_media_close_session
: R.string.controls_media_active_session);
// Dismiss
mViewHolder.getDismissLabel().setAlpha(isDismissible ? 1 : DISABLED_ALPHA);
mViewHolder.getDismiss().setEnabled(isDismissible);
mViewHolder.getDismiss().setOnClickListener(v -> {
if (mKey != null) {
closeGuts();

View File

@@ -46,7 +46,7 @@ class MediaTimeoutListener @Inject constructor(
/**
* Callback representing that a media object is now expired:
* @param token Media session unique identifier
* @param pauseTimeuot True when expired for {@code PAUSED_MEDIA_TIMEOUT}
* @param pauseTimeout True when expired for {@code PAUSED_MEDIA_TIMEOUT}
*/
lateinit var timeoutCallback: (String, Boolean) -> Unit
@@ -57,11 +57,10 @@ class MediaTimeoutListener @Inject constructor(
// Having an old key means that we're migrating from/to resumption. We should update
// the old listener to make sure that events will be dispatched to the new location.
val migrating = oldKey != null && key != oldKey
var wasPlaying = false
if (migrating) {
val reusedListener = mediaListeners.remove(oldKey)
if (reusedListener != null) {
wasPlaying = reusedListener.playing ?: false
val wasPlaying = reusedListener.playing ?: false
if (DEBUG) Log.d(TAG, "migrating key $oldKey to $key, for resumption")
reusedListener.mediaData = data
reusedListener.key = key
@@ -159,9 +158,8 @@ class MediaTimeoutListener @Inject constructor(
Log.v(TAG, "Execute timeout for $key")
}
timedOut = true
if (dispatchEvents) {
timeoutCallback(key, timedOut)
}
// this event is async, so it's safe even when `dispatchEvents` is false
timeoutCallback(key, timedOut)
}, PAUSED_MEDIA_TIMEOUT)
} else {
expireMediaTimeout(key, "playback started - $state, $key")

View File

@@ -60,8 +60,10 @@ class PlayerViewHolder private constructor(itemView: View) {
val action4 = itemView.requireViewById<ImageButton>(R.id.action4)
// Settings screen
val settingsText = itemView.requireViewById<TextView>(R.id.remove_text)
val cancel = itemView.requireViewById<View>(R.id.cancel)
val dismiss = itemView.requireViewById<View>(R.id.dismiss)
val dismiss = itemView.requireViewById<ViewGroup>(R.id.dismiss)
val dismissLabel = dismiss.getChildAt(0)
val settings = itemView.requireViewById<View>(R.id.settings)
init {

View File

@@ -40,6 +40,7 @@ import android.os.Trace;
import android.os.UserHandle;
import android.provider.DeviceConfig;
import android.provider.DeviceConfig.Properties;
import android.service.notification.NotificationListenerService;
import android.util.ArraySet;
import android.util.Log;
import android.view.View;
@@ -52,6 +53,7 @@ import com.android.systemui.Dumpable;
import com.android.systemui.Interpolators;
import com.android.systemui.colorextraction.SysuiColorExtractor;
import com.android.systemui.dagger.qualifiers.Main;
import com.android.systemui.media.MediaData;
import com.android.systemui.media.MediaDataManager;
import com.android.systemui.plugins.statusbar.StatusBarStateController;
import com.android.systemui.statusbar.dagger.StatusBarModule;
@@ -250,6 +252,24 @@ public class NotificationMediaManager implements Dumpable {
}
});
mMediaDataManager.addListener(new MediaDataManager.Listener() {
@Override
public void onMediaDataLoaded(@NonNull String key,
@Nullable String oldKey, @NonNull MediaData data) {
}
@Override
public void onMediaDataRemoved(@NonNull String key) {
NotificationEntry entry = mEntryManager.getPendingOrActiveNotif(key);
if (entry != null) {
// TODO(b/160713608): "removing" this notification won't happen and
// won't send the 'deleteIntent' if the notification is ongoing.
mEntryManager.performRemoveNotification(entry.getSbn(),
NotificationListenerService.REASON_CANCEL);
}
}
});
mShowCompactMediaSeekbar = "true".equals(
DeviceConfig.getProperty(DeviceConfig.NAMESPACE_SYSTEMUI,
SystemUiDeviceConfigFlags.COMPACT_MEDIA_SEEKBAR_ENABLED));

View File

@@ -109,9 +109,11 @@ public class MediaControlPanelTest : SysuiTestCase() {
private lateinit var action2: ImageButton
private lateinit var action3: ImageButton
private lateinit var action4: ImageButton
private lateinit var settingsText: TextView
private lateinit var settings: View
private lateinit var cancel: View
private lateinit var dismiss: View
private lateinit var dismiss: FrameLayout
private lateinit var dismissLabel: View
private lateinit var session: MediaSession
private val device = MediaDeviceData(true, null, DEVICE_NAME)
@@ -168,12 +170,16 @@ public class MediaControlPanelTest : SysuiTestCase() {
whenever(holder.action3).thenReturn(action3)
action4 = ImageButton(context)
whenever(holder.action4).thenReturn(action4)
settingsText = TextView(context)
whenever(holder.settingsText).thenReturn(settingsText)
settings = View(context)
whenever(holder.settings).thenReturn(settings)
cancel = View(context)
whenever(holder.cancel).thenReturn(cancel)
dismiss = View(context)
dismiss = FrameLayout(context)
whenever(holder.dismiss).thenReturn(dismiss)
dismissLabel = View(context)
whenever(holder.dismissLabel).thenReturn(dismissLabel)
// Create media session
val metadataBuilder = MediaMetadata.Builder().apply {
@@ -327,6 +333,7 @@ public class MediaControlPanelTest : SysuiTestCase() {
notificationKey = KEY)
player.bind(state, mediaKey)
assertThat(dismiss.isEnabled).isEqualTo(true)
dismiss.callOnClick()
val captor = ArgumentCaptor.forClass(ActivityStarter.OnDismissAction::class.java)
verify(keyguardDismissUtil).executeWhenUnlocked(captor.capture(), anyBoolean())
@@ -334,4 +341,16 @@ public class MediaControlPanelTest : SysuiTestCase() {
captor.value.onDismiss()
verify(mediaDataManager).dismissMediaData(eq(mediaKey), anyLong())
}
@Test
fun dismissButtonDisabled() {
val mediaKey = "key for dismissal"
player.attach(holder)
val state = MediaData(USER_ID, true, BG_COLOR, APP, null, ARTIST, TITLE, null, emptyList(),
emptyList(), PACKAGE, session.getSessionToken(), null, null, true, null,
isClearable = false, notificationKey = KEY)
player.bind(state, mediaKey)
assertThat(dismiss.isEnabled).isEqualTo(false)
}
}