From 5b6f49c993cbcb53ab38955b51e98da997f4b7e5 Mon Sep 17 00:00:00 2001 From: Moxie Marlinspike Date: Mon, 2 Nov 2015 14:32:02 -0800 Subject: [PATCH] Switch RedPhone view<->service interaction to use event bus Fixes #4234 // FREEBIE --- proguard.cfg | 3 + src/org/thoughtcrime/redphone/RedPhone.java | 257 +++++++----------- .../redphone/RedPhoneService.java | 162 +++++------ .../redphone/call/CallStateListener.java | 2 - .../redphone/ui/CallControls.java | 5 +- .../thoughtcrime/redphone/ui/CallScreen.java | 4 +- .../securesms/components/AudioView.java | 2 +- .../components/TransferControlView.java | 2 +- .../{jobs => events}/PartProgressEvent.java | 2 +- .../securesms/events/RedPhoneEvent.java | 51 ++++ .../securesms/jobs/AttachmentDownloadJob.java | 1 + .../securesms/jobs/PushSendJob.java | 1 + 12 files changed, 218 insertions(+), 274 deletions(-) rename src/org/thoughtcrime/securesms/{jobs => events}/PartProgressEvent.java (91%) create mode 100644 src/org/thoughtcrime/securesms/events/RedPhoneEvent.java diff --git a/proguard.cfg b/proguard.cfg index 50377be6e..2634d86b9 100644 --- a/proguard.cfg +++ b/proguard.cfg @@ -2,4 +2,7 @@ -keepattributes SourceFile,LineNumberTable -keep class org.whispersystems.** { *; } -keep class org.thoughtcrime.securesms.** { *; } +-keepclassmembers class ** { + public void onEvent*(**); +} diff --git a/src/org/thoughtcrime/redphone/RedPhone.java b/src/org/thoughtcrime/redphone/RedPhone.java index 229a9458d..bd84dc567 100644 --- a/src/org/thoughtcrime/redphone/RedPhone.java +++ b/src/org/thoughtcrime/redphone/RedPhone.java @@ -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); - Intent intent = new Intent(this, RedPhoneService.class); - intent.setAction(RedPhoneService.ACTION_ANSWER_CALL); - startService(intent); + 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); - Intent intent = new Intent(this, RedPhoneService.class); - intent.setAction(RedPhoneService.ACTION_DENY_CALL); - startService(intent); + 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)); - delayedFinish(); + 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 handleIncomingCall(@NonNull RedPhoneEvent event) { + callScreen.setIncomingCall(event.getRecipient()); } - private void handleOutgoingCall(Recipient recipient) { - state = STATE_DIALING; - callScreen.setActiveCall(recipient, getString(org.thoughtcrime.securesms.R.string.RedPhone_dialing)); + private void handleOutgoingCall(@NonNull RedPhoneEvent event) { + callScreen.setActiveCall(event.getRecipient(), getString(org.thoughtcrime.securesms.R.string.RedPhone_dialing)); } - private void handleTerminate( int terminationType ) { + 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() { - - public void run() { - RedPhone.this.finish(); - }}, delayMillis); + callScreen.postDelayed(new Runnable() { + public void run() { + RedPhone.this.finish(); + } + }, 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); - } - }; } \ No newline at end of file diff --git a/src/org/thoughtcrime/redphone/RedPhoneService.java b/src/org/thoughtcrime/redphone/RedPhoneService.java index 0c7b3b13a..a228b8d23 100644 --- a/src/org/thoughtcrime/redphone/RedPhoneService.java +++ b/src/org/thoughtcrime/redphone/RedPhoneService.java @@ -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 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); diff --git a/src/org/thoughtcrime/redphone/call/CallStateListener.java b/src/org/thoughtcrime/redphone/call/CallStateListener.java index a4ea44764..653ebec91 100644 --- a/src/org/thoughtcrime/redphone/call/CallStateListener.java +++ b/src/org/thoughtcrime/redphone/call/CallStateListener.java @@ -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(); } diff --git a/src/org/thoughtcrime/redphone/ui/CallControls.java b/src/org/thoughtcrime/redphone/ui/CallControls.java index 0238c6781..177bebc33 100644 --- a/src/org/thoughtcrime/redphone/ui/CallControls.java +++ b/src/org/thoughtcrime/redphone/ui/CallControls.java @@ -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); } diff --git a/src/org/thoughtcrime/redphone/ui/CallScreen.java b/src/org/thoughtcrime/redphone/ui/CallScreen.java index 0693e081d..842f3acdb 100644 --- a/src/org/thoughtcrime/redphone/ui/CallScreen.java +++ b/src/org/thoughtcrime/redphone/ui/CallScreen.java @@ -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); } diff --git a/src/org/thoughtcrime/securesms/components/AudioView.java b/src/org/thoughtcrime/securesms/components/AudioView.java index 55bfd52c8..041cd15c9 100644 --- a/src/org/thoughtcrime/securesms/components/AudioView.java +++ b/src/org/thoughtcrime/securesms/components/AudioView.java @@ -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; diff --git a/src/org/thoughtcrime/securesms/components/TransferControlView.java b/src/org/thoughtcrime/securesms/components/TransferControlView.java index 67479cad2..70bdefc8c 100644 --- a/src/org/thoughtcrime/securesms/components/TransferControlView.java +++ b/src/org/thoughtcrime/securesms/components/TransferControlView.java @@ -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; diff --git a/src/org/thoughtcrime/securesms/jobs/PartProgressEvent.java b/src/org/thoughtcrime/securesms/events/PartProgressEvent.java similarity index 91% rename from src/org/thoughtcrime/securesms/jobs/PartProgressEvent.java rename to src/org/thoughtcrime/securesms/events/PartProgressEvent.java index b8addb12a..30817fd7d 100644 --- a/src/org/thoughtcrime/securesms/jobs/PartProgressEvent.java +++ b/src/org/thoughtcrime/securesms/events/PartProgressEvent.java @@ -1,4 +1,4 @@ -package org.thoughtcrime.securesms.jobs; +package org.thoughtcrime.securesms.events; import android.support.annotation.NonNull; diff --git a/src/org/thoughtcrime/securesms/events/RedPhoneEvent.java b/src/org/thoughtcrime/securesms/events/RedPhoneEvent.java new file mode 100644 index 000000000..0fcd3f97f --- /dev/null +++ b/src/org/thoughtcrime/securesms/events/RedPhoneEvent.java @@ -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; + } +} diff --git a/src/org/thoughtcrime/securesms/jobs/AttachmentDownloadJob.java b/src/org/thoughtcrime/securesms/jobs/AttachmentDownloadJob.java index b197d9827..ee46d4ed7 100644 --- a/src/org/thoughtcrime/securesms/jobs/AttachmentDownloadJob.java +++ b/src/org/thoughtcrime/securesms/jobs/AttachmentDownloadJob.java @@ -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; diff --git a/src/org/thoughtcrime/securesms/jobs/PushSendJob.java b/src/org/thoughtcrime/securesms/jobs/PushSendJob.java index 422833349..02d1f633f 100644 --- a/src/org/thoughtcrime/securesms/jobs/PushSendJob.java +++ b/src/org/thoughtcrime/securesms/jobs/PushSendJob.java @@ -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;