Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(9)

Unified Diff: webrtc/examples/androidapp/src/org/appspot/apprtc/AppRTCAudioManager.java

Issue 2501983002: Adds basic Bluetooth support to AppRTCMobile (Closed)
Patch Set: Cleaned up AppRTCBluetoothManager.java Created 4 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: webrtc/examples/androidapp/src/org/appspot/apprtc/AppRTCAudioManager.java
diff --git a/webrtc/examples/androidapp/src/org/appspot/apprtc/AppRTCAudioManager.java b/webrtc/examples/androidapp/src/org/appspot/apprtc/AppRTCAudioManager.java
index 6e66b08395ca78e26a72887ce831ab6c4cf232d3..4bb6639850acab39e989095efa6ea04fc4f7a487 100644
--- a/webrtc/examples/androidapp/src/org/appspot/apprtc/AppRTCAudioManager.java
+++ b/webrtc/examples/androidapp/src/org/appspot/apprtc/AppRTCAudioManager.java
@@ -16,57 +16,72 @@ import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
-import android.content.SharedPreferences;
import android.content.pm.PackageManager;
magjed_webrtc 2016/12/07 11:09:43 Revert this change, it's not sorted now.
henrika_webrtc 2016/12/07 12:55:41 I might be slow but what's wrong? Can't see that a
+import android.content.SharedPreferences;
import android.media.AudioManager;
import android.preference.PreferenceManager;
import android.util.Log;
+import org.webrtc.ThreadUtils;
+
import java.util.Collections;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
-/**
- * AppRTCAudioManager manages all audio related parts of the AppRTC demo.
- */
+// AppRTCAudioManager manages all audio related parts of the AppRTC demo.
magjed_webrtc 2016/12/07 11:09:43 Revert these comment changes.
henrika_webrtc 2016/12/07 12:55:41 Done.
public class AppRTCAudioManager {
private static final String TAG = "AppRTCAudioManager";
private static final String SPEAKERPHONE_AUTO = "auto";
private static final String SPEAKERPHONE_TRUE = "true";
private static final String SPEAKERPHONE_FALSE = "false";
- /**
- * AudioDevice is the names of possible audio devices that we currently
- * support.
- */
- // TODO(henrika): add support for BLUETOOTH as well.
- public enum AudioDevice {
- SPEAKER_PHONE,
- WIRED_HEADSET,
- EARPIECE,
+ // AudioDevice is the names of possible audio devices that we currently
magjed_webrtc 2016/12/07 11:09:43 Revert this comment change as well. Same for the r
henrika_webrtc 2016/12/07 12:55:42 Done.
+ // support.
+ public enum AudioDevice { SPEAKER_PHONE, WIRED_HEADSET, EARPIECE, BLUETOOTH, NONE }
+
+ // AudioManager state.
+ public enum AudioManagerState {
+ UNINITIALIZED,
+ PREINITIALIZED,
+ RUNNING,
+ }
+
+ // Selected audio device change event.
+ public static interface AudioManagerEvents {
+ // Callback fired once audio device is changed or list of available audio devices changed.
+ void onAudioDeviceChanged(
+ AudioDevice selectedAudioDevice, Set<AudioDevice> availableAudioDevices);
}
+ private final ThreadUtils.ThreadChecker threadChecker = new ThreadUtils.ThreadChecker();
+
private final Context apprtcContext;
- private final Runnable onStateChangeListener;
- private boolean initialized = false;
private AudioManager audioManager;
+
+ private AudioManagerEvents audioManagerEvents;
+ private AudioManagerState amState;
private int savedAudioMode = AudioManager.MODE_INVALID;
private boolean savedIsSpeakerPhoneOn = false;
private boolean savedIsMicrophoneMute = false;
+ private boolean hasWiredHeadset = false;
- private final AudioDevice defaultAudioDevice;
+ // Default audio device; speaker phone for video calls or earpiece for audio
+ // only calls.
+ private AudioDevice defaultAudioDevice;
+
+ // Contains the currently selected audio device.
+ private AudioDevice selectedAudioDevice;
+
+ // Contains user selected audio device.
+ // TODO(henrika): always set to AudioDevice.NONE today. Add support for
+ // explicit selection based on choice by userSelectedAudioDevice.
+ private AudioDevice userSelectedAudioDevice;
// Contains speakerphone setting: auto, true or false
private final String useSpeakerphone;
- // Proximity sensor object. It measures the proximity of an object in cm
magjed_webrtc 2016/12/07 11:09:43 I'm sorry to have to give more annoying comments,
henrika_webrtc 2016/12/07 12:55:41 Will fix of course ;-)
- // 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 AppRTCProximitySensor proximitySensor = null;
-
- // Contains the currently selected audio device.
- private AudioDevice selectedAudioDevice;
+ private final AppRTCBluetoothManager bluetoothManager;
// Contains a list of available audio devices. A Set collection is used to
// avoid duplicate elements.
@@ -78,73 +93,71 @@ public class AppRTCAudioManager {
// Callback method for changes in audio focus.
private AudioManager.OnAudioFocusChangeListener audioFocusChangeListener;
- // 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)) {
- return;
+ // Receiver which handles changes in wired headset availability.
+ private class WiredHeadsetReceiver extends BroadcastReceiver {
+ private static final int STATE_UNPLUGGED = 0;
+ private static final int STATE_PLUGGED = 1;
+ private static final int HAS_NO_MIC = 0;
+ private static final int HAS_MIC = 1;
+
+ @Override
+ public void onReceive(Context context, Intent intent) {
+ int state = intent.getIntExtra("state", STATE_UNPLUGGED);
+ int microphone = intent.getIntExtra("microphone", HAS_NO_MIC);
+ String name = intent.getStringExtra("name");
+ Log.d(TAG, "WiredHeadsetReceiver.onReceive" + AppRTCUtils.getThreadInfo() + ": "
+ + "a=" + intent.getAction() + ", s="
+ + (state == STATE_UNPLUGGED ? "unplugged" : "plugged") + ", m="
+ + (microphone == HAS_MIC ? "mic" : "no mic") + ", n=" + name + ", sb="
+ + isInitialStickyBroadcast());
+ hasWiredHeadset = (state == STATE_PLUGGED);
+ updateAudioDeviceState();
}
+ };
- // The proximity sensor should only be activated when there are exactly two
- // available audio devices.
- if (audioDevices.size() == 2 && audioDevices.contains(AppRTCAudioManager.AudioDevice.EARPIECE)
- && audioDevices.contains(AppRTCAudioManager.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".
- setAudioDevice(AppRTCAudioManager.AudioDevice.EARPIECE);
- } else {
- // Sensor reports that a "handset is removed from a person's ear", or
- // "the light sensor is no longer covered".
- setAudioDevice(AppRTCAudioManager.AudioDevice.SPEAKER_PHONE);
- }
- }
- }
-
- /** Construction */
- static AppRTCAudioManager create(Context context, Runnable deviceStateChangeListener) {
- return new AppRTCAudioManager(context, deviceStateChangeListener);
+ // Construction.
+ static AppRTCAudioManager create(Context context) {
+ return new AppRTCAudioManager(context);
}
- private AppRTCAudioManager(Context context, Runnable deviceStateChangeListener) {
+ private AppRTCAudioManager(Context context) {
+ Log.d(TAG, "ctor");
apprtcContext = context;
- onStateChangeListener = deviceStateChangeListener;
audioManager = ((AudioManager) context.getSystemService(Context.AUDIO_SERVICE));
+ bluetoothManager = AppRTCBluetoothManager.create(context, this);
+ wiredHeadsetReceiver = new WiredHeadsetReceiver();
+ amState = AudioManagerState.UNINITIALIZED;
SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(context);
useSpeakerphone = sharedPreferences.getString(context.getString(R.string.pref_speakerphone_key),
context.getString(R.string.pref_speakerphone_default));
-
+ Log.d(TAG, "useSpeakerphone: " + useSpeakerphone);
if (useSpeakerphone.equals(SPEAKERPHONE_FALSE)) {
defaultAudioDevice = AudioDevice.EARPIECE;
} else {
defaultAudioDevice = AudioDevice.SPEAKER_PHONE;
}
-
- // Create and initialize the proximity sensor.
- // Tablet devices (e.g. Nexus 7) does not support proximity sensors.
- // Note that, the sensor will not be active until start() has been called.
- proximitySensor = AppRTCProximitySensor.create(context, new Runnable() {
- // This method will be called each time a state change is detected.
- // Example: user holds his hand over the device (closer than ~5 cm),
- // or removes his hand from the device.
- public void run() {
- onProximitySensorChangedState();
- }
- });
+ Log.d(TAG, "defaultAudioDevice: " + defaultAudioDevice);
AppRTCUtils.logDeviceInfo(TAG);
}
- public void init() {
- Log.d(TAG, "init");
- if (initialized) {
+ public void start(AudioManagerEvents audioManagerEvents) {
+ Log.d(TAG, "start");
+ if (amState == AudioManagerState.RUNNING) {
+ Log.e(TAG, "AudioManager is already active");
return;
}
+ // TODO(henrika): perhaps call new method called preInitAudio() here if UNINITIALIZED.
- // Store current audio state so we can restore it when close() is called.
+ Log.d(TAG, "AudioManager starts...");
+ this.audioManagerEvents = audioManagerEvents;
+ amState = AudioManagerState.RUNNING;
+
+ // Store current audio state so we can restore it when stop() is called.
savedAudioMode = audioManager.getMode();
savedIsSpeakerPhoneOn = audioManager.isSpeakerphoneOn();
savedIsMicrophoneMute = audioManager.isMicrophoneMute();
+ hasWiredHeadset = hasWiredHeadset();
// Create an AudioManager.OnAudioFocusChangeListener instance.
audioFocusChangeListener = new AudioManager.OnAudioFocusChangeListener() {
@@ -199,31 +212,42 @@ public class AppRTCAudioManager {
// Start by setting MODE_IN_COMMUNICATION as default audio mode. It is
// required to be in this mode when playout and/or recording starts for
// best possible VoIP performance.
- // TODO(henrika): we migh want to start with RINGTONE mode here instead.
audioManager.setMode(AudioManager.MODE_IN_COMMUNICATION);
// Always disable microphone mute during a WebRTC call.
setMicrophoneMute(false);
+ // Set initial device states.
+ userSelectedAudioDevice = AudioDevice.NONE;
+ selectedAudioDevice = AudioDevice.NONE;
+ audioDevices.clear();
+
+ // Initialize and start Bluetooth if a BT device is available or initiate
+ // detection of new (enabled) BT devices.
+ bluetoothManager.start();
+
// Do initial selection of audio device. This setting can later be changed
- // either by adding/removing a wired headset or by covering/uncovering the
- // proximity sensor.
- updateAudioDeviceState(hasWiredHeadset());
+ // either by adding/removing a BT or wired headset or by covering/uncovering
+ // the proximity sensor.
+ updateAudioDeviceState();
// Register receiver for broadcast intents related to adding/removing a
- // wired headset (Intent.ACTION_HEADSET_PLUG).
- registerForWiredHeadsetIntentBroadcast();
-
- initialized = true;
+ // wired headset.
+ registerReceiver(wiredHeadsetReceiver, new IntentFilter(Intent.ACTION_HEADSET_PLUG));
+ Log.d(TAG, "AudioManager started");
}
- public void close() {
- Log.d(TAG, "close");
- if (!initialized) {
+ public void stop() {
+ Log.d(TAG, "stop");
+ if (amState != AudioManagerState.RUNNING) {
+ Log.e(TAG, "Trying to stop AudioManager in incorrect state: " + amState);
return;
}
+ amState = AudioManagerState.UNINITIALIZED;
- unregisterForWiredHeadsetIntentBroadcast();
+ unregisterReceiver(wiredHeadsetReceiver);
+
+ bluetoothManager.stop();
// Restore previously stored audio states.
setSpeakerphoneOn(savedIsSpeakerPhoneOn);
@@ -235,102 +259,225 @@ public class AppRTCAudioManager {
audioFocusChangeListener = null;
Log.d(TAG, "Abandoned audio focus for VOICE_CALL streams");
- if (proximitySensor != null) {
- proximitySensor.stop();
- proximitySensor = null;
- }
-
- initialized = false;
+ audioManagerEvents = null;
+ Log.d(TAG, "AudioManager stopped");
}
- /** Changes selection of the currently active audio device. */
- public void setAudioDevice(AudioDevice device) {
- Log.d(TAG, "setAudioDevice(device=" + device + ")");
+ // Changes selection of the currently active audio device.
+ private void setAudioDeviceInternal(AudioDevice device) {
+ Log.d(TAG, "setAudioDeviceInternal(device=" + device + ")");
AppRTCUtils.assertIsTrue(audioDevices.contains(device));
switch (device) {
case SPEAKER_PHONE:
setSpeakerphoneOn(true);
- selectedAudioDevice = AudioDevice.SPEAKER_PHONE;
break;
case EARPIECE:
setSpeakerphoneOn(false);
- selectedAudioDevice = AudioDevice.EARPIECE;
break;
case WIRED_HEADSET:
setSpeakerphoneOn(false);
- selectedAudioDevice = AudioDevice.WIRED_HEADSET;
+ break;
+ case BLUETOOTH:
+ setSpeakerphoneOn(false);
break;
default:
Log.e(TAG, "Invalid audio device selection");
break;
}
- onAudioManagerChangedState();
+ selectedAudioDevice = device;
+ }
+
+ // Changes default audio device.
+ // TODO(henrika): add usage of this method in the AppRTCMobile client.
+ public synchronized void setDefaultAudioDevice(AudioDevice defaultDevice) {
+ 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;
+ }
+ Log.d(TAG, "setDefaultAudioDevice(device=" + defaultAudioDevice + ")");
+ updateAudioDeviceState();
+ }
+
+ // Changes selection of the currently active audio device.
+ public synchronized void selectAudioDevice(AudioDevice device) {
+ if (!audioDevices.contains(device)) {
+ Log.e(TAG, "Can not select " + device + " from available " + audioDevices);
+ }
+ userSelectedAudioDevice = device;
+ updateAudioDeviceState();
}
- /** Returns current set of available/selectable audio devices. */
- public Set<AudioDevice> getAudioDevices() {
+ // Returns current set of available/selectable audio devices.
+ public synchronized Set<AudioDevice> getAudioDevices() {
return Collections.unmodifiableSet(new HashSet<AudioDevice>(audioDevices));
}
- /** Returns the currently selected audio device. */
- public AudioDevice getSelectedAudioDevice() {
+ // Returns the currently selected audio device.
+ public synchronized AudioDevice getSelectedAudioDevice() {
return selectedAudioDevice;
}
- /**
- * Registers receiver for the broadcasted intent when a wired headset is
- * plugged in or unplugged. The received intent will have an extra
- * 'state' value where 0 means unplugged, and 1 means plugged.
- */
- private void registerForWiredHeadsetIntentBroadcast() {
- IntentFilter filter = new IntentFilter(Intent.ACTION_HEADSET_PLUG);
-
- /** Receiver which handles changes in wired headset availability. */
- wiredHeadsetReceiver = new BroadcastReceiver() {
- private static final int STATE_UNPLUGGED = 0;
- private static final int STATE_PLUGGED = 1;
- private static final int HAS_NO_MIC = 0;
- private static final int HAS_MIC = 1;
+ // Update list of possible audio devices and make new device selection.
+ public void updateAudioDeviceState() {
magjed_webrtc 2016/12/07 11:09:43 Please move this function back to make the diff sm
henrika_webrtc 2016/12/07 12:55:41 Done.
+ threadChecker.checkIsOnValidThread();
+ Log.d(TAG, "--- updateAudioDeviceState: "
+ + "wired headset=" + hasWiredHeadset + ", "
+ + "BT state=" + bluetoothManager.getState());
+ Log.d(TAG, "Device status: "
+ + "available=" + audioDevices + ", "
+ + "selected=" + selectedAudioDevice + ", "
+ + "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() == AppRTCBluetoothManager.State.HEADSET_AVAILABLE
+ || bluetoothManager.getState() == AppRTCBluetoothManager.State.HEADSET_UNAVAILABLE
+ || bluetoothManager.getState() == AppRTCBluetoothManager.State.SCO_DISCONNECTING) {
+ bluetoothManager.updateDevice();
+ }
- @Override
- public void onReceive(Context context, Intent intent) {
- int state = intent.getIntExtra("state", STATE_UNPLUGGED);
- int microphone = intent.getIntExtra("microphone", HAS_NO_MIC);
- String name = intent.getStringExtra("name");
- Log.d(TAG, "BroadcastReceiver.onReceive" + AppRTCUtils.getThreadInfo() + ": "
- + "a=" + intent.getAction() + ", s="
- + (state == STATE_UNPLUGGED ? "unplugged" : "plugged") + ", m="
- + (microphone == HAS_MIC ? "mic" : "no mic") + ", n=" + name + ", sb="
- + isInitialStickyBroadcast());
-
- boolean hasWiredHeadset = (state == STATE_PLUGGED);
- switch (state) {
- case STATE_UNPLUGGED:
- updateAudioDeviceState(hasWiredHeadset);
- break;
- case STATE_PLUGGED:
- if (selectedAudioDevice != AudioDevice.WIRED_HEADSET) {
- updateAudioDeviceState(hasWiredHeadset);
- }
- break;
- default:
- Log.e(TAG, "Invalid state");
- break;
- }
+ // Update the set of available audio devices.
+ Set<AudioDevice> newAudioDevices = new HashSet<>();
+
+ if (bluetoothManager.getState() == AppRTCBluetoothManager.State.SCO_CONNECTED
+ || bluetoothManager.getState() == AppRTCBluetoothManager.State.SCO_CONNECTING
+ || bluetoothManager.getState() == AppRTCBluetoothManager.State.HEADSET_AVAILABLE) {
+ newAudioDevices.add(AudioDevice.BLUETOOTH);
+ }
+
+ if (hasWiredHeadset) {
+ // 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);
}
- };
+ }
+
+ // Update the existing audio device set if needed.
+ boolean audioDeviceSetUpdated =
+ !audioDevices.containsAll(newAudioDevices) || !newAudioDevices.containsAll(audioDevices);
+ if (audioDeviceSetUpdated) {
+ audioDevices.clear();
+ audioDevices.addAll(newAudioDevices);
+ }
- apprtcContext.registerReceiver(wiredHeadsetReceiver, filter);
+ // Correct user selected audio devices if needed.
+ if (bluetoothManager.getState() == AppRTCBluetoothManager.State.HEADSET_UNAVAILABLE
+ && userSelectedAudioDevice == AudioDevice.BLUETOOTH) {
+ // If BT is not available, it can't be the user selection.
+ userSelectedAudioDevice = AudioDevice.NONE;
+ }
+ if (hasWiredHeadset && userSelectedAudioDevice == AudioDevice.SPEAKER_PHONE) {
+ // If user selected speaker phone, but then plugged wired headset then make
+ // wired headset as user selected device.
+ 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.
+ 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() == AppRTCBluetoothManager.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() == AppRTCBluetoothManager.State.SCO_CONNECTED
+ || bluetoothManager.getState() == AppRTCBluetoothManager.State.SCO_CONNECTING)
+ && (userSelectedAudioDevice != AudioDevice.NONE
+ && userSelectedAudioDevice != AudioDevice.BLUETOOTH);
+
+ if (bluetoothManager.getState() == AppRTCBluetoothManager.State.HEADSET_AVAILABLE
+ || bluetoothManager.getState() == AppRTCBluetoothManager.State.SCO_CONNECTING
+ || bluetoothManager.getState() == AppRTCBluetoothManager.State.SCO_CONNECTED) {
+ Log.d(TAG, "Need BT audio: start=" + needBluetoothAudioStart + ", "
+ + "stop=" + needBluetoothAudioStop + ", "
+ + "BT state=" + bluetoothManager.getState());
+ }
+
+ // Start or stop Bluetooth SCO connection given states set earlier.
+ if (needBluetoothAudioStop) {
+ bluetoothManager.stopScoAudio();
+ bluetoothManager.updateDevice();
+ }
+
+ if (needBluetoothAudioStart && !needBluetoothAudioStop) {
+ // Attempt to start Bluetooth SCO audio (takes a few second to start).
+ if (!bluetoothManager.startScoAudio()) {
+ // Remove BLUETOOTH from list of available devices since SCO failed.
+ audioDevices.remove(AudioDevice.BLUETOOTH);
+ audioDeviceSetUpdated = true;
+ }
+ }
+
+ // Update selected audio device.
+ AudioDevice newAudioDevice = selectedAudioDevice;
+
+ if (bluetoothManager.getState() == AppRTCBluetoothManager.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;
+ } 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;
+ } 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;
+ }
+ // Switch to new device but only if there has been any changes.
+ if (newAudioDevice != selectedAudioDevice || audioDeviceSetUpdated) {
+ // Do the required device switch.
+ setAudioDeviceInternal(newAudioDevice);
+ Log.d(TAG, "New device status: "
+ + "available=" + audioDevices + ", "
+ + "selected=" + newAudioDevice);
+ if (audioManagerEvents != null) {
+ // Notify a listening client that audio device has been changed.
+ audioManagerEvents.onAudioDeviceChanged(selectedAudioDevice, audioDevices);
+ }
+ }
+ Log.d(TAG, "--- updateAudioDeviceState done");
}
- /** Unregister receiver for broadcasted ACTION_HEADSET_PLUG intent. */
- private void unregisterForWiredHeadsetIntentBroadcast() {
- apprtcContext.unregisterReceiver(wiredHeadsetReceiver);
- wiredHeadsetReceiver = null;
+ // Helper method for receiver registration.
+ private void registerReceiver(BroadcastReceiver receiver, IntentFilter filter) {
+ apprtcContext.registerReceiver(receiver, filter);
}
- /** Sets the speaker phone mode. */
+ // Helper method for unregistration of an existing receiver.
+ private void unregisterReceiver(BroadcastReceiver receiver) {
+ apprtcContext.unregisterReceiver(receiver);
+ }
+
+ // Sets the speaker phone mode.
private void setSpeakerphoneOn(boolean on) {
boolean wasOn = audioManager.isSpeakerphoneOn();
if (wasOn == on) {
@@ -339,7 +486,7 @@ public class AppRTCAudioManager {
audioManager.setSpeakerphoneOn(on);
}
- /** Sets the microphone mute state. */
+ // Sets the microphone mute state.
private void setMicrophoneMute(boolean on) {
boolean wasMuted = audioManager.isMicrophoneMute();
if (wasMuted == on) {
@@ -348,72 +495,18 @@ public class AppRTCAudioManager {
audioManager.setMicrophoneMute(on);
}
- /** Gets the current earpiece state. */
+ // Gets the current earpiece state.
private boolean hasEarpiece() {
return apprtcContext.getPackageManager().hasSystemFeature(PackageManager.FEATURE_TELEPHONY);
}
- /**
- * 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() {
return audioManager.isWiredHeadsetOn();
}
-
- /** Update list of possible audio devices and make new device selection. */
- private void updateAudioDeviceState(boolean hasWiredHeadset) {
- // Update the list of available audio devices.
- audioDevices.clear();
- if (hasWiredHeadset) {
- // If a wired headset is connected, then it is the only possible option.
- audioDevices.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).
- audioDevices.add(AudioDevice.SPEAKER_PHONE);
- if (hasEarpiece()) {
- audioDevices.add(AudioDevice.EARPIECE);
- }
- }
- Log.d(TAG, "audioDevices: " + audioDevices);
-
- // Switch to correct audio device given the list of available audio devices.
- if (hasWiredHeadset) {
- setAudioDevice(AudioDevice.WIRED_HEADSET);
- } else {
- setAudioDevice(defaultAudioDevice);
- }
- }
-
- /** Called each time a new audio device has been added or removed. */
- private void onAudioManagerChangedState() {
- Log.d(TAG, "onAudioManagerChangedState: devices=" + audioDevices + ", selected="
- + selectedAudioDevice);
-
- // Enable the proximity sensor if there are two available audio devices
- // in the list. Given the current implementation, we know that the choice
- // will then be between EARPIECE and SPEAKER_PHONE.
- if (audioDevices.size() == 2) {
- AppRTCUtils.assertIsTrue(audioDevices.contains(AudioDevice.EARPIECE)
- && audioDevices.contains(AudioDevice.SPEAKER_PHONE));
- // Start the proximity sensor.
- proximitySensor.start();
- } else if (audioDevices.size() == 1) {
- // Stop the proximity sensor since it is no longer needed.
- proximitySensor.stop();
- } else {
- Log.e(TAG, "Invalid device list");
- }
-
- if (onStateChangeListener != null) {
- // Run callback to notify a listening client. The client can then
- // use public getters to query the new state.
- onStateChangeListener.run();
- }
- }
}

Powered by Google App Engine
This is Rietveld 408576698