|
@@ -41,8 +41,10 @@ import android.media.AudioDeviceInfo;
|
|
|
import android.media.AudioManager;
|
|
|
import android.os.Build;
|
|
|
import android.util.Log;
|
|
|
+
|
|
|
import com.nextcloud.talk.events.PeerConnectionEvent;
|
|
|
import com.nextcloud.talk.utils.power.PowerManagerUtils;
|
|
|
+
|
|
|
import org.greenrobot.eventbus.EventBus;
|
|
|
import org.webrtc.ThreadUtils;
|
|
|
|
|
@@ -55,45 +57,25 @@ import java.util.Set;
|
|
|
*/
|
|
|
public class MagicAudioManager {
|
|
|
private static final String TAG = "MagicAudioManager";
|
|
|
- private static final String SPEAKERPHONE_AUTO = "auto";
|
|
|
- private static final String SPEAKERPHONE_FALSE = "false";
|
|
|
private final Context magicContext;
|
|
|
- // Handles all tasks related to Bluetooth headset devices.
|
|
|
private final MagicBluetoothManager bluetoothManager;
|
|
|
- // Contains speakerphone setting: auto, true or false
|
|
|
- private String useSpeakerphone;
|
|
|
+ private boolean useProximitySensor;
|
|
|
private AudioManager audioManager;
|
|
|
- private AudioManagerEvents audioManagerEvents;
|
|
|
+ private AudioManagerListener audioManagerListener;
|
|
|
private AudioManagerState amState;
|
|
|
private int savedAudioMode = AudioManager.MODE_INVALID;
|
|
|
private boolean savedIsSpeakerPhoneOn = false;
|
|
|
private boolean savedIsMicrophoneMute = false;
|
|
|
private boolean hasWiredHeadset = false;
|
|
|
- // Default audio device; speaker phone for video calls or earpiece for audio
|
|
|
- // only calls.
|
|
|
- private AudioDevice defaultAudioDevice;
|
|
|
- // Contains the currently selected audio device.
|
|
|
- // This device is changed automatically using a certain scheme where e.g.
|
|
|
- // a wired headset "wins" over speaker phone. It is also possible for a
|
|
|
- // user to explicitly select a device (and overrid any predefined scheme).
|
|
|
- // See |userSelectedAudioDevice| for details.
|
|
|
- private AudioDevice selectedAudioDevice;
|
|
|
- // Contains the user-selected audio device which overrides the predefined
|
|
|
- // selection scheme.
|
|
|
- // TODO(henrika): always set to AudioDevice.NONE today. Add support for
|
|
|
- // explicit selection based on choice by userSelectedAudioDevice.
|
|
|
+
|
|
|
private AudioDevice userSelectedAudioDevice;
|
|
|
- // Proximity sensor object. It measures the proximity of an object in cm
|
|
|
- // relative to the view screen of a device and can therefore be used to
|
|
|
- // assist device switching (close to ear <=> use headset earpiece if
|
|
|
- // available, far from ear <=> use speaker phone).
|
|
|
+ private AudioDevice currentAudioDevice;
|
|
|
+
|
|
|
private MagicProximitySensor proximitySensor = null;
|
|
|
- // Contains a list of available audio devices. A Set collection is used to
|
|
|
- // avoid duplicate elements.
|
|
|
+
|
|
|
private Set<AudioDevice> audioDevices = new HashSet<>();
|
|
|
- // Broadcast receiver for wired headset intent broadcasts.
|
|
|
+
|
|
|
private BroadcastReceiver wiredHeadsetReceiver;
|
|
|
- // Callback method for changes in audio focus.
|
|
|
private AudioManager.OnAudioFocusChangeListener audioFocusChangeListener;
|
|
|
|
|
|
private PowerManagerUtils powerManagerUtils;
|
|
@@ -110,18 +92,8 @@ public class MagicAudioManager {
|
|
|
powerManagerUtils = new PowerManagerUtils();
|
|
|
powerManagerUtils.updatePhoneState(PowerManagerUtils.PhoneState.WITH_PROXIMITY_SENSOR_LOCK);
|
|
|
|
|
|
- if (useProximitySensor) {
|
|
|
- useSpeakerphone = SPEAKERPHONE_AUTO;
|
|
|
- } else {
|
|
|
- useSpeakerphone = SPEAKERPHONE_FALSE;
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- if (useSpeakerphone.equals(SPEAKERPHONE_FALSE)) {
|
|
|
- defaultAudioDevice = AudioDevice.EARPIECE;
|
|
|
- } else {
|
|
|
- defaultAudioDevice = AudioDevice.SPEAKER_PHONE;
|
|
|
- }
|
|
|
+ this.useProximitySensor = useProximitySensor;
|
|
|
+ updateAudioDeviceState();
|
|
|
|
|
|
// Create and initialize the proximity sensor.
|
|
|
// Tablet devices (e.g. Nexus 7) does not support proximity sensors.
|
|
@@ -134,8 +106,6 @@ public class MagicAudioManager {
|
|
|
onProximitySensorChangedState();
|
|
|
}
|
|
|
});
|
|
|
-
|
|
|
- Log.d(TAG, "defaultAudioDevice: " + defaultAudioDevice);
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -145,57 +115,38 @@ public class MagicAudioManager {
|
|
|
return new MagicAudioManager(context, useProximitySensor);
|
|
|
}
|
|
|
|
|
|
- public void toggleUseSpeakerphone() {
|
|
|
- if (useSpeakerphone.equals(SPEAKERPHONE_FALSE)) {
|
|
|
- useSpeakerphone = SPEAKERPHONE_AUTO;
|
|
|
- setDefaultAudioDevice(AudioDevice.SPEAKER_PHONE);
|
|
|
- } else {
|
|
|
- useSpeakerphone = SPEAKERPHONE_FALSE;
|
|
|
- setDefaultAudioDevice(AudioDevice.EARPIECE);
|
|
|
- }
|
|
|
-
|
|
|
- updateAudioDeviceState();
|
|
|
- }
|
|
|
-
|
|
|
- public boolean isSpeakerphoneAutoOn() {
|
|
|
- return (useSpeakerphone.equals(SPEAKERPHONE_AUTO));
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
- * This method is called when the proximity sensor reports a state change,
|
|
|
- * e.g. from "NEAR to FAR" or from "FAR to NEAR".
|
|
|
+ * This method is called when the proximity sensor reports a state change, e.g. from "NEAR to FAR" or from "FAR to
|
|
|
+ * NEAR".
|
|
|
*/
|
|
|
private void onProximitySensorChangedState() {
|
|
|
-
|
|
|
- if (!useSpeakerphone.equals(SPEAKERPHONE_AUTO)) {
|
|
|
+ if (!useProximitySensor) {
|
|
|
return;
|
|
|
}
|
|
|
|
|
|
- // The proximity sensor should only be activated when there are exactly two
|
|
|
- // available audio devices.
|
|
|
- if (audioDevices.size() == 2 && audioDevices.contains(MagicAudioManager.AudioDevice.EARPIECE)
|
|
|
- && audioDevices.contains(MagicAudioManager.AudioDevice.SPEAKER_PHONE)) {
|
|
|
+ if (userSelectedAudioDevice.equals(AudioDevice.SPEAKER_PHONE)
|
|
|
+ && audioDevices.contains(AudioDevice.EARPIECE)
|
|
|
+ && audioDevices.contains(AudioDevice.SPEAKER_PHONE)) {
|
|
|
+
|
|
|
if (proximitySensor.sensorReportsNearState()) {
|
|
|
- // Sensor reports that a "handset is being held up to a person's ear",
|
|
|
- // or "something is covering the light sensor".
|
|
|
- setAudioDeviceInternal(MagicAudioManager.AudioDevice.EARPIECE);
|
|
|
+ setAudioDeviceInternal(AudioDevice.EARPIECE);
|
|
|
+ Log.d(TAG, "switched to EARPIECE because userSelectedAudioDevice was SPEAKER_PHONE and proximity=near");
|
|
|
|
|
|
EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType
|
|
|
- .SENSOR_NEAR, null, null, null, null));
|
|
|
+ .SENSOR_NEAR, null, null, null, null));
|
|
|
|
|
|
} else {
|
|
|
- // Sensor reports that a "handset is removed from a person's ear", or
|
|
|
- // "the light sensor is no longer covered".
|
|
|
setAudioDeviceInternal(MagicAudioManager.AudioDevice.SPEAKER_PHONE);
|
|
|
+ Log.d(TAG, "switched to SPEAKER_PHONE because userSelectedAudioDevice was SPEAKER_PHONE and proximity=far");
|
|
|
|
|
|
EventBus.getDefault().post(new PeerConnectionEvent(PeerConnectionEvent.PeerConnectionEventType
|
|
|
- .SENSOR_FAR, null, null, null, null));
|
|
|
+ .SENSOR_FAR, null, null, null, null));
|
|
|
}
|
|
|
}
|
|
|
}
|
|
|
|
|
|
@SuppressLint("WrongConstant")
|
|
|
- public void start(AudioManagerEvents audioManagerEvents) {
|
|
|
+ public void start(AudioManagerListener audioManagerListener) {
|
|
|
Log.d(TAG, "start");
|
|
|
ThreadUtils.checkIsOnMainThread();
|
|
|
if (amState == AudioManagerState.RUNNING) {
|
|
@@ -205,7 +156,7 @@ public class MagicAudioManager {
|
|
|
// TODO(henrika): perhaps call new method called preInitAudio() here if UNINITIALIZED.
|
|
|
|
|
|
Log.d(TAG, "AudioManager starts...");
|
|
|
- this.audioManagerEvents = audioManagerEvents;
|
|
|
+ this.audioManagerListener = audioManagerListener;
|
|
|
amState = AudioManagerState.RUNNING;
|
|
|
|
|
|
// Store current audio state so we can restore it when stop() is called.
|
|
@@ -257,7 +208,7 @@ public class MagicAudioManager {
|
|
|
|
|
|
// Request audio playout focus (without ducking) and install listener for changes in focus.
|
|
|
int result = audioManager.requestAudioFocus(audioFocusChangeListener,
|
|
|
- AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
|
|
|
+ AudioManager.STREAM_VOICE_CALL, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT);
|
|
|
if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
|
|
|
Log.d(TAG, "Audio focus request granted for VOICE_CALL streams");
|
|
|
} else {
|
|
@@ -274,7 +225,7 @@ public class MagicAudioManager {
|
|
|
|
|
|
// Set initial device states.
|
|
|
userSelectedAudioDevice = AudioDevice.NONE;
|
|
|
- selectedAudioDevice = AudioDevice.NONE;
|
|
|
+ currentAudioDevice = AudioDevice.NONE;
|
|
|
audioDevices.clear();
|
|
|
|
|
|
// Initialize and start Bluetooth if a BT device is available or initiate
|
|
@@ -324,7 +275,7 @@ public class MagicAudioManager {
|
|
|
|
|
|
powerManagerUtils.updatePhoneState(PowerManagerUtils.PhoneState.IDLE);
|
|
|
|
|
|
- audioManagerEvents = null;
|
|
|
+ audioManagerListener = null;
|
|
|
Log.d(TAG, "AudioManager stopped");
|
|
|
}
|
|
|
|
|
@@ -333,21 +284,16 @@ public class MagicAudioManager {
|
|
|
/**
|
|
|
* Changes selection of the currently active audio device.
|
|
|
*/
|
|
|
- private void setAudioDeviceInternal(AudioDevice device) {
|
|
|
- Log.d(TAG, "setAudioDeviceInternal(device=" + device + ")");
|
|
|
-
|
|
|
- if (audioDevices.contains(device)) {
|
|
|
+ private void setAudioDeviceInternal(AudioDevice audioDevice) {
|
|
|
+ Log.d(TAG, "setAudioDeviceInternal(device=" + audioDevice + ")");
|
|
|
|
|
|
- switch (device) {
|
|
|
+ if (audioDevices.contains(audioDevice)) {
|
|
|
+ switch (audioDevice) {
|
|
|
case SPEAKER_PHONE:
|
|
|
setSpeakerphoneOn(true);
|
|
|
break;
|
|
|
case EARPIECE:
|
|
|
- setSpeakerphoneOn(false);
|
|
|
- break;
|
|
|
case WIRED_HEADSET:
|
|
|
- setSpeakerphoneOn(false);
|
|
|
- break;
|
|
|
case BLUETOOTH:
|
|
|
setSpeakerphoneOn(false);
|
|
|
break;
|
|
@@ -355,33 +301,8 @@ public class MagicAudioManager {
|
|
|
Log.e(TAG, "Invalid audio device selection");
|
|
|
break;
|
|
|
}
|
|
|
- selectedAudioDevice = device;
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- /**
|
|
|
- * Changes default audio device.
|
|
|
- * TODO(henrika): add usage of this method in the AppRTCMobile client.
|
|
|
- */
|
|
|
- public void setDefaultAudioDevice(AudioDevice defaultDevice) {
|
|
|
- ThreadUtils.checkIsOnMainThread();
|
|
|
- switch (defaultDevice) {
|
|
|
- case SPEAKER_PHONE:
|
|
|
- defaultAudioDevice = defaultDevice;
|
|
|
- break;
|
|
|
- case EARPIECE:
|
|
|
- if (hasEarpiece()) {
|
|
|
- defaultAudioDevice = defaultDevice;
|
|
|
- } else {
|
|
|
- defaultAudioDevice = AudioDevice.SPEAKER_PHONE;
|
|
|
- }
|
|
|
- break;
|
|
|
- default:
|
|
|
- Log.e(TAG, "Invalid default audio device selection");
|
|
|
- break;
|
|
|
+ currentAudioDevice = audioDevice;
|
|
|
}
|
|
|
- Log.d(TAG, "setDefaultAudioDevice(device=" + defaultAudioDevice + ")");
|
|
|
- updateAudioDeviceState();
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -407,9 +328,9 @@ public class MagicAudioManager {
|
|
|
/**
|
|
|
* Returns the currently selected audio device.
|
|
|
*/
|
|
|
- public AudioDevice getSelectedAudioDevice() {
|
|
|
+ public AudioDevice getCurrentAudioDevice() {
|
|
|
ThreadUtils.checkIsOnMainThread();
|
|
|
- return selectedAudioDevice;
|
|
|
+ return currentAudioDevice;
|
|
|
}
|
|
|
|
|
|
/**
|
|
@@ -456,11 +377,9 @@ public class MagicAudioManager {
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Checks whether a wired headset is connected or not.
|
|
|
- * This is not a valid indication that audio playback is actually over
|
|
|
- * the wired headset as audio routing depends on other conditions. We
|
|
|
- * only use it as an early indicator (during initialization) of an attached
|
|
|
- * wired headset.
|
|
|
+ * Checks whether a wired headset is connected or not. This is not a valid indication that audio playback is
|
|
|
+ * actually over the wired headset as audio routing depends on other conditions. We only use it as an early
|
|
|
+ * indicator (during initialization) of an attached wired headset.
|
|
|
*/
|
|
|
@Deprecated
|
|
|
private boolean hasWiredHeadset() {
|
|
@@ -482,35 +401,27 @@ public class MagicAudioManager {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * Updates list of possible audio devices and make new device selection.
|
|
|
- * TODO(henrika): add unit test to verify all state transitions.
|
|
|
- */
|
|
|
public void updateAudioDeviceState() {
|
|
|
ThreadUtils.checkIsOnMainThread();
|
|
|
Log.d(TAG, "--- updateAudioDeviceState: "
|
|
|
- + "wired headset=" + hasWiredHeadset + ", "
|
|
|
- + "BT state=" + bluetoothManager.getState());
|
|
|
+ + "wired headset=" + hasWiredHeadset + ", "
|
|
|
+ + "BT state=" + bluetoothManager.getState());
|
|
|
Log.d(TAG, "Device status: "
|
|
|
- + "available=" + audioDevices + ", "
|
|
|
- + "selected=" + selectedAudioDevice + ", "
|
|
|
- + "user selected=" + userSelectedAudioDevice);
|
|
|
+ + "available=" + audioDevices + ", "
|
|
|
+ + "current=" + currentAudioDevice + ", "
|
|
|
+ + "user selected=" + userSelectedAudioDevice);
|
|
|
|
|
|
- // Check if any Bluetooth headset is connected. The internal BT state will
|
|
|
- // change accordingly.
|
|
|
- // TODO(henrika): perhaps wrap required state into BT manager.
|
|
|
if (bluetoothManager.getState() == MagicBluetoothManager.State.HEADSET_AVAILABLE
|
|
|
- || bluetoothManager.getState() == MagicBluetoothManager.State.HEADSET_UNAVAILABLE
|
|
|
- || bluetoothManager.getState() == MagicBluetoothManager.State.SCO_DISCONNECTING) {
|
|
|
+ || bluetoothManager.getState() == MagicBluetoothManager.State.HEADSET_UNAVAILABLE
|
|
|
+ || bluetoothManager.getState() == MagicBluetoothManager.State.SCO_DISCONNECTING) {
|
|
|
bluetoothManager.updateDevice();
|
|
|
}
|
|
|
|
|
|
- // Update the set of available audio devices.
|
|
|
Set<AudioDevice> newAudioDevices = new HashSet<>();
|
|
|
|
|
|
if (bluetoothManager.getState() == MagicBluetoothManager.State.SCO_CONNECTED
|
|
|
- || bluetoothManager.getState() == MagicBluetoothManager.State.SCO_CONNECTING
|
|
|
- || bluetoothManager.getState() == MagicBluetoothManager.State.HEADSET_AVAILABLE) {
|
|
|
+ || bluetoothManager.getState() == MagicBluetoothManager.State.SCO_CONNECTING
|
|
|
+ || bluetoothManager.getState() == MagicBluetoothManager.State.HEADSET_AVAILABLE) {
|
|
|
newAudioDevices.add(AudioDevice.BLUETOOTH);
|
|
|
}
|
|
|
|
|
@@ -518,55 +429,50 @@ public class MagicAudioManager {
|
|
|
// If a wired headset is connected, then it is the only possible option.
|
|
|
newAudioDevices.add(AudioDevice.WIRED_HEADSET);
|
|
|
} else {
|
|
|
- // No wired headset, hence the audio-device list can contain speaker
|
|
|
- // phone (on a tablet), or speaker phone and earpiece (on mobile phone).
|
|
|
newAudioDevices.add(AudioDevice.SPEAKER_PHONE);
|
|
|
if (hasEarpiece()) {
|
|
|
newAudioDevices.add(AudioDevice.EARPIECE);
|
|
|
}
|
|
|
}
|
|
|
- // Store state which is set to true if the device list has changed.
|
|
|
+
|
|
|
boolean audioDeviceSetUpdated = !audioDevices.equals(newAudioDevices);
|
|
|
- // Update the existing audio device set.
|
|
|
audioDevices = newAudioDevices;
|
|
|
+
|
|
|
+
|
|
|
// Correct user selected audio devices if needed.
|
|
|
- if (bluetoothManager.getState() == MagicBluetoothManager.State.HEADSET_UNAVAILABLE
|
|
|
- && userSelectedAudioDevice == AudioDevice.BLUETOOTH) {
|
|
|
- // If BT is not available, it can't be the user selection.
|
|
|
- userSelectedAudioDevice = AudioDevice.NONE;
|
|
|
+ if (userSelectedAudioDevice == AudioDevice.BLUETOOTH
|
|
|
+ && bluetoothManager.getState() == MagicBluetoothManager.State.HEADSET_UNAVAILABLE) {
|
|
|
+ userSelectedAudioDevice = AudioDevice.SPEAKER_PHONE;
|
|
|
}
|
|
|
- if (hasWiredHeadset && userSelectedAudioDevice == AudioDevice.SPEAKER_PHONE) {
|
|
|
- // If user selected speaker phone, but then plugged wired headset then make
|
|
|
- // wired headset as user selected device.
|
|
|
+ if (userSelectedAudioDevice == AudioDevice.SPEAKER_PHONE && hasWiredHeadset) {
|
|
|
userSelectedAudioDevice = AudioDevice.WIRED_HEADSET;
|
|
|
}
|
|
|
- if (!hasWiredHeadset && userSelectedAudioDevice == AudioDevice.WIRED_HEADSET) {
|
|
|
- // If user selected wired headset, but then unplugged wired headset then make
|
|
|
- // speaker phone as user selected device.
|
|
|
+ if (userSelectedAudioDevice == AudioDevice.WIRED_HEADSET && !hasWiredHeadset) {
|
|
|
userSelectedAudioDevice = AudioDevice.SPEAKER_PHONE;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
// Need to start Bluetooth if it is available and user either selected it explicitly or
|
|
|
// user did not select any output device.
|
|
|
boolean needBluetoothAudioStart =
|
|
|
- bluetoothManager.getState() == MagicBluetoothManager.State.HEADSET_AVAILABLE
|
|
|
- && (userSelectedAudioDevice == AudioDevice.NONE
|
|
|
- || userSelectedAudioDevice == AudioDevice.BLUETOOTH);
|
|
|
+ bluetoothManager.getState() == MagicBluetoothManager.State.HEADSET_AVAILABLE
|
|
|
+ && (userSelectedAudioDevice == AudioDevice.NONE
|
|
|
+ || userSelectedAudioDevice == AudioDevice.BLUETOOTH);
|
|
|
|
|
|
// Need to stop Bluetooth audio if user selected different device and
|
|
|
// Bluetooth SCO connection is established or in the process.
|
|
|
boolean needBluetoothAudioStop =
|
|
|
- (bluetoothManager.getState() == MagicBluetoothManager.State.SCO_CONNECTED
|
|
|
- || bluetoothManager.getState() == MagicBluetoothManager.State.SCO_CONNECTING)
|
|
|
- && (userSelectedAudioDevice != AudioDevice.NONE
|
|
|
- && userSelectedAudioDevice != AudioDevice.BLUETOOTH);
|
|
|
+ (bluetoothManager.getState() == MagicBluetoothManager.State.SCO_CONNECTED
|
|
|
+ || bluetoothManager.getState() == MagicBluetoothManager.State.SCO_CONNECTING)
|
|
|
+ && (userSelectedAudioDevice != AudioDevice.NONE
|
|
|
+ && userSelectedAudioDevice != AudioDevice.BLUETOOTH);
|
|
|
|
|
|
if (bluetoothManager.getState() == MagicBluetoothManager.State.HEADSET_AVAILABLE
|
|
|
- || bluetoothManager.getState() == MagicBluetoothManager.State.SCO_CONNECTING
|
|
|
- || bluetoothManager.getState() == MagicBluetoothManager.State.SCO_CONNECTED) {
|
|
|
+ || bluetoothManager.getState() == MagicBluetoothManager.State.SCO_CONNECTING
|
|
|
+ || bluetoothManager.getState() == MagicBluetoothManager.State.SCO_CONNECTED) {
|
|
|
Log.d(TAG, "Need BT audio: start=" + needBluetoothAudioStart + ", "
|
|
|
- + "stop=" + needBluetoothAudioStop + ", "
|
|
|
- + "BT state=" + bluetoothManager.getState());
|
|
|
+ + "stop=" + needBluetoothAudioStop + ", "
|
|
|
+ + "BT state=" + bluetoothManager.getState());
|
|
|
}
|
|
|
|
|
|
// Start or stop Bluetooth SCO connection given states set earlier.
|
|
@@ -577,8 +483,8 @@ public class MagicAudioManager {
|
|
|
|
|
|
// Attempt to start Bluetooth SCO audio (takes a few second to start).
|
|
|
if (needBluetoothAudioStart &&
|
|
|
- !needBluetoothAudioStop &&
|
|
|
- !bluetoothManager.startScoAudio()) {
|
|
|
+ !needBluetoothAudioStop &&
|
|
|
+ !bluetoothManager.startScoAudio()) {
|
|
|
// Remove BLUETOOTH from list of available devices since SCO failed.
|
|
|
audioDevices.remove(AudioDevice.BLUETOOTH);
|
|
|
audioDeviceSetUpdated = true;
|
|
@@ -586,42 +492,41 @@ public class MagicAudioManager {
|
|
|
|
|
|
|
|
|
// Update selected audio device.
|
|
|
- AudioDevice newAudioDevice = selectedAudioDevice;
|
|
|
+ AudioDevice newCurrentAudioDevice;
|
|
|
|
|
|
if (bluetoothManager.getState() == MagicBluetoothManager.State.SCO_CONNECTED) {
|
|
|
// If a Bluetooth is connected, then it should be used as output audio
|
|
|
// device. Note that it is not sufficient that a headset is available;
|
|
|
// an active SCO channel must also be up and running.
|
|
|
- newAudioDevice = AudioDevice.BLUETOOTH;
|
|
|
+ newCurrentAudioDevice = AudioDevice.BLUETOOTH;
|
|
|
} else if (hasWiredHeadset) {
|
|
|
// If a wired headset is connected, but Bluetooth is not, then wired headset is used as
|
|
|
// audio device.
|
|
|
- newAudioDevice = AudioDevice.WIRED_HEADSET;
|
|
|
+ newCurrentAudioDevice = AudioDevice.WIRED_HEADSET;
|
|
|
} else {
|
|
|
// No wired headset and no Bluetooth, hence the audio-device list can contain speaker
|
|
|
// phone (on a tablet), or speaker phone and earpiece (on mobile phone).
|
|
|
// |defaultAudioDevice| contains either AudioDevice.SPEAKER_PHONE or AudioDevice.EARPIECE
|
|
|
// depending on the user's selection.
|
|
|
- newAudioDevice = defaultAudioDevice;
|
|
|
+ newCurrentAudioDevice = userSelectedAudioDevice;
|
|
|
}
|
|
|
// Switch to new device but only if there has been any changes.
|
|
|
- if (newAudioDevice != selectedAudioDevice || audioDeviceSetUpdated) {
|
|
|
+ if (newCurrentAudioDevice != currentAudioDevice || audioDeviceSetUpdated) {
|
|
|
// Do the required device switch.
|
|
|
- setAudioDeviceInternal(newAudioDevice);
|
|
|
+ setAudioDeviceInternal(newCurrentAudioDevice);
|
|
|
Log.d(TAG, "New device status: "
|
|
|
- + "available=" + audioDevices + ", "
|
|
|
- + "selected=" + newAudioDevice);
|
|
|
- if (audioManagerEvents != null) {
|
|
|
+ + "available=" + audioDevices + ", "
|
|
|
+ + "current(new)=" + newCurrentAudioDevice);
|
|
|
+ if (audioManagerListener != null) {
|
|
|
// Notify a listening client that audio device has been changed.
|
|
|
- audioManagerEvents.onAudioDeviceChanged(selectedAudioDevice, audioDevices);
|
|
|
+ audioManagerListener.onAudioDeviceChanged(currentAudioDevice, audioDevices);
|
|
|
}
|
|
|
}
|
|
|
Log.d(TAG, "--- updateAudioDeviceState done");
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * AudioDevice is the names of possible audio devices that we currently
|
|
|
- * support.
|
|
|
+ * AudioDevice is the names of possible audio devices that we currently support.
|
|
|
*/
|
|
|
public enum AudioDevice {
|
|
|
SPEAKER_PHONE, WIRED_HEADSET, EARPIECE, BLUETOOTH, NONE
|
|
@@ -639,10 +544,10 @@ public class MagicAudioManager {
|
|
|
/**
|
|
|
* Selected audio device change event.
|
|
|
*/
|
|
|
- public static interface AudioManagerEvents {
|
|
|
+ public static interface AudioManagerListener {
|
|
|
// Callback fired once audio device is changed or list of available audio devices changed.
|
|
|
void onAudioDeviceChanged(
|
|
|
- AudioDevice selectedAudioDevice, Set<AudioDevice> availableAudioDevices);
|
|
|
+ AudioDevice selectedAudioDevice, Set<AudioDevice> availableAudioDevices);
|
|
|
}
|
|
|
|
|
|
/* Receiver which handles changes in wired headset availability. */
|