FM: Audio changes
setDeviceConnectionState (DSP AFE loop) for the default device(HS)
use application loop back(AudioRecord->AudioTrack) to route
FM audio to non-default devices(Speaker).
Change-Id: Ib74d228375c47e4ee595ddbc2a3c033b691de06a
diff --git a/fmapp2/src/com/caf/fmradio/FMRadioService.java b/fmapp2/src/com/caf/fmradio/FMRadioService.java
index 36c486b..28da6fd 100644
--- a/fmapp2/src/com/caf/fmradio/FMRadioService.java
+++ b/fmapp2/src/com/caf/fmradio/FMRadioService.java
@@ -59,6 +59,7 @@
import android.media.AudioPortConfig;
import android.media.AudioRecord;
import android.media.AudioTrack;
+import android.media.AudioDeviceInfo;
import android.os.Environment;
import android.os.Handler;
@@ -377,7 +378,14 @@
super.onDestroy();
}
- private synchronized void startAudioRecordSink() {
+ private synchronized void CreateRecordSessions() {
+
+ if (mAudioRecord != null) {
+ mAudioRecord.stop();
+ }
+ if (mAudioTrack != null) {
+ mAudioTrack.stop();
+ }
mAudioRecord = new AudioRecord(MediaRecorder.AudioSource.RADIO_TUNER,
AUDIO_SAMPLE_RATE, AUDIO_CHANNEL_CONFIG,
AUDIO_ENCODING_FORMAT, FM_RECORD_BUF_SIZE);
@@ -393,13 +401,6 @@
Log.d(LOGTAG, "startRecordSink "
+ AudioSystem.getForceUse(AudioSystem.FOR_MEDIA));
- if (mAudioRecord != null) {
- mAudioRecord.stop();
- }
- if (mAudioTrack != null) {
- mAudioTrack.stop();
- }
- startAudioRecordSink();
createRecordSinkThread();
mIsRecordSink = true;
@@ -452,10 +453,13 @@
// to AudioRecrd and write data to AudioTrack.
if (mAudioRecord.getRecordingState() == AudioRecord.RECORDSTATE_STOPPED) {
mAudioRecord.startRecording();
+ Log.d(LOGTAG, "mAudioRecord.startRecording started");
}
if (mAudioTrack.getPlayState() == AudioTrack.PLAYSTATE_STOPPED) {
+ Log.d(LOGTAG, "mAudioTrack.play executed");
mAudioTrack.play();
+ Log.d(LOGTAG, "mAudioTrack.play completed");
}
int size = mAudioRecord.read(buffer, 0, FM_RECORD_BUF_SIZE);
// check whether need to ignore first 3 frames audio data from AudioRecord
@@ -536,6 +540,7 @@
Log.d(LOGTAG, "configureAudioDataPath:" + enable +
" mA2dpConnected:" + mA2dpConnected +
" isRecordSinking" + isRecordSinking() +
+ " mSpeakerPhoneOn:" + mSpeakerPhoneOn +
" mIsFMDeviceLoopbackActive:" + mIsFMDeviceLoopbackActive);
if (enable) {
@@ -544,20 +549,13 @@
"audio path");
return;
}
- // stop existing playback path before starting new one
- if (mA2dpConnected && mIsFMDeviceLoopbackActive) {
- // on BT but earlier device loopback is active
- configureFMDeviceLoopback(false);
- } else if (!mA2dpConnected && !mIsFMDeviceLoopbackActive) {
+ if ((!mIsFMDeviceLoopbackActive) && (!mA2dpConnected) && (!mSpeakerPhoneOn)) {
// not on BT and device loop is also not active
exitRecordSinkThread();
configureFMDeviceLoopback(true);
}
-
- // start app thread if none of the path started yet
- if (!mIsFMDeviceLoopbackActive && !isRecordSinking())
- startRecordSink();
} else {
+ //inform audio to disbale fm audio
configureFMDeviceLoopback(false);
exitRecordSinkThread();
}
@@ -704,21 +702,24 @@
e.printStackTrace();
}
- mSpeakerPhoneOn = bA2dpConnected;
- Log.d(LOGTAG, "A2DP, mSpeakerPhoneOn: " + bA2dpConnected);
-
+ //mSpeakerPhoneOn = bA2dpConnected;
+ mA2dpConnected = bA2dpConnected;
+ mA2dpDisconnected = !bA2dpConnected;
+ Log.d(LOGTAG, "A2DP, mSpeakerPhoneOn: " + mSpeakerPhoneOn);
if (!bA2dpConnected) {
Log.d(LOGTAG, "A2DP device is dis-connected!");
- mA2dpDisconnected = true;
- mA2dpConnected = false;
- AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_NO_BT_A2DP);
+ //stop record session of audio and switch to default audio output device
+ // getOutputDeviceAndSwitchAudio(AudioDeviceInfo.TYPE_WIRED_HEADSET);
} else {
- Log.d(LOGTAG, "A2DP device is connected!");
- mA2dpDisconnected = false;
- mA2dpConnected = true;
- }
- if (isFmOn())
- configureAudioDataPath(true);
+ Log.d(LOGTAG, "A2DP device is connected!");
+ if (mSpeakerPhoneOn) {
+ Log.d(LOGTAG, "route audio to speaker");
+ getOutputDeviceAndSwitchAudio(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
+ } else {
+ Log.d(LOGTAG, "route audio to wiredHeadset");
+ getOutputDeviceAndSwitchAudio(AudioDeviceInfo.TYPE_WIRED_HEADSET);
+ }
+ }
} else if (action.equals("HDMI_CONNECTED")) {
//FM should be off when HDMI is connected.
fmOff();
@@ -1157,12 +1158,15 @@
mStoppedOnFactoryReset = false;
mSpeakerPhoneOn = false;
// In FM stop, the audio route is set to default audio device
- } else if (mSpeakerPhoneOn) {
- String temp = mA2dpConnected ? "A2DP HS" : "Speaker";
+ } else if (mA2dpConnected || mSpeakerPhoneOn) {
+ String temp = mSpeakerPhoneOn ? "Speaker" : "WiredHeadset";
Log.d(LOGTAG, "Route audio to " + temp);
- AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_SPEAKER);
+ if(!mSpeakerPhoneOn) {
+ getOutputDeviceAndSwitchAudio(AudioDeviceInfo.TYPE_WIRED_HEADSET);
+ } else {
+ getOutputDeviceAndSwitchAudio(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
+ }
}
-
mPlaybackInProgress = true;
configureAudioDataPath(true);
try {
@@ -1624,7 +1628,7 @@
private Runnable mSpeakerDisableTask = new Runnable() {
public void run() {
Log.v(LOGTAG, "*** Disabling Speaker");
- AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_NONE);
+ exitRecordSinkThread();
}
};
@@ -1671,7 +1675,7 @@
Log.v(LOGTAG, "AudioFocus: received AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK");
if (mSpeakerPhoneOn) {
Log.v(LOGTAG, "Focus Loss/TLoss - Disabling speaker");
- AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_NONE);
+ exitRecordSinkThread();
}
if ((mReceiver != null) && mReceiver.isCherokeeChip() && (mPref.getBoolean("SLIMBUS_SEQ", true))) {
mEventReceived = false;
@@ -2524,11 +2528,8 @@
private void resetAudioRoute() {
if (isSpeakerEnabled() == true) {
if (mA2dpConnected == true) {
- Log.d(LOGTAG, "A2DP connected, de-select BT");
- AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_NO_BT_A2DP);
- } else {
- Log.d(LOGTAG, "A2DP is not connected, force none");
- AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_NONE);
+ Log.d(LOGTAG, "A2DP connected, resetAudioRoute to wiredHeadset");
+ getOutputDeviceAndSwitchAudio(AudioDeviceInfo.TYPE_WIRED_HEADSET);
}
}
}
@@ -2602,7 +2603,7 @@
if ( mSpeakerPhoneOn) {
mSpeakerPhoneOn = false;
- AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_NONE);
+ exitRecordSinkThread();
}
}
@@ -2740,16 +2741,11 @@
mSpeakerPhoneOn = speakerOn;
if (speakerOn == false) {
- if (mA2dpConnected == true) {
- Log.d(LOGTAG, "A2DP connected, de-select BT");
- AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_NO_BT_A2DP);
- } else {
- Log.d(LOGTAG, "A2DP is not connected, force none");
- AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_NONE);
- }
+ Log.d(LOGTAG, "route audio to wired headset");
+ getOutputDeviceAndSwitchAudio(AudioDeviceInfo.TYPE_WIRED_HEADSET);
} else if (speakerOn == true) {
Log.d(LOGTAG, "enabling speaker");
- AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_SPEAKER);
+ getOutputDeviceAndSwitchAudio(AudioDeviceInfo.TYPE_BUILTIN_SPEAKER);
}
Log.d(LOGTAG, "speakerOn completed:" + speakerOn);
@@ -4185,7 +4181,7 @@
mA2dpConnected = true;
mA2dpDisconnected = !mA2dpConnected;
- mSpeakerPhoneOn = mA2dpConnected;
+ //mSpeakerPhoneOn = mA2dpConnected;
Log.d(LOGTAG, "A2DP Status: " + mA2dpConnected);
}
@@ -4217,4 +4213,35 @@
//TODO unregister the fm service here.
}
}
+ private boolean getOutputDeviceAndSwitchAudio(int deviceType) {
+
+ // stop existing playback path before starting new one
+ Log.d(LOGTAG,"getOutputDeviceAndSwitchAudio for device "+deviceType);
+
+ AudioDeviceInfo outputDevice = null;
+ AudioDeviceInfo[] deviceList = mAudioManager.getDevices(AudioManager.GET_DEVICES_OUTPUTS);
+ for (int index = 0; index < deviceList.length; index++) {
+ if (deviceList[index].getType() == deviceType) {
+ outputDevice = deviceList[index];
+ }
+ }
+
+ if (outputDevice == null) {
+ Log.d(LOGTAG,"no output device" + deviceType + " found");
+ return false;
+ }
+ if(mIsFMDeviceLoopbackActive) {
+ configureFMDeviceLoopback(false);
+ }
+ if(!isRecordSinking()) {
+ CreateRecordSessions();
+ Log.d(LOGTAG,"creating AudioTrack session");
+ }
+ mAudioTrack.setPreferredDevice(outputDevice);
+ Log.d(LOGTAG,"PreferredDevice is set to "+ deviceType);
+ if(!isRecordSinking()) {
+ startRecordSink();
+ }
+ return true;
+ }
}