mirror of
https://github.com/oxen-io/session-android.git
synced 2024-11-24 02:25:19 +00:00
Correctly manage busy state for (webrtc, redphone, pstn) tuple
Fixes #6156 // FREEBIE
This commit is contained in:
parent
d92cbfe305
commit
fb8440f886
@ -18,15 +18,20 @@
|
|||||||
package org.thoughtcrime.redphone;
|
package org.thoughtcrime.redphone;
|
||||||
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.content.SharedPreferences;
|
import android.content.SharedPreferences;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.HandlerThread;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.os.ResultReceiver;
|
||||||
import android.preference.PreferenceManager;
|
import android.preference.PreferenceManager;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.annotation.WorkerThread;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -40,8 +45,7 @@ import org.thoughtcrime.redphone.call.InitiatingCallManager;
|
|||||||
import org.thoughtcrime.redphone.call.LockManager;
|
import org.thoughtcrime.redphone.call.LockManager;
|
||||||
import org.thoughtcrime.redphone.call.ResponderCallManager;
|
import org.thoughtcrime.redphone.call.ResponderCallManager;
|
||||||
import org.thoughtcrime.redphone.crypto.zrtp.SASInfo;
|
import org.thoughtcrime.redphone.crypto.zrtp.SASInfo;
|
||||||
import org.thoughtcrime.redphone.pstn.CallStateView;
|
import org.thoughtcrime.redphone.pstn.IncomingPstnCallReceiver;
|
||||||
import org.thoughtcrime.redphone.pstn.IncomingPstnCallListener;
|
|
||||||
import org.thoughtcrime.redphone.signaling.OtpCounterProvider;
|
import org.thoughtcrime.redphone.signaling.OtpCounterProvider;
|
||||||
import org.thoughtcrime.redphone.signaling.SessionDescriptor;
|
import org.thoughtcrime.redphone.signaling.SessionDescriptor;
|
||||||
import org.thoughtcrime.redphone.signaling.SignalingException;
|
import org.thoughtcrime.redphone.signaling.SignalingException;
|
||||||
@ -56,13 +60,16 @@ import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
|||||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||||
import org.thoughtcrime.securesms.service.KeyCachingService;
|
import org.thoughtcrime.securesms.service.KeyCachingService;
|
||||||
|
import org.thoughtcrime.securesms.service.WebRtcCallService;
|
||||||
import org.thoughtcrime.securesms.util.Base64;
|
import org.thoughtcrime.securesms.util.Base64;
|
||||||
import org.thoughtcrime.securesms.util.ServiceUtil;
|
import org.thoughtcrime.securesms.util.ServiceUtil;
|
||||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||||
|
import org.whispersystems.signalservice.internal.util.concurrent.SettableFuture;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import de.greenrobot.event.EventBus;
|
import de.greenrobot.event.EventBus;
|
||||||
|
|
||||||
@ -75,7 +82,7 @@ import de.greenrobot.event.EventBus;
|
|||||||
* @author Moxie Marlinspike
|
* @author Moxie Marlinspike
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class RedPhoneService extends Service implements CallStateListener, CallStateView {
|
public class RedPhoneService extends Service implements CallStateListener {
|
||||||
|
|
||||||
private static final String TAG = RedPhoneService.class.getSimpleName();
|
private static final String TAG = RedPhoneService.class.getSimpleName();
|
||||||
|
|
||||||
@ -88,6 +95,7 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
|||||||
public static final String EXTRA_REMOTE_NUMBER = "remote_number";
|
public static final String EXTRA_REMOTE_NUMBER = "remote_number";
|
||||||
public static final String EXTRA_SESSION_DESCRIPTOR = "session_descriptor";
|
public static final String EXTRA_SESSION_DESCRIPTOR = "session_descriptor";
|
||||||
public static final String EXTRA_MUTE = "mute_value";
|
public static final String EXTRA_MUTE = "mute_value";
|
||||||
|
public static final String EXTRA_RESULT_RECEIVER = "result_receiver";
|
||||||
|
|
||||||
public static final String ACTION_INCOMING_CALL = "org.thoughtcrime.redphone.RedPhoneService.INCOMING_CALL";
|
public static final String ACTION_INCOMING_CALL = "org.thoughtcrime.redphone.RedPhoneService.INCOMING_CALL";
|
||||||
public static final String ACTION_OUTGOING_CALL = "org.thoughtcrime.redphone.RedPhoneService.OUTGOING_CALL";
|
public static final String ACTION_OUTGOING_CALL = "org.thoughtcrime.redphone.RedPhoneService.OUTGOING_CALL";
|
||||||
@ -95,6 +103,7 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
|||||||
public static final String ACTION_DENY_CALL = "org.thoughtcrime.redphone.RedPhoneService.DENY_CALL";
|
public static final String ACTION_DENY_CALL = "org.thoughtcrime.redphone.RedPhoneService.DENY_CALL";
|
||||||
public static final String ACTION_HANGUP_CALL = "org.thoughtcrime.redphone.RedPhoneService.HANGUP";
|
public static final String ACTION_HANGUP_CALL = "org.thoughtcrime.redphone.RedPhoneService.HANGUP";
|
||||||
public static final String ACTION_SET_MUTE = "org.thoughtcrime.redphone.RedPhoneService.SET_MUTE";
|
public static final String ACTION_SET_MUTE = "org.thoughtcrime.redphone.RedPhoneService.SET_MUTE";
|
||||||
|
public static final String ACTION_IS_IN_CALL_QUERY = "org.thoughtcrime.redphone.RedPhoneService.IS_IN_CALL";
|
||||||
|
|
||||||
private final Handler serviceHandler = new Handler();
|
private final Handler serviceHandler = new Handler();
|
||||||
|
|
||||||
@ -108,7 +117,7 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
|||||||
private LockManager lockManager;
|
private LockManager lockManager;
|
||||||
private UncaughtExceptionHandlerManager uncaughtExceptionHandlerManager;
|
private UncaughtExceptionHandlerManager uncaughtExceptionHandlerManager;
|
||||||
|
|
||||||
private IncomingPstnCallListener pstnCallListener;
|
private IncomingPstnCallReceiver pstnCallListener;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onCreate() {
|
public void onCreate() {
|
||||||
@ -150,6 +159,7 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
|||||||
else if (intent.getAction().equals(ACTION_DENY_CALL)) handleDenyCall(intent);
|
else if (intent.getAction().equals(ACTION_DENY_CALL)) handleDenyCall(intent);
|
||||||
else if (intent.getAction().equals(ACTION_HANGUP_CALL)) handleHangupCall(intent);
|
else if (intent.getAction().equals(ACTION_HANGUP_CALL)) handleHangupCall(intent);
|
||||||
else if (intent.getAction().equals(ACTION_SET_MUTE)) handleSetMute(intent);
|
else if (intent.getAction().equals(ACTION_SET_MUTE)) handleSetMute(intent);
|
||||||
|
else if (intent.getAction().equals(ACTION_IS_IN_CALL_QUERY)) handleIsInCallQuery(intent);
|
||||||
else Log.w(TAG, "Unhandled intent: " + intent.getAction() + ", state: " + state);
|
else Log.w(TAG, "Unhandled intent: " + intent.getAction() + ", state: " + state);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -161,7 +171,7 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
|||||||
}
|
}
|
||||||
|
|
||||||
private void initializePstnCallListener() {
|
private void initializePstnCallListener() {
|
||||||
pstnCallListener = new IncomingPstnCallListener(this);
|
pstnCallListener = new IncomingPstnCallReceiver();
|
||||||
registerReceiver(pstnCallListener, new IntentFilter("android.intent.action.PHONE_STATE"));
|
registerReceiver(pstnCallListener, new IntentFilter("android.intent.action.PHONE_STATE"));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -279,12 +289,22 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleIsInCallQuery(Intent intent) {
|
||||||
|
ResultReceiver resultReceiver = intent.getParcelableExtra(EXTRA_RESULT_RECEIVER);
|
||||||
|
|
||||||
|
if (resultReceiver != null) {
|
||||||
|
resultReceiver.send(state != STATE_IDLE ? 1 : 0, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Helper Methods
|
/// Helper Methods
|
||||||
|
|
||||||
private boolean isBusy() {
|
private boolean isBusy() {
|
||||||
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
|
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
|
||||||
return ((currentCallManager != null && state != STATE_IDLE) ||
|
|
||||||
telephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE);
|
return ((currentCallManager != null && state != STATE_IDLE) ||
|
||||||
|
telephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE) ||
|
||||||
|
WebRtcCallService.isCallActive(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isIdle() {
|
private boolean isIdle() {
|
||||||
@ -528,22 +548,6 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isInCall() {
|
|
||||||
switch(state) {
|
|
||||||
case STATE_IDLE:
|
|
||||||
return false;
|
|
||||||
case STATE_DIALING:
|
|
||||||
case STATE_RINGING:
|
|
||||||
case STATE_ANSWERING:
|
|
||||||
case STATE_CONNECTED:
|
|
||||||
return true;
|
|
||||||
default:
|
|
||||||
Log.e(TAG, "Unhandled call state: " + state);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private static class ProximityLockRelease implements Thread.UncaughtExceptionHandler {
|
private static class ProximityLockRelease implements Thread.UncaughtExceptionHandler {
|
||||||
private final LockManager lockManager;
|
private final LockManager lockManager;
|
||||||
|
|
||||||
@ -557,4 +561,47 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
|||||||
lockManager.updatePhoneState(LockManager.PhoneState.IDLE);
|
lockManager.updatePhoneState(LockManager.PhoneState.IDLE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WorkerThread
|
||||||
|
public static boolean isCallActive(Context context) {
|
||||||
|
Log.w(TAG, "isCallActive()");
|
||||||
|
|
||||||
|
HandlerThread handlerThread = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
handlerThread = new HandlerThread("webrtc-callback");
|
||||||
|
handlerThread.start();
|
||||||
|
|
||||||
|
final SettableFuture<Boolean> future = new SettableFuture<>();
|
||||||
|
|
||||||
|
ResultReceiver resultReceiver = new ResultReceiver(new Handler(handlerThread.getLooper())) {
|
||||||
|
protected void onReceiveResult(int resultCode, Bundle resultData) {
|
||||||
|
Log.w(TAG, "onReceiveResult");
|
||||||
|
future.set(resultCode == 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Intent intent = new Intent(context, RedPhoneService.class);
|
||||||
|
intent.setAction(ACTION_IS_IN_CALL_QUERY);
|
||||||
|
intent.putExtra(EXTRA_RESULT_RECEIVER, resultReceiver);
|
||||||
|
|
||||||
|
context.startService(intent);
|
||||||
|
|
||||||
|
Log.w(TAG, "Blocking on result...");
|
||||||
|
return future.get();
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
Log.w(TAG, e);
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
if (handlerThread != null) handlerThread.quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void isCallActive(Context context, ResultReceiver resultReceiver) {
|
||||||
|
Intent intent = new Intent(context, RedPhoneService.class);
|
||||||
|
intent.setAction(ACTION_IS_IN_CALL_QUERY);
|
||||||
|
intent.putExtra(EXTRA_RESULT_RECEIVER, resultReceiver);
|
||||||
|
|
||||||
|
context.startService(intent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,10 +0,0 @@
|
|||||||
package org.thoughtcrime.redphone.pstn;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Provides access to the state of a call
|
|
||||||
*
|
|
||||||
* @author Stuart O. Anderson
|
|
||||||
*/
|
|
||||||
public interface CallStateView {
|
|
||||||
boolean isInCall();
|
|
||||||
}
|
|
@ -1,51 +0,0 @@
|
|||||||
package org.thoughtcrime.redphone.pstn;
|
|
||||||
|
|
||||||
import android.content.BroadcastReceiver;
|
|
||||||
import android.content.Context;
|
|
||||||
import android.content.Intent;
|
|
||||||
import android.telephony.TelephonyManager;
|
|
||||||
import android.util.Log;
|
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Listens for incoming PSTN calls and rejects them if a RedPhone call is already in progress.
|
|
||||||
*
|
|
||||||
* Unstable use of reflection employed to gain access to ITelephony.
|
|
||||||
*
|
|
||||||
* @author Stuart O. Anderson
|
|
||||||
*/
|
|
||||||
public class IncomingPstnCallListener extends BroadcastReceiver {
|
|
||||||
private static final String TAG = IncomingPstnCallListener.class.getName();
|
|
||||||
private final CallStateView callState;
|
|
||||||
|
|
||||||
public IncomingPstnCallListener(CallStateView callState) {
|
|
||||||
this.callState = callState;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public void onReceive(Context context, Intent intent) {
|
|
||||||
if(!(intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER) != null
|
|
||||||
&& intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING)
|
|
||||||
&& callState.isInCall())) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
Log.d(TAG, "Attempting to deny incoming PSTN call.");
|
|
||||||
TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
|
|
||||||
try {
|
|
||||||
Method getTelephony = tm.getClass().getDeclaredMethod("getITelephony");
|
|
||||||
getTelephony.setAccessible(true);
|
|
||||||
Object telephonyService = getTelephony.invoke(tm);
|
|
||||||
Method endCall = telephonyService.getClass().getDeclaredMethod("endCall");
|
|
||||||
endCall.invoke(telephonyService);
|
|
||||||
Log.d(TAG, "Denied Incoming Call From: " + intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER));
|
|
||||||
} catch (NoSuchMethodException e) {
|
|
||||||
Log.d(TAG, "Unable to access ITelephony API", e);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
Log.d(TAG, "Unable to access ITelephony API", e);
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
Log.d(TAG, "Unable to access ITelephony API", e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
@ -0,0 +1,80 @@
|
|||||||
|
package org.thoughtcrime.redphone.pstn;
|
||||||
|
|
||||||
|
import android.content.BroadcastReceiver;
|
||||||
|
import android.content.Context;
|
||||||
|
import android.content.Intent;
|
||||||
|
import android.os.Bundle;
|
||||||
|
import android.os.Handler;
|
||||||
|
import android.os.ResultReceiver;
|
||||||
|
import android.telephony.TelephonyManager;
|
||||||
|
import android.util.Log;
|
||||||
|
|
||||||
|
import org.thoughtcrime.redphone.RedPhoneService;
|
||||||
|
import org.thoughtcrime.securesms.service.WebRtcCallService;
|
||||||
|
|
||||||
|
import java.lang.reflect.InvocationTargetException;
|
||||||
|
import java.lang.reflect.Method;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Listens for incoming PSTN calls and rejects them if a RedPhone call is already in progress.
|
||||||
|
*
|
||||||
|
* Unstable use of reflection employed to gain access to ITelephony.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class IncomingPstnCallReceiver extends BroadcastReceiver {
|
||||||
|
|
||||||
|
private static final String TAG = IncomingPstnCallReceiver.class.getName();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onReceive(Context context, Intent intent) {
|
||||||
|
Log.w(TAG, "Checking incoming call...");
|
||||||
|
|
||||||
|
if (intent.getStringExtra(TelephonyManager.EXTRA_INCOMING_NUMBER) == null) {
|
||||||
|
Log.w(TAG, "Telephony event does not contain number...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!intent.getStringExtra(TelephonyManager.EXTRA_STATE).equals(TelephonyManager.EXTRA_STATE_RINGING)) {
|
||||||
|
Log.w(TAG, "Telephony event is not state rining...");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
InCallListener listener = new InCallListener(context, new Handler());
|
||||||
|
|
||||||
|
WebRtcCallService.isCallActive(context, listener);
|
||||||
|
RedPhoneService.isCallActive(context, listener);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static class InCallListener extends ResultReceiver {
|
||||||
|
|
||||||
|
private final Context context;
|
||||||
|
|
||||||
|
InCallListener(Context context, Handler handler) {
|
||||||
|
super(handler);
|
||||||
|
this.context = context.getApplicationContext();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected void onReceiveResult(int resultCode, Bundle resultData) {
|
||||||
|
if (resultCode == 1) {
|
||||||
|
Log.w(TAG, "Attempting to deny incoming PSTN call.");
|
||||||
|
|
||||||
|
TelephonyManager tm = (TelephonyManager)context.getSystemService(Context.TELEPHONY_SERVICE);
|
||||||
|
|
||||||
|
try {
|
||||||
|
Method getTelephony = tm.getClass().getDeclaredMethod("getITelephony");
|
||||||
|
getTelephony.setAccessible(true);
|
||||||
|
Object telephonyService = getTelephony.invoke(tm);
|
||||||
|
Method endCall = telephonyService.getClass().getDeclaredMethod("endCall");
|
||||||
|
endCall.invoke(telephonyService);
|
||||||
|
Log.w(TAG, "Denied Incoming Call.");
|
||||||
|
} catch (NoSuchMethodException e) {
|
||||||
|
Log.w(TAG, "Unable to access ITelephony API", e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
Log.w(TAG, "Unable to access ITelephony API", e);
|
||||||
|
} catch (InvocationTargetException e) {
|
||||||
|
Log.w(TAG, "Unable to access ITelephony API", e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -2,13 +2,18 @@ package org.thoughtcrime.securesms.service;
|
|||||||
|
|
||||||
|
|
||||||
import android.app.Service;
|
import android.app.Service;
|
||||||
|
import android.content.Context;
|
||||||
import android.content.Intent;
|
import android.content.Intent;
|
||||||
import android.content.IntentFilter;
|
import android.content.IntentFilter;
|
||||||
import android.media.AudioManager;
|
import android.media.AudioManager;
|
||||||
|
import android.os.Bundle;
|
||||||
import android.os.Handler;
|
import android.os.Handler;
|
||||||
|
import android.os.HandlerThread;
|
||||||
import android.os.IBinder;
|
import android.os.IBinder;
|
||||||
|
import android.os.ResultReceiver;
|
||||||
import android.support.annotation.NonNull;
|
import android.support.annotation.NonNull;
|
||||||
import android.support.annotation.Nullable;
|
import android.support.annotation.Nullable;
|
||||||
|
import android.support.annotation.WorkerThread;
|
||||||
import android.telephony.TelephonyManager;
|
import android.telephony.TelephonyManager;
|
||||||
import android.text.TextUtils;
|
import android.text.TextUtils;
|
||||||
import android.util.Log;
|
import android.util.Log;
|
||||||
@ -16,10 +21,10 @@ import android.util.Pair;
|
|||||||
|
|
||||||
import com.google.protobuf.InvalidProtocolBufferException;
|
import com.google.protobuf.InvalidProtocolBufferException;
|
||||||
|
|
||||||
|
import org.thoughtcrime.redphone.RedPhoneService;
|
||||||
import org.thoughtcrime.redphone.audio.IncomingRinger;
|
import org.thoughtcrime.redphone.audio.IncomingRinger;
|
||||||
import org.thoughtcrime.redphone.call.LockManager;
|
import org.thoughtcrime.redphone.call.LockManager;
|
||||||
import org.thoughtcrime.redphone.pstn.CallStateView;
|
import org.thoughtcrime.redphone.pstn.IncomingPstnCallReceiver;
|
||||||
import org.thoughtcrime.redphone.pstn.IncomingPstnCallListener;
|
|
||||||
import org.thoughtcrime.redphone.util.AudioUtils;
|
import org.thoughtcrime.redphone.util.AudioUtils;
|
||||||
import org.thoughtcrime.redphone.util.UncaughtExceptionHandlerManager;
|
import org.thoughtcrime.redphone.util.UncaughtExceptionHandlerManager;
|
||||||
import org.thoughtcrime.securesms.ApplicationContext;
|
import org.thoughtcrime.securesms.ApplicationContext;
|
||||||
@ -71,6 +76,7 @@ import org.whispersystems.signalservice.api.messages.calls.TurnServerInfo;
|
|||||||
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
import org.whispersystems.signalservice.api.push.SignalServiceAddress;
|
||||||
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
|
import org.whispersystems.signalservice.api.push.exceptions.UnregisteredUserException;
|
||||||
import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
import org.whispersystems.signalservice.api.util.InvalidNumberException;
|
||||||
|
import org.whispersystems.signalservice.internal.util.concurrent.SettableFuture;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.nio.ByteBuffer;
|
import java.nio.ByteBuffer;
|
||||||
@ -93,7 +99,7 @@ import static org.thoughtcrime.securesms.webrtc.CallNotificationManager.TYPE_EST
|
|||||||
import static org.thoughtcrime.securesms.webrtc.CallNotificationManager.TYPE_INCOMING_RINGING;
|
import static org.thoughtcrime.securesms.webrtc.CallNotificationManager.TYPE_INCOMING_RINGING;
|
||||||
import static org.thoughtcrime.securesms.webrtc.CallNotificationManager.TYPE_OUTGOING_RINGING;
|
import static org.thoughtcrime.securesms.webrtc.CallNotificationManager.TYPE_OUTGOING_RINGING;
|
||||||
|
|
||||||
public class WebRtcCallService extends Service implements InjectableType, CallStateView, PeerConnection.Observer, DataChannel.Observer {
|
public class WebRtcCallService extends Service implements InjectableType, PeerConnection.Observer, DataChannel.Observer {
|
||||||
|
|
||||||
private static final String TAG = WebRtcCallService.class.getSimpleName();
|
private static final String TAG = WebRtcCallService.class.getSimpleName();
|
||||||
|
|
||||||
@ -111,6 +117,7 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
|
|||||||
public static final String EXTRA_ICE_SDP = "ice_sdp";
|
public static final String EXTRA_ICE_SDP = "ice_sdp";
|
||||||
public static final String EXTRA_ICE_SDP_MID = "ice_sdp_mid";
|
public static final String EXTRA_ICE_SDP_MID = "ice_sdp_mid";
|
||||||
public static final String EXTRA_ICE_SDP_LINE_INDEX = "ice_sdp_line_index";
|
public static final String EXTRA_ICE_SDP_LINE_INDEX = "ice_sdp_line_index";
|
||||||
|
public static final String EXTRA_RESULT_RECEIVER = "result_receiver";
|
||||||
|
|
||||||
public static final String ACTION_INCOMING_CALL = "CALL_INCOMING";
|
public static final String ACTION_INCOMING_CALL = "CALL_INCOMING";
|
||||||
public static final String ACTION_OUTGOING_CALL = "CALL_OUTGOING";
|
public static final String ACTION_OUTGOING_CALL = "CALL_OUTGOING";
|
||||||
@ -120,6 +127,7 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
|
|||||||
public static final String ACTION_SET_MUTE_AUDIO = "SET_MUTE_AUDIO";
|
public static final String ACTION_SET_MUTE_AUDIO = "SET_MUTE_AUDIO";
|
||||||
public static final String ACTION_SET_MUTE_VIDEO = "SET_MUTE_VIDEO";
|
public static final String ACTION_SET_MUTE_VIDEO = "SET_MUTE_VIDEO";
|
||||||
public static final String ACTION_CHECK_TIMEOUT = "CHECK_TIMEOUT";
|
public static final String ACTION_CHECK_TIMEOUT = "CHECK_TIMEOUT";
|
||||||
|
public static final String ACTION_IS_IN_CALL_QUERY = "IS_IN_CALL";
|
||||||
|
|
||||||
public static final String ACTION_RESPONSE_MESSAGE = "RESPONSE_MESSAGE";
|
public static final String ACTION_RESPONSE_MESSAGE = "RESPONSE_MESSAGE";
|
||||||
public static final String ACTION_ICE_MESSAGE = "ICE_MESSAGE";
|
public static final String ACTION_ICE_MESSAGE = "ICE_MESSAGE";
|
||||||
@ -145,6 +153,9 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
|
|||||||
private OutgoingRinger outgoingRinger;
|
private OutgoingRinger outgoingRinger;
|
||||||
private LockManager lockManager;
|
private LockManager lockManager;
|
||||||
|
|
||||||
|
private IncomingPstnCallReceiver callReceiver;
|
||||||
|
private UncaughtExceptionHandlerManager uncaughtExceptionHandlerManager;
|
||||||
|
|
||||||
@Nullable private Long callId;
|
@Nullable private Long callId;
|
||||||
@Nullable private Recipient recipient;
|
@Nullable private Recipient recipient;
|
||||||
@Nullable private PeerConnectionWrapper peerConnection;
|
@Nullable private PeerConnectionWrapper peerConnection;
|
||||||
@ -165,7 +176,8 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
|
|||||||
|
|
||||||
initializeResources();
|
initializeResources();
|
||||||
initializeRingers();
|
initializeRingers();
|
||||||
initializePstnCallListener();
|
|
||||||
|
registerIncomingPstnCallReceiver();
|
||||||
registerUncaughtExceptionHandler();
|
registerUncaughtExceptionHandler();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -194,12 +206,26 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
|
|||||||
else if (intent.getAction().equals(ACTION_ICE_CONNECTED)) handleIceConnected(intent);
|
else if (intent.getAction().equals(ACTION_ICE_CONNECTED)) handleIceConnected(intent);
|
||||||
else if (intent.getAction().equals(ACTION_CALL_CONNECTED)) handleCallConnected(intent);
|
else if (intent.getAction().equals(ACTION_CALL_CONNECTED)) handleCallConnected(intent);
|
||||||
else if (intent.getAction().equals(ACTION_CHECK_TIMEOUT)) handleCheckTimeout(intent);
|
else if (intent.getAction().equals(ACTION_CHECK_TIMEOUT)) handleCheckTimeout(intent);
|
||||||
|
else if (intent.getAction().equals(ACTION_IS_IN_CALL_QUERY)) handleIsInCallQuery(intent);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
return START_NOT_STICKY;
|
return START_NOT_STICKY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void onDestroy() {
|
||||||
|
super.onDestroy();
|
||||||
|
|
||||||
|
if (callReceiver != null) {
|
||||||
|
unregisterReceiver(callReceiver);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (uncaughtExceptionHandlerManager != null) {
|
||||||
|
uncaughtExceptionHandlerManager.unregister();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Initializers
|
// Initializers
|
||||||
|
|
||||||
private void initializeRingers() {
|
private void initializeRingers() {
|
||||||
@ -207,11 +233,6 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
|
|||||||
this.incomingRinger = new IncomingRinger(this);
|
this.incomingRinger = new IncomingRinger(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void initializePstnCallListener() {
|
|
||||||
IncomingPstnCallListener pstnCallListener = new IncomingPstnCallListener(this);
|
|
||||||
registerReceiver(pstnCallListener, new IntentFilter("android.intent.action.PHONE_STATE"));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void initializeResources() {
|
private void initializeResources() {
|
||||||
ApplicationContext.getInstance(this).injectDependencies(this);
|
ApplicationContext.getInstance(this).injectDependencies(this);
|
||||||
|
|
||||||
@ -223,8 +244,13 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
|
|||||||
this.accountManager.setSoTimeoutMillis(TimeUnit.SECONDS.toMillis(10));
|
this.accountManager.setSoTimeoutMillis(TimeUnit.SECONDS.toMillis(10));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void registerIncomingPstnCallReceiver() {
|
||||||
|
callReceiver = new IncomingPstnCallReceiver();
|
||||||
|
registerReceiver(callReceiver, new IntentFilter("android.intent.action.PHONE_STATE"));
|
||||||
|
}
|
||||||
|
|
||||||
private void registerUncaughtExceptionHandler() {
|
private void registerUncaughtExceptionHandler() {
|
||||||
UncaughtExceptionHandlerManager uncaughtExceptionHandlerManager = new UncaughtExceptionHandlerManager();
|
uncaughtExceptionHandlerManager = new UncaughtExceptionHandlerManager();
|
||||||
uncaughtExceptionHandlerManager.registerHandler(new ProximityLockRelease(lockManager));
|
uncaughtExceptionHandlerManager.registerHandler(new ProximityLockRelease(lockManager));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -515,6 +541,14 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void handleIsInCallQuery(Intent intent) {
|
||||||
|
ResultReceiver resultReceiver = intent.getParcelableExtra(EXTRA_RESULT_RECEIVER);
|
||||||
|
|
||||||
|
if (resultReceiver != null) {
|
||||||
|
resultReceiver.send(callState != CallState.STATE_IDLE ? 1 : 0, null);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void insertMissedCall(@NonNull Recipient recipient, boolean signal) {
|
private void insertMissedCall(@NonNull Recipient recipient, boolean signal) {
|
||||||
Pair<Long, Long> messageAndThreadId = DatabaseFactory.getSmsDatabase(this).insertMissedCall(recipient.getNumber());
|
Pair<Long, Long> messageAndThreadId = DatabaseFactory.getSmsDatabase(this).insertMissedCall(recipient.getNumber());
|
||||||
MessageNotifier.updateNotification(this, KeyCachingService.getMasterSecret(this),
|
MessageNotifier.updateNotification(this, KeyCachingService.getMasterSecret(this),
|
||||||
@ -643,7 +677,10 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
|
|||||||
|
|
||||||
private boolean isBusy() {
|
private boolean isBusy() {
|
||||||
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
|
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
|
||||||
return callState != CallState.STATE_IDLE || telephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE;
|
|
||||||
|
return callState != CallState.STATE_IDLE ||
|
||||||
|
telephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE ||
|
||||||
|
RedPhoneService.isCallActive(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
private boolean isIdle() {
|
private boolean isIdle() {
|
||||||
@ -793,11 +830,6 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean isInCall() {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// PeerConnection Observer
|
/// PeerConnection Observer
|
||||||
@Override
|
@Override
|
||||||
public void onSignalingChange(PeerConnection.SignalingState newState) {
|
public void onSignalingChange(PeerConnection.SignalingState newState) {
|
||||||
@ -1067,4 +1099,47 @@ public class WebRtcCallService extends Service implements InjectableType, CallSt
|
|||||||
throw new AssertionError(throwable);
|
throw new AssertionError(throwable);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@WorkerThread
|
||||||
|
public static boolean isCallActive(Context context) {
|
||||||
|
Log.w(TAG, "isCallActive()");
|
||||||
|
|
||||||
|
HandlerThread handlerThread = null;
|
||||||
|
|
||||||
|
try {
|
||||||
|
handlerThread = new HandlerThread("webrtc-callback");
|
||||||
|
handlerThread.start();
|
||||||
|
|
||||||
|
final SettableFuture<Boolean> future = new SettableFuture<>();
|
||||||
|
|
||||||
|
ResultReceiver resultReceiver = new ResultReceiver(new Handler(handlerThread.getLooper())) {
|
||||||
|
protected void onReceiveResult(int resultCode, Bundle resultData) {
|
||||||
|
Log.w(TAG, "Got result...");
|
||||||
|
future.set(resultCode == 1);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Intent intent = new Intent(context, WebRtcCallService.class);
|
||||||
|
intent.setAction(ACTION_IS_IN_CALL_QUERY);
|
||||||
|
intent.putExtra(EXTRA_RESULT_RECEIVER, resultReceiver);
|
||||||
|
|
||||||
|
context.startService(intent);
|
||||||
|
|
||||||
|
Log.w(TAG, "Blocking on result...");
|
||||||
|
return future.get();
|
||||||
|
} catch (InterruptedException | ExecutionException e) {
|
||||||
|
Log.w(TAG, e);
|
||||||
|
return false;
|
||||||
|
} finally {
|
||||||
|
if (handlerThread != null) handlerThread.quit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void isCallActive(Context context, ResultReceiver resultReceiver) {
|
||||||
|
Intent intent = new Intent(context, WebRtcCallService.class);
|
||||||
|
intent.setAction(ACTION_IS_IN_CALL_QUERY);
|
||||||
|
intent.putExtra(EXTRA_RESULT_RECEIVER, resultReceiver);
|
||||||
|
|
||||||
|
context.startService(intent);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user