1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.systemui.statusbar.notification.row.wrapper; 18 19 import static org.junit.Assert.assertTrue; 20 import static org.mockito.ArgumentMatchers.argThat; 21 import static org.mockito.Mockito.times; 22 import static org.mockito.Mockito.verify; 23 24 import android.app.Notification; 25 import android.media.MediaMetadata; 26 import android.media.session.MediaSession; 27 import android.media.session.PlaybackState; 28 import android.testing.AndroidTestingRunner; 29 import android.testing.TestableLooper; 30 import android.testing.TestableLooper.RunWithLooper; 31 import android.view.View; 32 import android.widget.RemoteViews; 33 import android.widget.SeekBar; 34 35 import androidx.test.filters.SmallTest; 36 37 import com.android.internal.logging.MetricsLogger; 38 import com.android.internal.logging.nano.MetricsProto.MetricsEvent; 39 import com.android.systemui.R; 40 import com.android.systemui.SysuiTestCase; 41 import com.android.systemui.statusbar.NotificationTestHelper; 42 import com.android.systemui.statusbar.notification.row.ExpandableNotificationRow; 43 44 import org.junit.Before; 45 import org.junit.Test; 46 import org.junit.runner.RunWith; 47 import org.mockito.Mock; 48 import org.mockito.MockitoAnnotations; 49 50 51 @SmallTest 52 @RunWith(AndroidTestingRunner.class) 53 @RunWithLooper 54 public class NotificationMediaTemplateViewWrapperTest extends SysuiTestCase { 55 56 private ExpandableNotificationRow mRow; 57 private Notification mNotif; 58 private View mView; 59 private NotificationMediaTemplateViewWrapper mWrapper; 60 61 @Mock 62 private MetricsLogger mMetricsLogger; 63 64 @Before setUp()65 public void setUp() { 66 MockitoAnnotations.initMocks(this); 67 com.android.systemui.util.Assert.sMainLooper = TestableLooper.get(this).getLooper(); 68 69 mDependency.injectTestDependency(MetricsLogger.class, mMetricsLogger); 70 } 71 makeTestNotification(long duration, boolean allowSeeking)72 private void makeTestNotification(long duration, boolean allowSeeking) throws Exception { 73 Notification.Builder builder = new Notification.Builder(mContext) 74 .setSmallIcon(R.drawable.ic_person) 75 .setContentTitle("Title") 76 .setContentText("Text"); 77 78 MediaMetadata metadata = new MediaMetadata.Builder() 79 .putLong(MediaMetadata.METADATA_KEY_DURATION, duration) 80 .build(); 81 MediaSession session = new MediaSession(mContext, "TEST_CHANNEL"); 82 session.setMetadata(metadata); 83 84 PlaybackState playbackState = new PlaybackState.Builder() 85 .setActions(allowSeeking ? PlaybackState.ACTION_SEEK_TO : 0) 86 .build(); 87 88 session.setPlaybackState(playbackState); 89 90 builder.setStyle(new Notification.MediaStyle() 91 .setMediaSession(session.getSessionToken()) 92 ); 93 94 mNotif = builder.build(); 95 assertTrue(mNotif.hasMediaSession()); 96 97 mRow = new NotificationTestHelper(mContext).createRow(mNotif); 98 99 RemoteViews views = new RemoteViews(mContext.getPackageName(), 100 com.android.internal.R.layout.notification_template_material_big_media); 101 mView = views.apply(mContext, null); 102 mWrapper = new NotificationMediaTemplateViewWrapper(mContext, 103 mView, mRow); 104 mWrapper.onContentUpdated(mRow); 105 } 106 107 @Test testLogging_NoSeekbar()108 public void testLogging_NoSeekbar() throws Exception { 109 // Media sessions with duration <= 0 should not include a seekbar 110 makeTestNotification(0, false); 111 112 verify(mMetricsLogger).write(argThat(logMaker -> 113 logMaker.getCategory() == MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR 114 && logMaker.getType() == MetricsEvent.TYPE_CLOSE 115 )); 116 117 verify(mMetricsLogger, times(0)).write(argThat(logMaker -> 118 logMaker.getCategory() == MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR 119 && logMaker.getType() == MetricsEvent.TYPE_OPEN 120 )); 121 } 122 123 @Test testLogging_HasSeekbarNoScrubber()124 public void testLogging_HasSeekbarNoScrubber() throws Exception { 125 // Media sessions that do not support seeking should have a seekbar, but no scrubber 126 makeTestNotification(1000, false); 127 128 verify(mMetricsLogger).write(argThat(logMaker -> 129 logMaker.getCategory() == MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR 130 && logMaker.getType() == MetricsEvent.TYPE_OPEN 131 )); 132 133 // Ensure the callback runs at least once 134 mWrapper.mOnUpdateTimerTick.run(); 135 136 verify(mMetricsLogger).write(argThat(logMaker -> 137 logMaker.getCategory() == MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR 138 && logMaker.getType() == MetricsEvent.TYPE_DETAIL 139 && logMaker.getSubtype() == 0 140 )); 141 } 142 143 @Test testLogging_HasSeekbarAndScrubber()144 public void testLogging_HasSeekbarAndScrubber() throws Exception { 145 makeTestNotification(1000, true); 146 147 verify(mMetricsLogger).write(argThat(logMaker -> 148 logMaker.getCategory() == MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR 149 && logMaker.getType() == MetricsEvent.TYPE_OPEN 150 )); 151 152 verify(mMetricsLogger).write(argThat(logMaker -> 153 logMaker.getCategory() == MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR 154 && logMaker.getType() == MetricsEvent.TYPE_DETAIL 155 && logMaker.getSubtype() == 1 156 )); 157 } 158 159 @Test testLogging_UpdateSeekbar()160 public void testLogging_UpdateSeekbar() throws Exception { 161 makeTestNotification(1000, true); 162 163 SeekBar seekbar = mView.findViewById( 164 com.android.internal.R.id.notification_media_progress_bar); 165 assertTrue(seekbar != null); 166 167 mWrapper.mSeekListener.onStopTrackingTouch(seekbar); 168 169 verify(mMetricsLogger).write(argThat(logMaker -> 170 logMaker.getCategory() == MetricsEvent.MEDIA_NOTIFICATION_SEEKBAR 171 && logMaker.getType() == MetricsEvent.TYPE_UPDATE)); 172 } 173 } 174