1 /* 2 * Copyright (C) 2016 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 com.google.common.truth.Truth.assertThat; 20 21 import static org.mockito.ArgumentMatchers.nullable; 22 import static org.mockito.Matchers.anyInt; 23 import static org.mockito.Matchers.eq; 24 import static org.mockito.Mockito.mock; 25 import static org.mockito.Mockito.times; 26 import static org.mockito.Mockito.verify; 27 import static org.mockito.Mockito.when; 28 29 import android.content.Context; 30 import android.os.UserHandle; 31 import android.os.UserManager; 32 import android.support.v7.preference.Preference; 33 import android.support.v7.preference.PreferenceCategory; 34 import android.support.v7.preference.PreferenceScreen; 35 import android.support.v7.preference.TwoStatePreference; 36 import android.telephony.TelephonyManager; 37 38 import com.android.settings.DefaultRingtonePreference; 39 import com.android.settings.R; 40 import com.android.settings.RingtonePreference; 41 import com.android.settings.testutils.SettingsRobolectricTestRunner; 42 import com.android.settings.TestConfig; 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 import org.robolectric.annotation.Config; 50 51 @RunWith(SettingsRobolectricTestRunner.class) 52 @Config(manifest = TestConfig.MANIFEST_PATH, sdk = TestConfig.SDK_VERSION) 53 public class WorkSoundPreferenceControllerTest { 54 55 private static final String KEY_WORK_CATEGORY = "sound_work_settings_section"; 56 private static final String KEY_WORK_USE_PERSONAL_SOUNDS = "work_use_personal_sounds"; 57 private static final String KEY_WORK_PHONE_RINGTONE = "work_ringtone"; 58 private static final String KEY_WORK_NOTIFICATION_RINGTONE = "work_notification_ringtone"; 59 private static final String KEY_WORK_ALARM_RINGTONE = "work_alarm_ringtone"; 60 61 @Mock 62 private Context mContext; 63 @Mock 64 private PreferenceScreen mScreen; 65 @Mock 66 private PreferenceCategory mWorkCategory; 67 @Mock 68 private TelephonyManager mTelephonyManager; 69 @Mock 70 private AudioHelper mAudioHelper; 71 @Mock 72 private SoundSettings mFragment; 73 74 private WorkSoundPreferenceController mController; 75 76 @Before 77 public void setUp() { 78 MockitoAnnotations.initMocks(this); 79 when(mContext.getSystemService(Context.TELEPHONY_SERVICE)).thenReturn(mTelephonyManager); 80 when(mTelephonyManager.isVoiceCapable()).thenReturn(true); 81 when(mScreen.findPreference(KEY_WORK_CATEGORY)) 82 .thenReturn(mWorkCategory); 83 when(mWorkCategory.findPreference(KEY_WORK_USE_PERSONAL_SOUNDS)) 84 .thenReturn(mock(TwoStatePreference.class)); 85 when(mWorkCategory.findPreference(KEY_WORK_PHONE_RINGTONE)) 86 .thenReturn(mock(DefaultRingtonePreference.class)); 87 when(mWorkCategory.findPreference(KEY_WORK_NOTIFICATION_RINGTONE)) 88 .thenReturn(mock(DefaultRingtonePreference.class)); 89 when(mWorkCategory.findPreference(KEY_WORK_ALARM_RINGTONE)) 90 .thenReturn(mock(DefaultRingtonePreference.class)); 91 92 mController = new WorkSoundPreferenceController(mContext, mFragment, null, mAudioHelper); 93 } 94 95 @Test 96 public void isAvailable_managedProfileAndNotSingleVolume_shouldReturnTrue() { 97 when(mAudioHelper.getManagedProfileId(nullable(UserManager.class))) 98 .thenReturn(UserHandle.myUserId()); 99 when(mAudioHelper.isUserUnlocked(nullable(UserManager.class), anyInt())).thenReturn(true); 100 when(mAudioHelper.isSingleVolume()).thenReturn(false); 101 102 assertThat(mController.isAvailable()).isTrue(); 103 } 104 105 @Test 106 public void isAvailable_noManagedProfile_shouldReturnFalse() { 107 when(mAudioHelper.getManagedProfileId(nullable(UserManager.class))) 108 .thenReturn(UserHandle.USER_NULL); 109 when(mAudioHelper.isUserUnlocked(nullable(UserManager.class), anyInt())).thenReturn(true); 110 when(mAudioHelper.isSingleVolume()).thenReturn(false); 111 112 assertThat(mController.isAvailable()).isFalse(); 113 } 114 115 @Test 116 public void isAvailable_singleVolume_shouldReturnFalse() { 117 when(mAudioHelper.getManagedProfileId(nullable(UserManager.class))) 118 .thenReturn(UserHandle.myUserId()); 119 when(mAudioHelper.isUserUnlocked(nullable(UserManager.class), anyInt())).thenReturn(true); 120 when(mAudioHelper.isSingleVolume()).thenReturn(true); 121 122 assertThat(mController.isAvailable()).isFalse(); 123 } 124 125 @Test 126 public void onManagedProfileAdded_shouldDisplayPreferenceCategory() { 127 // Given a device without any managed profiles: 128 when(mAudioHelper.isSingleVolume()).thenReturn(false); 129 when(mFragment.getPreferenceScreen()).thenReturn(mScreen); 130 when(mAudioHelper.createPackageContextAsUser(anyInt())).thenReturn(mContext); 131 when(mAudioHelper.getManagedProfileId(nullable(UserManager.class))) 132 .thenReturn(UserHandle.USER_NULL); 133 134 // When the fragment first displays, the category should not appear. 135 mController.displayPreference(mScreen); 136 verify(mWorkCategory).setVisible(false); 137 138 // However, when a managed profile is added later, the category should appear. 139 mController.onResume(); 140 when(mAudioHelper.getManagedProfileId(nullable(UserManager.class))) 141 .thenReturn(UserHandle.myUserId()); 142 mController.onManagedProfileAdded(UserHandle.myUserId()); 143 144 verify(mWorkCategory).setVisible(true); 145 } 146 147 @Test 148 public void onManagedProfileRemoved_shouldHidePreferenceCategory() { 149 // Given a device with a managed profile: 150 when(mAudioHelper.isSingleVolume()).thenReturn(false); 151 when(mFragment.getPreferenceScreen()).thenReturn(mScreen); 152 when(mAudioHelper.createPackageContextAsUser(anyInt())).thenReturn(mContext); 153 when(mAudioHelper.getManagedProfileId(nullable(UserManager.class))) 154 .thenReturn(UserHandle.myUserId()); 155 when(mAudioHelper.isUserUnlocked(nullable(UserManager.class), anyInt())).thenReturn(true); 156 157 // Which is in resumed state: 158 mController.displayPreference(mScreen); 159 mController.onResume(); 160 161 verify(mWorkCategory, times(2)).setVisible(true); 162 163 // When a managed profile is removed, the category should be hidden. 164 when(mAudioHelper.getManagedProfileId(nullable(UserManager.class))) 165 .thenReturn(UserHandle.USER_NULL); 166 mController.onManagedProfileRemoved(UserHandle.myUserId()); 167 168 verify(mWorkCategory).setVisible(false); 169 } 170 171 172 @Test 173 public void displayPreference_isAvailable_shouldShowPreferenceCategory() { 174 when(mAudioHelper.getManagedProfileId(nullable(UserManager.class))) 175 .thenReturn(UserHandle.myUserId()); 176 when(mAudioHelper.isUserUnlocked(nullable(UserManager.class), anyInt())).thenReturn(true); 177 when(mAudioHelper.isSingleVolume()).thenReturn(false); 178 when(mFragment.getPreferenceScreen()).thenReturn(mScreen); 179 when(mAudioHelper.createPackageContextAsUser(anyInt())).thenReturn(mContext); 180 181 mController.displayPreference(mScreen); 182 verify(mWorkCategory).setVisible(true); 183 } 184 185 @Test 186 public void displayPreference_notAvailable_shouldHidePreferenceCategory() { 187 when(mAudioHelper.getManagedProfileId(nullable(UserManager.class))) 188 .thenReturn(UserHandle.USER_NULL); 189 when(mAudioHelper.isSingleVolume()).thenReturn(true); 190 when(mFragment.getPreferenceScreen()).thenReturn(mScreen); 191 192 mController.displayPreference(mScreen); 193 verify(mWorkCategory).setVisible(false); 194 } 195 196 @Test 197 public void onPreferenceChange_shouldUpdateSummary() { 198 final Preference preference = mock(Preference.class); 199 when(preference.getKey()).thenReturn(KEY_WORK_PHONE_RINGTONE); 200 201 mController.onPreferenceChange(preference, "hello"); 202 203 verify(preference).setSummary(nullable(String.class)); 204 } 205 206 @Test 207 public void onResume_noVoiceCapability_shouldHidePhoneRingtone() { 208 when(mTelephonyManager.isVoiceCapable()).thenReturn(false); 209 mController = new WorkSoundPreferenceController(mContext, mFragment, null, mAudioHelper); 210 211 when(mAudioHelper.getManagedProfileId(nullable(UserManager.class))) 212 .thenReturn(UserHandle.myUserId()); 213 when(mAudioHelper.isUserUnlocked(nullable(UserManager.class), anyInt())).thenReturn(true); 214 when(mAudioHelper.isSingleVolume()).thenReturn(false); 215 when(mFragment.getPreferenceScreen()).thenReturn(mScreen); 216 when(mAudioHelper.createPackageContextAsUser(anyInt())).thenReturn(mContext); 217 218 // Precondition: work profile is available. 219 assertThat(mController.isAvailable()).isTrue(); 220 221 mController.displayPreference(mScreen); 222 mController.onResume(); 223 224 verify(mWorkCategory.findPreference(KEY_WORK_PHONE_RINGTONE)).setVisible(false); 225 } 226 227 @Test 228 public void onResume_availableButLocked_shouldRedactPreferences() { 229 final String notAvailable = "(not available)"; 230 when(mContext.getString(R.string.managed_profile_not_available_label)) 231 .thenReturn(notAvailable); 232 233 // Given a device with a managed profile: 234 when(mAudioHelper.isSingleVolume()).thenReturn(false); 235 when(mFragment.getPreferenceScreen()).thenReturn(mScreen); 236 when(mAudioHelper.createPackageContextAsUser(anyInt())).thenReturn(mContext); 237 when(mAudioHelper.getManagedProfileId(nullable(UserManager.class))) 238 .thenReturn(UserHandle.myUserId()); 239 when(mAudioHelper.isUserUnlocked(nullable(UserManager.class), anyInt())).thenReturn(false); 240 241 // When resumed: 242 mController.displayPreference(mScreen); 243 mController.onResume(); 244 245 verify(mWorkCategory, times(2)).setVisible(true); 246 247 // Sound preferences should explain that the profile isn't available yet. 248 verify(mWorkCategory.findPreference(KEY_WORK_PHONE_RINGTONE)) 249 .setSummary(eq(notAvailable)); 250 verify(mWorkCategory.findPreference(KEY_WORK_NOTIFICATION_RINGTONE)) 251 .setSummary(eq(notAvailable)); 252 verify(mWorkCategory.findPreference(KEY_WORK_ALARM_RINGTONE)) 253 .setSummary(eq(notAvailable)); 254 } 255 256 @Test 257 public void onResume_shouldSetUserIdToPreference() { 258 final int managedProfileUserId = 10; 259 when(mAudioHelper.getManagedProfileId(nullable(UserManager.class))) 260 .thenReturn(managedProfileUserId); 261 when(mAudioHelper.isUserUnlocked(nullable(UserManager.class), anyInt())).thenReturn(true); 262 when(mAudioHelper.isSingleVolume()).thenReturn(false); 263 when(mFragment.getPreferenceScreen()).thenReturn(mScreen); 264 when(mAudioHelper.createPackageContextAsUser(anyInt())).thenReturn(mContext); 265 266 mController.displayPreference(mScreen); 267 mController.onResume(); 268 269 verify((RingtonePreference) mWorkCategory.findPreference(KEY_WORK_PHONE_RINGTONE)) 270 .setUserId(managedProfileUserId); 271 verify((RingtonePreference) mWorkCategory.findPreference(KEY_WORK_NOTIFICATION_RINGTONE)) 272 .setUserId(managedProfileUserId); 273 verify((RingtonePreference) mWorkCategory.findPreference(KEY_WORK_ALARM_RINGTONE)) 274 .setUserId(managedProfileUserId); 275 } 276 277 } 278