blob: 0aaf11fc82ce6cbcc5ef88d8fe4348cea5a838c4 [file] [log] [blame]
/*
* Copyright (C) 2010 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.media.cts;
import com.android.cts.stub.R;
import android.content.res.AssetFileDescriptor;
import android.media.audiofx.AudioEffect;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.media.audiofx.PresetReverb;
import android.media.audiofx.EnvironmentalReverb;
import android.media.audiofx.Equalizer;
import android.media.MediaPlayer;
import android.os.Looper;
import android.test.AndroidTestCase;
import android.util.Log;
import dalvik.annotation.TestLevel;
import dalvik.annotation.TestTargetClass;
import dalvik.annotation.TestTargetNew;
import dalvik.annotation.TestTargets;
import java.util.UUID;
@TestTargetClass(AudioEffect.class)
public class AudioEffectTest extends AndroidTestCase {
private String TAG = "AudioEffectTest";
private final static int MIN_NUMBER_EFFECTS = 5;
// allow +/- 5% tolerance between set and get delays
private final static float DELAY_TOLERANCE = 1.05f;
// allow +/- 5% tolerance between set and get ratios
private final static float RATIO_TOLERANCE = 1.05f;
private AudioEffect mEffect = null;
private AudioEffect mEffect2 = null;
private int mSession = -1;
private boolean mHasControl = false;
private boolean mIsEnabled = false;
private int mChangedParameter = -1;
private boolean mInitialized = false;
private Looper mLooper = null;
private MediaPlayer mMediaPlayer = null;
private int mError = 0;
private final Object mLock = new Object();
//-----------------------------------------------------------------
// AUDIOEFFECT TESTS:
//----------------------------------
//-----------------------------------------------------------------
// 0 - static methods
//----------------------------------
//Test case 0.0: test queryEffects() and platfrom at least provides Equalizer, Bass Boost,
// Virtualizer, Environmental reverb and Preset reverb effects
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "queryEffects",
args = {}
)
})
public void test0_0QueryEffects() throws Exception {
AudioEffect.Descriptor[] desc = AudioEffect.queryEffects();
assertTrue("test0_0QueryEffects: number of effects < MIN_NUMBER_EFFECTS: "+desc.length,
(desc.length >= MIN_NUMBER_EFFECTS));
boolean hasEQ = false;
boolean hasBassBoost = false;
boolean hasVirtualizer = false;
boolean hasEnvReverb = false;
boolean hasPresetReverb = false;
for (int i = 0; i < desc.length; i++) {
if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_EQUALIZER)) {
hasEQ = true;
} else if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_BASS_BOOST)) {
hasBassBoost = true;
} else if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_VIRTUALIZER)) {
hasVirtualizer = true;
} else if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_ENV_REVERB)) {
hasEnvReverb = true;
} else if (desc[i].type.equals(AudioEffect.EFFECT_TYPE_PRESET_REVERB)) {
hasPresetReverb = true;
}
}
assertTrue("test0_0QueryEffects: equalizer not found", hasEQ);
assertTrue("test0_0QueryEffects: bass boost not found", hasBassBoost);
assertTrue("test0_0QueryEffects: virtualizer not found", hasVirtualizer);
assertTrue("test0_0QueryEffects: environmental reverb not found", hasEnvReverb);
assertTrue("test0_0QueryEffects: preset reverb not found", hasPresetReverb);
}
//-----------------------------------------------------------------
// 1 - constructor
//----------------------------------
//Test case 1.0: test constructor from effect type and get effect ID
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "AudioEffect",
args = {UUID.class, UUID.class, int.class, int.class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getId",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "release",
args = {}
)
})
public void test1_0ConstructorFromType() throws Exception {
AudioEffect.Descriptor[] desc = AudioEffect.queryEffects();
assertTrue("no effects found", (desc.length != 0));
for (int i = 0; i < desc.length; i++) {
if (!desc[i].type.equals(AudioEffect.EFFECT_TYPE_NULL)) {
try {
AudioEffect effect = new AudioEffect(desc[i].type,
AudioEffect.EFFECT_TYPE_NULL,
0,
0);
assertNotNull("could not create AudioEffect", effect);
try {
assertTrue("invalid effect ID", (effect.getId() != 0));
} catch (IllegalStateException e) {
fail("AudioEffect not initialized");
} finally {
effect.release();
}
} catch (IllegalArgumentException e) {
fail("Effect not found: "+desc[i].name);
} catch (UnsupportedOperationException e) {
fail("Effect library not loaded");
}
}
}
}
//Test case 1.1: test constructor from effect uuid
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "AudioEffect",
args = {UUID.class, UUID.class, int.class, int.class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getId",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "release",
args = {}
)
})
public void test1_1ConstructorFromUuid() throws Exception {
AudioEffect.Descriptor[] desc = AudioEffect.queryEffects();
assertTrue("no effects found", (desc.length != 0));
for (int i = 0; i < desc.length; i++) {
try {
AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_NULL,
desc[i].uuid,
0,
0);
assertNotNull("could not create AudioEffect", effect);
try {
assertTrue("invalid effect ID", (effect.getId() != 0));
} catch (IllegalStateException e) {
fail("AudioEffect not initialized");
} finally {
effect.release();
}
} catch (IllegalArgumentException e) {
fail("Effect not found: "+desc[i].name);
} catch (UnsupportedOperationException e) {
fail("Effect library not loaded");
}
}
}
//Test case 1.2: test constructor failure from unknown type
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "AudioEffect",
args = {UUID.class, UUID.class, int.class, int.class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "release",
args = {}
)
})
public void test1_2ConstructorUnknownType() throws Exception {
try {
AudioEffect effect = new AudioEffect(UUID.randomUUID(),
AudioEffect.EFFECT_TYPE_NULL,
0,
0);
fail("could create random AudioEffect");
if (effect != null) {
effect.release();
}
} catch (IllegalArgumentException e) {
} catch (UnsupportedOperationException e) {
fail("Effect library not loaded");
}
}
//Test case 1.3: test getEnabled() failure when called on released effect
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "AudioEffect",
args = {UUID.class, UUID.class, int.class, int.class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getEnabled",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "release",
args = {}
)
})
public void test1_3GetEnabledAfterRelease() throws Exception {
try {
AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER,
AudioEffect.EFFECT_TYPE_NULL,
0,
0);
assertNotNull("could not create AudioEffect", effect);
effect.release();
try {
effect.getEnabled();
fail("getEnabled() processed after release()");
} catch (IllegalStateException e) {
}
} catch (IllegalArgumentException e) {
fail("AudioEffect not found");
} catch (UnsupportedOperationException e) {
fail("Effect library not loaded");
}
}
//Test case 1.4: test contructor on mediaPlayer audio session
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "setEnabled",
args = {boolean.class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "MediaPlayer.getAudioSessionId",
args = {}
)
})
public void test1_4InsertOnMediaPlayer() throws Exception {
MediaPlayer mp = new MediaPlayer();
assertNotNull("could not create mediaplayer", mp);
AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(R.raw.testmp3);
mp.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
getEffect(AudioEffect.EFFECT_TYPE_EQUALIZER, mp.getAudioSessionId());
try {
mEffect.setEnabled(true);
} catch (IllegalStateException e) {
fail("AudioEffect not initialized");
} finally {
mp.release();
releaseEffect();
}
}
//Test case 1.5: test auxiliary effect attachement on MediaPlayer
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getId",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "MediaPlayer.attachAuxEffect",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "MediaPlayer.setAuxEffectSendLevel",
args = {}
)
})
public void test1_5AuxiliaryOnMediaPlayer() throws Exception {
createMediaPlayerLooper();
synchronized(mLock) {
try {
mLock.wait(1000);
} catch(Exception e) {
fail("Looper creation: wait was interrupted.");
}
}
assertTrue(mInitialized); // mMediaPlayer has been initialized?
mError = 0;
AssetFileDescriptor afd = mContext.getResources().openRawResourceFd(R.raw.testmp3);
mMediaPlayer.setDataSource(afd.getFileDescriptor(), afd.getStartOffset(), afd.getLength());
afd.close();
getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
try {
synchronized(mLock) {
try {
mMediaPlayer.attachAuxEffect(mEffect.getId());
mMediaPlayer.setAuxEffectSendLevel(1.0f);
mLock.wait(200);
} catch(Exception e) {
fail("Attach effect: wait was interrupted.");
}
}
assertTrue("error on attachAuxEffect", mError == 0);
} catch (IllegalStateException e) {
fail("attach aux effect failed");
} finally {
terminateMediaPlayerLooper();
releaseEffect();
}
}
//Test case 1.6: test auxiliary effect attachement failure before setDatasource
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getId",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "MediaPlayer.attachAuxEffect",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "MediaPlayer.setAuxEffectSendLevel",
args = {}
)
})
public void test1_6AuxiliaryOnMediaPlayerFailure() throws Exception {
createMediaPlayerLooper();
synchronized(mLock) {
try {
mLock.wait(1000);
} catch(Exception e) {
fail("Looper creation: wait was interrupted.");
}
}
assertTrue(mInitialized); // mMediaPlayer has been initialized?
mError = 0;
getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
try {
synchronized(mLock) {
try {
mMediaPlayer.attachAuxEffect(mEffect.getId());
mLock.wait(1000);
} catch(Exception e) {
fail("Attach effect: wait was interrupted.");
}
}
assertTrue("no error on attachAuxEffect", mError != 0);
} catch (IllegalStateException e) {
fail("attach aux effect failed");
} finally {
terminateMediaPlayerLooper();
releaseEffect();
}
}
//Test case 1.7: test auxiliary effect attachement on AudioTrack
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getId",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "AudioTrack.attachAuxEffect",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "AudioTrack.setAuxEffectSendLevel",
args = {}
)
})
public void test1_7AuxiliaryOnAudioTrack() throws Exception {
AudioTrack track = null;
getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
try {
track = new AudioTrack(
AudioManager.STREAM_MUSIC,
44100,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT,
AudioTrack.getMinBufferSize(44100,
AudioFormat.CHANNEL_OUT_MONO,
AudioFormat.ENCODING_PCM_16BIT),
AudioTrack.MODE_STREAM);
assertNotNull("could not create AudioTrack", track);
int status = track.attachAuxEffect(mEffect.getId());
if (status != AudioTrack.SUCCESS) {
fail("could not attach aux effect");
}
status = track.setAuxEffectSendLevel(1.0f);
if (status != AudioTrack.SUCCESS) {
fail("could not set send level");
}
} catch (IllegalStateException e) {
fail("could not attach aux effect");
} catch (IllegalArgumentException e) {
fail("could not create AudioTrack");
} finally {
if (track != null) {
track.release();
}
releaseEffect();
}
}
//-----------------------------------------------------------------
// 2 - enable/ disable
//----------------------------------
//Test case 2.0: test setEnabled() and getEnabled() in valid state
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "setEnabled",
args = {boolean.class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getEnabled",
args = {}
)
})
public void test2_0SetEnabledGetEnabled() throws Exception {
try {
AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER,
AudioEffect.EFFECT_TYPE_NULL,
0,
0);
assertNotNull("could not create AudioEffect", effect);
try {
effect.setEnabled(true);
assertTrue("invalid state from getEnabled", effect.getEnabled());
effect.setEnabled(false);
assertFalse("invalid state to getEnabled", effect.getEnabled());
} catch (IllegalStateException e) {
fail("setEnabled() in wrong state");
} finally {
effect.release();
}
} catch (IllegalArgumentException e) {
fail("AudioEffect not found");
} catch (UnsupportedOperationException e) {
fail("Effect library not loaded");
}
}
//Test case 2.1: test setEnabled() throws exception after release
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "setEnabled",
args = {boolean.class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getEnabled",
args = {}
)
})
public void test2_1SetEnabledAfterRelease() throws Exception {
try {
AudioEffect effect = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER,
AudioEffect.EFFECT_TYPE_NULL,
0,
0);
assertNotNull("could not create AudioEffect", effect);
effect.release();
try {
effect.setEnabled(true);
fail("setEnabled() processed after release");
} catch (IllegalStateException e) {
// test passed
}
} catch (IllegalArgumentException e) {
fail("AudioEffect not found");
} catch (UnsupportedOperationException e) {
fail("Effect library not loaded");
}
}
//-----------------------------------------------------------------
// 3 - set/get parameters
//----------------------------------
//Test case 3.0: test setParameter(byte[], byte[]) / getParameter(byte[], byte[])
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "setParameter",
args = {byte[].class, byte[].class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getParameter",
args = {byte[].class, byte[].class}
)
})
public void test3_0SetParameterByteArrayByteArray() throws Exception {
getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
try {
byte[] param = mEffect.intToByteArray(PresetReverb.PARAM_PRESET);
byte[] value = new byte[2];
int status = mEffect.getParameter(param, value);
assertEquals("getParameter 1 failed", AudioEffect.SUCCESS, status);
short preset = PresetReverb.PRESET_SMALLROOM;
if (mEffect.byteArrayToShort(value) == preset) {
preset = PresetReverb.PRESET_MEDIUMROOM;
}
value = mEffect.shortToByteArray(preset);
status = mEffect.setParameter(param, value);
assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
status = mEffect.getParameter(param, value);
assertEquals("getParameter 2 failed", AudioEffect.SUCCESS, status);
assertEquals("get/set Parameter failed", preset,
mEffect.byteArrayToShort(value));
} catch (IllegalArgumentException e) {
fail("Bad parameter value");
} catch (UnsupportedOperationException e) {
fail("setParameter() rejected");
} catch (IllegalStateException e) {
fail("setParameter() called in wrong state");
} finally {
releaseEffect();
}
}
//Test case 3.1: test setParameter(int, int) / getParameter(int, int[])
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "setParameter",
args = {int.class, int.class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getParameter",
args = {int.class, int[].class}
)
})
public void test3_1SetParameterIntInt() throws Exception {
getEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, 0);
try {
int param = EnvironmentalReverb.PARAM_DECAY_TIME;
int[] value = new int[1];
int status = mEffect.getParameter(param, value);
assertEquals("getParameter 1 failed", AudioEffect.SUCCESS, status);
int time = 500;
if (value[0] == time) {
time = 1000;
}
status = mEffect.setParameter(param, time);
assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
status = mEffect.getParameter(param, value);
assertEquals("getParameter 2 failed", AudioEffect.SUCCESS, status);
assertTrue("got incorrect decay time",
((float)value[0] > (float)(time / DELAY_TOLERANCE)) &&
((float)value[0] < (float)(time * DELAY_TOLERANCE)));
} catch (IllegalArgumentException e) {
fail("Bad parameter value");
} catch (UnsupportedOperationException e) {
fail("setParameter() rejected");
} catch (IllegalStateException e) {
fail("setParameter() called in wrong state");
} finally {
releaseEffect();
}
}
//Test case 3.2: test setParameter(int, short) / getParameter(int, short[])
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "setParameter",
args = {int.class, short.class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getParameter",
args = {int.class, short[].class}
)
})
public void test3_2SetParameterIntShort() throws Exception {
getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
try {
int param = PresetReverb.PARAM_PRESET;
short[] value = new short[1];
int status = mEffect.getParameter(param, value);
assertEquals("getParameter 1 failed", AudioEffect.SUCCESS, status);
short preset = PresetReverb.PRESET_SMALLROOM;
if (value[0] == preset) {
preset = PresetReverb.PRESET_MEDIUMROOM;
}
status = mEffect.setParameter(param, preset);
assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
status = mEffect.getParameter(param, value);
assertEquals("getParameter 2 failed", AudioEffect.SUCCESS, status);
assertEquals("get/set Parameter failed", preset, value[0]);
} catch (IllegalArgumentException e) {
fail("Bad parameter value");
} catch (UnsupportedOperationException e) {
fail("setParameter() rejected");
} catch (IllegalStateException e) {
fail("setParameter() called in wrong state");
} finally {
releaseEffect();
}
}
//Test case 3.3: test setParameter(int, byte[]) / getParameter(int, byte[])
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "setParameter",
args = {int.class, byte[].class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getParameter",
args = {int.class, byte[].class}
)
})
public void test3_3SetParameterIntByteArray() throws Exception {
getEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, 0);
try {
int param = EnvironmentalReverb.PARAM_DECAY_TIME;
byte[] value = new byte[4];
int status = mEffect.getParameter(param, value);
assertEquals("getParameter 1 failed", AudioEffect.SUCCESS, status);
int time = 500;
if (mEffect.byteArrayToInt(value) == time) {
time = 1000;
}
value = mEffect.intToByteArray(time);
status = mEffect.setParameter(param, value);
assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
status = mEffect.getParameter(param, value);
assertEquals("getParameter 2 failed", AudioEffect.SUCCESS, status);
int time2 = mEffect.byteArrayToInt(value);
assertTrue("got incorrect decay time",
((float)time2 > (float)(time / DELAY_TOLERANCE)) &&
((float)time2 < (float)(time * DELAY_TOLERANCE)));
} catch (IllegalArgumentException e) {
fail("Bad parameter value");
} catch (UnsupportedOperationException e) {
fail("setParameter() rejected");
} catch (IllegalStateException e) {
fail("setParameter() called in wrong state");
} finally {
releaseEffect();
}
}
//Test case 3.4: test setParameter(int[], int[]) / getParameter(int[], int[])
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "setParameter",
args = {int[].class, int[].class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getParameter",
args = {int[].class, int[].class}
)
})
public void test3_4SetParameterIntArrayIntArray() throws Exception {
getEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, 0);
try {
int[] param = new int[1];
int[] value = new int[1];
param[0] = EnvironmentalReverb.PARAM_DECAY_TIME;
int status = mEffect.getParameter(param, value);
assertEquals("getParameter 1 failed", AudioEffect.SUCCESS, status);
int[] time = new int[1];
time[0] = 500;
if (value[0] == time[0]) {
time[0] = 1000;
}
status = mEffect.setParameter(param, time);
assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
status = mEffect.getParameter(param, value);
assertEquals("getParameter 2 failed", AudioEffect.SUCCESS, status);
assertTrue("got incorrect decay time",
((float)value[0] > (float)(time[0] / DELAY_TOLERANCE)) &&
((float)value[0] < (float)(time[0] * DELAY_TOLERANCE)));
} catch (IllegalArgumentException e) {
fail("Bad parameter value");
} catch (UnsupportedOperationException e) {
fail("setParameter() rejected");
} catch (IllegalStateException e) {
fail("setParameter() called in wrong state");
} finally {
releaseEffect();
}
}
//Test case 3.5: test setParameter(int[], short[]) / getParameter(int[], short[])
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "setParameter",
args = {int[].class, short[].class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getParameter",
args = {int[].class, short[].class}
)
})
public void test3_5SetParameterIntArrayShortArray() throws Exception {
getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
try {
int[] param = new int[1];
param[0] = PresetReverb.PARAM_PRESET;
short[] value = new short[1];
int status = mEffect.getParameter(param, value);
assertEquals("getParameter 1 failed", AudioEffect.SUCCESS, status);
short[] preset = new short[1];
preset[0] = PresetReverb.PRESET_SMALLROOM;
if (value[0] == preset[0]) {
preset[0] = PresetReverb.PRESET_MEDIUMROOM;
}
status = mEffect.setParameter(param, preset);
assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
status = mEffect.getParameter(param, value);
assertEquals("getParameter 2 failed", AudioEffect.SUCCESS, status);
assertEquals("get/set Parameter failed", preset[0], value[0]);
} catch (IllegalArgumentException e) {
fail("Bad parameter value");
} catch (UnsupportedOperationException e) {
fail("setParameter() rejected");
} catch (IllegalStateException e) {
fail("setParameter() called in wrong state");
} finally {
releaseEffect();
}
}
//Test case 3.6: test setParameter(int[], byte[]) / getParameter(int[], byte[])
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "setParameter",
args = {int[].class, byte[].class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getParameter",
args = {int[].class, byte[].class}
)
})
public void test3_6SetParameterIntArrayByteArray() throws Exception {
getEffect(AudioEffect.EFFECT_TYPE_ENV_REVERB, 0);
try {
int[] param = new int[1];
param[0] = EnvironmentalReverb.PARAM_DECAY_TIME;
byte[] value = new byte[4];
int status = mEffect.getParameter(param, value);
assertEquals("getParameter 1 failed", AudioEffect.SUCCESS, status);
int time = 500;
if (mEffect.byteArrayToInt(value) == time) {
time = 1000;
}
status = mEffect.setParameter(param, mEffect.intToByteArray(time));
assertEquals("setParameter failed", AudioEffect.SUCCESS, status);
status = mEffect.getParameter(param, value);
assertEquals("getParameter 2 failed", AudioEffect.SUCCESS, status);
int time2 = mEffect.byteArrayToInt(value);
assertTrue("got incorrect decay time",
((float)time2 > (float)(time / DELAY_TOLERANCE)) &&
((float)time2 < (float)(time * DELAY_TOLERANCE)));
} catch (IllegalArgumentException e) {
fail("Bad parameter value");
} catch (UnsupportedOperationException e) {
fail("setParameter() rejected");
} catch (IllegalStateException e) {
fail("setParameter() called in wrong state");
} finally {
releaseEffect();
}
}
//Test case 3.7: test setParameter() throws exception after release()
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "setParameter",
args = {int.class, short.class}
)
})
public void test3_7SetParameterAfterRelease() throws Exception {
AudioEffect effect = null;
try {
effect = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB,
AudioEffect.EFFECT_TYPE_NULL,
0,
0);
assertNotNull("could not create AudioEffect", effect);
effect.release();
effect.setParameter(PresetReverb.PARAM_PRESET, PresetReverb.PRESET_SMALLROOM);
fail("setParameter() processed after release");
} catch (IllegalArgumentException e) {
fail("Bad parameter value");
} catch (UnsupportedOperationException e) {
fail("setParameter() rejected");
} catch (IllegalStateException e) {
// test passed
} finally {
if (effect != null) {
effect.release();
}
}
}
//Test case 3.8: test getParameter() throws exception after release()
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "setParameter",
args = {int.class, short[].class}
)
})
public void test3_8GetParameterAfterRelease() throws Exception {
AudioEffect effect = null;
try {
effect = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB,
AudioEffect.EFFECT_TYPE_NULL,
0,
0);
assertNotNull("could not create AudioEffect", effect);
effect.release();
short[] value = new short[1];
effect.getParameter(PresetReverb.PARAM_PRESET, value);
fail("getParameter() processed after release");
} catch (IllegalArgumentException e) {
fail("Bad parameter value");
} catch (UnsupportedOperationException e) {
fail("getParameter() rejected");
} catch (IllegalStateException e) {
// test passed
} finally {
if (effect != null) {
effect.release();
}
}
}
//-----------------------------------------------------------------
// 4 priority and listeners
//----------------------------------
//Test case 4.0: test control passed to higher priority client
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "hasControl",
args = {}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "setEnabled",
args = {boolean.class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getEnabled",
args = {}
)
})
public void test4_0setEnabledLowerPriority() throws Exception {
AudioEffect effect1 = null;
AudioEffect effect2 = null;
try {
effect1 = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER,
AudioEffect.EFFECT_TYPE_NULL,
0,
0);
effect2 = new AudioEffect(AudioEffect.EFFECT_TYPE_EQUALIZER,
AudioEffect.EFFECT_TYPE_NULL,
1,
0);
assertNotNull("could not create AudioEffect", effect1);
assertNotNull("could not create AudioEffect", effect2);
assertTrue("Effect2 does not have control", effect2.hasControl());
assertFalse("Effect1 has control", effect1.hasControl());
assertTrue("Effect1 can enable",
effect1.setEnabled(true) == AudioEffect.ERROR_INVALID_OPERATION);
assertFalse("Effect1 has enabled", effect2.getEnabled());
} catch (IllegalArgumentException e) {
fail("Effect not found");
} catch (UnsupportedOperationException e) {
fail("Effect library not loaded");
} finally {
if (effect1 != null) {
effect1.release();
}
if (effect2 != null) {
effect2.release();
}
}
}
//Test case 4.1: test control passed to higher priority client
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "setParameter",
args = {int.class, short.class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getParameter",
args = {int.class, short[].class}
)
})
public void test4_1setParameterLowerPriority() throws Exception {
AudioEffect effect1 = null;
AudioEffect effect2 = null;
try {
effect1 = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB,
AudioEffect.EFFECT_TYPE_NULL,
0,
0);
effect2 = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB,
AudioEffect.EFFECT_TYPE_NULL,
1,
0);
assertNotNull("could not create AudioEffect", effect1);
assertNotNull("could not create AudioEffect", effect2);
int status = effect2.setParameter(PresetReverb.PARAM_PRESET,
PresetReverb.PRESET_SMALLROOM);
assertEquals("Effect2 setParameter failed",
AudioEffect.SUCCESS, status);
status = effect1.setParameter(PresetReverb.PARAM_PRESET,
PresetReverb.PRESET_MEDIUMROOM);
assertEquals("Effect1 setParameter did not fail",
AudioEffect.ERROR_INVALID_OPERATION, status);
short[] value = new short[1];
status = effect2.getParameter(PresetReverb.PARAM_PRESET, value);
assertEquals("Effect2 getParameter failed",
AudioEffect.SUCCESS, status);
assertEquals("Effect1 changed parameter", PresetReverb.PRESET_SMALLROOM
, value[0]);
} catch (IllegalArgumentException e) {
fail("Effect not found");
} catch (UnsupportedOperationException e) {
fail("Effect library not loaded");
} finally {
if (effect1 != null) {
effect1.release();
}
if (effect2 != null) {
effect2.release();
}
}
}
//Test case 4.2: test control status listener
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "setControlStatusListener",
args = {AudioEffect.OnControlStatusChangeListener.class}
)
})
public void test4_2ControlStatusListener() throws Exception {
mHasControl = true;
createListenerLooper(true, false, false);
synchronized(mLock) {
try {
mLock.wait(1000);
} catch(Exception e) {
fail("Looper creation: wait was interrupted.");
}
}
assertTrue(mInitialized);
synchronized(mLock) {
try {
getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
mLock.wait(1000);
} catch(Exception e) {
fail("Create second effect: wait was interrupted.");
} finally {
releaseEffect();
terminateListenerLooper();
}
}
assertFalse("effect control not lost by effect1", mHasControl);
}
//Test case 4.3: test enable status listener
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "setEnableStatusListener",
args = {AudioEffect.OnEnableStatusChangeListener.class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "setEnabled",
args = {boolean.class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "getEnabled",
args = {}
)
})
public void test4_3EnableStatusListener() throws Exception {
createListenerLooper(false, true, false);
synchronized(mLock) {
try {
mLock.wait(1000);
} catch(Exception e) {
fail("Looper creation: wait was interrupted.");
}
}
assertTrue(mInitialized);
mEffect2.setEnabled(true);
mIsEnabled = true;
getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
assertTrue("effect not enabled", mEffect.getEnabled());
synchronized(mLock) {
try {
mEffect.setEnabled(false);
mLock.wait(1000);
} catch(Exception e) {
fail("Second effect setEnabled: wait was interrupted.");
} finally {
releaseEffect();
terminateListenerLooper();
}
}
assertFalse("enable status not updated", mIsEnabled);
}
//Test case 4.4: test parameter changed listener
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "setParameterListener",
args = {AudioEffect.OnParameterChangeListener.class}
),
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "setParameter",
args = {int.class, short.class}
)
})
public void test4_4ParameterChangedListener() throws Exception {
createListenerLooper(false, false, true);
synchronized(mLock) {
try {
mLock.wait(1000);
} catch(Exception e) {
fail("Looper creation: wait was interrupted.");
}
}
assertTrue(mInitialized);
int status = mEffect2.setParameter(PresetReverb.PARAM_PRESET,
PresetReverb.PRESET_SMALLROOM);
assertEquals("mEffect2 setParameter failed",
AudioEffect.SUCCESS, status);
getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
synchronized(mLock) {
try {
mChangedParameter = -1;
mEffect.setParameter(PresetReverb.PARAM_PRESET,
PresetReverb.PRESET_MEDIUMROOM);
mLock.wait(1000);
} catch(Exception e) {
fail("set Parameter: wait was interrupted.");
} finally {
releaseEffect();
terminateListenerLooper();
}
}
assertEquals("parameter change not received",
PresetReverb.PARAM_PRESET, mChangedParameter);
}
//-----------------------------------------------------------------
// 5 command method
//----------------------------------
//Test case 5.0: test command method
@TestTargets({
@TestTargetNew(
level = TestLevel.COMPLETE,
method = "command",
args = {int.class, byte[].class, byte[].class}
)
})
public void test5_0Command() throws Exception {
getEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB, 0);
try {
byte[] cmd = new byte[0];
byte[] reply = new byte[4];
// command 3 is ENABLE
int status = mEffect.command(3, cmd, reply);
assertEquals("command failed", AudioEffect.SUCCESS, status);
assertTrue("effect not enabled", mEffect.getEnabled());
} catch (IllegalStateException e) {
fail("command in illegal state");
} finally {
releaseEffect();
}
}
//-----------------------------------------------------------------
// private methods
//----------------------------------
private void getEffect(UUID type, int session) {
if (mEffect == null || session != mSession) {
if (session != mSession && mEffect != null) {
mEffect.release();
mEffect = null;
}
try {
mEffect = new AudioEffect(type,
AudioEffect.EFFECT_TYPE_NULL,
0,
session);
mSession = session;
} catch (IllegalArgumentException e) {
Log.e(TAG, "getEffect() AudioEffect not found exception: "+e);
} catch (UnsupportedOperationException e) {
Log.e(TAG, "getEffect() Effect library not loaded exception: "+e);
}
}
assertNotNull("could not create mEffect", mEffect);
}
private void releaseEffect() {
if (mEffect != null) {
mEffect.release();
mEffect = null;
}
}
// Initializes the equalizer listener looper
class ListenerThread extends Thread {
boolean mControl;
boolean mEnable;
boolean mParameter;
public ListenerThread(boolean control, boolean enable, boolean parameter) {
super();
mControl = control;
mEnable = enable;
mParameter = parameter;
}
}
private void createListenerLooper(boolean control, boolean enable, boolean parameter) {
mInitialized = false;
new ListenerThread(control, enable, parameter) {
@Override
public void run() {
// Set up a looper
Looper.prepare();
// Save the looper so that we can terminate this thread
// after we are done with it.
mLooper = Looper.myLooper();
mEffect2 = new AudioEffect(AudioEffect.EFFECT_TYPE_PRESET_REVERB,
AudioEffect.EFFECT_TYPE_NULL,
0,
0);
assertNotNull("could not create Equalizer2", mEffect2);
if (mControl) {
mEffect2.setControlStatusListener(
new AudioEffect.OnControlStatusChangeListener() {
public void onControlStatusChange(
AudioEffect effect, boolean controlGranted) {
synchronized(mLock) {
if (effect == mEffect2) {
mHasControl = controlGranted;
mLock.notify();
}
}
}
});
}
if (mEnable) {
mEffect2.setEnableStatusListener(
new AudioEffect.OnEnableStatusChangeListener() {
public void onEnableStatusChange(AudioEffect effect, boolean enabled) {
synchronized(mLock) {
if (effect == mEffect2) {
mIsEnabled = enabled;
mLock.notify();
}
}
}
});
}
if (mParameter) {
mEffect2.setParameterListener(new AudioEffect.OnParameterChangeListener() {
public void onParameterChange(AudioEffect effect, int status, byte[] param,
byte[] value)
{
synchronized(mLock) {
if (effect == mEffect2) {
mChangedParameter = mEffect2.byteArrayToInt(param);
mLock.notify();
}
}
}
});
}
synchronized(mLock) {
mInitialized = true;
mLock.notify();
}
Looper.loop(); // Blocks forever until Looper.quit() is called.
}
}.start();
}
// Terminates the listener looper thread.
private void terminateListenerLooper() {
if (mEffect2 != null) {
mEffect2.release();
mEffect2 = null;
}
if (mLooper != null) {
mLooper.quit();
mLooper = null;
}
}
/*
* Initializes the message looper so that the MediaPlayer object can
* receive the callback messages.
*/
private void createMediaPlayerLooper() {
mInitialized = false;
new Thread() {
@Override
public void run() {
// Set up a looper to be used by mMediaPlayer.
Looper.prepare();
// Save the looper so that we can terminate this thread
// after we are done with it.
mLooper = Looper.myLooper();
mMediaPlayer = new MediaPlayer();
mMediaPlayer.setOnErrorListener(new MediaPlayer.OnErrorListener() {
public boolean onError(MediaPlayer player, int what, int extra) {
synchronized(mLock) {
mError = what;
mLock.notify();
}
return true;
}
});
mMediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
public void onCompletion(MediaPlayer player) {
synchronized(mLock) {
mLock.notify();
}
}
});
synchronized(mLock) {
mInitialized = true;
mLock.notify();
}
Looper.loop(); // Blocks forever until Looper.quit() is called.
}
}.start();
}
/*
* Terminates the message looper thread.
*/
private void terminateMediaPlayerLooper() {
if (mLooper != null) {
mLooper.quit();
mLooper = null;
}
if (mMediaPlayer != null) {
mMediaPlayer.release();
}
}
}