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
46    public MediaAudioManagerTest() {
47        super("com.android.mediaframeworktest", MediaFrameworkTest.class);
48    }
49
50    private void initializeAudioManagerWithLooper() {
51        new Thread() {
52            @Override
53            public void run() {
54                Looper.prepare();
55                mAudioManagerLooper = Looper.myLooper();
56                mAudioManager = (AudioManager)getActivity().getSystemService(Context.AUDIO_SERVICE);
57                synchronized (mLooperLock) {
58                    mLooperLock.notify();
59                }
60                Looper.loop();
61            }
62        }.start();
63    }
64
65    @Override
66    protected void setUp() throws Exception {
67        super.setUp();
68        synchronized(mLooperLock) {
69            initializeAudioManagerWithLooper();
70            try {
71                mLooperLock.wait(WAIT_FOR_LOOPER_TO_INITIALIZE_MS);
72            } catch (Exception e) {
73                assertTrue("initializeAudioManagerWithLooper() failed to complete in time", false);
74            }
75        }
76     }
77
78     @Override
79     protected void tearDown() throws Exception {
80         super.tearDown();
81         synchronized(mLooperLock) {
82             if (mAudioManagerLooper != null) {
83                 mAudioManagerLooper.quit();
84             }
85         }
86     }
87
88     //-----------------------------------------------------------------
89     //      Ringer Mode
90     //----------------------------------
91
92     public boolean validateSetRingTone(int i) {
93         int getRingtone = mAudioManager.getRingerMode();
94         if (i != getRingtone)
95             return false;
96         else
97             return true;
98     }
99
100     // Test case 1: Simple test case to validate the set ringtone mode
101     @MediumTest
102     public void testSetRingtoneMode() throws Exception {
103         boolean result = false;
104
105         for (int i = 0; i < ringtoneMode.length; i++) {
106             mAudioManager.setRingerMode(ringtoneMode[i]);
107             result = validateSetRingTone(ringtoneMode[i]);
108             assertTrue("SetRingtoneMode : " + ringtoneMode[i], result);
109         }
110     }
111
112    //-----------------------------------------------------------------
113    //      AudioFocus
114    //----------------------------------
115
116    private static AudioFocusListener mAudioFocusListener;
117    private final static int INVALID_FOCUS = -80; // initialized to magic invalid focus change type
118    private final static int WAIT_FOR_AUDIOFOCUS_LOSS_MS = 10;
119
120    private static class AudioFocusListener implements OnAudioFocusChangeListener {
121        public int mLastFocusChange = INVALID_FOCUS;
122        public int mFocusChangeCounter = 0;
123        public AudioFocusListener() {
124        }
125        public void onAudioFocusChange(int focusChange) {
126            mLastFocusChange = focusChange;
127            mFocusChangeCounter++;
128        }
129    }
130
131    /**
132     * Fails the test if expectedFocusLossMode != mAudioFocusListener.mLastFocusChange
133     */
134    private void verifyAudioFocusLoss(int focusGainMode, int expectedFocusLossMode)
135            throws Exception {
136        // request AudioFocus so we can test that mAudioFocusListener loses it when another
137        //     request comes in
138        int result = mAudioManager.requestAudioFocus(mAudioFocusListener,
139                AudioManager.STREAM_MUSIC,
140                AudioManager.AUDIOFOCUS_GAIN);
141        assertTrue("requestAudioFocus returned " + result,
142                result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
143        // cause mAudioFocusListener to lose AudioFocus
144        result = mAudioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC,
145                focusGainMode);
146        assertTrue("requestAudioFocus returned " + result,
147                result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
148        // the audio focus request is async, so wait a bit to verify it had the expected effect
149        java.lang.Thread.sleep(WAIT_FOR_AUDIOFOCUS_LOSS_MS);
150        // test successful if the expected focus loss was recorded
151        assertEquals("listener lost focus",
152                mAudioFocusListener.mLastFocusChange, expectedFocusLossMode);
153    }
154
155    private void setupAudioFocusListener() {
156        mAudioFocusListener = new AudioFocusListener();
157        mAudioManager.registerAudioFocusListener(mAudioFocusListener);
158    }
159
160    private void cleanupAudioFocusListener() {
161        // clean up
162        mAudioManager.abandonAudioFocus(mAudioFocusListener);
163        mAudioManager.unregisterAudioFocusListener(mAudioFocusListener);
164    }
165
166    //----------------------------------
167
168    //Test case 1: test audio focus listener loses audio focus:
169    //   AUDIOFOCUS_GAIN causes AUDIOFOCUS_LOSS
170    @MediumTest
171    public void testAudioFocusLoss() throws Exception {
172        setupAudioFocusListener();
173
174        verifyAudioFocusLoss(AudioManager.AUDIOFOCUS_GAIN, AudioManager.AUDIOFOCUS_LOSS);
175
176        cleanupAudioFocusListener();
177    }
178
179    //Test case 2: test audio focus listener loses audio focus:
180    //   AUDIOFOCUS_GAIN_TRANSIENT causes AUDIOFOCUS_LOSS_TRANSIENT
181    @MediumTest
182    public void testAudioFocusLossTransient() throws Exception {
183        setupAudioFocusListener();
184
185        verifyAudioFocusLoss(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT,
186                AudioManager.AUDIOFOCUS_LOSS_TRANSIENT);
187
188        cleanupAudioFocusListener();
189    }
190
191    //Test case 3: test audio focus listener loses audio focus:
192    //   AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK causes AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK
193    @MediumTest
194    public void testAudioFocusLossTransientDuck() throws Exception {
195        setupAudioFocusListener();
196
197        verifyAudioFocusLoss(AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK,
198                AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK);
199
200        cleanupAudioFocusListener();
201    }
202
203    //Test case 4: test audio focus registering and use over 3000 iterations
204    @LargeTest
205    public void testAudioFocusStressListenerRequestAbandon() throws Exception {
206        final int ITERATIONS = 3000;
207        // here we only test the life cycle of a focus listener, and make sure we don't crash
208        // when doing it many times without waiting
209        for (int i = 0 ; i < ITERATIONS ; i++) {
210            setupAudioFocusListener();
211            int result = mAudioManager.requestAudioFocus(mAudioFocusListener,
212                    AudioManager.STREAM_MUSIC, AudioManager.AUDIOFOCUS_GAIN);
213            assertTrue("audio focus request was not granted",
214                    result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED);
215            cleanupAudioFocusListener();
216        }
217        assertTrue("testAudioFocusListenerLifeCycle : tested" + ITERATIONS +" iterations", true);
218    }
219
220    //Test case 5: test audio focus use without listener
221    @LargeTest
222    public void testAudioFocusStressNoListenerRequestAbandon() throws Exception {
223        final int ITERATIONS = 1000;
224        // make sure we have a listener in the stack
225        setupAudioFocusListener();
226        mAudioManager.requestAudioFocus(mAudioFocusListener, AudioManager.STREAM_MUSIC,
227                AudioManager.AUDIOFOCUS_GAIN);
228        // keep making the current owner lose and gain audio focus repeatedly
229        for (int i = 0 ; i < ITERATIONS ; i++) {
230            mAudioManager.requestAudioFocus(null, AudioManager.STREAM_MUSIC,
231                    AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
232            mAudioManager.abandonAudioFocus(null);
233            // the audio focus request is async, so wait a bit to verify it had the expected effect
234            java.lang.Thread.sleep(WAIT_FOR_AUDIOFOCUS_LOSS_MS);
235        }
236        // verify there were 2 audio focus changes per iteration (one loss + one gain)
237        assertTrue("testAudioFocusListenerLifeCycle : observed " +
238                mAudioFocusListener.mFocusChangeCounter + " AudioFocus changes",
239                mAudioFocusListener.mFocusChangeCounter == ITERATIONS * 2);
240        mAudioManager.abandonAudioFocus(mAudioFocusListener);
241        mAudioManager.unregisterAudioFocusListener(mAudioFocusListener);
242    }
243 }
244