1 /*
2  * Copyright (C) 2018 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.ui;
18 
19 import android.content.ContentResolver;
20 import android.os.SystemClock;
21 import android.provider.Settings;
22 import android.system.helpers.SettingsHelper;
23 import android.system.helpers.SettingsHelper.SettingsType;
24 import android.test.InstrumentationTestCase;
25 
26 import androidx.test.filters.MediumTest;
27 import androidx.test.filters.Suppress;
28 import androidx.test.uiautomator.By;
29 import androidx.test.uiautomator.UiDevice;
30 import androidx.test.uiautomator.UiObject2;
31 import androidx.test.uiautomator.Until;
32 
33 import org.junit.Ignore;
34 
35 import java.util.Map;
36 
37 @Ignore
38 public class SoundSettingsTest extends InstrumentationTestCase {
39     private static final String PAGE = Settings.ACTION_SOUND_SETTINGS;
40     private static final int TIMEOUT = 2000;
41 
42     private UiDevice mDevice;
43     private ContentResolver mResolver;
44     private SettingsHelper mHelper;
45 
46 
47     private final Map<String, String> ringtoneSounds = Map.of(
48             "angler", "Dione",
49             "bullhead", "Dione",
50             "marlin", "Spaceship",
51             "sailfish", "Spaceship",
52             "walleye", "Copycat",
53             "taimen", "Copycat");
54 
55     private final Map<String, String> ringtoneCodes = Map.of(
56             "angler", "38",
57             "bullhead", "38",
58             "marlin", "37",
59             "sailfish", "37",
60             "walleye", "26",
61             "taimen", "26");
62 
63     private final Map<String, String> alarmSounds = Map.of(
64             "angler", "Awaken",
65             "bullhead", "Awaken",
66             "marlin", "Bounce",
67             "sailfish", "Bounce",
68             "walleye", "Cuckoo clock",
69             "taimen", "Cuckoo clock");
70 
71     private final Map<String, String> alarmCodes = Map.of(
72             "angler", "6",
73             "bullhead", "6",
74             "marlin", "49",
75             "sailfish", "49",
76             "walleye", "15",
77             "taimen", "15");
78 
79     private final Map<String, String> notificationSounds = Map.of(
80             "angler", "Ceres",
81             "bullhead", "Ceres",
82             "marlin", "Trill",
83             "sailfish", "Trill",
84             "walleye", "Pipes",
85             "taimen", "Pipes");
86 
87 
88     private final Map<String, String> notificationCodes = Map.of(
89             "angler", "26",
90             "bullhead", "26",
91             "marlin", "57",
92             "sailfish", "57",
93             "walleye", "69",
94             "taimen", "69");
95 
96     @Override
setUp()97     public void setUp() throws Exception {
98         super.setUp();
99         mDevice = UiDevice.getInstance(getInstrumentation());
100         mDevice.setOrientationNatural();
101         mResolver = getInstrumentation().getContext().getContentResolver();
102         mHelper = new SettingsHelper();
103     }
104 
105     @Override
tearDown()106     public void tearDown() throws Exception {
107         mDevice.pressBack();
108         mDevice.pressHome();
109         mDevice.waitForIdle();
110         mDevice.unfreezeRotation();
111         super.tearDown();
112     }
113 
114     @MediumTest
testCallVibrate()115     public void testCallVibrate() throws Exception {
116         assertTrue(mHelper.verifyToggleSetting(SettingsType.SYSTEM, PAGE,
117                 "Also vibrate for calls", Settings.System.VIBRATE_WHEN_RINGING));
118         assertTrue(mHelper.verifyToggleSetting(SettingsType.SYSTEM, PAGE,
119                 "Also vibrate for calls", Settings.System.VIBRATE_WHEN_RINGING));
120     }
121 
122     @MediumTest
testOtherSoundsDialPadTones()123     public void testOtherSoundsDialPadTones() throws Exception {
124         loadOtherSoundsPage();
125         assertTrue("Dial pad tones not toggled", mHelper.verifyToggleSetting(
126                 SettingsType.SYSTEM, PAGE, "Dial pad tones",
127                 Settings.System.DTMF_TONE_WHEN_DIALING));
128     }
129 
130     @MediumTest
testOtherSoundsScreenLocking()131     public void testOtherSoundsScreenLocking() throws Exception {
132         loadOtherSoundsPage();
133         assertTrue("Screen locking sounds not toggled",
134                     mHelper.verifyToggleSetting(SettingsType.SYSTEM, PAGE,
135                     "Screen locking sounds", Settings.System.LOCKSCREEN_SOUNDS_ENABLED));
136     }
137 
138     @MediumTest
testOtherSoundsCharging()139     public void testOtherSoundsCharging() throws Exception {
140         loadOtherSoundsPage();
141         assertTrue("Charging sounds not toggled",
142                     mHelper.verifyToggleSetting(SettingsType.GLOBAL, PAGE,
143                     "Charging sounds", Settings.Global.CHARGING_SOUNDS_ENABLED));
144     }
145 
146     @MediumTest
testOtherSoundsTouch()147     public void testOtherSoundsTouch() throws Exception {
148         loadOtherSoundsPage();
149         assertTrue("Touch sounds not toggled",
150                     mHelper.verifyToggleSetting(SettingsType.SYSTEM, PAGE,
151                     "Touch sounds", Settings.System.SOUND_EFFECTS_ENABLED));
152     }
153 
loadOtherSoundsPage()154     private void loadOtherSoundsPage() throws Exception {
155         launchSoundSettings();
156         mHelper.scrollVert(false);
157         Thread.sleep(1000);
158     }
159 
launchSoundSettings()160     private void launchSoundSettings() throws Exception {
161         SettingsHelper.launchSettingsPage(getInstrumentation().getContext(), PAGE);
162         mHelper.scrollVert(false);
163         clickMore();
164         Thread.sleep(1000);
165         mHelper.scrollVert(true);
166         Thread.sleep(1000);
167     }
168 
169     /*
170      * Rather than verifying every ringtone, verify the ones least likely to change
171      * (None and Hangouts) and an arbitrary one from the ringtone pool.
172      */
173     @MediumTest
testPhoneRingtoneNone()174     public void testPhoneRingtoneNone() throws Exception {
175         launchSoundSettings();
176         mHelper.clickSetting("Phone ringtone");
177         verifyRingtone(new RingtoneSetting("None", "null"),
178                 Settings.System.RINGTONE);
179     }
180 
181     @MediumTest
182     @Suppress
testPhoneRingtoneHangouts()183     public void testPhoneRingtoneHangouts() throws Exception {
184         launchSoundSettings();
185         mHelper.clickSetting("Phone ringtone");
186         verifyRingtone(new RingtoneSetting("Hangouts Call", "31"), Settings.System.RINGTONE);
187     }
188 
189     @MediumTest
testPhoneRingtone()190     public void testPhoneRingtone() throws Exception {
191         launchSoundSettings();
192         mHelper.clickSetting("Phone ringtone");
193         String ringtone = ringtoneSounds.get(mDevice.getProductName()).toString();
194         String ringtoneSettingValue = ringtoneCodes.get(mDevice.getProductName()).toString();
195         verifyRingtone(new RingtoneSetting(ringtone, ringtoneSettingValue),
196                 Settings.System.RINGTONE);
197     }
198 
199     @MediumTest
testNotificationRingtoneNone()200     public void testNotificationRingtoneNone() throws Exception {
201         launchSoundSettings();
202         mHelper.clickSetting("Default notification sound");
203         verifyRingtone(new RingtoneSetting("None", "null"),
204                 Settings.System.NOTIFICATION_SOUND);
205     }
206 
207     @MediumTest
208     @Suppress
testNotificationRingtoneHangouts()209     public void testNotificationRingtoneHangouts() throws Exception {
210         launchSoundSettings();
211         mHelper.clickSetting("Default notification sound");
212         verifyRingtone(new RingtoneSetting("Hangouts Message", "30"),
213                 Settings.System.NOTIFICATION_SOUND);
214     }
215 
216     @MediumTest
testNotificationRingtone()217     public void testNotificationRingtone() throws Exception {
218         launchSoundSettings();
219         mHelper.clickSetting("Default notification sound");
220         String notificationRingtone = notificationSounds.get(mDevice.getProductName()).toString();
221         String notificationSettingValue = notificationCodes.get(mDevice.getProductName()).toString();
222         verifyRingtone(new RingtoneSetting(notificationRingtone, notificationSettingValue),
223                 Settings.System.NOTIFICATION_SOUND);
224     }
225 
226     @MediumTest
testAlarmRingtoneNone()227     public void testAlarmRingtoneNone() throws Exception {
228         launchSoundSettings();
229         mHelper.clickSetting("Default alarm sound");
230         verifyRingtone(new RingtoneSetting("None", "null"),
231                 Settings.System.ALARM_ALERT);
232     }
233 
234     @MediumTest
testAlarmRingtone()235     public void testAlarmRingtone() throws Exception {
236         launchSoundSettings();
237         String alarmRingtone = alarmSounds.get(mDevice.getProductName()).toString();
238         String alarmSettingValue = alarmCodes.get(mDevice.getProductName()).toString();
239         mHelper.clickSetting("Default alarm sound");
240         verifyRingtone(new RingtoneSetting(alarmRingtone, alarmSettingValue),
241                 Settings.System.ALARM_ALERT);
242     }
243 
244     /*
245      * This method verifies that setting a custom ringtone changes the
246      * ringtone code setting on the system. Each ringtone sound corresponds
247      * to an arbitrary code. To see which ringtone code this is on your device, run
248      * adb shell settings get system ringtone
249      * The number you see at the end of the file path is the one you need.
250      * To see alarms and notifications ringtone codes, run the following:
251      * adb shell settings get system alarm_alert
252      * adb shell settings get system notification_sound
253      * @param r Ringtone setting - the name of the ringtone as displayed on device
254      * @param settingName - the code of the ringtone as explained above
255      * @param dir - the direction in which to scroll
256      */
verifyRingtone(RingtoneSetting r, String settingName)257     private void verifyRingtone(RingtoneSetting r, String settingName) throws Exception {
258         findRingtoneInList(r.getName()).click();
259         if (mDevice.getProductName().equals("walleye") || mDevice.getProductName().equals("taimen")) {
260             mDevice.wait(Until.findObject(By.text("SAVE")), TIMEOUT).click();
261         }
262         else {
263             mDevice.wait(Until.findObject(By.text("OK")), TIMEOUT).click();
264         }
265         SystemClock.sleep(1000);
266         if (r.getVal().equals("null")) {
267             assertEquals(null,
268                     Settings.System.getString(mResolver, settingName));
269         } else if (r.getName().contains("Hangouts")) {
270             assertEquals("content://media/external/audio/media/" + r.getVal(),
271                     Settings.System.getString(mResolver, settingName));
272         } else {
273             assertEquals("content://media/internal/audio/media/" + r.getVal(),
274                     Settings.System.getString(mResolver, settingName));
275         }
276     }
277 
278     private enum ScrollDir {
279         UP,
280         DOWN,
281         NOSCROLL
282     }
283 
284     class RingtoneSetting {
285         private final String mName;
286         private final String mMediaVal;
RingtoneSetting(String name, String fname)287         public RingtoneSetting(String name, String fname) {
288             mName = name;
289             mMediaVal = fname;
290         }
getName()291         public String getName() {
292             return mName;
293         }
getVal()294         public String getVal() {
295             return mMediaVal;
296         }
297     }
298 
clickMore()299     private void clickMore() throws InterruptedException {
300         UiObject2 more = mDevice.wait(Until.findObject(By.text("Advanced")), TIMEOUT);
301         if (more != null) {
302             more.click();
303             Thread.sleep(TIMEOUT);
304         }
305     }
306 
findRingtoneInList(String ringtone)307     private UiObject2 findRingtoneInList(String ringtone) throws Exception {
308         mHelper.scrollVert(false);
309         SystemClock.sleep(1000);
310         UiObject2 ringToneObject = mDevice.wait(Until.findObject(By.text(ringtone)), TIMEOUT);
311         int count = 0;
312         while (ringToneObject == null && count < 5) {
313             mHelper.scrollVert(true);
314             SystemClock.sleep(1000);
315             ringToneObject = mDevice.wait(Until.findObject(By.text(ringtone)), TIMEOUT);
316             count++;
317         }
318         return ringToneObject;
319     }
320 }
321