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
17package com.android.settings.notification;
18
19import static android.app.NotificationChannel.DEFAULT_CHANNEL_ID;
20import static android.app.NotificationManager.IMPORTANCE_DEFAULT;
21import static android.app.NotificationManager.IMPORTANCE_HIGH;
22import static android.app.NotificationManager.IMPORTANCE_LOW;
23import static junit.framework.Assert.assertFalse;
24import static junit.framework.Assert.assertTrue;
25import static org.mockito.ArgumentMatchers.any;
26import static org.mockito.ArgumentMatchers.anyInt;
27import static org.mockito.Mockito.mock;
28import static org.mockito.Mockito.spy;
29import static org.mockito.Mockito.times;
30import static org.mockito.Mockito.verify;
31import static org.mockito.Mockito.when;
32
33import android.app.NotificationChannel;
34import android.app.NotificationManager;
35import android.content.Context;
36import android.os.UserManager;
37import android.os.Vibrator;
38import android.support.v7.preference.Preference;
39import android.support.v7.preference.PreferenceScreen;
40
41import com.android.settings.testutils.SettingsRobolectricTestRunner;
42import com.android.settingslib.RestrictedLockUtils;
43import com.android.settingslib.RestrictedSwitchPreference;
44
45import org.junit.Before;
46import org.junit.Test;
47import org.junit.runner.RunWith;
48import org.mockito.Answers;
49import org.mockito.Mock;
50import org.mockito.MockitoAnnotations;
51import org.robolectric.RuntimeEnvironment;
52import org.robolectric.shadows.ShadowApplication;
53
54@RunWith(SettingsRobolectricTestRunner.class)
55public class VibrationPreferenceControllerTest {
56
57    private Context mContext;
58    @Mock
59    private NotificationBackend mBackend;
60    @Mock
61    private NotificationManager mNm;
62    @Mock
63    private Vibrator mVibrator;
64    @Mock
65    private UserManager mUm;
66    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
67    private PreferenceScreen mScreen;
68
69    private VibrationPreferenceController mController;
70
71    @Before
72    public void setUp() {
73        MockitoAnnotations.initMocks(this);
74        ShadowApplication shadowApplication = ShadowApplication.getInstance();
75        shadowApplication.setSystemService(Context.NOTIFICATION_SERVICE, mNm);
76        shadowApplication.setSystemService(Context.USER_SERVICE, mUm);
77        shadowApplication.setSystemService(Context.VIBRATOR_SERVICE, mVibrator);
78        mContext = RuntimeEnvironment.application;
79        mController = spy(new VibrationPreferenceController(mContext, mBackend));
80
81        // by default allow vibration
82        when(mVibrator.hasVibrator()).thenReturn(true);
83    }
84
85    @Test
86    public void testNoCrashIfNoOnResume() {
87        mController.isAvailable();
88        mController.updateState(mock(RestrictedSwitchPreference.class));
89        mController.onPreferenceChange(mock(RestrictedSwitchPreference.class), true);
90    }
91
92    @Test
93    public void testIsAvailable_notSystemDoesNotHave() {
94        when(mVibrator.hasVibrator()).thenReturn(false);
95        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
96        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_DEFAULT);
97        mController.onResume(appRow, channel, null, null);
98        assertFalse(mController.isAvailable());
99    }
100
101    @Test
102    public void testIsAvailable_notIfNotImportant() {
103        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
104        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_LOW);
105        mController.onResume(appRow, channel, null, null);
106        assertFalse(mController.isAvailable());
107    }
108
109    @Test
110    public void testIsAvailable_notIfDefaultChannel() {
111        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
112        NotificationChannel channel =
113                new NotificationChannel(DEFAULT_CHANNEL_ID, "", IMPORTANCE_DEFAULT);
114        mController.onResume(appRow, channel, null, null);
115        assertFalse(mController.isAvailable());
116    }
117
118    @Test
119    public void testIsAvailable() {
120        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
121        NotificationChannel channel = new NotificationChannel("", "", IMPORTANCE_DEFAULT);
122        mController.onResume(appRow, channel, null, null);
123        assertTrue(mController.isAvailable());
124    }
125
126    @Test
127    public void testUpdateState_disabledByAdmin() {
128        NotificationChannel channel = mock(NotificationChannel.class);
129        when(channel.getId()).thenReturn("something");
130        mController.onResume(new NotificationBackend.AppRow(), channel, null, mock(
131                RestrictedLockUtils.EnforcedAdmin.class));
132
133        Preference pref = new RestrictedSwitchPreference(RuntimeEnvironment.application);
134        mController.updateState(pref);
135
136        assertFalse(pref.isEnabled());
137    }
138
139    @Test
140    public void testUpdateState_notConfigurable() {
141        String lockedId = "locked";
142        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
143        appRow.lockedChannelId = lockedId;
144        NotificationChannel channel = mock(NotificationChannel.class);
145        when(channel.getId()).thenReturn(lockedId);
146        mController.onResume(appRow, channel, null, null);
147
148        Preference pref = new RestrictedSwitchPreference(RuntimeEnvironment.application);
149        mController.updateState(pref);
150
151        assertFalse(pref.isEnabled());
152    }
153
154    @Test
155    public void testUpdateState_configurable() {
156        NotificationBackend.AppRow appRow = new NotificationBackend.AppRow();
157        NotificationChannel channel = mock(NotificationChannel.class);
158        when(channel.getId()).thenReturn("something");
159        mController.onResume(appRow, channel, null, null);
160
161        Preference pref = new RestrictedSwitchPreference(RuntimeEnvironment.application);
162        mController.updateState(pref);
163
164        assertTrue(pref.isEnabled());
165    }
166
167    @Test
168    public void testUpdateState_vibrateOn() {
169        NotificationChannel channel = mock(NotificationChannel.class);
170        when(channel.shouldVibrate()).thenReturn(true);
171        mController.onResume(new NotificationBackend.AppRow(), channel, null, null);
172
173        RestrictedSwitchPreference pref =
174                new RestrictedSwitchPreference(RuntimeEnvironment.application);
175        mController.updateState(pref);
176        assertTrue(pref.isChecked());
177    }
178
179    @Test
180    public void testUpdateState_vibrateOff() {
181        NotificationChannel channel = mock(NotificationChannel.class);
182        when(channel.shouldVibrate()).thenReturn(false);
183        mController.onResume(new NotificationBackend.AppRow(), channel, null, null);
184
185        RestrictedSwitchPreference pref =
186                new RestrictedSwitchPreference(RuntimeEnvironment.application);
187        mController.updateState(pref);
188        assertFalse(pref.isChecked());
189    }
190
191    @Test
192    public void testOnPreferenceChange_on() {
193        NotificationChannel channel =
194                new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_DEFAULT);
195        mController.onResume(new NotificationBackend.AppRow(), channel, null, null);
196
197        RestrictedSwitchPreference pref =
198                new RestrictedSwitchPreference(RuntimeEnvironment.application);
199        mController.updateState(pref);
200
201        mController.onPreferenceChange(pref, true);
202
203        assertTrue(channel.shouldVibrate());
204        verify(mBackend, times(1)).updateChannel(any(), anyInt(), any());
205    }
206
207    @Test
208    public void testOnPreferenceChange_off() {
209        NotificationChannel channel =
210                new NotificationChannel(DEFAULT_CHANNEL_ID, "a", IMPORTANCE_HIGH);
211        mController.onResume(new NotificationBackend.AppRow(), channel, null, null);
212
213        RestrictedSwitchPreference pref =
214                new RestrictedSwitchPreference(RuntimeEnvironment.application);
215        when(mScreen.findPreference(mController.getPreferenceKey())).thenReturn(pref);
216        mController.displayPreference(mScreen);
217        mController.updateState(pref);
218
219        mController.onPreferenceChange(pref, false);
220
221        assertFalse(channel.shouldVibrate());
222        verify(mBackend, times(1)).updateChannel(any(), anyInt(), any());
223    }
224}
225