1 /*
2  * Copyright (C) 2008 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 android.media.cts;
18 
19 import android.content.Context;
20 import android.content.pm.PackageManager;
21 import android.media.AudioAttributes;
22 import android.media.AudioManager;
23 import android.media.Ringtone;
24 import android.media.RingtoneManager;
25 import android.media.audiofx.HapticGenerator;
26 import android.net.Uri;
27 import android.os.Build;
28 import android.platform.test.annotations.AppModeFull;
29 import android.provider.Settings;
30 import android.test.InstrumentationTestCase;
31 import android.util.Log;
32 
33 import com.android.compatibility.common.util.ApiLevelUtil;
34 
35 @AppModeFull(reason = "TODO: evaluate and port to instant")
36 public class RingtoneTest extends InstrumentationTestCase {
37     private static final String TAG = "RingtoneTest";
38 
39     private Context mContext;
40     private Ringtone mRingtone;
41     private AudioManager mAudioManager;
42     private int mOriginalVolume;
43     private int mOriginalRingerMode;
44     private int mOriginalStreamType;
45     private Uri mDefaultRingUri;
46 
47     private static boolean sIsAtLeastS = ApiLevelUtil.isAtLeast(Build.VERSION_CODES.S);
48 
49     @Override
setUp()50     protected void setUp() throws Exception {
51         super.setUp();
52         enableAppOps();
53         mContext = getInstrumentation().getContext();
54         mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
55         mRingtone = RingtoneManager.getRingtone(mContext, Settings.System.DEFAULT_RINGTONE_URI);
56         // backup ringer settings
57         mOriginalRingerMode = mAudioManager.getRingerMode();
58         mOriginalVolume = mAudioManager.getStreamVolume(AudioManager.STREAM_RING);
59         mOriginalStreamType = mRingtone.getStreamType();
60 
61         int maxVolume = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_RING);
62 
63         if (mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE) {
64             mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
65             mAudioManager.setStreamVolume(AudioManager.STREAM_RING, maxVolume / 2,
66                     AudioManager.FLAG_ALLOW_RINGER_MODES);
67         } else if (mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_NORMAL) {
68             mAudioManager.setStreamVolume(AudioManager.STREAM_RING, maxVolume / 2,
69                     AudioManager.FLAG_ALLOW_RINGER_MODES);
70         } else {
71             try {
72                 Utils.toggleNotificationPolicyAccess(
73                         mContext.getPackageName(), getInstrumentation(), true);
74                 // set ringer to a reasonable volume
75                 mAudioManager.setStreamVolume(AudioManager.STREAM_RING, maxVolume / 2,
76                         AudioManager.FLAG_ALLOW_RINGER_MODES);
77                 // make sure that we are not in silent mode
78                 mAudioManager.setRingerMode(AudioManager.RINGER_MODE_NORMAL);
79             } finally {
80                 Utils.toggleNotificationPolicyAccess(
81                         mContext.getPackageName(), getInstrumentation(), false);
82             }
83         }
84 
85         mDefaultRingUri = RingtoneManager.getActualDefaultRingtoneUri(mContext,
86                 RingtoneManager.TYPE_RINGTONE);
87     }
88 
enableAppOps()89     private void enableAppOps() {
90         StringBuilder cmd = new StringBuilder();
91         cmd.append("appops set ");
92         cmd.append(getInstrumentation().getContext().getPackageName());
93         cmd.append(" android:write_settings allow");
94         getInstrumentation().getUiAutomation().executeShellCommand(cmd.toString());
95         try {
96             Thread.sleep(2200);
97         } catch (InterruptedException e) {
98         }
99     }
100 
101     @Override
tearDown()102     protected void tearDown() throws Exception {
103         // restore original settings
104         if (mRingtone != null) {
105             if (mRingtone.isPlaying()) mRingtone.stop();
106             mRingtone.setStreamType(mOriginalStreamType);
107         }
108         if (mAudioManager != null) {
109             try {
110                 Utils.toggleNotificationPolicyAccess(
111                         mContext.getPackageName(), getInstrumentation(), true);
112                 mAudioManager.setRingerMode(mOriginalRingerMode);
113                 mAudioManager.setStreamVolume(AudioManager.STREAM_RING, mOriginalVolume,
114                         AudioManager.FLAG_ALLOW_RINGER_MODES);
115             } finally {
116                 Utils.toggleNotificationPolicyAccess(
117                         mContext.getPackageName(), getInstrumentation(), false);
118             }
119         }
120         RingtoneManager.setActualDefaultRingtoneUri(mContext, RingtoneManager.TYPE_RINGTONE,
121                 mDefaultRingUri);
122         super.tearDown();
123     }
124 
hasAudioOutput()125     private boolean hasAudioOutput() {
126         return getInstrumentation().getContext().getPackageManager()
127                 .hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT);
128     }
129 
isTV()130     private boolean isTV() {
131         return getInstrumentation().getContext().getPackageManager()
132                 .hasSystemFeature(PackageManager.FEATURE_LEANBACK_ONLY);
133     }
134 
testRingtone()135     public void testRingtone() {
136         if (isTV()) {
137             return;
138         }
139         if (!hasAudioOutput()) {
140             Log.i(TAG, "Skipping testRingtone(): device doesn't have audio output.");
141             return;
142         }
143 
144         assertNotNull(mRingtone.getTitle(mContext));
145         assertTrue(mOriginalStreamType >= 0);
146 
147         mRingtone.setStreamType(AudioManager.STREAM_MUSIC);
148         assertEquals(AudioManager.STREAM_MUSIC, mRingtone.getStreamType());
149         mRingtone.setStreamType(AudioManager.STREAM_ALARM);
150         assertEquals(AudioManager.STREAM_ALARM, mRingtone.getStreamType());
151         // make sure we play on STREAM_RING because we the volume on this stream is not 0
152         mRingtone.setStreamType(AudioManager.STREAM_RING);
153         assertEquals(AudioManager.STREAM_RING, mRingtone.getStreamType());
154 
155         // test both the "None" ringtone and an actual ringtone
156         RingtoneManager.setActualDefaultRingtoneUri(mContext, RingtoneManager.TYPE_RINGTONE, null);
157         mRingtone = RingtoneManager.getRingtone(mContext, Settings.System.DEFAULT_RINGTONE_URI);
158         assertTrue(mRingtone.getStreamType() == AudioManager.STREAM_RING);
159         mRingtone.play();
160         assertFalse(mRingtone.isPlaying());
161 
162         Uri uri = RingtoneManager.getValidRingtoneUri(mContext);
163         assertNotNull("ringtone was unexpectedly null", uri);
164         RingtoneManager.setActualDefaultRingtoneUri(mContext, RingtoneManager.TYPE_RINGTONE, uri);
165         mRingtone = RingtoneManager.getRingtone(mContext, Settings.System.DEFAULT_RINGTONE_URI);
166         assertTrue(mRingtone.getStreamType() == AudioManager.STREAM_RING);
167         mRingtone.play();
168         assertTrue("couldn't play ringtone " + uri, mRingtone.isPlaying());
169         mRingtone.stop();
170         assertFalse(mRingtone.isPlaying());
171     }
172 
testPlaybackProperties()173     public void testPlaybackProperties() {
174         if (isTV()) {
175             return;
176         }
177         if (!hasAudioOutput()) {
178             Log.i(TAG, "Skipping testRingtone(): device doesn't have audio output.");
179             return;
180         }
181 
182         Uri uri = RingtoneManager.getValidRingtoneUri(mContext);
183         assertNotNull("ringtone was unexpectedly null", uri);
184         RingtoneManager.setActualDefaultRingtoneUri(mContext, RingtoneManager.TYPE_RINGTONE, uri);
185         assertNotNull(mRingtone.getTitle(mContext));
186         final AudioAttributes ringtoneAa = new AudioAttributes.Builder()
187                 .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE).
188                 build();
189         mRingtone.setAudioAttributes(ringtoneAa);
190         assertEquals(ringtoneAa, mRingtone.getAudioAttributes());
191         mRingtone.setLooping(true);
192         mRingtone.setVolume(0.5f);
193         if (sIsAtLeastS) {
194             assertEquals(HapticGenerator.isAvailable(), mRingtone.setHapticGeneratorEnabled(true));
195         }
196         mRingtone.play();
197         assertTrue("couldn't play ringtone " + uri, mRingtone.isPlaying());
198         assertTrue(mRingtone.isLooping());
199         if (sIsAtLeastS) {
200             assertEquals(HapticGenerator.isAvailable(), mRingtone.isHapticGeneratorEnabled());
201         }
202         assertEquals("invalid ringtone player volume", 0.5f, mRingtone.getVolume());
203         mRingtone.stop();
204         assertFalse(mRingtone.isPlaying());
205     }
206 }
207