blob: f2e078adfa3cd9d169f0c955961ddca96520e3a2 [file] [log] [blame]
/*
* Copyright (C) 2015 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 android.content.Context;
import android.content.pm.PackageManager;
import android.media.AudioAttributes;
import android.media.AudioDeviceInfo;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioRecord;
import android.media.AudioRouting;
import android.media.AudioTrack;
import android.media.MediaPlayer;
import android.media.MediaFormat;
import android.media.MediaRecorder;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.platform.test.annotations.AppModeFull;
import android.test.AndroidTestCase;
import android.util.Log;
import com.android.compatibility.common.util.MediaUtils;
import java.io.File;
import java.lang.Runnable;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
/**
* AudioTrack / AudioRecord / MediaPlayer / MediaRecorder preferred device
* and routing listener tests.
* The routing tests are mostly here to exercise the routing code, as an actual test would require
* adding / removing an audio device for the listeners to be called.
* The routing listener code is designed to run for two versions of the routing code:
* - the deprecated AudioTrack.OnRoutingChangedListener and AudioRecord.OnRoutingChangedListener
* - the N AudioRouting.OnRoutingChangedListener
*/
@AppModeFull(reason = "TODO: evaluate and port to instant")
public class RoutingTest extends AndroidTestCase {
private static final String TAG = "RoutingTest";
private static final int MAX_WAITING_ROUTING_CHANGED_COUNT = 3;
private static final long WAIT_ROUTING_CHANGE_TIME_MS = 1000;
private static final int AUDIO_BIT_RATE_IN_BPS = 12200;
private static final int AUDIO_SAMPLE_RATE_HZ = 8000;
private static final long MAX_FILE_SIZE_BYTE = 5000;
private static final int RECORD_TIME_MS = 3000;
private static final Set<Integer> AVAILABLE_INPUT_DEVICES_TYPE = new HashSet<>(
Arrays.asList(AudioDeviceInfo.TYPE_BUILTIN_MIC));
private boolean mRoutingChanged;
private AudioManager mAudioManager;
private CountDownLatch mRoutingChangedLatch;
private File mOutFile;
private Looper mRoutingChangedLooper;
private Object mRoutingChangedLock = new Object();
@Override
protected void setUp() throws Exception {
super.setUp();
// get the AudioManager
mAudioManager = (AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE);
assertNotNull(mAudioManager);
}
@Override
protected void tearDown() throws Exception {
if (mOutFile != null && mOutFile.exists()) {
mOutFile.delete();
}
super.tearDown();
}
private AudioTrack allocAudioTrack() {
int bufferSize =
AudioTrack.getMinBufferSize(
41000,
AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT);
AudioTrack audioTrack =
new AudioTrack(
AudioManager.STREAM_MUSIC,
41000,
AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize,
AudioTrack.MODE_STREAM);
return audioTrack;
}
public void test_audioTrack_preferredDevice() {
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)) {
// Can't do it so skip this test
return;
}
AudioTrack audioTrack = allocAudioTrack();
assertNotNull(audioTrack);
// None selected (new AudioTrack), so check for default
assertNull(audioTrack.getPreferredDevice());
// resets to default
assertTrue(audioTrack.setPreferredDevice(null));
// test each device
AudioDeviceInfo[] deviceList = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
for (int index = 0; index < deviceList.length; index++) {
assertTrue(audioTrack.setPreferredDevice(deviceList[index]));
assertTrue(audioTrack.getPreferredDevice() == deviceList[index]);
}
// Check defaults again
assertTrue(audioTrack.setPreferredDevice(null));
assertNull(audioTrack.getPreferredDevice());
audioTrack.release();
}
public void test_audioTrack_incallMusicRoutingPermissions() {
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)) {
// Can't do it so skip this test
return;
}
// only apps with MODIFY_PHONE_STATE permission can route playback
// to the uplink stream during a phone call, so this test makes sure that
// audio is re-routed to default device when the permission is missing
AudioDeviceInfo telephonyDevice = getTelephonyDeviceAndSetInCommunicationMode();
if (telephonyDevice == null) {
// Can't do it so skip this test
return;
}
AudioTrack audioTrack = null;
try {
audioTrack = allocAudioTrack();
assertNotNull(audioTrack);
audioTrack.setPreferredDevice(telephonyDevice);
assertEquals(AudioDeviceInfo.TYPE_TELEPHONY, audioTrack.getPreferredDevice().getType());
audioTrack.play();
assertTrue(audioTrack.getRoutedDevice().getType() != AudioDeviceInfo.TYPE_TELEPHONY);
} finally {
if (audioTrack != null) {
audioTrack.stop();
audioTrack.release();
}
mAudioManager.setMode(AudioManager.MODE_NORMAL);
}
}
private AudioDeviceInfo getTelephonyDeviceAndSetInCommunicationMode() {
// get the output device for telephony
AudioDeviceInfo telephonyDevice = null;
AudioDeviceInfo[] deviceList = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
for (int index = 0; index < deviceList.length; index++) {
if (deviceList[index].getType() == AudioDeviceInfo.TYPE_TELEPHONY) {
telephonyDevice = deviceList[index];
}
}
if (telephonyDevice == null) {
return null;
}
// simulate an in call state using MODE_IN_COMMUNICATION since
// AudioManager.setMode requires MODIFY_PHONE_STATE permission
// for setMode with MODE_IN_CALL.
mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
assertEquals(AudioManager.MODE_IN_COMMUNICATION, mAudioManager.getMode());
return telephonyDevice;
}
/*
* tests if the Looper for the current thread has been prepared,
* If not, it makes one, prepares it and returns it.
* If this returns non-null, the caller is reponsible for calling quit()
* on the returned Looper.
*/
private Looper prepareIfNeededLooper() {
// non-null Handler
Looper myLooper = null;
if (Looper.myLooper() == null) {
Looper.prepare();
myLooper = Looper.myLooper();
assertNotNull(myLooper);
}
return myLooper;
}
private class AudioTrackRoutingListener implements AudioTrack.OnRoutingChangedListener,
AudioRouting.OnRoutingChangedListener
{
public void onRoutingChanged(AudioTrack audioTrack) {}
public void onRoutingChanged(AudioRouting audioRouting) {}
}
public void test_audioTrack_RoutingListener() {
test_audioTrack_RoutingListener(false /*usesAudioRouting*/);
}
public void test_audioTrack_audioRouting_RoutingListener() {
test_audioTrack_RoutingListener(true /*usesAudioRouting*/);
}
private void test_audioTrack_RoutingListener(boolean usesAudioRouting) {
AudioTrack audioTrack = allocAudioTrack();
// null listener
if (usesAudioRouting) {
audioTrack.addOnRoutingChangedListener(
(AudioRouting.OnRoutingChangedListener) null, null);
} else {
audioTrack.addOnRoutingChangedListener(
(AudioTrack.OnRoutingChangedListener) null, null);
}
AudioTrackRoutingListener listener = new AudioTrackRoutingListener();
AudioTrackRoutingListener someOtherListener = new AudioTrackRoutingListener();
// add a listener
if (usesAudioRouting) {
audioTrack.addOnRoutingChangedListener(
(AudioRouting.OnRoutingChangedListener) listener, null);
} else {
audioTrack.addOnRoutingChangedListener(listener, null);
}
// remove listeners
if (usesAudioRouting) {
// remove a listener we didn't add
audioTrack.removeOnRoutingChangedListener(
(AudioRouting.OnRoutingChangedListener) someOtherListener);
// remove a valid listener
audioTrack.removeOnRoutingChangedListener(
(AudioRouting.OnRoutingChangedListener) listener);
} else {
// remove a listener we didn't add
audioTrack.removeOnRoutingChangedListener(
(AudioTrack.OnRoutingChangedListener) someOtherListener);
// remove a valid listener
audioTrack.removeOnRoutingChangedListener(
(AudioTrack.OnRoutingChangedListener) listener);
}
Looper myLooper = prepareIfNeededLooper();
if (usesAudioRouting) {
audioTrack.addOnRoutingChangedListener(
(AudioRouting.OnRoutingChangedListener) listener, new Handler());
audioTrack.removeOnRoutingChangedListener(
(AudioRouting.OnRoutingChangedListener) listener);
} else {
audioTrack.addOnRoutingChangedListener(
(AudioTrack.OnRoutingChangedListener) listener, new Handler());
audioTrack.removeOnRoutingChangedListener(
(AudioTrack.OnRoutingChangedListener) listener);
}
audioTrack.release();
if (myLooper != null) {
myLooper.quit();
}
}
private AudioRecord allocAudioRecord() {
int bufferSize =
AudioRecord.getMinBufferSize(
41000,
AudioFormat.CHANNEL_OUT_DEFAULT,
AudioFormat.ENCODING_PCM_16BIT);
AudioRecord audioRecord =
new AudioRecord(
MediaRecorder.AudioSource.DEFAULT,
41000, AudioFormat.CHANNEL_OUT_DEFAULT,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize);
return audioRecord;
}
private class AudioRecordRoutingListener implements AudioRecord.OnRoutingChangedListener,
AudioRouting.OnRoutingChangedListener
{
public void onRoutingChanged(AudioRecord audioRecord) {}
public void onRoutingChanged(AudioRouting audioRouting) {}
}
public void test_audioRecord_RoutingListener() {
test_audioRecord_RoutingListener(false /*usesAudioRouting*/);
}
public void test_audioRecord_audioRouting_RoutingListener() {
test_audioRecord_RoutingListener(true /*usesAudioRouting*/);
}
private void test_audioRecord_RoutingListener(boolean usesAudioRouting) {
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MICROPHONE)) {
// Can't do it so skip this test
return;
}
AudioRecord audioRecord = allocAudioRecord();
// null listener
if (usesAudioRouting) {
audioRecord.addOnRoutingChangedListener(
(AudioRouting.OnRoutingChangedListener) null, null);
} else {
audioRecord.addOnRoutingChangedListener(
(AudioRecord.OnRoutingChangedListener) null, null);
}
AudioRecordRoutingListener listener = new AudioRecordRoutingListener();
AudioRecordRoutingListener someOtherListener = new AudioRecordRoutingListener();
// add a listener
if (usesAudioRouting) {
audioRecord.addOnRoutingChangedListener(
(AudioRouting.OnRoutingChangedListener) listener, null);
} else {
audioRecord.addOnRoutingChangedListener(
(AudioRecord.OnRoutingChangedListener) listener, null);
}
// remove listeners
if (usesAudioRouting) {
// remove a listener we didn't add
audioRecord.removeOnRoutingChangedListener(
(AudioRouting.OnRoutingChangedListener) someOtherListener);
// remove a valid listener
audioRecord.removeOnRoutingChangedListener(
(AudioRouting.OnRoutingChangedListener) listener);
} else {
// remove a listener we didn't add
audioRecord.removeOnRoutingChangedListener(
(AudioRecord.OnRoutingChangedListener) someOtherListener);
// remove a valid listener
audioRecord.removeOnRoutingChangedListener(
(AudioRecord.OnRoutingChangedListener) listener);
}
Looper myLooper = prepareIfNeededLooper();
if (usesAudioRouting) {
audioRecord.addOnRoutingChangedListener(
(AudioRouting.OnRoutingChangedListener) listener, new Handler());
audioRecord.removeOnRoutingChangedListener(
(AudioRouting.OnRoutingChangedListener) listener);
} else {
audioRecord.addOnRoutingChangedListener(
(AudioRecord.OnRoutingChangedListener) listener, new Handler());
audioRecord.removeOnRoutingChangedListener(
(AudioRecord.OnRoutingChangedListener) listener);
}
audioRecord.release();
if (myLooper != null) {
myLooper.quit();
}
}
public void test_audioRecord_preferredDevice() {
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MICROPHONE)) {
// Can't do it so skip this test
return;
}
AudioRecord audioRecord = allocAudioRecord();
assertNotNull(audioRecord);
// None selected (new AudioRecord), so check for default
assertNull(audioRecord.getPreferredDevice());
// resets to default
assertTrue(audioRecord.setPreferredDevice(null));
// test each device
AudioDeviceInfo[] deviceList = mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS);
for (int index = 0; index < deviceList.length; index++) {
assertTrue(audioRecord.setPreferredDevice(deviceList[index]));
assertTrue(audioRecord.getPreferredDevice() == deviceList[index]);
}
// Check defaults again
assertTrue(audioRecord.setPreferredDevice(null));
assertNull(audioRecord.getPreferredDevice());
audioRecord.release();
}
private class AudioTrackFiller implements Runnable {
AudioTrack mAudioTrack;
int mBufferSize;
boolean mPlaying;
short[] mAudioData;
public AudioTrackFiller(AudioTrack audioTrack, int bufferSize) {
mAudioTrack = audioTrack;
mBufferSize = bufferSize;
mPlaying = false;
// setup audio data (silence will suffice)
mAudioData = new short[mBufferSize];
for (int index = 0; index < mBufferSize; index++) {
mAudioData[index] = 0;
}
}
public void start() { mPlaying = true; }
public void stop() { mPlaying = false; }
@Override
public void run() {
while (mAudioTrack != null && mPlaying) {
mAudioTrack.write(mAudioData, 0, mBufferSize);
}
}
}
public void test_audioTrack_getRoutedDevice() {
if (!DeviceUtils.hasOutputDevice(mAudioManager)) {
Log.i(TAG, "No output devices. Test skipped");
return; // nothing to test here
}
int bufferSize =
AudioTrack.getMinBufferSize(
41000,
AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT);
AudioTrack audioTrack =
new AudioTrack(
AudioManager.STREAM_MUSIC,
41000,
AudioFormat.CHANNEL_OUT_STEREO,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize,
AudioTrack.MODE_STREAM);
AudioTrackFiller filler = new AudioTrackFiller(audioTrack, bufferSize);
filler.start();
audioTrack.play();
Thread fillerThread = new Thread(filler);
fillerThread.start();
try { Thread.sleep(1000); } catch (InterruptedException ex) {}
// No explicit route
AudioDeviceInfo routedDevice = audioTrack.getRoutedDevice();
assertNotNull(routedDevice); // we probably can't say anything more than this
filler.stop();
audioTrack.stop();
audioTrack.release();
}
private class AudioRecordPuller implements Runnable {
AudioRecord mAudioRecord;
int mBufferSize;
boolean mRecording;
short[] mAudioData;
public AudioRecordPuller(AudioRecord audioRecord, int bufferSize) {
mAudioRecord = audioRecord;
mBufferSize = bufferSize;
mRecording = false;
}
public void start() { mRecording = true; }
public void stop() { mRecording = false; }
@Override
public void run() {
while (mAudioRecord != null && mRecording) {
mAudioRecord.read(mAudioData, 0, mBufferSize);
}
}
}
public void test_audioRecord_getRoutedDevice() {
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MICROPHONE)) {
return;
}
if (!DeviceUtils.hasInputDevice(mAudioManager)) {
Log.i(TAG, "No input devices. Test skipped");
return; // nothing to test here
}
int bufferSize =
AudioRecord.getMinBufferSize(
41000,
AudioFormat.CHANNEL_OUT_DEFAULT,
AudioFormat.ENCODING_PCM_16BIT);
AudioRecord audioRecord =
new AudioRecord(
MediaRecorder.AudioSource.DEFAULT,
41000, AudioFormat.CHANNEL_OUT_DEFAULT,
AudioFormat.ENCODING_PCM_16BIT,
bufferSize);
AudioRecordPuller puller = new AudioRecordPuller(audioRecord, bufferSize);
puller.start();
audioRecord.startRecording();
Thread pullerThread = new Thread(puller);
pullerThread.start();
try { Thread.sleep(1000); } catch (InterruptedException ex) {}
// No explicit route
AudioDeviceInfo routedDevice = audioRecord.getRoutedDevice();
assertNotNull(routedDevice); // we probably can't say anything more than this
puller.stop();
audioRecord.stop();
audioRecord.release();
}
private class AudioRoutingListener implements AudioRouting.OnRoutingChangedListener
{
public void onRoutingChanged(AudioRouting audioRouting) {
if (mRoutingChangedLatch != null) {
mRoutingChangedLatch.countDown();
}
synchronized (mRoutingChangedLock) {
mRoutingChanged = true;
mRoutingChangedLock.notify();
}
}
}
private MediaPlayer allocMediaPlayer() {
final int resid = R.raw.testmp3_2;
MediaPlayer mediaPlayer = MediaPlayer.create(mContext, resid);
mediaPlayer.setAudioAttributes(
new AudioAttributes.Builder().setUsage(AudioAttributes.USAGE_MEDIA).build());
mediaPlayer.start();
return mediaPlayer;
}
public void test_mediaPlayer_preferredDevice() {
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)) {
// Can't do it so skip this test
return;
}
MediaPlayer mediaPlayer = allocMediaPlayer();
assertTrue(mediaPlayer.isPlaying());
// None selected (new MediaPlayer), so check for default
assertNull(mediaPlayer.getPreferredDevice());
// resets to default
assertTrue(mediaPlayer.setPreferredDevice(null));
// test each device
AudioDeviceInfo[] deviceList = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
for (int index = 0; index < deviceList.length; index++) {
assertTrue(mediaPlayer.setPreferredDevice(deviceList[index]));
assertTrue(mediaPlayer.getPreferredDevice() == deviceList[index]);
}
// Check defaults again
assertTrue(mediaPlayer.setPreferredDevice(null));
assertNull(mediaPlayer.getPreferredDevice());
mediaPlayer.stop();
mediaPlayer.release();
}
public void test_mediaPlayer_getRoutedDevice() {
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)) {
// Can't do it so skip this test
return;
}
MediaPlayer mediaPlayer = allocMediaPlayer();
assertTrue(mediaPlayer.isPlaying());
// Sleep for 1s to ensure the output device open
SystemClock.sleep(1000);
// No explicit route
AudioDeviceInfo routedDevice = mediaPlayer.getRoutedDevice();
assertNotNull(routedDevice);
mediaPlayer.stop();
mediaPlayer.release();
}
public void test_MediaPlayer_RoutingListener() {
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)) {
// Can't do it so skip this test
return;
}
MediaPlayer mediaPlayer = allocMediaPlayer();
// null listener
mediaPlayer.addOnRoutingChangedListener(null, null);
AudioRoutingListener listener = new AudioRoutingListener();
AudioRoutingListener someOtherListener = new AudioRoutingListener();
// add a listener
mediaPlayer.addOnRoutingChangedListener(listener, null);
// remove listeners
// remove a listener we didn't add
mediaPlayer.removeOnRoutingChangedListener(someOtherListener);
// remove a valid listener
mediaPlayer.removeOnRoutingChangedListener(listener);
Looper myLooper = prepareIfNeededLooper();
mediaPlayer.addOnRoutingChangedListener(listener, new Handler());
mediaPlayer.removeOnRoutingChangedListener(listener);
mediaPlayer.stop();
mediaPlayer.release();
if (myLooper != null) {
myLooper.quit();
}
}
public void test_MediaPlayer_RoutingChangedCallback() throws Exception {
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)) {
// Can't do it so skip this test
return;
}
AudioDeviceInfo[] devices = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
if (devices.length < 2) {
// In this case, we cannot switch output device, that may cause the test fail.
return;
}
mRoutingChanged = false;
mRoutingChangedLooper = null;
// Create MediaPlayer in another thread to make sure there is a looper active for events.
Thread t = new Thread() {
@Override
public void run() {
Looper.prepare();
// Keep looper to terminate when the test is finished.
mRoutingChangedLooper = Looper.myLooper();
AudioRoutingListener listener = new AudioRoutingListener();
MediaPlayer mediaPlayer = allocMediaPlayer();
mediaPlayer.addOnRoutingChangedListener(listener, null);
// With setting preferred device, the output device may switch.
// Post the request delayed to ensure the message queue is running
// so that the routing changed event can be handled correctly.
Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
AudioDeviceInfo routedDevice = mediaPlayer.getRoutedDevice();
if (routedDevice == null) {
return;
}
AudioDeviceInfo[] devices = mAudioManager.getDevices(
AudioManager.GET_DEVICES_OUTPUTS);
for (AudioDeviceInfo device : devices) {
if (routedDevice.getId() != device.getId()) {
mediaPlayer.setPreferredDevice(device);
break;
}
}
}
}, 1000);
Looper.loop();
mediaPlayer.removeOnRoutingChangedListener(listener);
mediaPlayer.stop();
mediaPlayer.release();
}
};
t.start();
synchronized (mRoutingChangedLock) {
mRoutingChangedLock.wait(WAIT_ROUTING_CHANGE_TIME_MS
* MAX_WAITING_ROUTING_CHANGED_COUNT);
}
if (mRoutingChangedLooper != null) {
mRoutingChangedLooper.quitSafely();
mRoutingChangedLooper = null;
}
t.join();
assertTrue("Routing changed callback has not been called", mRoutingChanged);
}
public void test_mediaPlayer_incallMusicRoutingPermissions() {
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_AUDIO_OUTPUT)) {
// Can't do it so skip this test
return;
}
// only apps with MODIFY_PHONE_STATE permission can route playback
// to the uplink stream during a phone call, so this test makes sure that
// audio is re-routed to default device when the permission is missing
AudioDeviceInfo telephonyDevice = getTelephonyDeviceAndSetInCommunicationMode();
if (telephonyDevice == null) {
// Can't do it so skip this test
return;
}
MediaPlayer mediaPlayer = null;
try {
mediaPlayer = allocMediaPlayer();
mediaPlayer.setPreferredDevice(telephonyDevice);
assertEquals(AudioDeviceInfo.TYPE_TELEPHONY, mediaPlayer.getPreferredDevice().getType());
// Sleep for 1s to ensure the output device open
SystemClock.sleep(1000);
assertTrue(mediaPlayer.getRoutedDevice().getType() != AudioDeviceInfo.TYPE_TELEPHONY);
} finally {
if (mediaPlayer != null) {
mediaPlayer.stop();
mediaPlayer.release();
}
mAudioManager.setMode(AudioManager.MODE_NORMAL);
}
}
private MediaRecorder allocMediaRecorder() throws Exception {
final String outputPath = new File(Environment.getExternalStorageDirectory(),
"record.out").getAbsolutePath();
mOutFile = new File(outputPath);
MediaRecorder mediaRecorder = new MediaRecorder();
mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);
assertEquals(0, mediaRecorder.getMaxAmplitude());
mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
mediaRecorder.setOutputFile(outputPath);
mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC);
mediaRecorder.setAudioChannels(AudioFormat.CHANNEL_OUT_DEFAULT);
mediaRecorder.setAudioSamplingRate(AUDIO_SAMPLE_RATE_HZ);
mediaRecorder.setAudioEncodingBitRate(AUDIO_BIT_RATE_IN_BPS);
mediaRecorder.setMaxFileSize(MAX_FILE_SIZE_BYTE);
mediaRecorder.prepare();
mediaRecorder.start();
// Sleep a while to ensure the underlying AudioRecord is initialized.
Thread.sleep(1000);
return mediaRecorder;
}
public void test_mediaRecorder_preferredDevice() throws Exception {
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MICROPHONE)
|| !MediaUtils.hasEncoder(MediaFormat.MIMETYPE_AUDIO_AAC)) {
MediaUtils.skipTest("no audio codecs or microphone");
return;
}
MediaRecorder mediaRecorder = allocMediaRecorder();
// None selected (new MediaPlayer), so check for default
assertNull(mediaRecorder.getPreferredDevice());
// resets to default
assertTrue(mediaRecorder.setPreferredDevice(null));
// test each device
AudioDeviceInfo[] deviceList = mAudioManager.getDevices(AudioManager.GET_DEVICES_INPUTS);
for (int index = 0; index < deviceList.length; index++) {
if (!AVAILABLE_INPUT_DEVICES_TYPE.contains(deviceList[index].getType())) {
// Only try to set devices whose type is contained in predefined set as preferred
// device in case of permission denied when switching input device.
continue;
}
assertTrue(mediaRecorder.setPreferredDevice(deviceList[index]));
assertTrue(mediaRecorder.getPreferredDevice() == deviceList[index]);
}
// Check defaults again
assertTrue(mediaRecorder.setPreferredDevice(null));
assertNull(mediaRecorder.getPreferredDevice());
Thread.sleep(RECORD_TIME_MS);
mediaRecorder.stop();
mediaRecorder.release();
}
public void test_mediaRecorder_getRoutedDeviceId() throws Exception {
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MICROPHONE)
|| !MediaUtils.hasEncoder(MediaFormat.MIMETYPE_AUDIO_AAC)) {
MediaUtils.skipTest("no audio codecs or microphone");
return;
}
MediaRecorder mediaRecorder = allocMediaRecorder();
AudioDeviceInfo routedDevice = mediaRecorder.getRoutedDevice();
assertNotNull(routedDevice); // we probably can't say anything more than this
Thread.sleep(RECORD_TIME_MS);
mediaRecorder.stop();
mediaRecorder.release();
}
public void test_mediaRecorder_RoutingListener() throws Exception {
if (!mContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_MICROPHONE)
|| !MediaUtils.hasEncoder(MediaFormat.MIMETYPE_AUDIO_AAC)) {
MediaUtils.skipTest("no audio codecs or microphone");
return;
}
MediaRecorder mediaRecorder = allocMediaRecorder();
// null listener
mediaRecorder.addOnRoutingChangedListener(null, null);
AudioRoutingListener listener = new AudioRoutingListener();
AudioRoutingListener someOtherListener = new AudioRoutingListener();
// add a listener
mediaRecorder.addOnRoutingChangedListener(listener, null);
// remove listeners we didn't add
mediaRecorder.removeOnRoutingChangedListener(someOtherListener);
// remove a valid listener
mediaRecorder.removeOnRoutingChangedListener(listener);
Looper myLooper = prepareIfNeededLooper();
mediaRecorder.addOnRoutingChangedListener(listener, new Handler());
mediaRecorder.removeOnRoutingChangedListener(listener);
Thread.sleep(RECORD_TIME_MS);
mediaRecorder.stop();
mediaRecorder.release();
if (myLooper != null) {
myLooper.quit();
}
}
}