• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2017 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.notification;
18 
19 import static android.app.NotificationChannel.DEFAULT_CHANNEL_ID;
20 import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
21 import static android.app.NotificationManager.IMPORTANCE_HIGH;
22 import static android.app.NotificationManager.IMPORTANCE_LOW;
23 import static junit.framework.Assert.assertFalse;
24 import static junit.framework.Assert.assertTrue;
25 import static org.junit.Assert.assertEquals;
26 import static org.mockito.ArgumentMatchers.any;
27 import static org.mockito.ArgumentMatchers.anyInt;
28 import static org.mockito.Mockito.mock;
29 import static org.mockito.Mockito.never;
30 import static org.mockito.Mockito.spy;
31 import static org.mockito.Mockito.times;
32 import static org.mockito.Mockito.verify;
33 import static org.mockito.Mockito.when;
34 
35 import android.app.Notification;
36 import android.app.NotificationChannel;
37 import android.app.NotificationManager;
38 import android.content.Context;
39 import android.content.Intent;
40 import android.net.Uri;
41 import android.os.UserManager;
42 import android.provider.Settings;
43 import android.support.v7.preference.Preference;
44 import android.support.v7.preference.PreferenceScreen;
45 import android.util.AttributeSet;
46 
47 import com.android.settings.SettingsPreferenceFragment;
48 import com.android.settings.testutils.SettingsRobolectricTestRunner;
49 import com.android.settings.testutils.shadow.SettingsShadowResources;
50 import com.android.settingslib.RestrictedLockUtils;
51 
52 import org.junit.After;
53 import org.junit.Before;
54 import org.junit.Test;
55 import org.junit.runner.RunWith;
56 import org.mockito.Answers;
57 import org.mockito.Mock;
58 import org.mockito.MockitoAnnotations;
59 import org.robolectric.annotation.Config;
60 import org.robolectric.shadows.ShadowApplication;
61 
62 @RunWith(SettingsRobolectricTestRunner.class)
63 @Config(shadows = SettingsShadowResources.class)
64 public class SoundPreferenceControllerTest {
65 
66     private Context mContext;
67     @Mock
68     private NotificationBackend mBackend;
69     @Mock
70     private NotificationManager mNm;
71     @Mock
72     private UserManager mUm;
73     @Mock(answer = Answers.RETURNS_DEEP_STUBS)
74     private PreferenceScreen mScreen;
75     @Mock
76     private SettingsPreferenceFragment mFragment;
77     @Mock
78     private NotificationSettingsBase.ImportanceListener mImportanceListener;
79 
80     private SoundPreferenceController mController;
81 
82     @Before
setUp()83     public void setUp() {
84         MockitoAnnotations.initMocks(this);
85         ShadowApplication shadowApplication = ShadowApplication.getInstance();
86         shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNm);
87         shadowApplication.setSystemService(Context.USER_SERVICE, mUm);
88         SettingsShadowResources.overrideResource(com.android.internal.R.string.ringtone_silent,
89                 "silent");
90         mContext = shadowApplication.getApplicationContext();
91         mController = spy(new SoundPreferenceController(
92                 mContext, mFragment, mImportanceListener, mBackend));
93     }
94 
95     @After
tearDown()96     public void tearDown() {
97         SettingsShadowResources.reset();
98     }
99 
100     @Test
testNoCrashIfNoOnResume()101     public void testNoCrashIfNoOnResume() throws Exception {
102         mController.isAvailable();
103         mController.updateState(mock(NotificationSoundPreference.class));
104         mController.onPreferenceChange(mock(NotificationSoundPreference.class), Uri.EMPTY);
105         mController.handlePreferenceTreeClick(mock(NotificationSoundPreference.class));
106         mController.onActivityResult(1, 1, null);
107         SoundPreferenceController.hasValidSound(null);
108     }
109 
110     @Test
testIsAvailable_notIfChannelNull()111     public void testIsAvailable_notIfChannelNull() throws Exception {
112         NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
113         mController.onResume(appRow, null, null, null);
114         assertFalse(mController.isAvailable());
115     }
116 
117     @Test
testIsAvailable_notIfNotImportant()118     public void testIsAvailable_notIfNotImportant() throws Exception {
119         NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
120         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_LOW);
121         mController.onResume(appRow, channel, null, null);
122         assertFalse(mController.isAvailable());
123     }
124 
125     @Test
testIsAvailable_notIfDefaultChannel()126     public void testIsAvailable_notIfDefaultChannel() throws Exception {
127         NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
128         NotificationChannel channel =
129                 new NotificationChannel(DEFAULT_CHANNEL_ID, "", IMPORTANCE_DEFAULT);
130         mController.onResume(appRow, channel, null, null);
131         assertFalse(mController.isAvailable());
132     }
133 
134     @Test
testIsAvailable()135     public void testIsAvailable() throws Exception {
136         NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
137         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_DEFAULT);
138         mController.onResume(appRow, channel, null, null);
139         assertTrue(mController.isAvailable());
140     }
141 
142     @Test
testDisplayPreference_savesPreference()143     public void testDisplayPreference_savesPreference() throws Exception {
144         NotificationSoundPreference pref = mock(NotificationSoundPreference.class);
145         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
146         mController.displayPreference(mScreen);
147 
148         mController.onActivityResult(SoundPreferenceController.CODE, 1, new Intent());
149         verify(pref, times(1)).onActivityResult(anyInt(), anyInt(), any());
150     }
151 
152     @Test
testUpdateState_disabledByAdmin()153     public void testUpdateState_disabledByAdmin() throws Exception {
154         NotificationChannel channel = mock(NotificationChannel.class);
155         when(channel.getId()).thenReturn("something");
156         mController.onResume(new NotificationBackend.AppRow(), channel, null, mock(
157                 RestrictedLockUtils.EnforcedAdmin.class));
158 
159         Preference pref = new NotificationSoundPreference(mContext, mock(AttributeSet.class));
160         mController.updateState(pref);
161 
162         assertFalse(pref.isEnabled());
163     }
164 
165     @Test
testUpdateState_notConfigurable()166     public void testUpdateState_notConfigurable() throws Exception {
167         String lockedId = "locked";
168         NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
169         appRow.lockedChannelId = lockedId;
170         NotificationChannel channel = mock(NotificationChannel.class);
171         when(channel.getId()).thenReturn(lockedId);
172         mController.onResume(appRow, channel, null, null);
173 
174         Preference pref = new NotificationSoundPreference(mContext, mock(AttributeSet.class));
175         mController.updateState(pref);
176 
177         assertFalse(pref.isEnabled());
178     }
179 
180     @Test
testUpdateState_configurable()181     public void testUpdateState_configurable() throws Exception {
182         Uri sound = Settings.System.DEFAULT_ALARM_ALERT_URI;
183         NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
184         NotificationChannel channel = mock(NotificationChannel.class);
185         when(channel.getId()).thenReturn("something");
186         when(channel.getSound()).thenReturn(sound);
187         mController.onResume(appRow, channel, null, null);
188 
189         NotificationSoundPreference pref =
190                 new NotificationSoundPreference(mContext, mock(AttributeSet.class));
191         mController.updateState(pref);
192 
193         assertEquals(sound, pref.onRestoreRingtone());
194         assertTrue(pref.isEnabled());
195     }
196 
197     @Test
testOnPreferenceChange()198     public void testOnPreferenceChange() throws Exception {
199         Uri sound = Settings.System.DEFAULT_ALARM_ALERT_URI;
200         NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
201         NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_HIGH);
202         channel.setSound(sound, Notification.AUDIO_ATTRIBUTES_DEFAULT);
203         mController.onResume(appRow, channel, null, null);
204 
205         NotificationSoundPreference pref =
206                 new NotificationSoundPreference(mContext, mock(AttributeSet.class));
207         mController.updateState(pref);
208 
209         mController.onPreferenceChange(pref, Uri.EMPTY);
210         assertEquals(Uri.EMPTY, channel.getSound());
211         assertEquals(Notification.AUDIO_ATTRIBUTES_DEFAULT, channel.getAudioAttributes());
212         verify(mBackend, times(1)).updateChannel(any(), anyInt(), any());
213     }
214 
215     @Test
testOnPreferenceTreeClick_incorrectPref()216     public void testOnPreferenceTreeClick_incorrectPref() throws Exception {
217         NotificationSoundPreference pref = mock(NotificationSoundPreference.class);
218         mController.handlePreferenceTreeClick(pref);
219 
220         verify(pref, never()).onPrepareRingtonePickerIntent(any());
221         verify(mFragment, never()).startActivityForResult(any(), anyInt());
222     }
223 
224     @Test
testOnPreferenceTreeClick_correctPref()225     public void testOnPreferenceTreeClick_correctPref() throws Exception {
226         NotificationSoundPreference pref =
227                 spy(new NotificationSoundPreference(mContext, mock(AttributeSet.class)));
228         pref.setKey(mController.getPreferenceKey());
229         mController.handlePreferenceTreeClick(pref);
230 
231         verify(pref, times(1)).onPrepareRingtonePickerIntent(any());
232         verify(mFragment, times(1)).startActivityForResult(any(), anyInt());
233     }
234 
235     @Test
testOnActivityResult()236     public void testOnActivityResult() {
237         NotificationSoundPreference pref = mock(NotificationSoundPreference.class);
238         when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
239         mController.displayPreference(mScreen);
240 
241         mController.onActivityResult(SoundPreferenceController.CODE, 1, new Intent("hi"));
242         verify(pref, times(1)).onActivityResult(anyInt(), anyInt(), any());
243         verify(mImportanceListener, times(1)).onImportanceChanged();
244     }
245 
246     @Test
testHasValidSound()247     public void testHasValidSound() {
248         NotificationChannel channel =
249                 new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_HIGH);
250         assertTrue(SoundPreferenceController.hasValidSound(channel));
251 
252         channel.setSound(Uri.EMPTY, Notification.AUDIO_ATTRIBUTES_DEFAULT);
253         assertFalse(SoundPreferenceController.hasValidSound(channel));
254 
255         channel.setSound(null, Notification.AUDIO_ATTRIBUTES_DEFAULT);
256         assertFalse(SoundPreferenceController.hasValidSound(channel));
257     }
258 }
259