check microphone availability on background thread

This commit is contained in:
Daniel Gultsch 2020-04-19 08:49:08 +02:00
parent 31dfb0c704
commit c7269bc0aa
4 changed files with 43 additions and 20 deletions

View file

@ -28,6 +28,7 @@ import org.webrtc.ThreadUtils;
import java.util.Collections; import java.util.Collections;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.concurrent.CountDownLatch;
import eu.siacs.conversations.Config; import eu.siacs.conversations.Config;
import eu.siacs.conversations.utils.AppRTCUtils; import eu.siacs.conversations.utils.AppRTCUtils;
@ -36,6 +37,9 @@ import eu.siacs.conversations.utils.AppRTCUtils;
* AppRTCAudioManager manages all audio related parts of the AppRTC demo. * AppRTCAudioManager manages all audio related parts of the AppRTC demo.
*/ */
public class AppRTCAudioManager { public class AppRTCAudioManager {
private static CountDownLatch microphoneLatch;
private final Context apprtcContext; private final Context apprtcContext;
// Contains speakerphone setting: auto, true or false // Contains speakerphone setting: auto, true or false
@Nullable @Nullable
@ -114,7 +118,8 @@ public class AppRTCAudioManager {
return new AppRTCAudioManager(context, speakerPhonePreference); return new AppRTCAudioManager(context, speakerPhonePreference);
} }
public static boolean isMicrophoneAvailable(final Context context) { public static boolean isMicrophoneAvailable() {
microphoneLatch = new CountDownLatch(1);
AudioRecord audioRecord = null; AudioRecord audioRecord = null;
boolean available = true; boolean available = true;
try { try {
@ -134,6 +139,7 @@ public class AppRTCAudioManager {
release(audioRecord); release(audioRecord);
} }
microphoneLatch.countDown();
return available; return available;
} }
@ -181,6 +187,7 @@ public class AppRTCAudioManager {
Log.e(Config.LOGTAG, "AudioManager is already active"); Log.e(Config.LOGTAG, "AudioManager is already active");
return; return;
} }
awaitMicrophoneLatch();
// TODO(henrika): perhaps call new method called preInitAudio() here if UNINITIALIZED. // TODO(henrika): perhaps call new method called preInitAudio() here if UNINITIALIZED.
Log.d(Config.LOGTAG, "AudioManager starts..."); Log.d(Config.LOGTAG, "AudioManager starts...");
this.audioManagerEvents = audioManagerEvents; this.audioManagerEvents = audioManagerEvents;
@ -261,6 +268,18 @@ public class AppRTCAudioManager {
Log.d(Config.LOGTAG, "AudioManager started"); Log.d(Config.LOGTAG, "AudioManager started");
} }
private void awaitMicrophoneLatch() {
final CountDownLatch latch = microphoneLatch;
if (latch == null) {
return;
}
try {
latch.await();
} catch (InterruptedException e) {
//ignore
}
}
@SuppressWarnings("deprecation") @SuppressWarnings("deprecation")
// TODO(henrika): audioManager.abandonAudioFocus() is deprecated. // TODO(henrika): audioManager.abandonAudioFocus() is deprecated.
public void stop() { public void stop() {

View file

@ -1273,16 +1273,12 @@ public class ConversationFragment extends XmppFragment implements EditMessage.Ke
private void triggerRtpSession(final String action) { private void triggerRtpSession(final String action) {
if (AppRTCAudioManager.isMicrophoneAvailable(getActivity())) {
final Contact contact = conversation.getContact(); final Contact contact = conversation.getContact();
final Intent intent = new Intent(activity, RtpSessionActivity.class); final Intent intent = new Intent(activity, RtpSessionActivity.class);
intent.setAction(action); intent.setAction(action);
intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, contact.getAccount().getJid().toEscapedString()); intent.putExtra(RtpSessionActivity.EXTRA_ACCOUNT, contact.getAccount().getJid().toEscapedString());
intent.putExtra(RtpSessionActivity.EXTRA_WITH, contact.getJid().asBareJid().toEscapedString()); intent.putExtra(RtpSessionActivity.EXTRA_WITH, contact.getJid().asBareJid().toEscapedString());
startActivity(intent); startActivity(intent);
} else {
Toast.makeText(getActivity(), R.string.microphone_unavailable, Toast.LENGTH_SHORT).show();
}
} }
private void handleAttachmentSelection(MenuItem item) { private void handleAttachmentSelection(MenuItem item) {

View file

@ -132,15 +132,22 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
} }
private void checkRecorderAndAcceptCall() { private void checkRecorderAndAcceptCall() {
checkMicrophoneAvailability();
requireRtpConnection().acceptCall();
}
private void checkMicrophoneAvailability() {
new Thread(() -> {
final long start = SystemClock.elapsedRealtime(); final long start = SystemClock.elapsedRealtime();
final boolean isMicrophoneAvailable = AppRTCAudioManager.isMicrophoneAvailable(this); final boolean isMicrophoneAvailable = AppRTCAudioManager.isMicrophoneAvailable();
final long stop = SystemClock.elapsedRealtime(); final long stop = SystemClock.elapsedRealtime();
Log.d(Config.LOGTAG, "checking microphone availability took " + (stop - start) + "ms"); Log.d(Config.LOGTAG, "checking microphone availability took " + (stop - start) + "ms");
if (isMicrophoneAvailable) { if (isMicrophoneAvailable) {
requireRtpConnection().acceptCall(); return;
} else {
Toast.makeText(this, R.string.microphone_unavailable, Toast.LENGTH_SHORT).show();
} }
runOnUiThread(() -> Toast.makeText(this, R.string.microphone_unavailable, Toast.LENGTH_SHORT).show());
}
).start();
} }
private void putScreenInCallMode() { private void putScreenInCallMode() {
@ -251,6 +258,7 @@ public class RtpSessionActivity extends XmppActivity implements XmppConnectionSe
} }
private void proposeJingleRtpSession(final Account account, final Jid with, final Set<Media> media) { private void proposeJingleRtpSession(final Account account, final Jid with, final Set<Media> media) {
checkMicrophoneAvailability();
xmppConnectionService.getJingleConnectionManager().proposeJingleRtpSession(account, with, media); xmppConnectionService.getJingleConnectionManager().proposeJingleRtpSession(account, with, media);
putScreenInCallMode(media); putScreenInCallMode(media);
} }

View file

@ -914,7 +914,7 @@
<string name="missed_call">Missed call</string> <string name="missed_call">Missed call</string>
<string name="audio_call">Audio call</string> <string name="audio_call">Audio call</string>
<string name="video_call">Video call</string> <string name="video_call">Video call</string>
<string name="microphone_unavailable">Microphone unavailable</string> <string name="microphone_unavailable">Your microphone is unavailable</string>
<plurals name="view_users"> <plurals name="view_users">
<item quantity="one">View %1$d Participant</item> <item quantity="one">View %1$d Participant</item>
<item quantity="other">View %1$d Participants</item> <item quantity="other">View %1$d Participants</item>