1 /* 2 * Copyright (C) 2020 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.deskclock.ringtone; 18 19 import android.content.Context; 20 import android.content.Intent; 21 import android.content.SharedPreferences; 22 import android.net.Uri; 23 import android.preference.PreferenceManager; 24 25 import androidx.recyclerview.widget.RecyclerView; 26 import androidx.test.InstrumentationRegistry; 27 import androidx.test.internal.runner.junit4.AndroidJUnit4ClassRunner; 28 import androidx.test.rule.ActivityTestRule; 29 30 import com.android.deskclock.ItemAdapter; 31 import com.android.deskclock.ItemAdapter.ItemHolder; 32 import com.android.deskclock.R; 33 import com.android.deskclock.Utils; 34 import com.android.deskclock.data.DataModel; 35 import com.android.deskclock.provider.Alarm; 36 37 import org.junit.After; 38 import org.junit.Before; 39 import org.junit.Rule; 40 import org.junit.Test; 41 import org.junit.runner.RunWith; 42 43 import java.util.Iterator; 44 import java.util.List; 45 46 import static org.junit.Assert.assertEquals; 47 48 /** 49 * Exercise the user interface that adjusts the selected ringtone. 50 */ 51 @RunWith(AndroidJUnit4ClassRunner.class) 52 public class RingtonePickerActivityTest { 53 54 private RingtonePickerActivity activity; 55 private RecyclerView ringtoneList; 56 private ItemAdapter<ItemHolder<Uri>> ringtoneAdapter; 57 58 public static final Uri ALERT = Uri.parse("content://settings/system/alarm_alert"); 59 public static final Uri CUSTOM_RINGTONE_1 = Uri.parse("content://media/external/audio/one.ogg"); 60 61 @Rule 62 public ActivityTestRule<RingtonePickerActivity> rule = 63 new ActivityTestRule<>(RingtonePickerActivity.class, true, false); 64 65 @Before 66 @After setUp()67 public void setUp() { 68 Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); 69 SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); 70 prefs.edit().clear().commit(); 71 } 72 73 @Test validateDefaultState_TimerRingtonePicker()74 public void validateDefaultState_TimerRingtonePicker() { 75 createTimerRingtonePickerActivity(); 76 77 final List<ItemHolder<Uri>> systemRingtoneHolders = ringtoneAdapter.items; 78 79 if (systemRingtoneHolders == null) { 80 return; 81 } 82 83 final Iterator<ItemHolder<Uri>> itemsIter = systemRingtoneHolders.iterator(); 84 85 final HeaderHolder filesHeaderHolder = (HeaderHolder) itemsIter.next(); 86 assertEquals(R.string.your_sounds, filesHeaderHolder.getTextResId()); 87 assertEquals(HeaderViewHolder.VIEW_TYPE_ITEM_HEADER, filesHeaderHolder.getItemViewType()); 88 89 final AddCustomRingtoneHolder addNewHolder = (AddCustomRingtoneHolder) itemsIter.next(); 90 assertEquals(AddCustomRingtoneViewHolder.VIEW_TYPE_ADD_NEW, addNewHolder.getItemViewType()); 91 92 final HeaderHolder systemHeaderHolder = (HeaderHolder) itemsIter.next(); 93 assertEquals(R.string.device_sounds, systemHeaderHolder.getTextResId()); 94 assertEquals(HeaderViewHolder.VIEW_TYPE_ITEM_HEADER, systemHeaderHolder.getItemViewType()); 95 96 final RingtoneHolder silentHolder = (RingtoneHolder) itemsIter.next(); 97 assertEquals(Utils.RINGTONE_SILENT, silentHolder.getUri()); 98 assertEquals(RingtoneViewHolder.VIEW_TYPE_SYSTEM_SOUND, silentHolder.getItemViewType()); 99 100 final RingtoneHolder defaultHolder = (RingtoneHolder) itemsIter.next(); 101 assertEquals(RingtoneViewHolder.VIEW_TYPE_SYSTEM_SOUND, defaultHolder.getItemViewType()); 102 103 Runnable assertRunnable = () -> { 104 assertEquals("Silent", silentHolder.getName()); 105 assertEquals("Timer Expired", defaultHolder.getName()); 106 assertEquals(DataModel.getDataModel().getDefaultTimerRingtoneUri(), 107 defaultHolder.getUri()); 108 // Verify initial selection. 109 assertEquals( 110 DataModel.getDataModel().getTimerRingtoneUri(), 111 DataModel.getDataModel().getDefaultTimerRingtoneUri()); 112 }; 113 InstrumentationRegistry.getInstrumentation().runOnMainSync(assertRunnable); 114 } 115 116 @Test validateDefaultState_AlarmRingtonePicker()117 public void validateDefaultState_AlarmRingtonePicker() { 118 createAlarmRingtonePickerActivity(ALERT); 119 120 final List<ItemHolder<Uri>> systemRingtoneHolders = ringtoneAdapter.items; 121 final Iterator<ItemHolder<Uri>> itemsIter = systemRingtoneHolders.iterator(); 122 123 final HeaderHolder filesHeaderHolder = (HeaderHolder) itemsIter.next(); 124 assertEquals(R.string.your_sounds, filesHeaderHolder.getTextResId()); 125 assertEquals(HeaderViewHolder.VIEW_TYPE_ITEM_HEADER, filesHeaderHolder.getItemViewType()); 126 127 final AddCustomRingtoneHolder addNewHolder = (AddCustomRingtoneHolder) itemsIter.next(); 128 assertEquals(AddCustomRingtoneViewHolder.VIEW_TYPE_ADD_NEW, addNewHolder.getItemViewType()); 129 130 final HeaderHolder systemHeaderHolder = (HeaderHolder) itemsIter.next(); 131 assertEquals(R.string.device_sounds, systemHeaderHolder.getTextResId()); 132 assertEquals(HeaderViewHolder.VIEW_TYPE_ITEM_HEADER, systemHeaderHolder.getItemViewType()); 133 134 final RingtoneHolder silentHolder = (RingtoneHolder) itemsIter.next(); 135 assertEquals(Utils.RINGTONE_SILENT, silentHolder.getUri()); 136 assertEquals(RingtoneViewHolder.VIEW_TYPE_SYSTEM_SOUND, silentHolder.getItemViewType()); 137 138 final RingtoneHolder defaultHolder = (RingtoneHolder) itemsIter.next(); 139 assertEquals(RingtoneViewHolder.VIEW_TYPE_SYSTEM_SOUND, defaultHolder.getItemViewType()); 140 141 Runnable assertRunnable = () -> { 142 assertEquals("Silent", silentHolder.getName()); 143 assertEquals("Default alarm sound", defaultHolder.getName()); 144 assertEquals(DataModel.getDataModel().getDefaultAlarmRingtoneUri(), 145 defaultHolder.getUri()); 146 }; 147 InstrumentationRegistry.getInstrumentation().runOnMainSync(assertRunnable); 148 } 149 150 @Test validateDefaultState_TimerRingtonePicker_WithCustomRingtones()151 public void validateDefaultState_TimerRingtonePicker_WithCustomRingtones() { 152 Runnable customRingtoneRunnable = () -> { 153 DataModel.getDataModel().addCustomRingtone(CUSTOM_RINGTONE_1, "CustomSound"); 154 }; 155 InstrumentationRegistry.getInstrumentation().runOnMainSync(customRingtoneRunnable); 156 createTimerRingtonePickerActivity(); 157 158 final List<ItemHolder<Uri>> systemRingtoneHolders = ringtoneAdapter.items; 159 final Iterator<ItemHolder<Uri>> itemsIter = systemRingtoneHolders.iterator(); 160 161 final HeaderHolder filesHeaderHolder = (HeaderHolder) itemsIter.next(); 162 assertEquals(R.string.your_sounds, filesHeaderHolder.getTextResId()); 163 assertEquals(HeaderViewHolder.VIEW_TYPE_ITEM_HEADER, filesHeaderHolder.getItemViewType()); 164 165 final CustomRingtoneHolder customRingtoneHolder = (CustomRingtoneHolder) itemsIter.next(); 166 assertEquals("CustomSound", customRingtoneHolder.getName()); 167 assertEquals(CUSTOM_RINGTONE_1, customRingtoneHolder.getUri()); 168 assertEquals(RingtoneViewHolder.VIEW_TYPE_CUSTOM_SOUND, 169 customRingtoneHolder.getItemViewType()); 170 171 final AddCustomRingtoneHolder addNewHolder = (AddCustomRingtoneHolder) itemsIter.next(); 172 assertEquals(AddCustomRingtoneViewHolder.VIEW_TYPE_ADD_NEW, addNewHolder.getItemViewType()); 173 174 final HeaderHolder systemHeaderHolder = (HeaderHolder) itemsIter.next(); 175 assertEquals(R.string.device_sounds, systemHeaderHolder.getTextResId()); 176 assertEquals(HeaderViewHolder.VIEW_TYPE_ITEM_HEADER, systemHeaderHolder.getItemViewType()); 177 178 final RingtoneHolder silentHolder = (RingtoneHolder) itemsIter.next(); 179 assertEquals(Utils.RINGTONE_SILENT, silentHolder.getUri()); 180 assertEquals(RingtoneViewHolder.VIEW_TYPE_SYSTEM_SOUND, silentHolder.getItemViewType()); 181 182 final RingtoneHolder defaultHolder = (RingtoneHolder) itemsIter.next(); 183 assertEquals(RingtoneViewHolder.VIEW_TYPE_SYSTEM_SOUND, defaultHolder.getItemViewType()); 184 185 Runnable assertRunnable = () -> { 186 assertEquals("Silent", silentHolder.getName()); 187 assertEquals("Timer Expired", defaultHolder.getName()); 188 assertEquals(DataModel.getDataModel().getDefaultTimerRingtoneUri(), 189 defaultHolder.getUri()); 190 // Verify initial selection. 191 assertEquals( 192 DataModel.getDataModel().getTimerRingtoneUri(), 193 DataModel.getDataModel().getDefaultTimerRingtoneUri()); 194 }; 195 InstrumentationRegistry.getInstrumentation().runOnMainSync(assertRunnable); 196 197 Runnable removeCustomRingtoneRunnable = () -> { 198 DataModel.getDataModel().removeCustomRingtone(CUSTOM_RINGTONE_1); 199 }; 200 InstrumentationRegistry.getInstrumentation().runOnMainSync(removeCustomRingtoneRunnable); 201 } 202 203 @Test validateDefaultState_AlarmRingtonePicker_WithCustomRingtones()204 public void validateDefaultState_AlarmRingtonePicker_WithCustomRingtones() { 205 Runnable customRingtoneRunnable = () -> { 206 DataModel.getDataModel().addCustomRingtone(CUSTOM_RINGTONE_1, "CustomSound"); 207 }; 208 InstrumentationRegistry.getInstrumentation().runOnMainSync(customRingtoneRunnable); 209 createAlarmRingtonePickerActivity(ALERT); 210 211 final List<ItemHolder<Uri>> systemRingtoneHolders = ringtoneAdapter.items; 212 final Iterator<ItemHolder<Uri>> itemsIter = systemRingtoneHolders.iterator(); 213 214 final HeaderHolder filesHeaderHolder = (HeaderHolder) itemsIter.next(); 215 assertEquals(R.string.your_sounds, filesHeaderHolder.getTextResId()); 216 assertEquals(HeaderViewHolder.VIEW_TYPE_ITEM_HEADER, filesHeaderHolder.getItemViewType()); 217 218 final CustomRingtoneHolder customRingtoneHolder = (CustomRingtoneHolder) itemsIter.next(); 219 assertEquals("CustomSound", customRingtoneHolder.getName()); 220 assertEquals(CUSTOM_RINGTONE_1, customRingtoneHolder.getUri()); 221 assertEquals(RingtoneViewHolder.VIEW_TYPE_CUSTOM_SOUND, 222 customRingtoneHolder.getItemViewType()); 223 224 final AddCustomRingtoneHolder addNewHolder = (AddCustomRingtoneHolder) itemsIter.next(); 225 assertEquals(AddCustomRingtoneViewHolder.VIEW_TYPE_ADD_NEW, addNewHolder.getItemViewType()); 226 227 final HeaderHolder systemHeaderHolder = (HeaderHolder) itemsIter.next(); 228 assertEquals(R.string.device_sounds, systemHeaderHolder.getTextResId()); 229 assertEquals(HeaderViewHolder.VIEW_TYPE_ITEM_HEADER, systemHeaderHolder.getItemViewType()); 230 231 final RingtoneHolder silentHolder = (RingtoneHolder) itemsIter.next(); 232 assertEquals(Utils.RINGTONE_SILENT, silentHolder.getUri()); 233 assertEquals(RingtoneViewHolder.VIEW_TYPE_SYSTEM_SOUND, silentHolder.getItemViewType()); 234 235 final RingtoneHolder defaultHolder = (RingtoneHolder) itemsIter.next(); 236 assertEquals(RingtoneViewHolder.VIEW_TYPE_SYSTEM_SOUND, defaultHolder.getItemViewType()); 237 238 Runnable assertRunnable = () -> { 239 assertEquals("Silent", silentHolder.getName()); 240 assertEquals("Default alarm sound", defaultHolder.getName()); 241 assertEquals(DataModel.getDataModel().getDefaultAlarmRingtoneUri(), 242 defaultHolder.getUri()); 243 }; 244 InstrumentationRegistry.getInstrumentation().runOnMainSync(assertRunnable); 245 246 Runnable removeCustomRingtoneRunnable = () -> { 247 DataModel.getDataModel().removeCustomRingtone(CUSTOM_RINGTONE_1); 248 }; 249 InstrumentationRegistry.getInstrumentation().runOnMainSync(removeCustomRingtoneRunnable); 250 } 251 createTimerRingtonePickerActivity()252 private void createTimerRingtonePickerActivity() { 253 final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); 254 final Intent newIntent = new Intent(); 255 256 Runnable createIntentRunnable = () -> { 257 final Intent intent = RingtonePickerActivity.createTimerRingtonePickerIntent(context); 258 newIntent.fillIn(intent, 0); 259 }; 260 InstrumentationRegistry.getInstrumentation().runOnMainSync(createIntentRunnable); 261 262 createRingtonePickerActivity(newIntent); 263 } 264 createAlarmRingtonePickerActivity(Uri ringtone)265 private void createAlarmRingtonePickerActivity(Uri ringtone) { 266 final Context context = InstrumentationRegistry.getInstrumentation().getTargetContext(); 267 final Intent newIntent = new Intent(); 268 269 Runnable createIntentRunnable = () -> { 270 // Use the custom ringtone in some alarms. 271 final Alarm alarm = new Alarm(1, 1); 272 alarm.enabled = true; 273 alarm.vibrate = true; 274 alarm.alert = ringtone; 275 alarm.deleteAfterUse = true; 276 277 final Intent intent = 278 RingtonePickerActivity.createAlarmRingtonePickerIntent(context, alarm); 279 newIntent.fillIn(intent, 0); 280 }; 281 InstrumentationRegistry.getInstrumentation().runOnMainSync(createIntentRunnable); 282 283 createRingtonePickerActivity(newIntent); 284 } 285 286 @SuppressWarnings("unchecked") createRingtonePickerActivity(Intent intent)287 private void createRingtonePickerActivity(Intent intent) { 288 activity = rule.launchActivity(intent); 289 ringtoneList = activity.findViewById(R.id.ringtone_content); 290 ringtoneAdapter = (ItemAdapter<ItemHolder<Uri>>) ringtoneList.getAdapter(); 291 } 292 } 293