mirror of
https://github.com/oxen-io/session-android.git
synced 2024-12-22 07:57:30 +00:00
Switch RedPhone view<->service interaction to use event bus
Fixes #4234 // FREEBIE
This commit is contained in:
parent
3e798a9863
commit
5b6f49c993
@ -2,4 +2,7 @@
|
||||
-keepattributes SourceFile,LineNumberTable
|
||||
-keep class org.whispersystems.** { *; }
|
||||
-keep class org.thoughtcrime.securesms.** { *; }
|
||||
-keepclassmembers class ** {
|
||||
public void onEvent*(**);
|
||||
}
|
||||
|
||||
|
@ -21,34 +21,32 @@ package org.thoughtcrime.redphone;
|
||||
import android.app.Activity;
|
||||
import android.app.AlertDialog;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.ComponentName;
|
||||
import android.content.Context;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.ServiceConnection;
|
||||
import android.content.res.Configuration;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Build;
|
||||
import android.os.Bundle;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.util.Log;
|
||||
import android.view.Window;
|
||||
import android.view.WindowManager;
|
||||
|
||||
import com.afollestad.materialdialogs.AlertDialogWrapper;
|
||||
|
||||
import org.thoughtcrime.redphone.crypto.zrtp.SASInfo;
|
||||
import org.thoughtcrime.redphone.ui.CallControls;
|
||||
import org.thoughtcrime.redphone.ui.CallScreen;
|
||||
import org.thoughtcrime.redphone.util.AudioUtils;
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.events.RedPhoneEvent;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
|
||||
import de.greenrobot.event.EventBus;
|
||||
|
||||
/**
|
||||
* The main UI class for RedPhone. Most of the heavy lifting is
|
||||
* done by RedPhoneService, so this activity is mostly responsible
|
||||
@ -62,40 +60,9 @@ public class RedPhone extends Activity {
|
||||
|
||||
private static final String TAG = RedPhone.class.getSimpleName();
|
||||
|
||||
private static final int REMOTE_TERMINATE = 0;
|
||||
private static final int LOCAL_TERMINATE = 1;
|
||||
|
||||
public static final int STATE_IDLE = 0;
|
||||
public static final int STATE_RINGING = 2;
|
||||
public static final int STATE_DIALING = 3;
|
||||
public static final int STATE_ANSWERING = 4;
|
||||
public static final int STATE_CONNECTED = 5;
|
||||
|
||||
private static final int STANDARD_DELAY_FINISH = 3000;
|
||||
private static final int STANDARD_DELAY_FINISH = 1000;
|
||||
public static final int BUSY_SIGNAL_DELAY_FINISH = 5500;
|
||||
|
||||
public static final int HANDLE_CALL_CONNECTED = 0;
|
||||
public static final int HANDLE_WAITING_FOR_RESPONDER = 1;
|
||||
public static final int HANDLE_SERVER_FAILURE = 2;
|
||||
public static final int HANDLE_PERFORMING_HANDSHAKE = 3;
|
||||
public static final int HANDLE_HANDSHAKE_FAILED = 4;
|
||||
public static final int HANDLE_CONNECTING_TO_INITIATOR = 5;
|
||||
public static final int HANDLE_CALL_DISCONNECTED = 6;
|
||||
public static final int HANDLE_CALL_RINGING = 7;
|
||||
public static final int HANDLE_SERVER_MESSAGE = 9;
|
||||
public static final int HANDLE_RECIPIENT_UNAVAILABLE = 10;
|
||||
public static final int HANDLE_INCOMING_CALL = 11;
|
||||
public static final int HANDLE_OUTGOING_CALL = 12;
|
||||
public static final int HANDLE_CALL_BUSY = 13;
|
||||
public static final int HANDLE_LOGIN_FAILED = 14;
|
||||
public static final int HANDLE_CLIENT_FAILURE = 15;
|
||||
public static final int HANDLE_DEBUG_INFO = 16;
|
||||
public static final int HANDLE_NO_SUCH_USER = 17;
|
||||
|
||||
private final Handler callStateHandler = new CallStateHandler();
|
||||
|
||||
private int state;
|
||||
private RedPhoneService redPhoneService;
|
||||
private CallScreen callScreen;
|
||||
private BroadcastReceiver bluetoothStateReceiver;
|
||||
|
||||
@ -118,7 +85,7 @@ public class RedPhone extends Activity {
|
||||
super.onResume();
|
||||
|
||||
initializeScreenshotSecurity();
|
||||
initializeServiceBinding();
|
||||
EventBus.getDefault().registerSticky(this);
|
||||
registerBluetoothReceiver();
|
||||
}
|
||||
|
||||
@ -127,7 +94,7 @@ public class RedPhone extends Activity {
|
||||
public void onPause() {
|
||||
super.onPause();
|
||||
|
||||
unbindService(serviceConnection);
|
||||
EventBus.getDefault().unregister(this);
|
||||
unregisterReceiver(bluetoothStateReceiver);
|
||||
}
|
||||
|
||||
@ -136,12 +103,6 @@ public class RedPhone extends Activity {
|
||||
super.onConfigurationChanged(newConfiguration);
|
||||
}
|
||||
|
||||
private void initializeServiceBinding() {
|
||||
Log.w(TAG, "Binding to RedPhoneService...");
|
||||
Intent bindIntent = new Intent(this, RedPhoneService.class);
|
||||
bindService(bindIntent, serviceConnection, Context.BIND_AUTO_CREATE);
|
||||
}
|
||||
|
||||
private void initializeScreenshotSecurity() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH &&
|
||||
TextSecurePreferences.isScreenSecurityEnabled(this))
|
||||
@ -154,8 +115,6 @@ public class RedPhone extends Activity {
|
||||
|
||||
private void initializeResources() {
|
||||
callScreen = (CallScreen)findViewById(R.id.callScreen);
|
||||
state = STATE_IDLE;
|
||||
|
||||
callScreen.setHangupButtonListener(new HangupButtonListener());
|
||||
callScreen.setIncomingCallActionListener(new IncomingCallActionListener());
|
||||
callScreen.setMuteButtonListener(new MuteButtonListener());
|
||||
@ -170,140 +129,123 @@ public class RedPhone extends Activity {
|
||||
}
|
||||
|
||||
private void handleAnswerCall() {
|
||||
state = STATE_ANSWERING;
|
||||
callScreen.setActiveCall(redPhoneService.getRecipient(), getString(org.thoughtcrime.securesms.R.string.RedPhone_answering));
|
||||
RedPhoneEvent event = EventBus.getDefault().getStickyEvent(RedPhoneEvent.class);
|
||||
|
||||
if (event != null) {
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(org.thoughtcrime.securesms.R.string.RedPhone_answering));
|
||||
|
||||
Intent intent = new Intent(this, RedPhoneService.class);
|
||||
intent.setAction(RedPhoneService.ACTION_ANSWER_CALL);
|
||||
startService(intent);
|
||||
}
|
||||
}
|
||||
|
||||
private void handleDenyCall() {
|
||||
state = STATE_IDLE;
|
||||
RedPhoneEvent event = EventBus.getDefault().getStickyEvent(RedPhoneEvent.class);
|
||||
|
||||
if (event != null) {
|
||||
Intent intent = new Intent(this, RedPhoneService.class);
|
||||
intent.setAction(RedPhoneService.ACTION_DENY_CALL);
|
||||
startService(intent);
|
||||
|
||||
callScreen.setActiveCall(redPhoneService.getRecipient(), getString(org.thoughtcrime.securesms.R.string.RedPhone_ending_call));
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(org.thoughtcrime.securesms.R.string.RedPhone_ending_call));
|
||||
delayedFinish();
|
||||
}
|
||||
|
||||
private void handleIncomingCall(Recipient recipient) {
|
||||
state = STATE_RINGING;
|
||||
callScreen.setIncomingCall(redPhoneService.getRecipient());
|
||||
}
|
||||
|
||||
private void handleOutgoingCall(Recipient recipient) {
|
||||
state = STATE_DIALING;
|
||||
callScreen.setActiveCall(recipient, getString(org.thoughtcrime.securesms.R.string.RedPhone_dialing));
|
||||
private void handleIncomingCall(@NonNull RedPhoneEvent event) {
|
||||
callScreen.setIncomingCall(event.getRecipient());
|
||||
}
|
||||
|
||||
private void handleTerminate( int terminationType ) {
|
||||
private void handleOutgoingCall(@NonNull RedPhoneEvent event) {
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(org.thoughtcrime.securesms.R.string.RedPhone_dialing));
|
||||
}
|
||||
|
||||
private void handleTerminate(@NonNull Recipient recipient /*, int terminationType */) {
|
||||
Log.w(TAG, "handleTerminate called");
|
||||
Log.w(TAG, "Termination Stack:", new Exception());
|
||||
|
||||
if( state == STATE_DIALING ) {
|
||||
if (terminationType == LOCAL_TERMINATE) {
|
||||
callScreen.setActiveCall(redPhoneService.getRecipient(), getString(org.thoughtcrime.securesms.R.string.RedPhone_canceling_call));
|
||||
} else {
|
||||
callScreen.setActiveCall(redPhoneService.getRecipient(), getString(R.string.RedPhone_call_rejected));
|
||||
}
|
||||
} else if (state != STATE_IDLE) {
|
||||
callScreen.setActiveCall(redPhoneService.getRecipient(), getString(R.string.RedPhone_ending_call));
|
||||
}
|
||||
callScreen.setActiveCall(recipient, getString(R.string.RedPhone_ending_call));
|
||||
|
||||
state = STATE_IDLE;
|
||||
delayedFinish();
|
||||
}
|
||||
|
||||
private void handleCallRinging() {
|
||||
callScreen.setActiveCall(redPhoneService.getRecipient(), getString(R.string.RedPhone_ringing));
|
||||
private void handleCallRinging(@NonNull RedPhoneEvent event) {
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_ringing));
|
||||
}
|
||||
|
||||
private void handleCallBusy() {
|
||||
callScreen.setActiveCall(redPhoneService.getRecipient(), getString(R.string.RedPhone_busy));
|
||||
private void handleCallBusy(@NonNull RedPhoneEvent event) {
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_busy));
|
||||
|
||||
state = STATE_IDLE;
|
||||
delayedFinish(BUSY_SIGNAL_DELAY_FINISH);
|
||||
}
|
||||
|
||||
private void handleCallConnected(SASInfo sas) {
|
||||
private void handleCallConnected(@NonNull RedPhoneEvent event) {
|
||||
getWindow().addFlags(WindowManager.LayoutParams.FLAG_IGNORE_CHEEK_PRESSES);
|
||||
callScreen.setActiveCall(redPhoneService.getRecipient(), getString(R.string.RedPhone_connected), sas);
|
||||
|
||||
state = STATE_CONNECTED;
|
||||
redPhoneService.notifyCallConnectionUIUpdateComplete();
|
||||
callScreen.setActiveCall(event.getRecipient(),
|
||||
getString(R.string.RedPhone_connected),
|
||||
event.getExtra());
|
||||
}
|
||||
|
||||
private void handleDebugInfo( String info ) {
|
||||
// debugCard.setInfo( info );
|
||||
private void handleConnectingToInitiator(@NonNull RedPhoneEvent event) {
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_connecting));
|
||||
}
|
||||
|
||||
private void handleConnectingToInitiator() {
|
||||
callScreen.setActiveCall(redPhoneService.getRecipient(), getString(R.string.RedPhone_connecting));
|
||||
}
|
||||
|
||||
private void handleHandshakeFailed() {
|
||||
state = STATE_IDLE;
|
||||
callScreen.setActiveCall(redPhoneService.getRecipient(), getString(R.string.RedPhone_handshake_failed));
|
||||
private void handleHandshakeFailed(@NonNull RedPhoneEvent event) {
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_handshake_failed));
|
||||
delayedFinish();
|
||||
}
|
||||
|
||||
private void handleRecipientUnavailable() {
|
||||
state = STATE_IDLE;
|
||||
callScreen.setActiveCall(redPhoneService.getRecipient(), getString(R.string.RedPhone_recipient_unavailable));
|
||||
private void handleRecipientUnavailable(@NonNull RedPhoneEvent event) {
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_recipient_unavailable));
|
||||
delayedFinish();
|
||||
}
|
||||
|
||||
private void handlePerformingHandshake() {
|
||||
callScreen.setActiveCall(redPhoneService.getRecipient(), getString(R.string.RedPhone_performing_handshake));
|
||||
private void handlePerformingHandshake(@NonNull RedPhoneEvent event) {
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_performing_handshake));
|
||||
}
|
||||
|
||||
private void handleServerFailure() {
|
||||
state = STATE_IDLE;
|
||||
callScreen.setActiveCall(redPhoneService.getRecipient(), getString(R.string.RedPhone_network_failed));
|
||||
private void handleServerFailure(@NonNull RedPhoneEvent event) {
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_network_failed));
|
||||
delayedFinish();
|
||||
}
|
||||
|
||||
private void handleClientFailure(String msg) {
|
||||
state = STATE_IDLE;
|
||||
callScreen.setActiveCall(redPhoneService.getRecipient(), getString(R.string.RedPhone_client_failed));
|
||||
if( msg != null && !isFinishing() ) {
|
||||
private void handleClientFailure(final @NonNull RedPhoneEvent event) {
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_client_failed));
|
||||
if( event.getExtra() != null && !isFinishing() ) {
|
||||
AlertDialog.Builder ad = new AlertDialog.Builder(this);
|
||||
ad.setTitle(R.string.RedPhone_fatal_error);
|
||||
ad.setMessage(msg);
|
||||
ad.setMessage(event.getExtra());
|
||||
ad.setCancelable(false);
|
||||
ad.setPositiveButton(android.R.string.ok, new OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int arg) {
|
||||
RedPhone.this.handleTerminate(LOCAL_TERMINATE);
|
||||
RedPhone.this.handleTerminate(event.getRecipient());
|
||||
}
|
||||
});
|
||||
ad.show();
|
||||
}
|
||||
}
|
||||
|
||||
private void handleLoginFailed() {
|
||||
state = STATE_IDLE;
|
||||
callScreen.setActiveCall(redPhoneService.getRecipient(), getString(R.string.RedPhone_login_failed));
|
||||
private void handleLoginFailed(@NonNull RedPhoneEvent event) {
|
||||
callScreen.setActiveCall(event.getRecipient(), getString(R.string.RedPhone_login_failed));
|
||||
delayedFinish();
|
||||
}
|
||||
|
||||
private void handleServerMessage(String message) {
|
||||
private void handleServerMessage(final @NonNull RedPhoneEvent event) {
|
||||
if( isFinishing() ) return; //we're already shutting down, this might crash
|
||||
AlertDialog.Builder ad = new AlertDialog.Builder(this);
|
||||
ad.setTitle(R.string.RedPhone_message_from_the_server);
|
||||
ad.setMessage(message);
|
||||
ad.setMessage(event.getExtra());
|
||||
ad.setCancelable(false);
|
||||
ad.setPositiveButton(android.R.string.ok, new OnClickListener() {
|
||||
public void onClick(DialogInterface dialog, int arg) {
|
||||
RedPhone.this.handleTerminate(LOCAL_TERMINATE);
|
||||
RedPhone.this.handleTerminate(event.getRecipient());
|
||||
}
|
||||
});
|
||||
ad.show();
|
||||
}
|
||||
|
||||
private void handleNoSuchUser(final Recipient recipient) {
|
||||
private void handleNoSuchUser(final @NonNull RedPhoneEvent event) {
|
||||
if (isFinishing()) return; // XXX Stuart added this check above, not sure why, so I'm repeating in ignorance. - moxie
|
||||
AlertDialogWrapper.Builder dialog = new AlertDialogWrapper.Builder(this);
|
||||
dialog.setTitle(R.string.RedPhone_number_not_registered);
|
||||
@ -313,13 +255,13 @@ public class RedPhone extends Activity {
|
||||
dialog.setPositiveButton(R.string.RedPhone_got_it, new OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
RedPhone.this.handleTerminate(LOCAL_TERMINATE);
|
||||
RedPhone.this.handleTerminate(event.getRecipient());
|
||||
}
|
||||
});
|
||||
dialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
|
||||
@Override
|
||||
public void onCancel(DialogInterface dialog) {
|
||||
RedPhone.this.handleTerminate(LOCAL_TERMINATE);
|
||||
RedPhone.this.handleTerminate(event.getRecipient());
|
||||
}
|
||||
});
|
||||
dialog.show();
|
||||
@ -330,35 +272,33 @@ public class RedPhone extends Activity {
|
||||
}
|
||||
|
||||
private void delayedFinish(int delayMillis) {
|
||||
callStateHandler.postDelayed(new Runnable() {
|
||||
|
||||
callScreen.postDelayed(new Runnable() {
|
||||
public void run() {
|
||||
RedPhone.this.finish();
|
||||
}}, delayMillis);
|
||||
}
|
||||
}, delayMillis);
|
||||
}
|
||||
|
||||
private class CallStateHandler extends Handler {
|
||||
@Override
|
||||
public void handleMessage(Message message) {
|
||||
Log.w(TAG, "Got message from service: " + message.what);
|
||||
switch (message.what) {
|
||||
case HANDLE_CALL_CONNECTED: handleCallConnected((SASInfo)message.obj); break;
|
||||
case HANDLE_SERVER_FAILURE: handleServerFailure(); break;
|
||||
case HANDLE_PERFORMING_HANDSHAKE: handlePerformingHandshake(); break;
|
||||
case HANDLE_HANDSHAKE_FAILED: handleHandshakeFailed(); break;
|
||||
case HANDLE_CONNECTING_TO_INITIATOR: handleConnectingToInitiator(); break;
|
||||
case HANDLE_CALL_RINGING: handleCallRinging(); break;
|
||||
case HANDLE_CALL_DISCONNECTED: handleTerminate( REMOTE_TERMINATE ); break;
|
||||
case HANDLE_SERVER_MESSAGE: handleServerMessage((String)message.obj); break;
|
||||
case HANDLE_NO_SUCH_USER: handleNoSuchUser((Recipient)message.obj); break;
|
||||
case HANDLE_RECIPIENT_UNAVAILABLE: handleRecipientUnavailable(); break;
|
||||
case HANDLE_INCOMING_CALL: handleIncomingCall((Recipient)message.obj); break;
|
||||
case HANDLE_OUTGOING_CALL: handleOutgoingCall((Recipient)message.obj); break;
|
||||
case HANDLE_CALL_BUSY: handleCallBusy(); break;
|
||||
case HANDLE_LOGIN_FAILED: handleLoginFailed(); break;
|
||||
case HANDLE_CLIENT_FAILURE: handleClientFailure((String)message.obj); break;
|
||||
case HANDLE_DEBUG_INFO: handleDebugInfo((String)message.obj); break;
|
||||
}
|
||||
@SuppressWarnings("unused")
|
||||
public void onEventMainThread(final RedPhoneEvent event) {
|
||||
Log.w(TAG, "Got message from service: " + event.getType());
|
||||
|
||||
switch (event.getType()) {
|
||||
case CALL_CONNECTED: handleCallConnected(event); break;
|
||||
case SERVER_FAILURE: handleServerFailure(event); break;
|
||||
case PERFORMING_HANDSHAKE: handlePerformingHandshake(event); break;
|
||||
case HANDSHAKE_FAILED: handleHandshakeFailed(event); break;
|
||||
case CONNECTING_TO_INITIATOR: handleConnectingToInitiator(event); break;
|
||||
case CALL_RINGING: handleCallRinging(event); break;
|
||||
case CALL_DISCONNECTED: handleTerminate(event.getRecipient()); break;
|
||||
case SERVER_MESSAGE: handleServerMessage(event); break;
|
||||
case NO_SUCH_USER: handleNoSuchUser(event); break;
|
||||
case RECIPIENT_UNAVAILABLE: handleRecipientUnavailable(event); break;
|
||||
case INCOMING_CALL: handleIncomingCall(event); break;
|
||||
case OUTGOING_CALL: handleOutgoingCall(event); break;
|
||||
case CALL_BUSY: handleCallBusy(event); break;
|
||||
case LOGIN_FAILED: handleLoginFailed(event); break;
|
||||
case CLIENT_FAILURE: handleClientFailure(event); break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -369,7 +309,11 @@ public class RedPhone extends Activity {
|
||||
intent.setAction(RedPhoneService.ACTION_HANGUP_CALL);
|
||||
startService(intent);
|
||||
|
||||
RedPhone.this.handleTerminate(LOCAL_TERMINATE);
|
||||
RedPhoneEvent event = EventBus.getDefault().getStickyEvent(RedPhoneEvent.class);
|
||||
|
||||
if (event != null) {
|
||||
RedPhone.this.handleTerminate(event.getRecipient());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -418,30 +362,11 @@ public class RedPhone extends Activity {
|
||||
public void onAcceptClick() {
|
||||
RedPhone.this.handleAnswerCall();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDenyClick() {
|
||||
RedPhone.this.handleDenyCall();
|
||||
}
|
||||
}
|
||||
|
||||
private ServiceConnection serviceConnection = new ServiceConnection() {
|
||||
public void onServiceConnected(ComponentName className, IBinder service) {
|
||||
RedPhone.this.redPhoneService = ((RedPhoneService.RedPhoneServiceBinder)service).getService();
|
||||
redPhoneService.setCallStateHandler(callStateHandler);
|
||||
|
||||
Recipient recipient = redPhoneService.getRecipient();
|
||||
|
||||
switch (redPhoneService.getState()) {
|
||||
case STATE_IDLE: callScreen.reset(); break;
|
||||
case STATE_RINGING: handleIncomingCall(recipient); break;
|
||||
case STATE_DIALING: handleOutgoingCall(recipient); break;
|
||||
case STATE_ANSWERING: handleAnswerCall(); break;
|
||||
case STATE_CONNECTED: handleCallConnected(redPhoneService.getCurrentCallSAS()); break;
|
||||
}
|
||||
}
|
||||
|
||||
public void onServiceDisconnected(ComponentName name) {
|
||||
redPhoneService.setCallStateHandler(null);
|
||||
}
|
||||
};
|
||||
}
|
@ -22,12 +22,13 @@ import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.content.SharedPreferences;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Binder;
|
||||
import android.os.Handler;
|
||||
import android.os.IBinder;
|
||||
import android.os.Message;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.telephony.TelephonyManager;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
|
||||
import org.thoughtcrime.redphone.audio.IncomingRinger;
|
||||
@ -47,6 +48,8 @@ import org.thoughtcrime.redphone.signaling.SignalingSocket;
|
||||
import org.thoughtcrime.redphone.ui.NotificationBarManager;
|
||||
import org.thoughtcrime.redphone.util.UncaughtExceptionHandlerManager;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.events.RedPhoneEvent;
|
||||
import org.thoughtcrime.securesms.events.RedPhoneEvent.Type;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
import org.thoughtcrime.securesms.recipients.RecipientFactory;
|
||||
@ -57,8 +60,8 @@ import org.thoughtcrime.securesms.util.TextSecurePreferences;
|
||||
import java.io.IOException;
|
||||
import java.security.NoSuchAlgorithmException;
|
||||
import java.security.SecureRandom;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
import de.greenrobot.event.EventBus;
|
||||
|
||||
/**
|
||||
* The major entry point for all of the heavy lifting associated with
|
||||
@ -73,6 +76,12 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
||||
|
||||
private static final String TAG = RedPhoneService.class.getSimpleName();
|
||||
|
||||
private static final int STATE_IDLE = 0;
|
||||
private static final int STATE_RINGING = 2;
|
||||
private static final int STATE_DIALING = 3;
|
||||
private static final int STATE_ANSWERING = 4;
|
||||
private static final int STATE_CONNECTED = 5;
|
||||
|
||||
public static final String EXTRA_REMOTE_NUMBER = "remote_number";
|
||||
public static final String EXTRA_SESSION_DESCRIPTOR = "session_descriptor";
|
||||
public static final String EXTRA_MUTE = "mute_value";
|
||||
@ -84,8 +93,6 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
||||
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";
|
||||
|
||||
private final List<Message> bufferedEvents = new LinkedList<>();
|
||||
private final IBinder binder = new RedPhoneServiceBinder();
|
||||
private final Handler serviceHandler = new Handler();
|
||||
|
||||
private OutgoingRinger outgoingRinger;
|
||||
@ -98,7 +105,6 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
||||
private LockManager lockManager;
|
||||
private UncaughtExceptionHandlerManager uncaughtExceptionHandlerManager;
|
||||
|
||||
private Handler handler;
|
||||
private IncomingPstnCallListener pstnCallListener;
|
||||
|
||||
@Override
|
||||
@ -119,7 +125,7 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
||||
|
||||
@Override
|
||||
public IBinder onBind(Intent intent) {
|
||||
return binder;
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -155,7 +161,7 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
||||
}
|
||||
|
||||
private void initializeResources() {
|
||||
this.state = RedPhone.STATE_IDLE;
|
||||
this.state = STATE_IDLE;
|
||||
this.zid = getZID();
|
||||
this.lockManager = new LockManager(this);
|
||||
}
|
||||
@ -173,7 +179,7 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
||||
SessionDescriptor session = intent.getParcelableExtra(EXTRA_SESSION_DESCRIPTOR);
|
||||
|
||||
remoteNumber = intent.getStringExtra(EXTRA_REMOTE_NUMBER);
|
||||
state = RedPhone.STATE_RINGING;
|
||||
state = STATE_RINGING;
|
||||
|
||||
lockManager.updatePhoneState(LockManager.PhoneState.PROCESSING);
|
||||
this.currentCallManager = new ResponderCallManager(this, this, remoteNumber, localNumber,
|
||||
@ -190,9 +196,9 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
||||
if (remoteNumber == null || remoteNumber.length() == 0)
|
||||
return;
|
||||
|
||||
sendMessage(RedPhone.HANDLE_OUTGOING_CALL, getRecipient());
|
||||
sendMessage(Type.OUTGOING_CALL, getRecipient(), null);
|
||||
|
||||
state = RedPhone.STATE_DIALING;
|
||||
state = STATE_DIALING;
|
||||
lockManager.updatePhoneState(LockManager.PhoneState.INTERACTIVE);
|
||||
this.currentCallManager = new InitiatingCallManager(this, this, localNumber, password,
|
||||
remoteNumber, zid);
|
||||
@ -234,7 +240,7 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
||||
}
|
||||
|
||||
private void handleAnswerCall(Intent intent) {
|
||||
state = RedPhone.STATE_ANSWERING;
|
||||
state = STATE_ANSWERING;
|
||||
incomingRinger.stop();
|
||||
DatabaseFactory.getSmsDatabase(this).insertReceivedCall(remoteNumber);
|
||||
if (currentCallManager != null) {
|
||||
@ -243,7 +249,7 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
||||
}
|
||||
|
||||
private void handleDenyCall(Intent intent) {
|
||||
state = RedPhone.STATE_IDLE;
|
||||
state = STATE_IDLE;
|
||||
incomingRinger.stop();
|
||||
DatabaseFactory.getSmsDatabase(this).insertMissedCall(remoteNumber);
|
||||
if(currentCallManager != null) {
|
||||
@ -266,12 +272,12 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
||||
|
||||
private boolean isBusy() {
|
||||
TelephonyManager telephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
|
||||
return ((currentCallManager != null && state != RedPhone.STATE_IDLE) ||
|
||||
return ((currentCallManager != null && state != STATE_IDLE) ||
|
||||
telephonyManager.getCallState() != TelephonyManager.CALL_STATE_IDLE);
|
||||
}
|
||||
|
||||
private boolean isIdle() {
|
||||
return state == RedPhone.STATE_IDLE;
|
||||
return state == STATE_IDLE;
|
||||
}
|
||||
|
||||
private void shutdownAudio() {
|
||||
@ -283,15 +289,9 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
||||
return state;
|
||||
}
|
||||
|
||||
public SASInfo getCurrentCallSAS() {
|
||||
if (currentCallManager != null)
|
||||
return currentCallManager.getSasInfo();
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
public Recipient getRecipient() {
|
||||
if (remoteNumber != null) {
|
||||
public @NonNull Recipient getRecipient() {
|
||||
if (!TextUtils.isEmpty(remoteNumber)) {
|
||||
//noinspection ConstantConditions
|
||||
return RecipientFactory.getRecipientsFromString(this, remoteNumber, true)
|
||||
.getPrimaryRecipient();
|
||||
} else {
|
||||
@ -351,22 +351,10 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
||||
|
||||
shutdownAudio();
|
||||
|
||||
state = RedPhone.STATE_IDLE;
|
||||
state = STATE_IDLE;
|
||||
lockManager.updatePhoneState(LockManager.PhoneState.IDLE);
|
||||
}
|
||||
|
||||
public void setCallStateHandler(Handler handler) {
|
||||
this.handler = handler;
|
||||
|
||||
if (handler != null) {
|
||||
for (Message message : bufferedEvents) {
|
||||
handler.sendMessage(message);
|
||||
}
|
||||
|
||||
bufferedEvents.clear();
|
||||
}
|
||||
}
|
||||
|
||||
///////// CallStateListener Implementation
|
||||
|
||||
public void notifyCallStale() {
|
||||
@ -377,7 +365,7 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
||||
|
||||
public void notifyCallFresh() {
|
||||
Log.w(TAG, "Good call, time to ring and display call card...");
|
||||
sendMessage(RedPhone.HANDLE_INCOMING_CALL, getRecipient());
|
||||
sendMessage(Type.INCOMING_CALL, getRecipient(), null);
|
||||
|
||||
lockManager.updatePhoneState(LockManager.PhoneState.INTERACTIVE);
|
||||
|
||||
@ -389,7 +377,8 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
||||
|
||||
public void notifyBusy() {
|
||||
Log.w("RedPhoneService", "Got busy signal from responder!");
|
||||
sendMessage(RedPhone.HANDLE_CALL_BUSY, null);
|
||||
sendMessage(Type.CALL_BUSY, getRecipient(), null);
|
||||
|
||||
outgoingRinger.playBusy();
|
||||
serviceHandler.postDelayed(new Runnable() {
|
||||
@Override
|
||||
@ -401,124 +390,103 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
||||
|
||||
public void notifyCallRinging() {
|
||||
outgoingRinger.playRing();
|
||||
sendMessage(RedPhone.HANDLE_CALL_RINGING, null);
|
||||
sendMessage(Type.CALL_RINGING, getRecipient(), null);
|
||||
}
|
||||
|
||||
public void notifyCallConnected(SASInfo sas) {
|
||||
outgoingRinger.playComplete();
|
||||
lockManager.updatePhoneState(LockManager.PhoneState.IN_CALL);
|
||||
state = RedPhone.STATE_CONNECTED;
|
||||
synchronized( this ) {
|
||||
sendMessage(RedPhone.HANDLE_CALL_CONNECTED, sas);
|
||||
try {
|
||||
wait();
|
||||
} catch (InterruptedException e) {
|
||||
throw new AssertionError( "Wait interrupted in RedPhoneService" );
|
||||
}
|
||||
}
|
||||
}
|
||||
public void notifyCallConnectionUIUpdateComplete() {
|
||||
synchronized( this ) {
|
||||
this.notify();
|
||||
}
|
||||
}
|
||||
public void notifyDebugInfo(String info) {
|
||||
sendMessage(RedPhone.HANDLE_DEBUG_INFO, info);
|
||||
state = STATE_CONNECTED;
|
||||
sendMessage(Type.CALL_CONNECTED, getRecipient(), sas.getSasText());
|
||||
}
|
||||
|
||||
public void notifyConnectingtoInitiator() {
|
||||
sendMessage(RedPhone.HANDLE_CONNECTING_TO_INITIATOR, null);
|
||||
sendMessage(Type.CONNECTING_TO_INITIATOR, getRecipient(), null);
|
||||
}
|
||||
|
||||
public void notifyCallDisconnected() {
|
||||
if (state == RedPhone.STATE_RINGING)
|
||||
if (state == STATE_RINGING)
|
||||
handleMissedCall(remoteNumber);
|
||||
|
||||
sendMessage(RedPhone.HANDLE_CALL_DISCONNECTED, null);
|
||||
sendMessage(Type.CALL_DISCONNECTED, getRecipient(), null);
|
||||
this.terminate();
|
||||
}
|
||||
|
||||
public void notifyHandshakeFailed() {
|
||||
state = RedPhone.STATE_IDLE;
|
||||
state = STATE_IDLE;
|
||||
outgoingRinger.playFailure();
|
||||
sendMessage(RedPhone.HANDLE_HANDSHAKE_FAILED, null);
|
||||
sendMessage(Type.HANDSHAKE_FAILED, getRecipient(), null);
|
||||
this.terminate();
|
||||
}
|
||||
|
||||
public void notifyRecipientUnavailable() {
|
||||
state = RedPhone.STATE_IDLE;
|
||||
state = STATE_IDLE;
|
||||
outgoingRinger.playFailure();
|
||||
sendMessage(RedPhone.HANDLE_RECIPIENT_UNAVAILABLE, null);
|
||||
sendMessage(Type.RECIPIENT_UNAVAILABLE, getRecipient(), null);
|
||||
this.terminate();
|
||||
}
|
||||
|
||||
public void notifyPerformingHandshake() {
|
||||
outgoingRinger.playHandshake();
|
||||
sendMessage(RedPhone.HANDLE_PERFORMING_HANDSHAKE, null);
|
||||
sendMessage(Type.PERFORMING_HANDSHAKE, getRecipient(), null);
|
||||
}
|
||||
|
||||
public void notifyServerFailure() {
|
||||
if (state == RedPhone.STATE_RINGING)
|
||||
if (state == STATE_RINGING)
|
||||
handleMissedCall(remoteNumber);
|
||||
|
||||
state = RedPhone.STATE_IDLE;
|
||||
state = STATE_IDLE;
|
||||
outgoingRinger.playFailure();
|
||||
sendMessage(RedPhone.HANDLE_SERVER_FAILURE, null);
|
||||
sendMessage(Type.SERVER_FAILURE, getRecipient(), null);
|
||||
this.terminate();
|
||||
}
|
||||
|
||||
public void notifyClientFailure() {
|
||||
if (state == RedPhone.STATE_RINGING)
|
||||
if (state == STATE_RINGING)
|
||||
handleMissedCall(remoteNumber);
|
||||
|
||||
state = RedPhone.STATE_IDLE;
|
||||
state = STATE_IDLE;
|
||||
outgoingRinger.playFailure();
|
||||
sendMessage(RedPhone.HANDLE_CLIENT_FAILURE, null);
|
||||
sendMessage(Type.CLIENT_FAILURE, getRecipient(), null);
|
||||
this.terminate();
|
||||
}
|
||||
|
||||
public void notifyLoginFailed() {
|
||||
if (state == RedPhone.STATE_RINGING)
|
||||
if (state == STATE_RINGING)
|
||||
handleMissedCall(remoteNumber);
|
||||
|
||||
state = RedPhone.STATE_IDLE;
|
||||
state = STATE_IDLE;
|
||||
outgoingRinger.playFailure();
|
||||
sendMessage(RedPhone.HANDLE_LOGIN_FAILED, null);
|
||||
sendMessage(Type.LOGIN_FAILED, getRecipient(), null);
|
||||
this.terminate();
|
||||
}
|
||||
|
||||
public void notifyNoSuchUser() {
|
||||
sendMessage(RedPhone.HANDLE_NO_SUCH_USER, getRecipient());
|
||||
sendMessage(Type.NO_SUCH_USER, getRecipient(), null);
|
||||
this.terminate();
|
||||
}
|
||||
|
||||
public void notifyServerMessage(String message) {
|
||||
sendMessage(RedPhone.HANDLE_SERVER_MESSAGE, message);
|
||||
sendMessage(Type.SERVER_MESSAGE, getRecipient(), message);
|
||||
this.terminate();
|
||||
}
|
||||
|
||||
public void notifyClientError(String msg) {
|
||||
sendMessage(RedPhone.HANDLE_CLIENT_FAILURE,msg);
|
||||
sendMessage(Type.CLIENT_FAILURE, getRecipient(), msg);
|
||||
this.terminate();
|
||||
}
|
||||
|
||||
public void notifyClientError(int messageId) {
|
||||
notifyClientError(getString(messageId));
|
||||
}
|
||||
|
||||
public void notifyCallConnecting() {
|
||||
outgoingRinger.playSonar();
|
||||
}
|
||||
|
||||
public void notifyWaitingForResponder() {}
|
||||
|
||||
private void sendMessage(int code, Object extra) {
|
||||
Message message = Message.obtain();
|
||||
message.what = code;
|
||||
message.obj = extra;
|
||||
|
||||
if (handler != null) handler.sendMessage(message);
|
||||
else bufferedEvents.add(message);
|
||||
private void sendMessage(@NonNull Type type,
|
||||
@NonNull Recipient recipient,
|
||||
@Nullable String error)
|
||||
{
|
||||
EventBus.getDefault().postSticky(new RedPhoneEvent(type, recipient, error));
|
||||
}
|
||||
|
||||
private class IntentRunnable implements Runnable {
|
||||
@ -533,21 +501,15 @@ public class RedPhoneService extends Service implements CallStateListener, CallS
|
||||
}
|
||||
}
|
||||
|
||||
public class RedPhoneServiceBinder extends Binder {
|
||||
public RedPhoneService getService() {
|
||||
return RedPhoneService.this;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInCall() {
|
||||
switch(state) {
|
||||
case RedPhone.STATE_IDLE:
|
||||
case STATE_IDLE:
|
||||
return false;
|
||||
case RedPhone.STATE_DIALING:
|
||||
case RedPhone.STATE_RINGING:
|
||||
case RedPhone.STATE_ANSWERING:
|
||||
case RedPhone.STATE_CONNECTED:
|
||||
case STATE_DIALING:
|
||||
case STATE_RINGING:
|
||||
case STATE_ANSWERING:
|
||||
case STATE_CONNECTED:
|
||||
return true;
|
||||
default:
|
||||
Log.e(TAG, "Unhandled call state: " + state);
|
||||
|
@ -43,10 +43,8 @@ public interface CallStateListener {
|
||||
public void notifyRecipientUnavailable();
|
||||
public void notifyBusy();
|
||||
public void notifyLoginFailed();
|
||||
public void notifyDebugInfo(String info);
|
||||
public void notifyCallStale();
|
||||
public void notifyCallFresh();
|
||||
public void notifyClientError(int msgId);
|
||||
public void notifyClientError(String message);
|
||||
public void notifyCallConnecting();
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ import android.content.IntentFilter;
|
||||
import android.media.AudioManager;
|
||||
import android.os.Handler;
|
||||
import android.os.Message;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.view.View;
|
||||
@ -104,9 +105,9 @@ public class CallControls extends RelativeLayout {
|
||||
sasTextView.setVisibility(View.GONE);
|
||||
}
|
||||
|
||||
public void setActiveCall(SASInfo sas) {
|
||||
public void setActiveCall(@Nullable String sas) {
|
||||
setActiveCall();
|
||||
sasTextView.setText(sas.getSasText());
|
||||
sasTextView.setText(sas);
|
||||
sasTextView.setVisibility(View.VISIBLE);
|
||||
}
|
||||
|
||||
|
@ -18,6 +18,8 @@
|
||||
package org.thoughtcrime.redphone.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.LayoutInflater;
|
||||
import android.widget.FrameLayout;
|
||||
@ -53,7 +55,7 @@ public class CallScreen extends FrameLayout {
|
||||
initialize();
|
||||
}
|
||||
|
||||
public void setActiveCall(Recipient personInfo, String message, SASInfo sas) {
|
||||
public void setActiveCall(@NonNull Recipient personInfo, @NonNull String message, @Nullable String sas) {
|
||||
callCard.setCard(personInfo, message);
|
||||
callControls.setActiveCall(sas);
|
||||
}
|
||||
|
@ -21,7 +21,7 @@ import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.audio.AudioSlidePlayer;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||
import org.thoughtcrime.securesms.jobs.PartProgressEvent;
|
||||
import org.thoughtcrime.securesms.events.PartProgressEvent;
|
||||
import org.thoughtcrime.securesms.mms.AudioSlide;
|
||||
import org.thoughtcrime.securesms.mms.SlideClickListener;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
|
@ -22,7 +22,7 @@ import com.pnikosis.materialishprogress.ProgressWheel;
|
||||
|
||||
import org.thoughtcrime.securesms.R;
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||
import org.thoughtcrime.securesms.jobs.PartProgressEvent;
|
||||
import org.thoughtcrime.securesms.events.PartProgressEvent;
|
||||
import org.thoughtcrime.securesms.mms.Slide;
|
||||
import org.thoughtcrime.securesms.util.Util;
|
||||
import org.thoughtcrime.securesms.util.ViewUtil;
|
||||
|
@ -1,4 +1,4 @@
|
||||
package org.thoughtcrime.securesms.jobs;
|
||||
package org.thoughtcrime.securesms.events;
|
||||
|
||||
|
||||
import android.support.annotation.NonNull;
|
51
src/org/thoughtcrime/securesms/events/RedPhoneEvent.java
Normal file
51
src/org/thoughtcrime/securesms/events/RedPhoneEvent.java
Normal file
@ -0,0 +1,51 @@
|
||||
package org.thoughtcrime.securesms.events;
|
||||
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
|
||||
import org.thoughtcrime.securesms.recipients.Recipient;
|
||||
|
||||
public class RedPhoneEvent {
|
||||
|
||||
public enum Type {
|
||||
CALL_CONNECTED,
|
||||
WAITING_FOR_RESPONDER,
|
||||
SERVER_FAILURE,
|
||||
PERFORMING_HANDSHAKE,
|
||||
HANDSHAKE_FAILED,
|
||||
CONNECTING_TO_INITIATOR,
|
||||
CALL_DISCONNECTED,
|
||||
CALL_RINGING,
|
||||
SERVER_MESSAGE,
|
||||
RECIPIENT_UNAVAILABLE,
|
||||
INCOMING_CALL,
|
||||
OUTGOING_CALL,
|
||||
CALL_BUSY,
|
||||
LOGIN_FAILED,
|
||||
CLIENT_FAILURE,
|
||||
DEBUG_INFO,
|
||||
NO_SUCH_USER
|
||||
}
|
||||
|
||||
private final @NonNull Type type;
|
||||
private final @NonNull Recipient recipient;
|
||||
private final @Nullable String extra;
|
||||
|
||||
public RedPhoneEvent(@NonNull Type type, @NonNull Recipient recipient, @Nullable String extra) {
|
||||
this.type = type;
|
||||
this.recipient = recipient;
|
||||
this.extra = extra;
|
||||
}
|
||||
|
||||
public @NonNull Type getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
public @NonNull Recipient getRecipient() {
|
||||
return recipient;
|
||||
}
|
||||
|
||||
public @Nullable String getExtra() {
|
||||
return extra;
|
||||
}
|
||||
}
|
@ -13,6 +13,7 @@ import org.thoughtcrime.securesms.crypto.MediaKey;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.AttachmentDatabase;
|
||||
import org.thoughtcrime.securesms.dependencies.InjectableType;
|
||||
import org.thoughtcrime.securesms.events.PartProgressEvent;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.MediaNetworkRequirement;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
|
@ -7,6 +7,7 @@ import org.thoughtcrime.securesms.attachments.Attachment;
|
||||
import org.thoughtcrime.securesms.crypto.MasterSecret;
|
||||
import org.thoughtcrime.securesms.database.DatabaseFactory;
|
||||
import org.thoughtcrime.securesms.database.TextSecureDirectory;
|
||||
import org.thoughtcrime.securesms.events.PartProgressEvent;
|
||||
import org.thoughtcrime.securesms.jobs.requirements.MasterSecretRequirement;
|
||||
import org.thoughtcrime.securesms.mms.PartAuthority;
|
||||
import org.thoughtcrime.securesms.notifications.MessageNotifier;
|
||||
|
Loading…
x
Reference in New Issue
Block a user