diff --git a/AndroidManifest.xml b/AndroidManifest.xml
index c6e3ea500..65f00d0da 100644
--- a/AndroidManifest.xml
+++ b/AndroidManifest.xml
@@ -120,11 +120,6 @@
-
-
-
-
-
@@ -134,8 +129,10 @@
+
+
diff --git a/src/org/linphone/BluetoothActionReceiver.java b/src/org/linphone/BluetoothActionReceiver.java
deleted file mode 100644
index c8a141fef..000000000
--- a/src/org/linphone/BluetoothActionReceiver.java
+++ /dev/null
@@ -1,54 +0,0 @@
-package org.linphone;
-
-/*
-BluetoothActionReceiver.java
-Copyright (C) 2014 Belledonne Communications, Grenoble, France
-
-This program is free software; you can redistribute it and/or
-modify it under the terms of the GNU General Public License
-as published by the Free Software Foundation; either version 2
-of the License, or (at your option) any later version.
-
-This program is distributed in the hope that it will be useful,
-but WITHOUT ANY WARRANTY; without even the implied warranty of
-MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-GNU General Public License for more details.
-
-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 org.linphone.mediastream.Log;
-
-import android.annotation.TargetApi;
-import android.bluetooth.BluetoothDevice;
-import android.bluetooth.BluetoothHeadset;
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.os.Build;
-
-@TargetApi(Build.VERSION_CODES.HONEYCOMB)
-public class BluetoothActionReceiver extends BroadcastReceiver {
- @Override
- public void onReceive(Context context, Intent intent) {
- if (intent.getAction().equals(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT)) {
- BluetoothDevice device = (BluetoothDevice) intent.getExtras().get(BluetoothDevice.EXTRA_DEVICE);
- String command = intent.getExtras().getString(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD);
- int type = intent.getExtras().getInt(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE);
-
- Object[] temp = (Object[]) intent.getExtras().get(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS);
- String[] args = new String[temp.length];
- String logArgs = "";
- for (int i = 0; i < temp.length; i++) {
- args[i] = (String) temp[i];
- logArgs += args[i] + " ";
- }
-
- Log.d("Bluetooth headset event from " + device.getName() + ", command: " + command + " (type: " + type + ") with args: " + logArgs);
-
- //TODO: parse command/args and do something with it
- }
- }
-}
diff --git a/src/org/linphone/BluetoothManager.java b/src/org/linphone/BluetoothManager.java
index 19737fb3c..5186b0e82 100644
--- a/src/org/linphone/BluetoothManager.java
+++ b/src/org/linphone/BluetoothManager.java
@@ -20,12 +20,12 @@ 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.BluetoothAssignedNumbers;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothHeadset;
import android.bluetooth.BluetoothProfile;
@@ -49,9 +49,7 @@ public class BluetoothManager extends BroadcastReceiver {
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) {
@@ -60,17 +58,11 @@ public class BluetoothManager extends BroadcastReceiver {
return instance;
}
- /**
- * Do not call !
- */
- public BluetoothManager() {
+ private BluetoothManager() {
isBluetoothConnected = false;
- isUsingBluetoothAudioRoute = false;
- try {
- mContext = LinphoneManager.getInstance().getContext();
- mAudioManager = ((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE));
- instance = this;
- } catch (Exception e) {}
+ mContext = LinphoneManager.getInstance().getContext();
+ mAudioManager = ((AudioManager) mContext.getSystemService(Context.AUDIO_SERVICE));
+ instance = this;
}
public void startBluetooth() {
@@ -80,9 +72,9 @@ public class BluetoothManager extends BroadcastReceiver {
}
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");
+ filter.addCategory(BluetoothHeadset.VENDOR_SPECIFIC_HEADSET_EVENT_COMPANY_ID_CATEGORY + "." + BluetoothAssignedNumbers.PLANTRONICS);
+ filter.addAction("android.media.ACTION_SCO_AUDIO_STATE_UPDATED");
+ filter.addAction(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT);
mContext.registerReceiver(this, filter);
Log.d("Bluetooth receiver started");
@@ -99,14 +91,12 @@ public class BluetoothManager extends BroadcastReceiver {
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");
@@ -134,27 +124,22 @@ public class BluetoothManager extends BroadcastReceiver {
}
if (mBluetoothAdapter.isEnabled() && mAudioManager.isBluetoothScoAvailableOffCall()) {
- isUsingBluetoothAudioRoute = isBluetoothHeadsetAvailable();
-
- if (isUsingBluetoothAudioRoute) {
- if (mAudioManager != null) {
+ if (isBluetoothHeadsetAvailable()) {
+ if (mAudioManager != null && !mAudioManager.isBluetoothScoOn()) {
mAudioManager.setBluetoothScoOn(true);
mAudioManager.startBluetoothSco();
- LinphoneManager.getInstance().audioStateChanged(AudioState.BLUETOOTH);
}
- } else {
- LinphoneManager.getInstance().audioStateChanged(AudioState.SPEAKER);
}
- isUsingBluetoothAudioRoute = mBluetoothHeadset.isAudioConnected(mBluetoothDevice);
- if (!isUsingBluetoothAudioRoute && !isRetry) {
+ boolean ok = mBluetoothHeadset != null && mBluetoothHeadset.isAudioConnected(mBluetoothDevice);
+ if (!ok && !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) {
+ if (ok) {
Log.d("Retry worked, audio is routed to bluetooth headset");
} else {
Log.e("Retry not worked, audio isn't routed to bluetooth headset...");
@@ -164,14 +149,14 @@ public class BluetoothManager extends BroadcastReceiver {
Log.d("Routing audio to bluetooth headset worked at first try");
}
- return isUsingBluetoothAudioRoute;
+ return ok;
}
return false;
}
public boolean isUsingBluetoothAudioRoute() {
- return mBluetoothHeadset.isAudioConnected(mBluetoothDevice);
+ return mBluetoothHeadset != null && mBluetoothHeadset.isAudioConnected(mBluetoothDevice);
}
public boolean isBluetoothHeadsetAvailable() {
@@ -183,7 +168,8 @@ public class BluetoothManager extends BroadcastReceiver {
if (Version.sdkAboveOrEqual(Version.API11_HONEYCOMB_30)) {
boolean isHeadsetConnected = false;
if (mBluetoothHeadset != null) {
- List devices = mBluetoothHeadset.getConnectedDevices();
+ List devices = mBluetoothHeadset.getConnectedDevices();
+ mBluetoothDevice = null;
for (final BluetoothDevice dev : devices) {
if (mBluetoothHeadset.getConnectionState(dev) == BluetoothHeadset.STATE_CONNECTED) {
mBluetoothDevice = dev;
@@ -201,8 +187,10 @@ public class BluetoothManager extends BroadcastReceiver {
}
public void disableBluetoothSCO() {
- isUsingBluetoothAudioRoute = false;
- if (mAudioManager != null) {
+ if (mAudioManager != null && mAudioManager.isBluetoothScoOn()) {
+ mAudioManager.stopBluetoothSco();
+ mAudioManager.setBluetoothScoOn(false);
+ Log.w("Hack: stopping bluetooth sco again since first time won't have succedded");
mAudioManager.stopBluetoothSco();
mAudioManager.setBluetoothScoOn(false);
Log.w("Bluetooth sco disconnected!");
@@ -212,28 +200,17 @@ public class BluetoothManager extends BroadcastReceiver {
public void stopBluetooth() {
Log.w("Stopping bluetooth...");
isBluetoothConnected = false;
- isUsingBluetoothAudioRoute = false;
- if (mAudioManager != null) {
- mAudioManager.stopBluetoothSco();
- mAudioManager.setBluetoothScoOn(false);
- }
+ disableBluetoothSCO();
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");
@@ -252,38 +229,42 @@ public class BluetoothManager extends BroadcastReceiver {
}
}
- @SuppressWarnings("deprecation")
public void onReceive(Context context, Intent intent) {
if (!LinphoneManager.isInstanciated())
return;
String action = intent.getAction();
- if (BluetoothDevice.ACTION_ACL_DISCONNECTED.equals(action)) {
- Log.d("Bluetooth Received Event" + " ACTION_ACL_DISCONNECTED");
-
- stopBluetooth();
- }
- else if (BluetoothDevice.ACTION_ACL_CONNECTED.equals(action)) {
- Log.d("Bluetooth Received Event" + " ACTION_ACL_CONNECTED");
- startBluetooth();
- }
- else if (AudioManager.ACTION_SCO_AUDIO_STATE_CHANGED.equals(action)) {
+ //Using real value instead of constant because not available before sdk 11
+ if ("android.media.ACTION_SCO_AUDIO_STATE_UPDATED".equals(action)) { // AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED
int state = intent.getIntExtra(AudioManager.EXTRA_SCO_AUDIO_STATE, 0);
- Log.d("Bluetooth sco state changed : " + state);
- if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
- startBluetooth();
+ if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) {
+ Log.d("Bluetooth sco state updated to connected");
+ LinphoneManager.getInstance().audioStateChanged(AudioState.BLUETOOTH);
+ //isUsingBluetoothAudioRoute = true;
} else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) {
- stopBluetooth();
+ Log.d("Bluetooth sco state updated to disconnected");
+ LinphoneManager.getInstance().audioStateChanged(AudioState.SPEAKER);
+ //isUsingBluetoothAudioRoute = false;
}
}
- //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
+ int state = intent.getIntExtra("android.bluetooth.adapter.extra.CONNECTION_STATE", //BluetoothAdapter.EXTRA_CONNECTION_STATE
0); //BluetoothAdapter.STATE_DISCONNECTED
- Log.d("Bluetooth state changed: " + currentConnState);
- if (currentConnState == 2) { //BluetoothAdapter.STATE_CONNECTED
- startBluetooth();
- }
- }
+ if (state == 0) {
+ Log.d("Bluetooth state updated to disconnected");
+ } else if (state == 2) {
+ Log.d("Bluetooth state updated to connected");
+ }
+ }
+ else if (intent.getAction().equals(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT)) {
+ String command = intent.getExtras().getString(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD);
+ int type = intent.getExtras().getInt(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE);
+
+ Object[] args = (Object[]) intent.getExtras().get(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_ARGS);
+ String eventName = (String) args[0];
+ Log.d("Bluetooth event: " + command + " (type: " + type + ") = " + eventName);
+
+ //TODO: parse command/args and do something with it
+ }
}
}
diff --git a/src/org/linphone/LinphoneManager.java b/src/org/linphone/LinphoneManager.java
index 9ede82a2a..6c5f4dd86 100644
--- a/src/org/linphone/LinphoneManager.java
+++ b/src/org/linphone/LinphoneManager.java
@@ -885,8 +885,10 @@ public class LinphoneManager implements LinphoneCoreListener {
if (activity != null) {
TelephonyManager tm = (TelephonyManager) activity.getSystemService(Context.TELEPHONY_SERVICE);
if (tm.getCallState() == TelephonyManager.CALL_STATE_IDLE) {
- mAudioManager.setMode(AudioManager.MODE_NORMAL);
Log.d("---AudioManager: back to MODE_NORMAL");
+ mAudioManager.setMode(AudioManager.MODE_NORMAL);
+ Log.d("All call terminated, routing back to earpiece");
+ routeAudioToReceiver();
}
}
}
@@ -1248,15 +1250,6 @@ public class LinphoneManager implements LinphoneCoreListener {
enableCamera(call, sendCamera);
}
- Context activity = getContext();
- 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();
- }
- }
-
if (serviceListener != null) serviceListener.onCallStateChanged(call, state, message);
for (LinphoneOnCallStateChangedListener l : getSimpleListeners(LinphoneOnCallStateChangedListener.class)) {
l.onCallStateChanged(call, state, message);