diff --git a/fmapp2/src/com/caf/fmradio/FMRadioService.java b/fmapp2/src/com/caf/fmradio/FMRadioService.java index 35e7e245aabaa0f2cb42d00eada882eb29edb82f..56d9aa6730b3145cb97ea87da79eaf8f490b929c 100644 --- a/fmapp2/src/com/caf/fmradio/FMRadioService.java +++ b/fmapp2/src/com/caf/fmradio/FMRadioService.java @@ -207,6 +207,7 @@ public class FMRadioService extends Service private boolean mIsRecordSink = false; private static final int AUDIO_FRAMES_COUNT_TO_IGNORE = 3; private Object mRecordSinkLock = new Object(); + private boolean mIsFMDeviceLoopbackActive = false; public FMRadioService() { } @@ -368,7 +369,7 @@ public class FMRadioService extends Service private synchronized void stopRecordSink() { Log.d(LOGTAG, "stopRecordSink"); - mRecordSinkLock = false; + mIsRecordSink = false; synchronized (mRecordSinkLock) { mRecordSinkLock.notify(); } @@ -464,6 +465,57 @@ public class FMRadioService extends Service } } + private boolean configureFMDeviceLoopback(boolean enable) { + boolean success = true; + int status = AudioSystem.SUCCESS; + + Log.d(LOGTAG, "configureFMDeviceLoopback enable:" + enable + + " DeviceLoopbackActive:" + mIsFMDeviceLoopbackActive); + if (enable && mIsFMDeviceLoopbackActive == false) { + status = AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM, + AudioSystem.DEVICE_STATE_AVAILABLE, "", ""); + if (status != AudioSystem.SUCCESS) { + success = false; + Log.e(LOGTAG, "configureFMDeviceLoopback failed! status:" + status); + AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM, + AudioSystem.DEVICE_STATE_UNAVAILABLE, "", ""); + } else { + mIsFMDeviceLoopbackActive = true; + } + } else if (!enable && mIsFMDeviceLoopbackActive == true) { + AudioSystem.setDeviceConnectionState(AudioSystem.DEVICE_OUT_FM, + AudioSystem.DEVICE_STATE_UNAVAILABLE, "", ""); + mIsFMDeviceLoopbackActive = false; + } + + return success; + } + + private synchronized void configureAudioDataPath(boolean enable) { + Log.d(LOGTAG, "configureAudioDataPath:" + enable + + " mA2dpConnected:" + mA2dpConnected + + " isRecordSinking" + isRecordSinking() + + " mIsFMDeviceLoopbackActive:" + mIsFMDeviceLoopbackActive); + if (enable) { + // 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) { + // 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 { + configureFMDeviceLoopback(false); + exitRecordSinkThread(); + } + } + /** * Registers an intent to listen for ACTION_MEDIA_UNMOUNTED notifications. * The intent will call closeExternalStorageFiles() if the external media @@ -570,6 +622,7 @@ public class FMRadioService extends Service mA2dpDisconnected = false; mA2dpConnected = true; } + configureAudioDataPath(true); } else if (action.equals("HDMI_CONNECTED")) { //FM should be off when HDMI is connected. fmOff(); @@ -592,6 +645,9 @@ public class FMRadioService extends Service } }; + AudioManager am = (AudioManager) getSystemService(Context.AUDIO_SERVICE); + mA2dpConnected = am.isBluetoothA2dpOn(); + mA2dpDisconnected = !mA2dpConnected; IntentFilter iFilter = new IntentFilter(); iFilter.addAction(Intent.ACTION_HEADSET_PLUG); iFilter.addAction(mA2dpDeviceState.getActionSinkStateChangedString()); @@ -1058,14 +1114,13 @@ public class FMRadioService extends Service AudioSystem.setForceUse(AudioSystem.FOR_MEDIA, AudioSystem.FORCE_NONE); } } - startRecordSink(); mPlaybackInProgress = true; + configureAudioDataPath(true); } private void stopFM(){ Log.d(LOGTAG, "In stopFM"); - stopRecordSink(); - exitRecordSinkThread(); + configureAudioDataPath(false); mPlaybackInProgress = false; }