ConnectionService: Dialer UI integration for incoming calls
For incoming calls, we fall back to the built-in call UI if the microphone permission is not granted. The reason is that if the Dialer UI is displayed over keyguard, then the user may not even be able to see the notification that we show in order for them to grant the permission. Having a small annoyance for the first incoming call is better than having the in-call UI hang.
This commit is contained in:
parent
b218b57c94
commit
788818fdda
|
@ -150,6 +150,29 @@ public class ConnectionService extends android.telecom.ConnectionService {
|
|||
return connection;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Connection onCreateIncomingConnection(PhoneAccountHandle handle, ConnectionRequest request) {
|
||||
Bundle extras = request.getExtras();
|
||||
String accountJid = extras.getString("account");
|
||||
String withJid = extras.getString("with");
|
||||
String sessionId = extras.getString("sessionId");
|
||||
|
||||
Account account = xmppConnectionService.findAccountByJid(Jid.of(accountJid));
|
||||
Jid with = Jid.of(withJid);
|
||||
|
||||
CheogramConnection connection = new CheogramConnection(account, with, null);
|
||||
connection.setSessionId(sessionId);
|
||||
connection.setAddress(
|
||||
Uri.fromParts("tel", with.getLocal(), null),
|
||||
TelecomManager.PRESENTATION_ALLOWED
|
||||
);
|
||||
connection.setRinging();
|
||||
|
||||
xmppConnectionService.setOnRtpConnectionUpdateListener(connection);
|
||||
|
||||
return connection;
|
||||
}
|
||||
|
||||
public class CheogramConnection extends Connection implements XmppConnectionService.OnJingleRtpConnectionUpdate {
|
||||
protected Account account;
|
||||
protected Jid with;
|
||||
|
@ -203,6 +226,8 @@ public class ConnectionService extends android.telecom.ConnectionService {
|
|||
setInitialized();
|
||||
} else if (state == RtpEndUserState.RINGING) {
|
||||
setDialing();
|
||||
} else if (state == RtpEndUserState.INCOMING_CALL) {
|
||||
setRinging();
|
||||
} else if (state == RtpEndUserState.CONNECTED) {
|
||||
xmppConnectionService.setDiallerIntegrationActive(true);
|
||||
setActive();
|
||||
|
@ -235,6 +260,15 @@ public class ConnectionService extends android.telecom.ConnectionService {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onAnswer() {
|
||||
// For incoming calls, a connection update may not have been triggered before answering
|
||||
// so we have to acquire the rtp connection object here
|
||||
this.rtpConnection = xmppConnectionService.getJingleConnectionManager().findJingleRtpConnection(account, with, sessionId);
|
||||
|
||||
rtpConnection.get().acceptCall();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDisconnect() {
|
||||
if (rtpConnection == null || rtpConnection.get() == null) {
|
||||
|
|
|
@ -599,7 +599,7 @@ public class Contact implements ListItem, Blockable {
|
|||
"/" + getJid().asBareJid().toString();
|
||||
}
|
||||
|
||||
protected PhoneAccountHandle phoneAccountHandle() {
|
||||
public PhoneAccountHandle phoneAccountHandle() {
|
||||
ComponentName componentName = new ComponentName(
|
||||
"com.cheogram.android",
|
||||
"com.cheogram.android.ConnectionService"
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
package eu.siacs.conversations.services;
|
||||
|
||||
import android.Manifest;
|
||||
import android.app.Notification;
|
||||
import android.app.NotificationChannel;
|
||||
import android.app.NotificationChannelGroup;
|
||||
|
@ -8,6 +9,7 @@ import android.app.PendingIntent;
|
|||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.SharedPreferences;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.res.Resources;
|
||||
import android.graphics.Bitmap;
|
||||
import android.graphics.Typeface;
|
||||
|
@ -16,9 +18,12 @@ import android.media.Ringtone;
|
|||
import android.media.RingtoneManager;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.SystemClock;
|
||||
import android.os.Vibrator;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.telecom.PhoneAccountHandle;
|
||||
import android.telecom.TelecomManager;
|
||||
import android.text.SpannableString;
|
||||
import android.text.style.StyleSpan;
|
||||
import android.util.DisplayMetrics;
|
||||
|
@ -423,7 +428,63 @@ public class NotificationService {
|
|||
notify(DELIVERY_FAILED_NOTIFICATION_ID, summaryNotification);
|
||||
}
|
||||
|
||||
private synchronized boolean tryRingingWithDialerUI(final AbstractJingleConnection.Id id, final Set<Media> media) {
|
||||
if (mXmppConnectionService.checkSelfPermission(Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) {
|
||||
// We cannot request audio permission in Dialer UI
|
||||
// when Dialer is shown over keyguard, the user cannot even necessarily
|
||||
// see notifications.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (media.size() != 1 || !media.contains(Media.AUDIO)) {
|
||||
// Currently our ConnectionService only handles single audio calls
|
||||
Log.w(Config.LOGTAG, "only audio calls can be handled by cheogram connection service");
|
||||
return false;
|
||||
}
|
||||
|
||||
PhoneAccountHandle handle = null;
|
||||
for (Contact contact : id.account.getRoster().getContacts()) {
|
||||
if (!contact.getJid().getDomain().equals(id.with.getDomain())) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!contact.getPresences().anyIdentity("gateway", "pstn")) {
|
||||
continue;
|
||||
}
|
||||
|
||||
handle = contact.phoneAccountHandle();
|
||||
break;
|
||||
}
|
||||
|
||||
if (handle == null) {
|
||||
Log.w(Config.LOGTAG, "Could not find phone account handle for " + id.account.getJid().toString());
|
||||
return false;
|
||||
}
|
||||
|
||||
Bundle callInfo = new Bundle();
|
||||
callInfo.putString("account", id.account.getJid().toString());
|
||||
callInfo.putString("with", id.with.toString());
|
||||
callInfo.putString("sessionId", id.sessionId);
|
||||
|
||||
TelecomManager telecomManager = mXmppConnectionService.getSystemService(TelecomManager.class);
|
||||
|
||||
try {
|
||||
telecomManager.addNewIncomingCall(handle, callInfo);
|
||||
} catch (SecurityException e) {
|
||||
// If the account is not registered or enabled, it could result in a security exception
|
||||
// Just fall back to the built-in UI in this case.
|
||||
Log.w(Config.LOGTAG, e);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public synchronized void startRinging(final AbstractJingleConnection.Id id, final Set<Media> media) {
|
||||
if (tryRingingWithDialerUI(id, media)) {
|
||||
return;
|
||||
}
|
||||
|
||||
showIncomingCallNotification(id, media);
|
||||
final NotificationManager notificationManager = (NotificationManager) mXmppConnectionService.getSystemService(Context.NOTIFICATION_SERVICE);
|
||||
final int currentInterruptionFilter;
|
||||
|
|
Loading…
Reference in a new issue