1 /*
2  * Copyright (C) 2010 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License"); you may not
5  * use this file except in compliance with the License. You may obtain a copy of
6  * 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, WITHOUT
12  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
13  * License for the specific language governing permissions and limitations under
14  * the License.
15  */
16
17package com.android.mediaframeworktest.functional.audio;
18
19import com.android.mediaframeworktest.MediaFrameworkTest;
20import android.content.Context;
21import android.media.AudioManager;
22import android.media.MediaPlayer;
23import android.media.AudioManager.OnAudioFocusChangeListener;
24import android.os.Looper;
25import android.test.ActivityInstrumentationTestCase2;
26import android.test.suitebuilder.annotation.MediumTest;
27import android.test.suitebuilder.annotation.LargeTest;
28import android.util.Log;
29
30/**
31 * Junit / Instrumentation test case for the media AudioManager api
32 */
33
34public class MediaAudioManagerTest extends ActivityInstrumentationTestCase2<MediaFrameworkTest> {
35
36    private final static String TAG = "MediaAudioManagerTest";
37    // the AudioManager used throughout the test
38    private AudioManager mAudioManager;
39    // keep track of looper for AudioManager so we can terminate it
40    private Looper mAudioManagerLooper;
41    private final Object mLooperLock = new Object();
42    private final static int WAIT_FOR_LOOPER_TO_INITIALIZE_MS = 60000;  // 60s
43    private int[] ringtoneMode = {AudioManager.RINGER_MODE_NORMAL,
44             AudioManager.RINGER_MODE_SILENT, AudioManager.RINGER_MODE_VIBRATE};
45    private boolean mUseFixedVolume;
46
47    public MediaAudioManagerTest() {
48        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
49    }
50
51    private void initializeAudioManagerWithLooper() {
52        new Thread() {
53            @Override
54            public void run() {
55                Looper.prepare();
56                mAudioManagerLooper = Looper.myLooper();
57                mAudioManager = (AudioManager)getActivity().getSystemService(Context.AUDIO_SERVICE);
58                synchronized (mLooperLock) {
59                    mLooperLock.notify();
60                }
61                Looper.loop();
62            }
63        }.start();
64    }
65
66    @Override
67    protected void setUp() throws Exception {
68        super.setUp();
69
70        mUseFixedVolume = getActivity().getResources().getBoolean(
71                com.android.internal.R.bool.config_useFixedVolume);
72
73        synchronized(mLooperLock) {
74            initializeAudioManagerWithLooper();
75            try {
76                mLooperLock.wait(WAIT_FOR_LOOPER_TO_INITIALIZE_MS);
77            } catch (Exception e) {
78                assertTrue("initializeAudioManagerWithLooper() failed to complete in time", false);
79            }
80        }
81     }
82
83     @Override
84     protected void tearDown() throws Exception {
85         super.tearDown();
86         synchronized(mLooperLock) {
87             if (mAudioManagerLooper != null) {
88                 mAudioManagerLooper.quit();
89             }
90         }
91     }
92
93     //-----------------------------------------------------------------
94     //      Ringer Mode
95     //----------------------------------
96
97     public boolean validateSetRingTone(int i) {
98         int getRingtone = mAudioManager.getRingerMode();
99
100         if (mUseFixedVolume) {
101             return (getRingtone == AudioManager.RINGER_MODE_NORMAL);
102         } else {
103             return (getRingtone == i);
104         }
105     }
106
107     // Test case 1: Simple test case to validate the set ringtone mode
108     @MediumTest
109     public void testSetRingtoneMode() throws Exception {
110         boolean result = false;
111
112         for (int i = 0; i < ringtoneMode.length; i++) {
113             mAudioManager.setRingerMode(ringtoneMode[i]);
114             result = validateSetRingTone(ringtoneMode[i]);
115             assertTrue("SetRingtoneMode : " + ringtoneMode[i], result);
116         }
117     }
118
119    //-----------------------------------------------------------------
120    //      AudioFocus
121    //----------------------------------
122
123    private static AudioFocusListener mAudioFocusListener;
124    private final static int INVALID_FOCUS = -80; // initialized to magic invalid focus change type
125    private final static int WAIT_FOR_AUDIOFOCUS_LOSS_MS = 10;
126
127    private static class AudioFocusListener implements OnAudioFocusChangeListener {
128        public int mLastFocusChange = INVALID_FOCUS;
129        public int mFocusChangeCounter = 0;
130        public AudioFocusListener() {
131        }
132        public void onAudioFocusChange(int focusChange) {
133            mLastFocusChange = focusChange;
134            mFocusChangeCounter++;
135        }
136    }
137
138    /**
139     * Fails the test if expectedFocusLossMode != mAudioFocusListener.mLastFocusChange
140     */
141    private void verifyAudioFocusLoss(int focusGainMode, int expectedFocusLossMode)
142            throws Exception {
143        // request AudioFocus so we can test that mAudioFocusListener loses it when another
144        //     request comes in
145        int result = mAudioManager.requestAudioFocus(mAudioFocusListener,
146                AudioManager.STREAM_MUSIC,
147                AudioManager.AUDIOFOCUS_GAIN);
148        assertTrue("requestAudioFocus returned " + result,
149                result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
150        // cause mAudioFocusListener to lose AudioFocus
151        result = mAudioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC,
152                focusGainMode);
153        assertTrue("requestAudioFocus returned " + result,
154                result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
155        // the audio focus request is async, so wait a bit to verify it had the expected effect
156        java.lang.Thread.sleep(WAIT_FOR_AUDIOFOCUS_LOSS_MS);
157        // test successful if the expected focus loss was recorded
158        assertEquals("listener lost focus",
159                mAudioFocusListener.mLastFocusChange, expectedFocusLossMode);
160    }
161
162    private void setupAudioFocusListener() {
163        mAudioFocusListener = new AudioFocusListener();
164        mAudioManager.registerAudioFocusListener(mAudioFocusListener);
165    }
166
167    private void cleanupAudioFocusListener() {
168        // clean up
169        mAudioManager.abandonAudioFocus(mAudioFocusListener);
170        mAudioManager.unregisterAudioFocusListener(mAudioFocusListener);
171    }
172
173    //----------------------------------
174
175    //Test case 1: test audio focus listener loses audio focus:
176    //   AUDIOFOCUS_GAIN causes AUDIOFOCUS_LOSS
177    @MediumTest
178    public void testAudioFocusLoss() throws Exception {
179        setupAudioFocusListener();
180
181        verifyAudioFocusLoss(AudioManager.AUDIOFOCUS_GAIN, AudioManager.AUDIOFOCUS_LOSS);
182
183        cleanupAudioFocusListener();
184    }
185
186    //Test case 2: test audio focus listener loses audio focus:
187    //   AUDIOFOCUS_GAIN_TRANSIENT causes AUDIOFOCUS_LOSS_TRANSIENT
188    @MediumTest
189    public void testAudioFocusLossTransient() throws Exception {
190        setupAudioFocusListener();
191
192        verifyAudioFocusLoss(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT,
193                AudioManager.AUDIOFOCUS_LOSS_TRANSIENT);
194
195        cleanupAudioFocusListener();
196    }
197
198    //Test case 3: test audio focus listener loses audio focus:
199    //   AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK causes AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
200    @MediumTest
201    public void testAudioFocusLossTransientDuck() throws Exception {
202        setupAudioFocusListener();
203
204        verifyAudioFocusLoss(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
205                AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK);
206
207        cleanupAudioFocusListener();
208    }
209
210    //Test case 4: test audio focus registering and use over 3000 iterations
211    @LargeTest
212    public void testAudioFocusStressListenerRequestAbandon() throws Exception {
213        final int ITERATIONS = 3000;
214        // here we only test the life cycle of a focus listener, and make sure we don't crash
215        // when doing it many times without waiting
216        for (int i = 0 ; i < ITERATIONS ; i++) {
217            setupAudioFocusListener();
218            int result = mAudioManager.requestAudioFocus(mAudioFocusListener,
219                    AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
220            assertTrue("audio focus request was not granted",
221                    result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
222            cleanupAudioFocusListener();
223        }
224        assertTrue("testAudioFocusListenerLifeCycle : tested" + ITERATIONS +" iterations", true);
225    }
226
227    //Test case 5: test audio focus use without listener
228    @LargeTest
229    public void testAudioFocusStressNoListenerRequestAbandon() throws Exception {
230        final int ITERATIONS = 1000;
231        // make sure we have a listener in the stack
232        setupAudioFocusListener();
233        mAudioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC,
234                AudioManager.AUDIOFOCUS_GAIN);
235        // keep making the current owner lose and gain audio focus repeatedly
236        for (int i = 0 ; i < ITERATIONS ; i++) {
237            mAudioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC,
238                    AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
239            mAudioManager.abandonAudioFocus(null);
240            // the audio focus request is async, so wait a bit to verify it had the expected effect
241            java.lang.Thread.sleep(WAIT_FOR_AUDIOFOCUS_LOSS_MS);
242        }
243        // verify there were 2 audio focus changes per iteration (one loss + one gain)
244        assertTrue("testAudioFocusListenerLifeCycle : observed " +
245                mAudioFocusListener.mFocusChangeCounter + " AudioFocus changes",
246                mAudioFocusListener.mFocusChangeCounter == ITERATIONS * 2);
247        mAudioManager.abandonAudioFocus(mAudioFocusListener);
248        mAudioManager.unregisterAudioFocusListener(mAudioFocusListener);
249    }
250 }
251