diff --git a/src/com/savoirfairelinux/sflphone/fragments/CallFragment.java b/src/com/savoirfairelinux/sflphone/fragments/CallFragment.java index 6917f02be15f685d0edb2c4f77f57ec2a2e52723..9e1addf835bfca76c25dcc176e6fb557a661f182 100644 --- a/src/com/savoirfairelinux/sflphone/fragments/CallFragment.java +++ b/src/com/savoirfairelinux/sflphone/fragments/CallFragment.java @@ -79,7 +79,7 @@ public class CallFragment extends Fragment implements Callback { public void onCreate(Bundle savedBundle) { super.onCreate(savedBundle); Bundle b = getArguments(); - conf = b.getParcelable("conference"); + conf = new Conference((Conference) b.getParcelable("conference")); model = new BubbleModel(getResources().getDisplayMetrics().density); } @@ -237,8 +237,20 @@ public class CallFragment extends Fragment implements Callback { public boolean onBubbleSucked(Bubble b) { Log.w(TAG, "Bubble sucked ! "); - mCallbacks.onCallEnded(b.associated_call); + if (b.associated_call.getContact().isUser()) { + try { + if (conf.hasMultipleParticipants()) + mCallbacks.getService().hangUpConference(conf.getId()); + else + mCallbacks.onCallEnded(conf.getParticipants().get(0)); + } catch (RemoteException e) { + e.printStackTrace(); + } + + } else { + mCallbacks.onCallEnded(b.associated_call); + } bubbleRemoved(b); return true; } @@ -356,7 +368,7 @@ public class CallFragment extends Fragment implements Callback { } public void changeCallState(String callID, String newState) { - + Log.w(TAG, "Call :" + callID + newState); if (newState.contentEquals("FAILURE")) { try { mCallbacks.getService().hangUp(callID); @@ -365,18 +377,22 @@ public class CallFragment extends Fragment implements Callback { } } if (conf.getParticipants() == null) { + Log.w(TAG, "IT IS NULL"); return; } + Log.w(TAG, "conf.getParticipants().size():" + conf.getParticipants().size()); for (int i = 0; i < conf.getParticipants().size(); ++i) { // conf.getParticipants().get(i).printCallInfo(); - + Log.w(TAG, "Call id:" + conf.getParticipants().get(i).getCallId()); + Log.w(TAG, "Searching:" + callID); if (callID.equals(conf.getParticipants().get(i).getCallId())) { if (newState.contentEquals("HUNGUP")) { - + Log.w(TAG, "Call hungup:" + conf.getParticipants().get(i).getContact().getmDisplayName()); model.removeBubble(conf.getParticipants().get(i)); conf.getParticipants().remove(i); } else { + Log.w(TAG, "Call:" + conf.getParticipants().get(i).getContact().getmDisplayName() + " state:" + newState); conf.getParticipants().get(i).setCallState(newState); } } diff --git a/src/com/savoirfairelinux/sflphone/model/BubbleModel.java b/src/com/savoirfairelinux/sflphone/model/BubbleModel.java index c1a87cb344740e6a9c61f483f7304dc9eba455ac..1a697962e9ffbd179b956fd94372ad67542aabad 100644 --- a/src/com/savoirfairelinux/sflphone/model/BubbleModel.java +++ b/src/com/savoirfairelinux/sflphone/model/BubbleModel.java @@ -198,7 +198,6 @@ public class BubbleModel } public void removeBubble(SipCall sipCall) { - bubbles.remove(getBubble(sipCall)); } diff --git a/src/com/savoirfairelinux/sflphone/model/CallContact.java b/src/com/savoirfairelinux/sflphone/model/CallContact.java index 4e3ae1a3479a2b470056baa222501984e02e3daf..adfd61de96aa2a8ef71b5bfb7fcf40dd94cc8664 100644 --- a/src/com/savoirfairelinux/sflphone/model/CallContact.java +++ b/src/com/savoirfairelinux/sflphone/model/CallContact.java @@ -45,14 +45,16 @@ public class CallContact implements Parcelable { private long photo_id; private ArrayList<Phone> phones, sip_phones; private String mEmail; + private boolean isUser; - private CallContact(long cID, String displayName, long photoID, ArrayList<Phone> p, ArrayList<Phone> sip, String mail) { + private CallContact(long cID, String displayName, long photoID, ArrayList<Phone> p, ArrayList<Phone> sip, String mail, boolean user) { id = cID; - mDisplayName = displayName.substring(0, displayName.length() > 10 ? 10 : displayName.length());; + mDisplayName = displayName.substring(0, displayName.length() > 10 ? 10 : displayName.length()); phones = p; sip_phones = sip; mEmail = mail; photo_id = photoID; + isUser = user; } public CallContact(Parcel in) { @@ -126,7 +128,7 @@ public class CallContact implements Parcelable { public ContactBuilder startNewContact(long id, String displayName, long photo_id) { contactID = id; - + contactName = displayName; contactPhoto = photo_id; phones = new ArrayList<Phone>(); @@ -145,7 +147,7 @@ public class CallContact implements Parcelable { } public CallContact build() { - return new CallContact(contactID, contactName, contactPhoto, phones, sip, contactMail); + return new CallContact(contactID, contactName, contactPhoto, phones, sip, contactMail, false); } public static ContactBuilder getInstance() { @@ -156,7 +158,7 @@ public class CallContact implements Parcelable { ArrayList<Phone> phones = new ArrayList<Phone>(); phones.add(new Phone(to, 0)); - return new CallContact(-1, to, 0, phones, new ArrayList<CallContact.Phone>(), ""); + return new CallContact(-1, to, 0, phones, new ArrayList<CallContact.Phone>(), "", false); } public static CallContact buildUserContact(ContentResolver cr, String displayName) { @@ -167,9 +169,9 @@ public class CallContact implements Parcelable { mProfileCursor.moveToFirst(); result = new CallContact(mProfileCursor.getLong(mProfileCursor.getColumnIndex(Profile._ID)), displayName, mProfileCursor.getLong(mProfileCursor.getColumnIndex(Profile.PHOTO_ID)), new ArrayList<Phone>(), - new ArrayList<CallContact.Phone>(), ""); + new ArrayList<CallContact.Phone>(), "", true); } else { - result = new CallContact(-1, displayName, 0, new ArrayList<Phone>(), new ArrayList<CallContact.Phone>(), ""); + result = new CallContact(-1, displayName, 0, new ArrayList<Phone>(), new ArrayList<CallContact.Phone>(), "", true); } mProfileCursor.close(); return result; @@ -192,6 +194,7 @@ public class CallContact implements Parcelable { dest.writeTypedList(sip_phones); dest.writeString(mEmail); + dest.writeByte((byte) (isUser ? 1 : 0)); } @@ -205,6 +208,7 @@ public class CallContact implements Parcelable { in.readTypedList(phones, Phone.CREATOR); in.readTypedList(sip_phones, Phone.CREATOR); mEmail = in.readString(); + isUser = in.readByte() == 1 ? true : false; } public static final Parcelable.Creator CREATOR = new Parcelable.Creator() { @@ -289,4 +293,8 @@ public class CallContact implements Parcelable { } + public boolean isUser() { + return isUser; + } + } diff --git a/src/com/savoirfairelinux/sflphone/model/Conference.java b/src/com/savoirfairelinux/sflphone/model/Conference.java index 02d06c7e912d21af54f1bcefae6a6eb35b87e5e4..4418210120b1fc33f4fd5cf0452b3c370ff2c3b0 100644 --- a/src/com/savoirfairelinux/sflphone/model/Conference.java +++ b/src/com/savoirfairelinux/sflphone/model/Conference.java @@ -1,6 +1,8 @@ package com.savoirfairelinux.sflphone.model; import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import android.os.Parcel; @@ -60,6 +62,13 @@ public class Conference implements Parcelable { participants = new ArrayList<SipCall>(); } + public Conference(Conference c) { + id = c.id; + state = c.state; + participants = new ArrayList<SipCall>(c.participants); + recording = c.recording; + } + public String getId() { return id; } @@ -69,7 +78,7 @@ public class Conference implements Parcelable { } public String getState() { - if(participants.size() == 1){ + if (participants.size() == 1) { return participants.get(0).getCallStateString(); } return state; @@ -84,16 +93,16 @@ public class Conference implements Parcelable { } public boolean contains(String callID) { - for (int i = 0 ; i < participants.size() ; ++i){ - if(participants.get(i).getCallId().contentEquals(callID)) + for (int i = 0; i < participants.size(); ++i) { + if (participants.get(i).getCallId().contentEquals(callID)) return true; } return false; } public SipCall getCall(String callID) { - for (int i = 0 ; i < participants.size() ; ++i){ - if(participants.get(i).getCallId().contentEquals(callID)) + for (int i = 0; i < participants.size(); ++i) { + if (participants.get(i).getCallId().contentEquals(callID)) return participants.get(i); } return null; @@ -104,7 +113,7 @@ public class Conference implements Parcelable { } public boolean isOnHold() { - if(participants.size() == 1 && participants.get(0).isOnHold()) + if (participants.size() == 1 && participants.get(0).isOnHold()) return true; return state.contentEquals("HOLD"); } @@ -118,12 +127,12 @@ public class Conference implements Parcelable { } public boolean isOnGoing() { - if(participants.size() == 1 && participants.get(0).isOngoing()) + if (participants.size() == 1 && participants.get(0).isOngoing()) return true; - + if (participants.size() > 1) return true; - + return false; } diff --git a/src/com/savoirfairelinux/sflphone/receivers/IncomingReceiver.java b/src/com/savoirfairelinux/sflphone/receivers/IncomingReceiver.java index 4fab834701e581c14680b101136ff55baf3814fd..f52012c65fcf90b85fc4d2f56eff061fbf289add 100644 --- a/src/com/savoirfairelinux/sflphone/receivers/IncomingReceiver.java +++ b/src/com/savoirfairelinux/sflphone/receivers/IncomingReceiver.java @@ -69,16 +69,62 @@ public class IncomingReceiver extends BroadcastReceiver { } else if (intent.getAction().contentEquals(CallManagerCallBack.CALL_STATE_CHANGED)) { + Log.i(TAG, "Received" + intent.getAction()); Bundle b = intent.getBundleExtra("com.savoirfairelinux.sflphone.service.newstate"); String newState = b.getString("State"); + try { + if (callback.getCurrent_calls().get(b.getString("CallID")) != null && mBinder.isConferenceParticipant(b.getString("CallID"))) { + callback.getCurrent_calls().remove(b.getString("CallID")); + } + } catch (RemoteException e) { + e.printStackTrace(); + } + if (newState.equals("INCOMING")) { callback.getCurrent_calls().get(b.getString("CallID")).setCallState(SipCall.state.CALL_STATE_INCOMING); } else if (newState.equals("RINGING")) { callback.getCurrent_calls().get(b.getString("CallID")).setCallState(SipCall.state.CALL_STATE_RINGING); } else if (newState.equals("CURRENT")) { - callback.getCurrent_calls().get(b.getString("CallID")).setCallState(SipCall.state.CALL_STATE_CURRENT); + if (callback.getCurrent_calls().get(b.getString("CallID")) != null) { + callback.getCurrent_calls().get(b.getString("CallID")).setCallState(SipCall.state.CALL_STATE_CURRENT); + } else { + // Check if call is in a conference + Iterator<Entry<String, Conference>> it = callback.getCurrent_confs().entrySet().iterator(); + while (it.hasNext()) { + Conference tmp = it.next().getValue(); + for (SipCall c : tmp.getParticipants()) { + if (c.getCallId().contentEquals(b.getString("CallID"))) + c.setCallState(SipCall.state.CALL_STATE_CURRENT); + } + } + } + } else if (newState.equals("HUNGUP")) { - callback.getCurrent_calls().remove(b.getString("CallID")); + Log.e(TAG, "HUNGUP call:" + b.getString("CallID")); + if (callback.getCurrent_calls().get(b.getString("CallID")) != null) { + callback.getCurrent_calls().remove(b.getString("CallID")); + } else { + ArrayList<Conference> it = new ArrayList<Conference>(callback.getCurrent_confs().values()); + + boolean found = false; + int i = 0; + while (!found && i < it.size()) { + Conference tmp = it.get(i); + + for (int j = 0; j < tmp.getParticipants().size(); ++j) { + if (tmp.getParticipants().get(j).getCallId().contentEquals(b.getString("CallID"))) { + callback.getCurrent_confs().get(tmp.getId()).getParticipants().remove(tmp.getParticipants().get(j)); + found = true; + } + + } + ++i; + + } + } + + callback.sendBroadcast(intent); + } else if (newState.equals("BUSY")) { callback.getCurrent_calls().remove(b.getString("CallID")); } else if (newState.equals("FAILURE")) { @@ -93,8 +139,7 @@ public class IncomingReceiver extends BroadcastReceiver { Conference tmp = it.next().getValue(); for (SipCall c : tmp.getParticipants()) { if (c.getCallId().contentEquals(b.getString("CallID"))) - ; - c.setCallState(SipCall.state.CALL_STATE_HOLD); + c.setCallState(SipCall.state.CALL_STATE_HOLD); } } } @@ -185,14 +230,14 @@ public class IncomingReceiver extends BroadcastReceiver { try { if (callback.getCurrent_confs().get(intent.getStringExtra("id")) != null) { callback.getCurrent_confs().get(intent.getStringExtra("id")).setRecording(mBinder.isRecording(intent.getStringExtra("id"))); - } else if (callback.getCurrent_calls().get(intent.getStringExtra("id")) != null){ + } else if (callback.getCurrent_calls().get(intent.getStringExtra("id")) != null) { callback.getCurrent_calls().get(intent.getStringExtra("id")).setRecording(mBinder.isRecording(intent.getStringExtra("id"))); } else { // A call in a conference has been put on hold Iterator<Conference> it = callback.getCurrent_confs().values().iterator(); - while(it.hasNext()){ + while (it.hasNext()) { Conference c = it.next(); - if(c.getCall(intent.getStringExtra("id")) != null) + if (c.getCall(intent.getStringExtra("id")) != null) c.getCall(intent.getStringExtra("id")).setRecording(mBinder.isRecording(intent.getStringExtra("id"))); } } diff --git a/src/com/savoirfairelinux/sflphone/service/ISipService.aidl b/src/com/savoirfairelinux/sflphone/service/ISipService.aidl index 3a79892d89864c6a03020de8bbdc3bf85aed53d6..4d99e42316db38cc154e1377471812ceecbaa69a 100644 --- a/src/com/savoirfairelinux/sflphone/service/ISipService.aidl +++ b/src/com/savoirfairelinux/sflphone/service/ISipService.aidl @@ -55,6 +55,7 @@ interface ISipService { void hangUpConference(in String confID); void holdConference(in String confID); void unholdConference(in String confID); + boolean isConferenceParticipant(in String callID); Map getConferenceList(); Map getCallList(); List getParticipantList(in String confID); diff --git a/src/com/savoirfairelinux/sflphone/service/SipService.java b/src/com/savoirfairelinux/sflphone/service/SipService.java index 3ab830e13dc3b84477b5553ea6427e6bb014ead1..80afd4e3e44392ebda7ecb5e57188bc12d1d69f6 100644 --- a/src/com/savoirfairelinux/sflphone/service/SipService.java +++ b/src/com/savoirfairelinux/sflphone/service/SipService.java @@ -770,6 +770,25 @@ public class SipService extends Service { }); } + + @Override + public boolean isConferenceParticipant(final String callID) throws RemoteException { + class IsParticipant extends SipRunnableWithReturn { + + @Override + protected Boolean doRun() throws SameThreadException { + Log.i(TAG, "SipService.isRecording() thread running..."); + return callManagerJNI.isConferenceParticipant(callID); + } + } + + IsParticipant runInstance = new IsParticipant(); + getExecutor().execute(runInstance); + while (!runInstance.isDone()) { + } + + return (Boolean) runInstance.getVal(); + } @Override public HashMap<String, Conference> getConferenceList() throws RemoteException { @@ -1067,6 +1086,8 @@ public class SipService extends Service { + + };