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