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