diff --git a/app/build.gradle b/app/build.gradle index 1443eedd5..bbac598de 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -187,6 +187,7 @@ dependencies { if (firebaseEnabled()) { implementation 'com.google.firebase:firebase-messaging:19.0.1' } + implementation 'androidx.media:media:1.2.0' implementation 'androidx.recyclerview:recyclerview:1.0.0' implementation 'androidx.appcompat:appcompat:1.1.0' implementation 'com.google.android:flexbox:1.1.0' diff --git a/app/src/main/java/org/linphone/LinphoneManager.java b/app/src/main/java/org/linphone/LinphoneManager.java index a4c965954..cd49efb0f 100644 --- a/app/src/main/java/org/linphone/LinphoneManager.java +++ b/app/src/main/java/org/linphone/LinphoneManager.java @@ -185,7 +185,6 @@ public class LinphoneManager implements SensorEventListener { if (mCore != null) { if (mCore.getCallsNb() > 0) { mCallManager.acceptCall(call); - mAudioManager.routeAudioToEarPiece(); } } } diff --git a/app/src/main/java/org/linphone/assistant/EchoCancellerCalibrationAssistantActivity.java b/app/src/main/java/org/linphone/assistant/EchoCancellerCalibrationAssistantActivity.java index 0936d7a34..a39dddcb0 100644 --- a/app/src/main/java/org/linphone/assistant/EchoCancellerCalibrationAssistantActivity.java +++ b/app/src/main/java/org/linphone/assistant/EchoCancellerCalibrationAssistantActivity.java @@ -20,9 +20,7 @@ package org.linphone.assistant; import android.Manifest; -import android.content.Context; import android.content.pm.PackageManager; -import android.media.AudioManager; import android.os.Bundle; import androidx.annotation.Nullable; import androidx.core.app.ActivityCompat; @@ -117,13 +115,9 @@ public class EchoCancellerCalibrationAssistantActivity extends AssistantActivity Core core, EcCalibratorStatus status, int delayMs) { if (status == EcCalibratorStatus.InProgress) return; core.removeListener(this); - LinphoneManager.getAudioManager().routeAudioToEarPiece(); goToLinphoneActivity(); - - ((AudioManager) getSystemService(Context.AUDIO_SERVICE)) - .setMode(AudioManager.MODE_NORMAL); } }); - LinphoneManager.getAudioManager().startEcCalibration(); + LinphoneManager.getCore().startEchoCancellerCalibration(); } } diff --git a/app/src/main/java/org/linphone/call/AndroidAudioManager.java b/app/src/main/java/org/linphone/call/AndroidAudioManager.java index fd98f91ea..e6931a2fd 100644 --- a/app/src/main/java/org/linphone/call/AndroidAudioManager.java +++ b/app/src/main/java/org/linphone/call/AndroidAudioManager.java @@ -19,69 +19,29 @@ */ package org.linphone.call; -import static android.media.AudioManager.MODE_RINGTONE; -import static android.media.AudioManager.STREAM_RING; import static android.media.AudioManager.STREAM_VOICE_CALL; -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothDevice; -import android.bluetooth.BluetoothHeadset; -import android.bluetooth.BluetoothProfile; import android.content.Context; -import android.content.Intent; -import android.content.IntentFilter; import android.media.AudioManager; -import android.media.MediaPlayer; -import android.net.Uri; -import android.os.Vibrator; -import android.provider.Settings; -import android.telephony.TelephonyManager; import android.view.KeyEvent; -import java.io.FileInputStream; -import java.io.IOException; -import java.util.List; -import org.linphone.LinphoneContext; import org.linphone.LinphoneManager; import org.linphone.R; -import org.linphone.compatibility.Compatibility; -import org.linphone.core.Address; +import org.linphone.core.AudioDevice; import org.linphone.core.Call; import org.linphone.core.Core; import org.linphone.core.CoreListenerStub; -import org.linphone.core.EcCalibratorStatus; import org.linphone.core.tools.Log; -import org.linphone.receivers.BluetoothReceiver; -import org.linphone.receivers.HeadsetReceiver; -import org.linphone.settings.LinphonePreferences; public class AndroidAudioManager { private Context mContext; private AudioManager mAudioManager; - private Call mRingingCall; - private MediaPlayer mRingerPlayer; - private final Vibrator mVibrator; - private BluetoothAdapter mBluetoothAdapter; - private BluetoothHeadset mBluetoothHeadset; - private BluetoothReceiver mBluetoothReceiver; - private HeadsetReceiver mHeadsetReceiver; - private boolean mHeadsetReceiverRegistered; - - private boolean mIsRinging; - private boolean mAudioFocused; - private boolean mEchoTesterIsRunning; - private boolean mIsBluetoothHeadsetConnected; - private boolean mIsBluetoothHeadsetScoConnected; + private boolean mEchoTesterIsRunning = false; private CoreListenerStub mListener; public AndroidAudioManager(Context context) { mContext = context; mAudioManager = ((AudioManager) context.getSystemService(Context.AUDIO_SERVICE)); - mVibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE); - mEchoTesterIsRunning = false; - mHeadsetReceiverRegistered = false; - - startBluetooth(); mListener = new CoreListenerStub() { @@ -91,36 +51,9 @@ public class AndroidAudioManager { final Call call, final Call.State state, final String message) { - if (state == Call.State.IncomingReceived - || (state == Call.State.IncomingEarlyMedia - && mContext.getResources() - .getBoolean( - R.bool.allow_ringing_while_early_media))) { - // Brighten screen for at least 10 seconds - if (core.getCallsNb() == 1) { - requestAudioFocus(STREAM_RING); - - mRingingCall = call; - startRinging(call.getRemoteAddress()); - // otherwise there is the beep - } - } else if (call == mRingingCall && mIsRinging) { - // previous state was ringing, so stop ringing - stopRinging(); - } - if (state == Call.State.Connected) { if (core.getCallsNb() == 1) { - // It is for incoming calls, because outgoing calls enter - // MODE_IN_COMMUNICATION immediately when they start. - // However, incoming call first use the MODE_RINGING to play the - // local ring. - if (call.getDir() == Call.Dir.Incoming) { - setAudioManagerInCallMode(); - // mAudioManager.abandonAudioFocus(null); - requestAudioFocus(STREAM_VOICE_CALL); - } - if (!mIsBluetoothHeadsetConnected) { + if (!isBluetoothHeadsetConnected()) { if (mContext.getResources().getBoolean(R.bool.isTablet)) { routeAudioToSpeaker(); } else { @@ -130,70 +63,11 @@ public class AndroidAudioManager { routeAudioToEarPiece(); } } - } - // Only register this one when a call is active - - enableHeadsetReceiver(); - } - } else if (state == Call.State.End || state == Call.State.Error) { - if (core.getCallsNb() == 0) { - if (mAudioFocused) { - int res = mAudioManager.abandonAudioFocus(null); - Log.d( - "[Audio Manager] Audio focus released a bit later: " - + (res - == AudioManager - .AUDIOFOCUS_REQUEST_GRANTED - ? "Granted" - : "Denied")); - mAudioFocused = false; - } - - // Only register this one when a call is active - if (mHeadsetReceiver != null && mHeadsetReceiverRegistered) { - Log.i("[Audio Manager] Unregistering headset receiver"); - mContext.unregisterReceiver(mHeadsetReceiver); - mHeadsetReceiverRegistered = false; - } - - TelephonyManager tm = - (TelephonyManager) - mContext.getSystemService( - Context.TELEPHONY_SERVICE); - if (tm.getCallState() == TelephonyManager.CALL_STATE_IDLE) { - Log.d( - "[Audio Manager] ---AndroidAudioManager: back to MODE_NORMAL"); - mAudioManager.setMode(AudioManager.MODE_NORMAL); - Log.d( - "[Audio Manager] All call terminated, routing back to earpiece"); - routeAudioToEarPiece(); + } else { + routeAudioToBluetooth(); } } } - if (state == Call.State.OutgoingInit) { - // Enter the MODE_IN_COMMUNICATION mode as soon as possible, so that - // ringback is heard normally in earpiece or bluetooth receiver. - setAudioManagerInCallMode(); - requestAudioFocus(STREAM_VOICE_CALL); - if (mIsBluetoothHeadsetConnected) { - routeAudioToBluetooth(); - } - } - - if (state == Call.State.StreamsRunning) { - setAudioManagerInCallMode(); - if (mIsBluetoothHeadsetConnected) { - routeAudioToBluetooth(); - } - } - } - - @Override - public void onEcCalibrationResult( - Core core, EcCalibratorStatus status, int delay_ms) { - mAudioManager.setMode(AudioManager.MODE_NORMAL); - mAudioManager.abandonAudioFocus(null); - Log.i("[Audio Manager] Set audio mode on 'Normal'"); } }; @@ -204,16 +78,6 @@ public class AndroidAudioManager { } public void destroy() { - if (mBluetoothAdapter != null && mBluetoothHeadset != null) { - Log.i("[Audio Manager] [Bluetooth] Closing HEADSET profile proxy"); - mBluetoothAdapter.closeProfileProxy(BluetoothProfile.HEADSET, mBluetoothHeadset); - } - - Log.i("[Audio Manager] [Bluetooth] Unegistering bluetooth receiver"); - if (mBluetoothReceiver != null) { - mContext.unregisterReceiver(mBluetoothReceiver); - } - Core core = LinphoneManager.getCore(); if (core != null) { core.removeListener(mListener); @@ -222,10 +86,6 @@ public class AndroidAudioManager { /* Audio routing */ - public void setAudioManagerModeNormal() { - mAudioManager.setMode(AudioManager.MODE_NORMAL); - } - public void routeAudioToEarPiece() { routeAudioToSpeakerHelper(false); } @@ -244,41 +104,17 @@ public class AndroidAudioManager { /* Echo cancellation */ - public void startEcCalibration() { - Core core = LinphoneManager.getCore(); - if (core == null) { - return; - } - - routeAudioToSpeaker(); - setAudioManagerInCallMode(); - Log.i("[Audio Manager] Set audio mode on 'Voice Communication'"); - requestAudioFocus(STREAM_VOICE_CALL); - int oldVolume = mAudioManager.getStreamVolume(STREAM_VOICE_CALL); - int maxVolume = mAudioManager.getStreamMaxVolume(STREAM_VOICE_CALL); - mAudioManager.setStreamVolume(STREAM_VOICE_CALL, maxVolume, 0); - core.startEchoCancellerCalibration(); - mAudioManager.setStreamVolume(STREAM_VOICE_CALL, oldVolume, 0); - } - public void startEchoTester() { Core core = LinphoneManager.getCore(); if (core == null) { return; } - - routeAudioToSpeaker(); - setAudioManagerInCallMode(); - Log.i("[Audio Manager] Set audio mode on 'Voice Communication'"); - requestAudioFocus(STREAM_VOICE_CALL); - int maxVolume = mAudioManager.getStreamMaxVolume(STREAM_VOICE_CALL); int sampleRate; - mAudioManager.setStreamVolume(STREAM_VOICE_CALL, maxVolume, 0); String sampleRateProperty = mAudioManager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE); sampleRate = Integer.parseInt(sampleRateProperty); - core.startEchoTester(sampleRate); mEchoTesterIsRunning = true; + core.startEchoTester(sampleRate); } public void stopEchoTester() { @@ -287,10 +123,8 @@ public class AndroidAudioManager { return; } - mEchoTesterIsRunning = false; core.stopEchoTester(); - routeAudioToEarPiece(); - mAudioManager.setMode(AudioManager.MODE_NORMAL); + mEchoTesterIsRunning = false; Log.i("[Audio Manager] Set audio mode on 'Normal'"); } @@ -309,107 +143,23 @@ public class AndroidAudioManager { return false; } - private void setAudioManagerInCallMode() { - if (mAudioManager.getMode() == AudioManager.MODE_IN_COMMUNICATION) { - Log.w("[Audio Manager] already in MODE_IN_COMMUNICATION, skipping..."); - return; - } - Log.d("[Audio Manager] Mode: MODE_IN_COMMUNICATION"); - - mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); - } - - private void requestAudioFocus(int stream) { - if (!mAudioFocused) { - int res = - mAudioManager.requestAudioFocus( - null, stream, AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE); - Log.d( - "[Audio Manager] Audio focus requested: " - + (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED - ? "Granted" - : "Denied")); - if (res == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) mAudioFocused = true; - } - } - - private synchronized void startRinging(Address remoteAddress) { - if (!LinphonePreferences.instance().isDeviceRingtoneEnabled()) { - // Enable speaker audio route, linphone library will do the ringing itself automatically - routeAudioToSpeaker(); - return; - } - - boolean doNotDisturbPolicyAllowsRinging = - Compatibility.isDoNotDisturbPolicyAllowingRinging(mContext, remoteAddress); - if (!doNotDisturbPolicyAllowsRinging) { - Log.e("[Audio Manager] Do not ring as Android Do Not Disturb Policy forbids it"); - return; - } - - routeAudioToSpeaker(); - mAudioManager.setMode(MODE_RINGTONE); - - try { - if ((mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_VIBRATE - || mAudioManager.getRingerMode() == AudioManager.RINGER_MODE_NORMAL) - && mVibrator != null - && LinphonePreferences.instance().isIncomingCallVibrationEnabled()) { - Compatibility.vibrate(mVibrator); - } - if (mRingerPlayer == null) { - requestAudioFocus(STREAM_RING); - mRingerPlayer = new MediaPlayer(); - mRingerPlayer.setAudioStreamType(STREAM_RING); - - String ringtone = - LinphonePreferences.instance() - .getRingtone(Settings.System.DEFAULT_RINGTONE_URI.toString()); - try { - if (ringtone.startsWith("content://")) { - mRingerPlayer.setDataSource(mContext, Uri.parse(ringtone)); - } else { - FileInputStream fis = new FileInputStream(ringtone); - mRingerPlayer.setDataSource(fis.getFD()); - fis.close(); - } - } catch (IOException e) { - Log.e(e, "[Audio Manager] Cannot set ringtone"); - } - - mRingerPlayer.prepare(); - mRingerPlayer.setLooping(true); - mRingerPlayer.start(); - } else { - Log.w("[Audio Manager] Already ringing"); - } - } catch (Exception e) { - Log.e(e, "[Audio Manager] Cannot handle incoming call"); - } - mIsRinging = true; - } - - private synchronized void stopRinging() { - if (mRingerPlayer != null) { - mRingerPlayer.stop(); - mRingerPlayer.release(); - mRingerPlayer = null; - } - if (mVibrator != null) { - mVibrator.cancel(); - } - - mIsRinging = false; - } - private void routeAudioToSpeakerHelper(boolean speakerOn) { Log.w("[Audio Manager] Routing audio to " + (speakerOn ? "speaker" : "earpiece")); - if (mIsBluetoothHeadsetScoConnected) { - Log.w("[Audio Manager] [Bluetooth] Disabling bluetooth audio route"); - changeBluetoothSco(false); - } - mAudioManager.setSpeakerphoneOn(speakerOn); + if (LinphoneManager.getCore().getCallsNb() == 0) return; + Call currentCall = LinphoneManager.getCore().getCurrentCall(); + if (currentCall == null) currentCall = LinphoneManager.getCore().getCalls()[0]; + if (currentCall == null) return; + + for (AudioDevice audioDevice : LinphoneManager.getCore().getAudioDevices()) { + if (speakerOn && audioDevice.getType() == AudioDevice.Type.Speaker) { + currentCall.setOutputAudioDevice(audioDevice); + return; + } else if (!speakerOn && audioDevice.getType() == AudioDevice.Type.Earpiece) { + currentCall.setOutputAudioDevice(audioDevice); + return; + } + } } private void adjustVolume(int i) { @@ -419,7 +169,7 @@ public class AndroidAudioManager { } int stream = STREAM_VOICE_CALL; - if (mIsBluetoothHeadsetScoConnected) { + if (isUsingBluetoothAudioRoute()) { Log.i( "[Audio Manager] Bluetooth is connected, try to change the volume on STREAM_BLUETOOTH_SCO"); stream = 6; // STREAM_BLUETOOTH_SCO, it's hidden... @@ -433,194 +183,45 @@ public class AndroidAudioManager { AudioManager.FLAG_SHOW_UI); } - // Bluetooth - - public synchronized void bluetoothHeadetConnectionChanged(boolean connected) { - mIsBluetoothHeadsetConnected = connected; - mAudioManager.setBluetoothScoOn(connected); - if (LinphoneContext.isReady()) LinphoneManager.getCallManager().refreshInCallActions(); - } - - public synchronized void bluetoothHeadetAudioConnectionChanged(boolean connected) { - mIsBluetoothHeadsetScoConnected = connected; - mAudioManager.setBluetoothScoOn(connected); + public synchronized boolean isUsingBluetoothAudioRoute() { + if (LinphoneManager.getCore().getCallsNb() == 0) return false; + Call currentCall = LinphoneManager.getCore().getCurrentCall(); + if (currentCall == null) currentCall = LinphoneManager.getCore().getCalls()[0]; + if (currentCall == null) return false; + AudioDevice audioDevice = currentCall.getOutputAudioDevice(); + Log.i("[Audio Manager] Currently used audio device: ", audioDevice.getDeviceName()); + return audioDevice.getType() == AudioDevice.Type.Bluetooth; } public synchronized boolean isBluetoothHeadsetConnected() { - return mIsBluetoothHeadsetConnected; - } - - public synchronized void bluetoothHeadetScoConnectionChanged(boolean connected) { - mIsBluetoothHeadsetScoConnected = connected; - if (LinphoneContext.isReady()) LinphoneManager.getCallManager().refreshInCallActions(); - } - - public synchronized boolean isUsingBluetoothAudioRoute() { - return mIsBluetoothHeadsetScoConnected; + for (AudioDevice audioDevice : LinphoneManager.getCore().getAudioDevices()) { + if (audioDevice.getType() == AudioDevice.Type.Bluetooth + && audioDevice.hasCapability(AudioDevice.Capabilities.CapabilityPlay)) { + Log.i("[Audio Manager] Found bluetooth device: ", audioDevice.getDeviceName()); + return true; + } + } + return false; } public synchronized void routeAudioToBluetooth() { - if (!isBluetoothHeadsetConnected()) { - Log.w("[Audio Manager] [Bluetooth] No headset connected"); - return; - } - if (mAudioManager.getMode() != AudioManager.MODE_IN_COMMUNICATION) { - Log.w( - "[Audio Manager] [Bluetooth] Changing audio mode to MODE_IN_COMMUNICATION and requesting STREAM_VOICE_CALL focus"); - mAudioManager.setMode(AudioManager.MODE_IN_COMMUNICATION); - requestAudioFocus(STREAM_VOICE_CALL); - } - changeBluetoothSco(true); - } + if (LinphoneManager.getCore().getCallsNb() == 0) return; + Call currentCall = LinphoneManager.getCore().getCurrentCall(); + if (currentCall == null) currentCall = LinphoneManager.getCore().getCalls()[0]; + if (currentCall == null) return; - private synchronized void changeBluetoothSco(final boolean enable) { - // IT WILL TAKE A CERTAIN NUMBER OF CALLS TO EITHER START/STOP BLUETOOTH SCO FOR IT TO WORK - if (enable && mIsBluetoothHeadsetScoConnected) { - Log.i("[Audio Manager] [Bluetooth] SCO already enabled, skipping"); - return; - } else if (!enable && !mIsBluetoothHeadsetScoConnected) { - Log.i("[Audio Manager] [Bluetooth] SCO already disabled, skipping"); - return; - } - - new Thread() { - @Override - public void run() { - Log.i("[Audio Manager] [Bluetooth] SCO start/stop thread started"); - boolean resultAcknowledged; - int retries = 0; - - do { - try { - Thread.sleep(200); - } catch (InterruptedException e) { - Log.e(e); - } - - synchronized (AndroidAudioManager.this) { - if (enable) { - Log.i( - "[Audio Manager] [Bluetooth] Starting SCO: try number " - + retries); - mAudioManager.startBluetoothSco(); - } else { - Log.i( - "[Audio Manager] [Bluetooth] Stopping SCO: try number " - + retries); - mAudioManager.stopBluetoothSco(); - } - resultAcknowledged = isUsingBluetoothAudioRoute() == enable; - retries++; - } - } while (!resultAcknowledged && retries < 10); + for (AudioDevice audioDevice : LinphoneManager.getCore().getAudioDevices()) { + if (audioDevice.getType() == AudioDevice.Type.Bluetooth + && audioDevice.hasCapability(AudioDevice.Capabilities.CapabilityPlay)) { + Log.i( + "[Audio Manager] Found bluetooth audio device", + audioDevice.getDeviceName(), + ", routing audio to it"); + currentCall.setOutputAudioDevice(audioDevice); + return; } - }.start(); - } - - public void bluetoothAdapterStateChanged() { - if (mBluetoothAdapter.isEnabled()) { - Log.i("[Audio Manager] [Bluetooth] Adapter enabled"); - mIsBluetoothHeadsetConnected = false; - mIsBluetoothHeadsetScoConnected = false; - - BluetoothProfile.ServiceListener bluetoothServiceListener = - new BluetoothProfile.ServiceListener() { - public void onServiceConnected(int profile, BluetoothProfile proxy) { - if (profile == BluetoothProfile.HEADSET) { - Log.i("[Audio Manager] [Bluetooth] HEADSET profile connected"); - mBluetoothHeadset = (BluetoothHeadset) proxy; - - List devices = - mBluetoothHeadset.getConnectedDevices(); - if (devices.size() > 0) { - Log.i( - "[Audio Manager] [Bluetooth] A device is already connected"); - bluetoothHeadetConnectionChanged(true); - } - - Log.i("[Audio Manager] [Bluetooth] Registering bluetooth receiver"); - - IntentFilter filter = new IntentFilter(); - filter.addAction(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED); - filter.addAction(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED); - filter.addAction(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED); - filter.addAction( - BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT); - - Intent sticky = - mContext.registerReceiver(mBluetoothReceiver, filter); - Log.i("[Audio Manager] [Bluetooth] Bluetooth receiver registered"); - int state = - sticky.getIntExtra( - AudioManager.EXTRA_SCO_AUDIO_STATE, - AudioManager.SCO_AUDIO_STATE_DISCONNECTED); - if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) { - Log.i( - "[Audio Manager] [Bluetooth] Bluetooth headset SCO connected"); - bluetoothHeadetScoConnectionChanged(true); - } else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) { - Log.i( - "[Audio Manager] [Bluetooth] Bluetooth headset SCO disconnected"); - bluetoothHeadetScoConnectionChanged(false); - } else if (state == AudioManager.SCO_AUDIO_STATE_CONNECTING) { - Log.i( - "[Audio Manager] [Bluetooth] Bluetooth headset SCO connecting"); - } else if (state == AudioManager.SCO_AUDIO_STATE_ERROR) { - Log.i( - "[Audio Manager] [Bluetooth] Bluetooth headset SCO connection error"); - } else { - Log.w( - "[Audio Manager] [Bluetooth] Bluetooth headset unknown SCO state changed: " - + state); - } - } - } - - public void onServiceDisconnected(int profile) { - if (profile == BluetoothProfile.HEADSET) { - Log.i("[Audio Manager] [Bluetooth] HEADSET profile disconnected"); - mBluetoothHeadset = null; - mIsBluetoothHeadsetConnected = false; - mIsBluetoothHeadsetScoConnected = false; - } - } - }; - - mBluetoothAdapter.getProfileProxy( - mContext, bluetoothServiceListener, BluetoothProfile.HEADSET); - } else { - Log.w("[Audio Manager] [Bluetooth] Adapter disabled"); } - } - - private void startBluetooth() { - mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter(); - if (mBluetoothAdapter != null) { - Log.i("[Audio Manager] [Bluetooth] Adapter found"); - if (mAudioManager.isBluetoothScoAvailableOffCall()) { - Log.i("[Audio Manager] [Bluetooth] SCO available off call, continue"); - } else { - Log.w("[Audio Manager] [Bluetooth] SCO not available off call !"); - } - - mBluetoothReceiver = new BluetoothReceiver(); - IntentFilter filter = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED); - mContext.registerReceiver(mBluetoothReceiver, filter); - - bluetoothAdapterStateChanged(); - } - } - - // HEADSET - - private void enableHeadsetReceiver() { - mHeadsetReceiver = new HeadsetReceiver(); - - Log.i("[Audio Manager] Registering headset receiver"); - mContext.registerReceiver( - mHeadsetReceiver, new IntentFilter(AudioManager.ACTION_AUDIO_BECOMING_NOISY)); - mContext.registerReceiver( - mHeadsetReceiver, new IntentFilter(AudioManager.ACTION_HEADSET_PLUG)); - mHeadsetReceiverRegistered = true; + Log.w( + "[Audio Manager] Didn't find any bluetooth audio device, keeping default audio route"); } } diff --git a/app/src/main/java/org/linphone/call/CallActivity.java b/app/src/main/java/org/linphone/call/CallActivity.java index d97f1c803..952a20ee9 100644 --- a/app/src/main/java/org/linphone/call/CallActivity.java +++ b/app/src/main/java/org/linphone/call/CallActivity.java @@ -430,6 +430,14 @@ public class CallActivity extends LinphoneGenericActivity updateButtons(); updateCallsList(); } + + @Override + public void onAudioDevicesListUpdated(@NonNull Core core) { + if (mAudioManager.isBluetoothHeadsetConnected()) { + mAudioManager.routeAudioToBluetooth(); + } + updateButtons(); + } }; mCore = LinphoneManager.getCore(); diff --git a/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java b/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java index bd803625a..70718bf9f 100644 --- a/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java +++ b/app/src/main/java/org/linphone/chat/ChatMessagesFragment.java @@ -50,6 +50,7 @@ import android.widget.CheckBox; import android.widget.ImageView; import android.widget.LinearLayout; import android.widget.TextView; +import androidx.annotation.NonNull; import androidx.appcompat.view.menu.MenuBuilder; import androidx.appcompat.view.menu.MenuPopupHelper; import androidx.core.view.inputmethod.InputConnectionCompat; @@ -1210,6 +1211,9 @@ public class ChatMessagesFragment extends Fragment * Chat room callbacks */ + @Override + public void onNewEvent(@NonNull ChatRoom chatRoom, @NonNull EventLog eventLog) {} + @Override public void onChatMessageSent(ChatRoom cr, EventLog event) { ((ChatMessagesGenericAdapter) mChatEventsList.getAdapter()).addToHistory(event); diff --git a/app/src/main/java/org/linphone/receivers/BluetoothReceiver.java b/app/src/main/java/org/linphone/receivers/BluetoothReceiver.java deleted file mode 100644 index 16cbe6b60..000000000 --- a/app/src/main/java/org/linphone/receivers/BluetoothReceiver.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright (c) 2010-2019 Belledonne Communications SARL. - * - * This file is part of linphone-android - * (see https://www.linphone.org). - * - * 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 3 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, see . - */ -package org.linphone.receivers; - -import android.bluetooth.BluetoothAdapter; -import android.bluetooth.BluetoothHeadset; -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.media.AudioManager; -import org.linphone.LinphoneManager; -import org.linphone.core.tools.Log; - -public class BluetoothReceiver extends BroadcastReceiver { - public BluetoothReceiver() { - super(); - Log.i("[Bluetooth] Bluetooth receiver created"); - } - - @Override - public void onReceive(Context context, Intent intent) { - String action = intent.getAction(); - Log.i("[Bluetooth] Bluetooth broadcast received"); - - if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { - int state = intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR); - switch (state) { - case BluetoothAdapter.STATE_OFF: - Log.w("[Bluetooth] Adapter has been turned off"); - break; - case BluetoothAdapter.STATE_TURNING_OFF: - Log.w("[Bluetooth] Adapter is being turned off"); - break; - case BluetoothAdapter.STATE_ON: - Log.i("[Bluetooth] Adapter has been turned on"); - LinphoneManager.getAudioManager().bluetoothAdapterStateChanged(); - break; - case BluetoothAdapter.STATE_TURNING_ON: - Log.i("[Bluetooth] Adapter is being turned on"); - break; - case BluetoothAdapter.ERROR: - Log.e("[Bluetooth] Adapter is in error state !"); - break; - default: - Log.w("[Bluetooth] Unknown adapter state: ", state); - break; - } - } else if (action.equals(BluetoothHeadset.ACTION_CONNECTION_STATE_CHANGED)) { - int state = - intent.getIntExtra( - BluetoothHeadset.EXTRA_STATE, BluetoothHeadset.STATE_DISCONNECTED); - if (state == BluetoothHeadset.STATE_CONNECTED) { - Log.i("[Bluetooth] Bluetooth headset connected"); - LinphoneManager.getAudioManager().bluetoothHeadetConnectionChanged(true); - } else if (state == BluetoothHeadset.STATE_DISCONNECTED) { - Log.i("[Bluetooth] Bluetooth headset disconnected"); - LinphoneManager.getAudioManager().bluetoothHeadetConnectionChanged(false); - } else { - Log.w("[Bluetooth] Bluetooth headset unknown state changed: " + state); - } - } else if (action.equals(BluetoothHeadset.ACTION_AUDIO_STATE_CHANGED)) { - int state = - intent.getIntExtra( - BluetoothHeadset.EXTRA_STATE, - BluetoothHeadset.STATE_AUDIO_DISCONNECTED); - if (state == BluetoothHeadset.STATE_AUDIO_CONNECTED) { - Log.i("[Bluetooth] Bluetooth headset audio connected"); - LinphoneManager.getAudioManager().bluetoothHeadetAudioConnectionChanged(true); - } else if (state == BluetoothHeadset.STATE_AUDIO_DISCONNECTED) { - Log.i("[Bluetooth] Bluetooth headset audio disconnected"); - LinphoneManager.getAudioManager().bluetoothHeadetAudioConnectionChanged(false); - } else if (state == BluetoothHeadset.STATE_AUDIO_CONNECTING) { - Log.i("[Bluetooth] Bluetooth headset audio connecting"); - } else { - Log.w("[Bluetooth] Bluetooth headset unknown audio state changed: " + state); - } - } else if (action.equals(AudioManager.ACTION_SCO_AUDIO_STATE_UPDATED)) { - int state = - intent.getIntExtra( - AudioManager.EXTRA_SCO_AUDIO_STATE, - AudioManager.SCO_AUDIO_STATE_DISCONNECTED); - if (state == AudioManager.SCO_AUDIO_STATE_CONNECTED) { - Log.i("[Bluetooth] Bluetooth headset SCO connected"); - LinphoneManager.getAudioManager().bluetoothHeadetScoConnectionChanged(true); - } else if (state == AudioManager.SCO_AUDIO_STATE_DISCONNECTED) { - Log.i("[Bluetooth] Bluetooth headset SCO disconnected"); - LinphoneManager.getAudioManager().bluetoothHeadetScoConnectionChanged(false); - } else if (state == AudioManager.SCO_AUDIO_STATE_CONNECTING) { - Log.i("[Bluetooth] Bluetooth headset SCO connecting"); - } else if (state == AudioManager.SCO_AUDIO_STATE_ERROR) { - Log.i("[Bluetooth] Bluetooth headset SCO connection error"); - } else { - Log.w("[Bluetooth] Bluetooth headset unknown SCO state changed: " + state); - } - } else if (action.equals(BluetoothHeadset.ACTION_VENDOR_SPECIFIC_HEADSET_EVENT)) { - String command = - intent.getStringExtra(BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD); - int type = - intent.getIntExtra( - BluetoothHeadset.EXTRA_VENDOR_SPECIFIC_HEADSET_EVENT_CMD_TYPE, -1); - - String commandType; - switch (type) { - case BluetoothHeadset.AT_CMD_TYPE_ACTION: - commandType = "AT Action"; - break; - case BluetoothHeadset.AT_CMD_TYPE_READ: - commandType = "AT Read"; - break; - case BluetoothHeadset.AT_CMD_TYPE_TEST: - commandType = "AT Test"; - break; - case BluetoothHeadset.AT_CMD_TYPE_SET: - commandType = "AT Set"; - break; - case BluetoothHeadset.AT_CMD_TYPE_BASIC: - commandType = "AT Basic"; - break; - default: - commandType = "AT Unknown"; - break; - } - Log.i("[Bluetooth] Vendor action " + commandType + " : " + command); - } else { - Log.w("[Bluetooth] Bluetooth unknown action: " + action); - } - } -} diff --git a/app/src/main/java/org/linphone/receivers/HeadsetReceiver.java b/app/src/main/java/org/linphone/receivers/HeadsetReceiver.java deleted file mode 100644 index 07cac4ff4..000000000 --- a/app/src/main/java/org/linphone/receivers/HeadsetReceiver.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2010-2019 Belledonne Communications SARL. - * - * This file is part of linphone-android - * (see https://www.linphone.org). - * - * 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 3 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, see . - */ -package org.linphone.receivers; - -import android.content.BroadcastReceiver; -import android.content.Context; -import android.content.Intent; -import android.media.AudioManager; -import org.linphone.LinphoneManager; -import org.linphone.core.tools.Log; - -public class HeadsetReceiver extends BroadcastReceiver { - @Override - public void onReceive(Context context, Intent intent) { - if (isInitialStickyBroadcast()) { - Log.i("[Headset] Received broadcast from sticky cache, ignoring..."); - return; - } - - String action = intent.getAction(); - if (action.equals(AudioManager.ACTION_HEADSET_PLUG)) { - // This happens when the user plugs a Jack headset to the device for example - // https://developer.android.com/reference/android/media/AudioManager.html#ACTION_HEADSET_PLUG - int state = intent.getIntExtra("state", 0); - String name = intent.getStringExtra("name"); - int hasMicrophone = intent.getIntExtra("microphone", 0); - - if (state == 0) { - Log.i("[Headset] Headset disconnected:" + name); - } else if (state == 1) { - Log.i("[Headset] Headset connected:" + name); - if (hasMicrophone == 1) { - Log.i("[Headset] Headset " + name + " has a microphone"); - } - } else { - Log.w("[Headset] Unknown headset plugged state: " + state); - } - - LinphoneManager.getAudioManager().routeAudioToEarPiece(); - LinphoneManager.getCallManager().refreshInCallActions(); - } else if (action.equals(AudioManager.ACTION_AUDIO_BECOMING_NOISY)) { - // This happens when the user disconnect a headset, so we shouldn't play audio loudly - Log.i("[Headset] Noisy state detected, most probably a headset has been disconnected"); - LinphoneManager.getAudioManager().routeAudioToEarPiece(); - LinphoneManager.getCallManager().refreshInCallActions(); - } else { - Log.w("[Headset] Unknown action: " + action); - } - } -} diff --git a/app/src/main/java/org/linphone/recording/RecordingsActivity.java b/app/src/main/java/org/linphone/recording/RecordingsActivity.java index f1a270d0f..00f4b0e13 100644 --- a/app/src/main/java/org/linphone/recording/RecordingsActivity.java +++ b/app/src/main/java/org/linphone/recording/RecordingsActivity.java @@ -107,7 +107,6 @@ public class RecordingsActivity extends MainActivity hideTopBar(); hideTabBar(); - LinphoneManager.getAudioManager().setAudioManagerModeNormal(); LinphoneManager.getAudioManager().routeAudioToSpeaker(); removeDeletedRecordings(); diff --git a/app/src/main/java/org/linphone/settings/AudioSettingsFragment.java b/app/src/main/java/org/linphone/settings/AudioSettingsFragment.java index 0e6036c88..64b24608d 100644 --- a/app/src/main/java/org/linphone/settings/AudioSettingsFragment.java +++ b/app/src/main/java/org/linphone/settings/AudioSettingsFragment.java @@ -20,9 +20,7 @@ package org.linphone.settings; import android.Manifest; -import android.content.Context; import android.content.pm.PackageManager; -import android.media.AudioManager; import android.os.Bundle; import android.text.InputType; import android.view.LayoutInflater; @@ -274,7 +272,6 @@ public class AudioSettingsFragment extends SettingsFragment { Core core, EcCalibratorStatus status, int delayMs) { if (status == EcCalibratorStatus.InProgress) return; core.removeListener(this); - LinphoneManager.getAudioManager().routeAudioToEarPiece(); if (status == EcCalibratorStatus.DoneNoEcho) { mEchoCalibration.setSubtitle(getString(R.string.no_echo)); @@ -287,12 +284,8 @@ public class AudioSettingsFragment extends SettingsFragment { mEchoCalibration.setSubtitle(getString(R.string.failed)); } mEchoCanceller.setChecked(status != EcCalibratorStatus.DoneNoEcho); - ((AudioManager) - getActivity() - .getSystemService(Context.AUDIO_SERVICE)) - .setMode(AudioManager.MODE_NORMAL); } }); - LinphoneManager.getAudioManager().startEcCalibration(); + LinphoneManager.getCore().startEchoCancellerCalibration(); } }