diff --git a/src/org/linphone/BluetoothManager.java b/src/org/linphone/BluetoothManager.java index 3d3d6badf..19737fb3c 100644 --- a/src/org/linphone/BluetoothManager.java +++ b/src/org/linphone/BluetoothManager.java @@ -17,13 +17,22 @@ You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ +import java.util.List; + +import org.linphone.LinphoneSimpleListener.LinphoneOnAudioChangedListener.AudioState; +import org.linphone.compatibility.Compatibility; import org.linphone.mediastream.Log; +import org.linphone.mediastream.Version; import android.annotation.TargetApi; +import android.bluetooth.BluetoothAdapter; import android.bluetooth.BluetoothDevice; +import android.bluetooth.BluetoothHeadset; +import android.bluetooth.BluetoothProfile; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; +import android.content.IntentFilter; import android.media.AudioManager; import android.os.Build; @@ -32,50 +41,248 @@ import android.os.Build; */ @TargetApi(Build.VERSION_CODES.HONEYCOMB) public class BluetoothManager extends BroadcastReceiver { + private static BluetoothManager instance; + + private Context mContext; + private AudioManager mAudioManager; + private BluetoothAdapter mBluetoothAdapter; + private BluetoothHeadset mBluetoothHeadset; + private BluetoothDevice mBluetoothDevice; + private BluetoothProfile.ServiceListener mProfileListener; + private BroadcastReceiver bluetoothActionReceiver = new BluetoothActionReceiver(); + private boolean isBluetoothConnected; + private boolean isUsingBluetoothAudioRoute; + + public static BluetoothManager getInstance() { + if (instance == null) { + instance = new BluetoothManager(); + } + return instance; + } + + /** + * Do not call ! + */ + public BluetoothManager() { + isBluetoothConnected = false; + isUsingBluetoothAudioRoute = false; + try { + mContext = LinphoneManager.getInstance().getContext(); + mAudioManager = ((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE)); + instance = this; + } catch (Exception e) {} + } + + public void startBluetooth() { + if (isBluetoothConnected) { + Log.e("Bluetooth already started"); + return; + } + + IntentFilter filter = new IntentFilter(); + filter.addAction("android.bluetooth.device.action.ACL_CONNECTED"); + filter.addAction("android.bluetooth.device.action.ACL_DISCONNECTED"); + filter.addAction("android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED"); + mContext.registerReceiver(this, filter); + Log.d("Bluetooth receiver started"); + + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + + if (mBluetoothAdapter.isEnabled()) { + if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) { + if (mProfileListener != null) { + Log.w("Bluetooth headset profile was already opened, let's close it"); + mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset); + } + + mProfileListener = new BluetoothProfile.ServiceListener() { + public void onServiceConnected(int profile, BluetoothProfile proxy) { + if (profile == BluetoothProfile.HEADSET) { + Log.d("Bluetooth headset connected"); + mContext.registerReceiver(bluetoothActionReceiver, new IntentFilter(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT)); + mBluetoothHeadset = (BluetoothHeadset) proxy; + isBluetoothConnected = true; + } + } + public void onServiceDisconnected(int profile) { + if (profile == BluetoothProfile.HEADSET) { + mContext.unregisterReceiver(bluetoothActionReceiver); + mBluetoothHeadset = null; + isBluetoothConnected = false; + Log.d("Bluetooth headset disconnected"); + LinphoneManager.getInstance().routeAudioToSpeaker(); + } + } + }; + boolean success = mBluetoothAdapter.getProfileProxy(mContext, mProfileListener, BluetoothProfile.HEADSET); + if (!success) { + Log.e("Bluetooth getProfileProxy failed !"); + } + } + } else { + Log.w("Bluetooth interface disabled on device"); + } + } + + public boolean routeAudioToBluetooth() { + return routeAudioToBluetooth(false); + } + + private boolean routeAudioToBluetooth(boolean isRetry) { + if (mBluetoothAdapter == null) { + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + } + + if (mBluetoothAdapter.isEnabled() && mAudioManager.isBluetoothScoAvailableOffCall()) { + isUsingBluetoothAudioRoute = isBluetoothHeadsetAvailable(); + + if (isUsingBluetoothAudioRoute) { + if (mAudioManager != null) { + mAudioManager.setBluetoothScoOn(true); + mAudioManager.startBluetoothSco(); + LinphoneManager.getInstance().audioStateChanged(AudioState.BLUETOOTH); + } + } else { + LinphoneManager.getInstance().audioStateChanged(AudioState.SPEAKER); + } + + isUsingBluetoothAudioRoute = mBluetoothHeadset.isAudioConnected(mBluetoothDevice); + if (!isUsingBluetoothAudioRoute && !isRetry) { + Log.w("Routing audio to bluetooth headset failed, retry...."); + try { + Thread.sleep(100); + } catch (InterruptedException e) {} + return routeAudioToBluetooth(true); + } else if (isRetry) { + if (isUsingBluetoothAudioRoute) { + Log.d("Retry worked, audio is routed to bluetooth headset"); + } else { + Log.e("Retry not worked, audio isn't routed to bluetooth headset..."); + disableBluetoothSCO(); + } + } else { + Log.d("Routing audio to bluetooth headset worked at first try"); + } + + return isUsingBluetoothAudioRoute; + } + + return false; + } + + public boolean isUsingBluetoothAudioRoute() { + return mBluetoothHeadset.isAudioConnected(mBluetoothDevice); + } + + public boolean isBluetoothHeadsetAvailable() { + if (mBluetoothAdapter == null) { + mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); + } + + if (mBluetoothAdapter.isEnabled() && mAudioManager.isBluetoothScoAvailableOffCall()) { + if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) { + boolean isHeadsetConnected = false; + if (mBluetoothHeadset != null) { + List devices = mBluetoothHeadset.getConnectedDevices(); + for (final BluetoothDevice dev : devices) { + if (mBluetoothHeadset.getConnectionState(dev) == BluetoothHeadset.STATE_CONNECTED) { + mBluetoothDevice = dev; + isHeadsetConnected = true; + break; + } + } + Log.d(isHeadsetConnected ? "Headset found, bluetooth audio route available" : "No headset found, bluetooth audio route unavailable"); + } + return isHeadsetConnected; + } + } + + return false; + } + + public void disableBluetoothSCO() { + isUsingBluetoothAudioRoute = false; + if (mAudioManager != null) { + mAudioManager.stopBluetoothSco(); + mAudioManager.setBluetoothScoOn(false); + Log.w("Bluetooth sco disconnected!"); + } + } + + public void stopBluetooth() { + Log.w("Stopping bluetooth..."); + isBluetoothConnected = false; + isUsingBluetoothAudioRoute = false; + + if (mAudioManager != null) { + mAudioManager.stopBluetoothSco(); + mAudioManager.setBluetoothScoOn(false); + } + + if (mProfileListener != null && mBluetoothHeadset != null) { + mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset); + mContext.unregisterReceiver(bluetoothActionReceiver); + mProfileListener = null; + mBluetoothHeadset = null; + } + mBluetoothDevice = null; + + Log.w("Bluetooth stopped!"); + + if (LinphoneManager.getLc().getCallsNb() > 0) { + Log.w("Bluetooth disabled, Going back to incall mode"); + Compatibility.setAudioManagerInCallMode(mAudioManager); + } + + try { + mContext.unregisterReceiver(this); + Log.d("Bluetooth receiver stopped"); + } catch (Exception e) {} + + if (LinphoneManager.isInstanciated()) { + LinphoneManager.getInstance().routeAudioToSpeaker(); + } + } + + public void destroy() { + try { + stopBluetooth(); + } catch (Exception e) { + e.printStackTrace(); + } + } + @SuppressWarnings("deprecation") public void onReceive(Context context, Intent intent) { if (!LinphoneManager.isInstanciated()) return; String action = intent.getAction(); - LinphoneManager lm = LinphoneManager.getInstance(); - if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) { - Log.e("Bluetooth Received Event" + " ACTION_ACL_DISCONNECTED" ); - - if (lm != null) { - lm.scoDisconnected(); - lm.routeAudioToReceiver(); - } + Log.d("Bluetooth Received Event" + " ACTION_ACL_DISCONNECTED"); + + stopBluetooth(); } else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) { - Log.e("Bluetooth Received Event" + " ACTION_ACL_CONNECTED" ); - - if (lm != null) { - lm.scoConnected(); - } + Log.d("Bluetooth Received Event" + " ACTION_ACL_CONNECTED"); + startBluetooth(); } else if (AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED.equals(action)) { int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, 0); - Log.e("Bluetooth sco state changed : " + state); + Log.d("Bluetooth sco state changed : " + state); if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) { - if (lm != null) { - lm.scoConnected(); - } + startBluetooth(); } else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) { - if (lm != null) { - lm.scoDisconnected(); - lm.routeAudioToReceiver(); - } + stopBluetooth(); } } //Using real value instead of constant because not available before sdk 11 else if ("android.bluetooth.adapter.action.CONNECTION_STATE_CHANGED".equals(action)) { //BluetoothAdapter.ACTION_CONNECTION_STATE_CHANGED int currentConnState = intent.getIntExtra("android.bluetooth.adapter.extra.CONNECTION_STATE", //BluetoothAdapter.EXTRA_CONNECTION_STATE 0); //BluetoothAdapter.STATE_DISCONNECTED - Log.e("Bluetooth state changed: " + currentConnState); - if (lm != null && currentConnState == 2) { //BluetoothAdapter.STATE_CONNECTED - lm.startBluetooth(); + Log.d("Bluetooth state changed: " + currentConnState); + if (currentConnState == 2) { //BluetoothAdapter.STATE_CONNECTED + startBluetooth(); } } } diff --git a/src/org/linphone/InCallActivity.java b/src/org/linphone/InCallActivity.java index 925e1e29e..f3fe8d31d 100644 --- a/src/org/linphone/InCallActivity.java +++ b/src/org/linphone/InCallActivity.java @@ -247,7 +247,7 @@ public class InCallActivity extends FragmentActivity implements slideOutTopToBottom = AnimationUtils.loadAnimation(this, R.anim.slide_out_top_to_bottom); } - if (LinphoneManager.getInstance().isBluetoothScoConnected) { + if (BluetoothManager.getInstance().isBluetoothHeadsetAvailable()) { try { if (routeLayout != null) routeLayout.setVisibility(View.VISIBLE); @@ -292,7 +292,7 @@ public class InCallActivity extends FragmentActivity implements } else { speaker.setBackgroundResource(R.drawable.speaker_off); routeSpeaker.setBackgroundResource(R.drawable.route_speaker_off); - if (LinphoneManager.getInstance().isUsingBluetoothAudioRoute) { + if (BluetoothManager.getInstance().isUsingBluetoothAudioRoute()) { routeReceiver.setBackgroundResource(R.drawable.route_receiver_off); routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_on); } else { @@ -404,12 +404,13 @@ public class InCallActivity extends FragmentActivity implements hideOrDisplayAudioRoutes(); } else if (id == R.id.routeBluetooth) { - LinphoneManager.getInstance().routeAudioToBluetooth(); - isSpeakerEnabled = false; - routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_on); - routeReceiver.setBackgroundResource(R.drawable.route_receiver_off); - routeSpeaker.setBackgroundResource(R.drawable.route_speaker_off); - hideOrDisplayAudioRoutes(); + if (BluetoothManager.getInstance().routeAudioToBluetooth()) { + isSpeakerEnabled = false; + routeBluetooth.setBackgroundResource(R.drawable.route_bluetooth_on); + routeReceiver.setBackgroundResource(R.drawable.route_receiver_off); + routeSpeaker.setBackgroundResource(R.drawable.route_speaker_off); + hideOrDisplayAudioRoutes(); + } } else if (id == R.id.routeReceiver) { LinphoneManager.getInstance().routeAudioToReceiver(); @@ -493,9 +494,12 @@ public class InCallActivity extends FragmentActivity implements } private void showVideoView() { - isSpeakerEnabled = true; - LinphoneManager.getInstance().routeAudioToSpeaker(); - speaker.setBackgroundResource(R.drawable.speaker_on); + if (!BluetoothManager.getInstance().isBluetoothHeadsetAvailable()) { + Log.w("Bluetooth not available, using speaker"); + LinphoneManager.getInstance().routeAudioToSpeaker(); + isSpeakerEnabled = true; + speaker.setBackgroundResource(R.drawable.speaker_on); + } video.setBackgroundResource(R.drawable.video_off); LinphoneManager.stopProximitySensorForActivity(InCallActivity.this); @@ -547,6 +551,7 @@ public class InCallActivity extends FragmentActivity implements speaker.setBackgroundResource(R.drawable.speaker_on); LinphoneManager.getLc().enableSpeaker(isSpeakerEnabled); } else { + Log.d("Toggle speaker off, routing back to earpiece"); LinphoneManager.getInstance().routeAudioToReceiver(); speaker.setBackgroundResource(R.drawable.speaker_off); } diff --git a/src/org/linphone/LinphoneManager.java b/src/org/linphone/LinphoneManager.java index 8099edee5..9ede82a2a 100644 --- a/src/org/linphone/LinphoneManager.java +++ b/src/org/linphone/LinphoneManager.java @@ -78,10 +78,6 @@ import org.linphone.mediastream.video.capture.hwconf.Hacks; import android.annotation.SuppressLint; import android.annotation.TargetApi; import android.app.Activity; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothHeadset; -import android.bluetooth.BluetoothProfile; import android.content.BroadcastReceiver; import android.content.ContentResolver; import android.content.Context; @@ -143,17 +139,7 @@ public class LinphoneManager implements LinphoneCoreListener { private int mLastNetworkType=-1; private ConnectivityManager mConnectivityManager; private Handler mHandler = new Handler(); - private WakeLock mIncallWakeLock; - - private BluetoothAdapter mBluetoothAdapter; - private BluetoothHeadset mBluetoothHeadset; - private BluetoothProfile.ServiceListener mProfileListener; - private BroadcastReceiver bluetoothReiceiver = new BluetoothManager(); - private BroadcastReceiver bluetoothActionReceiver = new BluetoothActionReceiver(); - public boolean isBluetoothScoConnected; - public boolean isUsingBluetoothAudioRoute; - private boolean mBluetoothStarted; public String wizardLoginViewDomain = null; @@ -208,13 +194,8 @@ public class LinphoneManager implements LinphoneCoreListener { private BroadcastReceiver mKeepAliveReceiver = new KeepAliveReceiver(); private void routeAudioToSpeakerHelper(boolean speakerOn) { - isUsingBluetoothAudioRoute = false; - if (mAudioManager != null && mBluetoothStarted) { - //Compatibility.setAudioManagerInCallMode(mAudioManager); - mAudioManager.stopBluetoothSco(); - mAudioManager.setBluetoothScoOn(false); - mBluetoothStarted = false; - } + Log.w("Routing audio to " + (speakerOn ? "speaker" : "earpiece") + ", disabling bluetooth audio route"); + BluetoothManager.getInstance().disableBluetoothSCO(); if (!speakerOn) { mLc.enableSpeaker(false); @@ -222,10 +203,15 @@ public class LinphoneManager implements LinphoneCoreListener { mLc.enableSpeaker(true); } + audioStateChanged(speakerOn ? AudioState.SPEAKER : AudioState.EARPIECE); + } + + public void audioStateChanged(AudioState state) { for (LinphoneOnAudioChangedListener listener : getSimpleListeners(LinphoneOnAudioChangedListener.class)) { - listener.onAudioStateChanged(speakerOn ? AudioState.SPEAKER : AudioState.EARPIECE); + listener.onAudioStateChanged(state); } } + public void routeAudioToSpeaker() { routeAudioToSpeakerHelper(true); } @@ -240,109 +226,9 @@ public class LinphoneManager implements LinphoneCoreListener { return userAgent.toString(); } - /** - * - */ public void routeAudioToReceiver() { routeAudioToSpeakerHelper(false); } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - @SuppressWarnings("deprecation") - public void startBluetooth() { - mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - if (mBluetoothAdapter.isEnabled()) { - if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) { - mProfileListener = new BluetoothProfile.ServiceListener() { - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public void onServiceConnected(int profile, BluetoothProfile proxy) { - if (profile == BluetoothProfile.HEADSET) { - Log.d("Bluetooth headset connected"); - mServiceContext.registerReceiver(bluetoothActionReceiver, new IntentFilter(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT)); - mBluetoothHeadset = (BluetoothHeadset) proxy; - isBluetoothScoConnected = true; - } - } - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public void onServiceDisconnected(int profile) { - if (profile == BluetoothProfile.HEADSET) { - mServiceContext.unregisterReceiver(bluetoothActionReceiver); - mBluetoothHeadset = null; - isBluetoothScoConnected = false; - Log.d("Bluetooth headset disconnected"); - routeAudioToReceiver(); - } - } - }; - mBluetoothAdapter.getProfileProxy(mServiceContext, mProfileListener, BluetoothProfile.HEADSET); - } else { - try { - mServiceContext.unregisterReceiver(bluetoothReiceiver); - } catch (Exception e) {} - - Intent currentValue = mServiceContext.registerReceiver(bluetoothReiceiver, new IntentFilter(AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED)); - int state = currentValue == null ? 0 : currentValue.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, 0); - if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) { - isBluetoothScoConnected = true; - } - } - } else { - isBluetoothScoConnected = false; - scoDisconnected(); - routeAudioToReceiver(); - } - } - - @TargetApi(Build.VERSION_CODES.HONEYCOMB) - public boolean routeAudioToBluetooth() { - BluetoothAdapter bluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - if (bluetoothAdapter.isEnabled() && mAudioManager.isBluetoothScoAvailableOffCall()) { - mAudioManager.setBluetoothScoOn(true); - mAudioManager.startBluetoothSco(); - mBluetoothStarted=true; - - if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) { - isUsingBluetoothAudioRoute = false; - if (mBluetoothHeadset != null) { - List devices = mBluetoothHeadset.getConnectedDevices(); - for (final BluetoothDevice dev : devices) { - isUsingBluetoothAudioRoute |= mBluetoothHeadset.getConnectionState(dev) == BluetoothHeadset.STATE_CONNECTED; - } - } - - if (!isUsingBluetoothAudioRoute) { - Log.d("No bluetooth device available"); - scoDisconnected(); - } else { - //Why is this for: - //mAudioManager.setMode(AudioManager.MODE_IN_CALL); - for (LinphoneOnAudioChangedListener listener : getSimpleListeners(LinphoneOnAudioChangedListener.class)) { - listener.onAudioStateChanged(AudioState.SPEAKER); - } - } - } - return isUsingBluetoothAudioRoute; - } - - return false; - } - - public void scoConnected() { - Log.i("Bluetooth sco connected!"); - isBluetoothScoConnected = true; - } - - public void scoDisconnected() { - Log.w("Bluetooth sco disconnected!"); - isUsingBluetoothAudioRoute = false; - isBluetoothScoConnected = false; - if (mAudioManager != null) { - //why is this for ? - //mAudioManager.setMode(AudioManager.MODE_NORMAL); - mAudioManager.stopBluetoothSco(); - mAudioManager.setBluetoothScoOn(false); - } - } public synchronized static final LinphoneManager createAndStart(Context c, LinphoneServiceListener listener) { if (instance != null) @@ -654,7 +540,7 @@ public class LinphoneManager implements LinphoneCoreListener { updateNetworkReachability(); - startBluetooth(); + BluetoothManager.getInstance().startBluetooth(); resetCameraFromPreferences(); } @@ -741,19 +627,7 @@ public class LinphoneManager implements LinphoneCoreListener { if (LinphoneService.isReady()) // indeed, no need to crash ChatStorage.getInstance().close(); - try { - mServiceContext.unregisterReceiver(bluetoothReiceiver); - } catch (Exception e) {} - - try { - mServiceContext.unregisterReceiver(bluetoothActionReceiver); - } catch (Exception e) {} - - try { - if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) - mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset); - } catch (Exception e) {} - + BluetoothManager.getInstance().destroy(); try { mTimer.cancel(); mLc.destroy(); @@ -994,6 +868,7 @@ public class LinphoneManager implements LinphoneCoreListener { } if (Hacks.needSoftvolume()) { + Log.w("Using soft volume audio hack"); adjustVolume(0); // Synchronize } } @@ -1001,9 +876,9 @@ public class LinphoneManager implements LinphoneCoreListener { if (state == State.CallReleased || state == State.Error) { if (mLc.getCallsNb() == 0) { if (mAudioFocused){ - int res=mAudioManager.abandonAudioFocus(null); + int res = mAudioManager.abandonAudioFocus(null); Log.d("Audio focus released a bit later: " + (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED ? "Granted" : "Denied")); - mAudioFocused=false; + mAudioFocused = false; } Context activity = getContext(); @@ -1027,7 +902,21 @@ public class LinphoneManager implements LinphoneCoreListener { } } } + if (state == State.StreamsRunning) { + if (BluetoothManager.getInstance().isBluetoothHeadsetAvailable()) { + BluetoothManager.getInstance().routeAudioToBluetooth(); + // Hack for Android 4.2.2: we have to retry later, the first call will fail + if (Build.VERSION.SDK_INT == 17) { + mHandler.postDelayed(new Runnable() { + @Override + public void run() { + BluetoothManager.getInstance().routeAudioToBluetooth(); + } + }, 500); + } + } + if (mIncallWakeLock == null) { mIncallWakeLock = mPowerManager.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "incall"); } @@ -1148,7 +1037,10 @@ public class LinphoneManager implements LinphoneCoreListener { isRinging = false; // You may need to call galaxys audio hack after this method - routeAudioToReceiver(); + if (!BluetoothManager.getInstance().isBluetoothHeadsetAvailable()) { + Log.d("Stopped ringing, routing back to earpiece"); + routeAudioToReceiver(); + } } @@ -1360,6 +1252,7 @@ public class LinphoneManager implements LinphoneCoreListener { if (activity != null) { TelephonyManager tm = (TelephonyManager) activity.getSystemService(Context.TELEPHONY_SERVICE); if (state == State.CallEnd && mLc.getCallsNb() == 0 && tm.getCallState() == TelephonyManager.CALL_STATE_IDLE) { + Log.d("All call terminated, routing back to earpiece"); routeAudioToReceiver(); } }