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