1 /*
2  * Copyright (C) 2020 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.settings.media;
18 
19 import static android.app.slice.Slice.EXTRA_RANGE_VALUE;
20 import static android.app.slice.Slice.HINT_LIST_ITEM;
21 import static android.app.slice.SliceItem.FORMAT_SLICE;
22 
23 import static com.android.settings.slices.CustomSliceRegistry.REMOTE_MEDIA_SLICE_URI;
24 
25 import static com.google.common.truth.Truth.assertThat;
26 
27 import static org.mockito.Mockito.mock;
28 import static org.mockito.Mockito.never;
29 import static org.mockito.Mockito.spy;
30 import static org.mockito.Mockito.verify;
31 import static org.mockito.Mockito.when;
32 
33 import android.content.Context;
34 import android.content.Intent;
35 import android.media.MediaRouter2Manager;
36 import android.media.RoutingSessionInfo;
37 import android.net.Uri;
38 
39 import androidx.slice.Slice;
40 import androidx.slice.SliceMetadata;
41 import androidx.slice.SliceProvider;
42 import androidx.slice.core.SliceAction;
43 import androidx.slice.core.SliceQuery;
44 import androidx.slice.widget.SliceLiveData;
45 
46 import com.android.settings.slices.SliceBackgroundWorker;
47 import com.android.settingslib.media.LocalMediaManager;
48 
49 import org.junit.Before;
50 import org.junit.Test;
51 import org.junit.runner.RunWith;
52 import org.mockito.Mock;
53 import org.mockito.MockitoAnnotations;
54 import org.robolectric.RobolectricTestRunner;
55 import org.robolectric.RuntimeEnvironment;
56 import org.robolectric.annotation.Config;
57 import org.robolectric.annotation.Implementation;
58 import org.robolectric.annotation.Implements;
59 
60 import java.util.ArrayList;
61 import java.util.List;
62 
63 @RunWith(RobolectricTestRunner.class)
64 @Config(shadows = RemoteMediaSliceTest.ShadowSliceBackgroundWorker.class)
65 public class RemoteMediaSliceTest {
66 
67     private static final String MEDIA_ID = "media_id";
68     private static final String TEST_SESSION_1_ID = "test_session_1_id";
69     private static final String TEST_SESSION_1_NAME = "test_session_1_name";
70     private static final int TEST_VOLUME = 3;
71 
72     private static MediaDeviceUpdateWorker sMediaDeviceUpdateWorker;
73 
74     @Mock
75     private LocalMediaManager mLocalMediaManager;
76 
77     private final List<RoutingSessionInfo> mRoutingSessionInfos = new ArrayList<>();
78 
79     private Context mContext;
80     private RemoteMediaSlice mRemoteMediaSlice;
81 
82     @Before
setUp()83     public void setUp() throws Exception {
84         MockitoAnnotations.initMocks(this);
85         mContext = spy(RuntimeEnvironment.application);
86 
87         // Set-up specs for SliceMetadata.
88         SliceProvider.setSpecs(SliceLiveData.SUPPORTED_SPECS);
89 
90         mRemoteMediaSlice = new RemoteMediaSlice(mContext);
91         mRemoteMediaSlice.mRouterManager = mock(MediaRouter2Manager.class);
92         sMediaDeviceUpdateWorker = spy(new MediaDeviceUpdateWorker(mContext,
93                 REMOTE_MEDIA_SLICE_URI));
94         sMediaDeviceUpdateWorker.mLocalMediaManager = mLocalMediaManager;
95         final RoutingSessionInfo remoteSessionInfo = mock(RoutingSessionInfo.class);
96         when(remoteSessionInfo.getId()).thenReturn(TEST_SESSION_1_ID);
97         when(remoteSessionInfo.getName()).thenReturn(TEST_SESSION_1_NAME);
98         when(remoteSessionInfo.getVolumeMax()).thenReturn(100);
99         when(remoteSessionInfo.getVolume()).thenReturn(10);
100         when(remoteSessionInfo.isSystemSession()).thenReturn(false);
101         mRoutingSessionInfos.add(remoteSessionInfo);
102         when(sMediaDeviceUpdateWorker.getActiveRemoteMediaDevice()).thenReturn(
103                 mRoutingSessionInfos);
104     }
105 
106     @Test
onNotifyChange_noId_doNothing()107     public void onNotifyChange_noId_doNothing() {
108         final Intent intent = new Intent();
109         intent.putExtra(EXTRA_RANGE_VALUE, TEST_VOLUME);
110 
111         mRemoteMediaSlice.onNotifyChange(intent);
112 
113         verify(sMediaDeviceUpdateWorker, never())
114                 .adjustSessionVolume(TEST_SESSION_1_ID, TEST_VOLUME);
115     }
116 
117     @Test
onNotifyChange_verifyAdjustVolume()118     public void onNotifyChange_verifyAdjustVolume() {
119         final Intent intent = new Intent();
120         intent.putExtra(MEDIA_ID, TEST_SESSION_1_ID);
121         intent.putExtra(EXTRA_RANGE_VALUE, TEST_VOLUME);
122 
123         mRemoteMediaSlice.onNotifyChange(intent);
124 
125         verify(sMediaDeviceUpdateWorker).adjustSessionVolume(TEST_SESSION_1_ID, TEST_VOLUME);
126     }
127 
128     @Test
getSlice_noActiveSession_checkRowNumber()129     public void getSlice_noActiveSession_checkRowNumber() {
130         mRoutingSessionInfos.clear();
131         final Slice slice = mRemoteMediaSlice.getSlice();
132         final int rows = SliceQuery.findAll(slice, FORMAT_SLICE, HINT_LIST_ITEM, null).size();
133 
134         assertThat(rows).isEqualTo(0);
135     }
136 
137     @Test
getSlice_withActiveSession_checkRowNumber()138     public void getSlice_withActiveSession_checkRowNumber() {
139         final Slice slice = mRemoteMediaSlice.getSlice();
140         final int rows = SliceQuery.findAll(slice, FORMAT_SLICE, HINT_LIST_ITEM, null).size();
141 
142         // InputRange and Row
143         assertThat(rows).isEqualTo(2);
144     }
145 
146     @Test
getSlice_withActiveSession_checkTitle()147     public void getSlice_withActiveSession_checkTitle() {
148         final Slice slice = mRemoteMediaSlice.getSlice();
149         final SliceMetadata metadata = SliceMetadata.from(mContext, slice);
150         final SliceAction primaryAction = metadata.getPrimaryAction();
151 
152         assertThat(primaryAction.getTitle().toString()).isEqualTo(mContext.getText(
153                 com.android.settings.R.string.remote_media_volume_option_title));
154     }
155 
156     @Implements(SliceBackgroundWorker.class)
157     public static class ShadowSliceBackgroundWorker {
158 
159         @Implementation
getInstance(Uri uri)160         public static SliceBackgroundWorker getInstance(Uri uri) {
161             return sMediaDeviceUpdateWorker;
162         }
163     }
164 }
165