* #38608: better handling of conferences
Home interface now only have one list to display conferences (renamed conversations)
There are still some issues with conference mapping client side.
diff --git a/src/org/sflphone/adapters/SectionsPagerAdapter.java b/src/org/sflphone/adapters/SectionsPagerAdapter.java
index 485c005..a92ccad 100644
--- a/src/org/sflphone/adapters/SectionsPagerAdapter.java
+++ b/src/org/sflphone/adapters/SectionsPagerAdapter.java
@@ -112,16 +112,6 @@
return null;
}
- public void updateHome() {
- try {
- ((CallListFragment) fragments.get(1)).updateLists();
- } catch (RemoteException e) {
- e.printStackTrace();
- } catch (Exception e1) {
- e1.printStackTrace();
- }
- }
-
@Override
public int getPageIconResId(int position) {
switch (position) {
diff --git a/src/org/sflphone/client/HomeActivity.java b/src/org/sflphone/client/HomeActivity.java
index b56dce6..8581959 100644
--- a/src/org/sflphone/client/HomeActivity.java
+++ b/src/org/sflphone/client/HomeActivity.java
@@ -97,7 +97,7 @@
private ISipService service;
public static final int REQUEST_CODE_PREFERENCES = 1;
- private static final int REQUEST_CODE_CALL = 3;
+ public static final int REQUEST_CODE_CALL = 3;
SlidingUpPanelLayout mContactDrawer;
private DrawerLayout mNavigationDrawer;
@@ -598,14 +598,6 @@
}
@Override
- public void selectedCall(Conference c) {
- Intent intent = new Intent().setClass(this, CallActivity.class);
- intent.putExtra("resuming", true);
- intent.putExtra("conference", c);
- startActivityForResult(intent, REQUEST_CODE_CALL);
- }
-
- @Override
public void setDragView(RelativeLayout relativeLayout) {
mContactDrawer.setDragView(relativeLayout);
}
diff --git a/src/org/sflphone/fragments/CallListFragment.java b/src/org/sflphone/fragments/CallListFragment.java
index a324b6a..ea63b7e 100644
--- a/src/org/sflphone/fragments/CallListFragment.java
+++ b/src/org/sflphone/fragments/CallListFragment.java
@@ -30,32 +30,15 @@
*/
package org.sflphone.fragments;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Observable;
-import java.util.Observer;
-
-import android.content.IntentFilter;
-import org.sflphone.R;
-import org.sflphone.interfaces.CallInterface;
-import org.sflphone.model.CallTimer;
-import org.sflphone.model.Conference;
-import org.sflphone.receivers.CallReceiver;
-import org.sflphone.service.CallManagerCallBack;
-import org.sflphone.service.ISipService;
-
import android.app.Activity;
+import android.app.Fragment;
import android.content.ClipData;
import android.content.ClipData.Item;
import android.content.Context;
import android.content.Intent;
+import android.content.IntentFilter;
import android.graphics.Color;
-import android.os.Bundle;
-import android.os.Handler;
-import android.os.RemoteException;
-import android.os.SystemClock;
-import android.os.Vibrator;
-import android.app.Fragment;
+import android.os.*;
import android.util.Log;
import android.view.DragEvent;
import android.view.LayoutInflater;
@@ -63,21 +46,30 @@
import android.view.View.DragShadowBuilder;
import android.view.View.OnDragListener;
import android.view.ViewGroup;
-import android.widget.AdapterView;
+import android.widget.*;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.AdapterView.OnItemLongClickListener;
-import android.widget.BaseAdapter;
-import android.widget.ListView;
-import android.widget.TextView;
-import android.widget.Toast;
+import org.sflphone.R;
+import org.sflphone.client.CallActivity;
+import org.sflphone.client.HomeActivity;
+import org.sflphone.interfaces.CallInterface;
+import org.sflphone.model.Conference;
+import org.sflphone.receivers.CallReceiver;
+import org.sflphone.service.CallManagerCallBack;
+import org.sflphone.service.ISipService;
-public class CallListFragment extends Fragment implements CallInterface{
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Observable;
+import java.util.Observer;
+
+public class CallListFragment extends Fragment implements CallInterface {
+
private static final String TAG = CallListFragment.class.getSimpleName();
private Callbacks mCallbacks = sDummyCallbacks;
- private TextView nb_calls, nb_confs;
- CallListAdapter confs_adapter, calls_adapter;
- CallTimer timer;
+ private TextView nb_confs;
+ CallListAdapter confs_adapter;
CallReceiver callReceiver;
public static final int REQUEST_TRANSFER = 10;
@@ -94,9 +86,6 @@
return null;
}
- @Override
- public void selectedCall(Conference c) {
- }
};
@Override
@@ -105,11 +94,9 @@
String cID = b.getString("CallID");
String state = b.getString("State");
Log.i(TAG, "callStateChanged" + cID + " " + state);
- try {
- updateLists();
- } catch (RemoteException e) {
- e.printStackTrace();
- }
+
+ updateLists();
+
}
@Override
@@ -123,21 +110,20 @@
@Override
public void confCreated(Intent intent) {
- try {
- updateLists();
- } catch (RemoteException e) {
- e.printStackTrace();
- }
+ Log.i(TAG, "confCreated");
+ updateLists();
}
@Override
public void confRemoved(Intent intent) {
-
+ Log.i(TAG, "confRemoved");
+ updateLists();
}
@Override
public void confChanged(Intent intent) {
-
+ Log.i(TAG, "confChanged");
+ updateLists();
}
@Override
@@ -149,11 +135,7 @@
* The Activity calling this fragment has to implement this interface
*/
public interface Callbacks {
-
public ISipService getService();
-
- public void selectedCall(Conference c);
-
}
@Override
@@ -176,7 +158,6 @@
int minutes = seconds / 60;
seconds = seconds % 60;
- calls_adapter.notifyDataSetChanged();
confs_adapter.notifyDataSetChanged();
mHandler.postAtTime(this, start + (((minutes * 60) + seconds + 1) * 1000));
}
@@ -193,14 +174,10 @@
intentFilter.addAction(CallManagerCallBack.CALL_STATE_CHANGED);
getActivity().registerReceiver(callReceiver, intentFilter);
if (mCallbacks.getService() != null) {
- try {
- updateLists();
- if (!calls_adapter.isEmpty() || !confs_adapter.isEmpty()) {
- mHandler.postDelayed(mUpdateTimeTask, 0);
- }
- } catch (RemoteException e) {
- Log.e(TAG, e.toString());
+ updateLists();
+ if (!confs_adapter.isEmpty()) {
+ mHandler.postDelayed(mUpdateTimeTask, 0);
}
}
@@ -208,27 +185,16 @@
@SuppressWarnings("unchecked")
// No proper solution with HashMap runtime cast
- public void updateLists() throws RemoteException {
- HashMap<String, Conference> confs = (HashMap<String, Conference>) mCallbacks.getService().getConferenceList();
- Log.i(TAG, "There are " + confs.size());
- sortConferences(confs);
- }
-
- private void sortConferences(HashMap<String, Conference> conferences) {
-
- ArrayList<Conference> multiConfs = new ArrayList<Conference>();
- ArrayList<Conference> oneToOneConfs = new ArrayList<Conference>();
- for (Conference conf : conferences.values()) {
- if (conf.hasMultipleParticipants())
- multiConfs.add(conf);
- else
- oneToOneConfs.add(conf);
+ public void updateLists() {
+ HashMap<String, Conference> confs;
+ try {
+ confs = (HashMap<String, Conference>) mCallbacks.getService().getConferenceList();
+ nb_confs.setText("" + confs.size());
+ confs_adapter.updateDataset(new ArrayList<Conference>(confs.values()));
+ } catch (RemoteException e) {
+ e.printStackTrace();
}
- nb_confs.setText("" + multiConfs.size());
- nb_calls.setText("" + oneToOneConfs.size());
- confs_adapter.updateDataset(multiConfs);
- calls_adapter.updateDataset(oneToOneConfs);
}
@Override
@@ -261,18 +227,11 @@
Log.i(TAG, "onCreateView");
View inflatedView = inflater.inflate(R.layout.frag_call_list, container, false);
- nb_calls = (TextView) inflatedView.findViewById(R.id.calls_counter);
nb_confs = (TextView) inflatedView.findViewById(R.id.confs_counter);
confs_adapter = new CallListAdapter(getActivity());
((ListView) inflatedView.findViewById(R.id.confs_list)).setAdapter(confs_adapter);
-
- calls_adapter = new CallListAdapter(getActivity());
- ((ListView) inflatedView.findViewById(R.id.calls_list)).setAdapter(calls_adapter);
- ((ListView) inflatedView.findViewById(R.id.calls_list)).setOnItemClickListener(callClickListener);
((ListView) inflatedView.findViewById(R.id.confs_list)).setOnItemClickListener(callClickListener);
-
- ((ListView) inflatedView.findViewById(R.id.calls_list)).setOnItemLongClickListener(mItemLongClickListener);
((ListView) inflatedView.findViewById(R.id.confs_list)).setOnItemLongClickListener(mItemLongClickListener);
return inflatedView;
@@ -282,7 +241,10 @@
@Override
public void onItemClick(AdapterView<?> arg0, View v, int arg2, long arg3) {
- mCallbacks.selectedCall((Conference) v.getTag());
+ Intent intent = new Intent().setClass(getActivity(), CallActivity.class);
+ intent.putExtra("resuming", true);
+ intent.putExtra("conference", (Conference) v.getTag());
+ startActivityForResult(intent, HomeActivity.REQUEST_CODE_CALL);
}
};
@@ -442,7 +404,7 @@
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
- Conference transfer = null;
+ Conference transfer;
if (requestCode == REQUEST_TRANSFER) {
switch (resultCode) {
case 0:
@@ -451,9 +413,9 @@
try {
mCallbacks.getService().attendedTransfer(transfer.getParticipants().get(0).getCallId(), c.getParticipants().get(0).getCallId());
- calls_adapter.remove(transfer);
- calls_adapter.remove(c);
- calls_adapter.notifyDataSetChanged();
+ confs_adapter.remove(transfer);
+ confs_adapter.remove(c);
+ confs_adapter.notifyDataSetChanged();
} catch (RemoteException e) {
// TODO Auto-generated catch block
e.printStackTrace();
@@ -496,7 +458,7 @@
private void bindCalls(Conference call_to_add, Conference call_target) {
try {
- Log.i(TAG, "joining calls:"+ call_to_add.getId() + " and " + call_target.getId());
+ Log.i(TAG, "joining calls:" + call_to_add.getId() + " and " + call_target.getId());
if (call_target.hasMultipleParticipants() && !call_to_add.hasMultipleParticipants()) {
diff --git a/src/org/sflphone/history/HistoryCall.java b/src/org/sflphone/history/HistoryCall.java
index ac13f48..972a1c4 100644
--- a/src/org/sflphone/history/HistoryCall.java
+++ b/src/org/sflphone/history/HistoryCall.java
@@ -56,7 +56,7 @@
@DatabaseField
boolean missed;
@DatabaseField
- String direction;
+ int direction;
@DatabaseField
String recordPath;
@DatabaseField
@@ -79,8 +79,8 @@
call_end = call.getTimestampEnd_();
accountID = call.getAccount().getAccountID();
number = call.getContact().getPhones().get(0).getNumber();
- missed = call.isRinging() || call.isIncoming();
- direction = call.getCallTypeString();
+ missed = call.isRinging() && call.isIncoming();
+ direction = call.getCallType();
recordPath = call.getRecordPath();
contactID = call.getContact().getId();
callID = call.getCallId();
@@ -91,7 +91,14 @@
}
public String getDirection() {
- return direction;
+ switch (direction) {
+ case SipCall.direction.CALL_TYPE_INCOMING:
+ return "CALL_TYPE_INCOMING";
+ case SipCall.direction.CALL_TYPE_OUTGOING:
+ return "CALL_TYPE_OUTGOING";
+ default:
+ return "CALL_TYPE_UNDETERMINED";
+ }
}
public String getDate() {
@@ -145,7 +152,7 @@
dest.writeString(accountID);
dest.writeString(number);
dest.writeByte((byte) (missed ? 1 : 0));
- dest.writeString(direction);
+ dest.writeInt(direction);
dest.writeString(recordPath);
dest.writeLong(contactID);
dest.writeString(callID);
@@ -167,7 +174,7 @@
accountID = in.readString();
number = in.readString();
missed = in.readByte() == 1 ? true : false;
- direction = in.readString();
+ direction = in.readInt();
recordPath = in.readString();
contactID = in.readLong();
callID = in.readString();
@@ -178,7 +185,7 @@
}
public boolean isIncoming() {
- return true;
+ return direction == SipCall.direction.CALL_TYPE_INCOMING;
}
public boolean isMissed() {
diff --git a/src/org/sflphone/history/HistoryManager.java b/src/org/sflphone/history/HistoryManager.java
index 70108e1..bc90274 100644
--- a/src/org/sflphone/history/HistoryManager.java
+++ b/src/org/sflphone/history/HistoryManager.java
@@ -65,6 +65,10 @@
return true;
}
+ /*
+ * Necessary when user hang up a call in a Conference
+ * The call creates an HistoryCall, but the conference still goes on
+ */
public boolean insertNewEntry(SipCall toInsert){
return true;
}
diff --git a/src/org/sflphone/model/SipCall.java b/src/org/sflphone/model/SipCall.java
index a1f4a1e..1b1e6cb 100644
--- a/src/org/sflphone/model/SipCall.java
+++ b/src/org/sflphone/model/SipCall.java
@@ -72,7 +72,7 @@
timestampEnd_ = in.readLong();
}
- public SipCall(String id, Account account, int call_type, int call_state, int media_state, CallContact c) {
+ private SipCall(String id, Account account, int call_type, int call_state, int media_state, CallContact c) {
mCallID = id;
mAccount = account;
mCallType = call_type;
@@ -89,6 +89,10 @@
return "";
}
+ public int getCallType() {
+ return mCallType;
+ }
+
public interface direction {
public static final int CALL_TYPE_INCOMING = 1;
public static final int CALL_TYPE_OUTGOING = 2;
@@ -314,7 +318,6 @@
public boolean isOutGoing() {
if (mCallType == direction.CALL_TYPE_OUTGOING)
return true;
-
return false;
}
diff --git a/src/org/sflphone/service/CallManagerCallBack.java b/src/org/sflphone/service/CallManagerCallBack.java
index de06377..40ae6ac 100644
--- a/src/org/sflphone/service/CallManagerCallBack.java
+++ b/src/org/sflphone/service/CallManagerCallBack.java
@@ -243,43 +243,51 @@
@Override
public void on_conference_removed(String confID) {
+ Log.i(TAG, "on_conference_removed:");
Intent intent = new Intent(CONF_REMOVED);
intent.putExtra("confID", confID);
Conference toReInsert = mService.getConferences().get(confID);
- /*for (int i = 0; i < toDestroy.getParticipants().size(); ++i) {
- mService.getCurrentCalls().put(toDestroy.getParticipants().get(i).getCallId(), toDestroy.getParticipants().get(i));
- }*/
+ for (SipCall call : toReInsert.getParticipants()) {
+ mService.getConferences().put(call.getCallId(), new Conference(call));
+ }
mService.getConferences().remove(confID);
- mService.getConferences().put(toReInsert.getId(), toReInsert);
mService.sendBroadcast(intent);
}
@Override
public void on_conference_state_changed(String confID, String state) {
-
+ Log.i(TAG, "on_conference_state_changed:");
Intent intent = new Intent(CONF_CHANGED);
intent.putExtra("confID", confID);
intent.putExtra("State", state);
+ mService.getConferences().get(confID).setCallState(confID, state);
- StringVect all_participants = mService.getCallManagerJNI().getParticipantList(intent.getStringExtra("confID"));
- for (int i = 0; i < all_participants.size(); ++i) {
- if (mService.getConferences().get(confID).getParticipants().size() < all_participants.size()
- && mService.getConferences().get(all_participants.get(i)) != null) { // We need to add the new participant to the conf
- mService.getConferences().get(confID).addParticipant(mService.getConferences().get(all_participants.get(i)).getCallById(all_participants.get(i)));
- mService.getConferences().remove(all_participants.get(i));
- mService.getConferences().get(confID).setCallState(confID, intent.getStringExtra("State"));
- mService.sendBroadcast(intent);
- return;
+ Log.i(TAG, "Received:" + intent.getAction());
+ Log.i(TAG, "State:" + state);
+
+ Conference toModify = mService.getConferences().get(confID);
+
+ ArrayList<String> newParticipants = SwigNativeConverter.convertSwigToNative(mService.getCallManagerJNI().getParticipantList(intent.getStringExtra("confID")));
+
+ if (toModify.getParticipants().size() < newParticipants.size()) {
+ // We need to add the new participant to the conf
+ for (int i = 0; i < newParticipants.size(); ++i) {
+ if(toModify.getCallById(newParticipants.get(i))==null){
+ mService.addCallToConference(toModify.getId(), newParticipants.get(i));
+ }
+ }
+ } else if (toModify.getParticipants().size() > newParticipants.size()) {
+
+ for (SipCall participant : toModify.getParticipants()) {
+ if (!newParticipants.contains(participant.getCallId())) {
+ mService.removeCallFromConference(toModify.getId(), participant.getCallId());
+ }
}
}
- Log.i(TAG, "Received" + intent.getAction());
- if (mService.getConferences().get(confID) != null) {
- mService.getConferences().get(confID).setCallState(confID, state);
- mService.sendBroadcast(intent);
- }
+ mService.sendBroadcast(intent);
}
@Override
diff --git a/src/org/sflphone/service/SipService.java b/src/org/sflphone/service/SipService.java
index 78221ba..c5de94d 100644
--- a/src/org/sflphone/service/SipService.java
+++ b/src/org/sflphone/service/SipService.java
@@ -83,6 +83,33 @@
return mConferences;
}
+ public void addCallToConference(String confId, String callId) {
+ if(mConferences.get(callId) != null){
+ // We add a simple call to a conference
+ mConferences.get(confId).addParticipant(mConferences.get(callId).getParticipants().get(0));
+ mConferences.remove(callId);
+ } else {
+ Iterator<Map.Entry<String, Conference>> it = mConferences.entrySet().iterator();
+ while (it.hasNext()) {
+ Conference tmp = it.next().getValue();
+ for (SipCall c : tmp.getParticipants()) {
+ if (c.getCallId().contentEquals(callId)) {
+ mConferences.get(confId).addParticipant(c);
+ mConferences.get(tmp.getId()).removeParticipant(c.getCallId());
+ }
+ }
+ }
+ }
+
+ }
+
+ public void removeCallFromConference(String confId, String callId) {
+ SipCall call = mConferences.get(confId).getCallById(callId);
+ Conference separate = new Conference(call);
+ mConferences.put(separate.getId(), separate);
+ }
+
+
@Override
public boolean onUnbind(Intent i) {
super.onUnbind(i);
@@ -125,7 +152,7 @@
Log.i(TAG, "onDestroy");
/* called once by stopService() */
mNotificationManager.onServiceDestroy();
-
+ mMediaManager.stopService();
getExecutor().execute(new FinalizeRunnable());
super.onDestroy();
@@ -358,7 +385,8 @@
protected void doRun() throws SameThreadException {
Log.i(TAG, "SipService.hangUp() thread running...");
callManagerJNI.hangUp(callID);
- mMediaManager.abandonAudioFocus();
+ if(mConferences.size() == 0)
+ mMediaManager.abandonAudioFocus();
}
});
}
diff --git a/src/org/sflphone/utils/SwigNativeConverter.java b/src/org/sflphone/utils/SwigNativeConverter.java
index aa6fce5..306d580 100644
--- a/src/org/sflphone/utils/SwigNativeConverter.java
+++ b/src/org/sflphone/utils/SwigNativeConverter.java
@@ -42,6 +42,7 @@
import org.sflphone.account.AccountDetailTls;
import org.sflphone.service.ServiceConstants;
import org.sflphone.service.StringMap;
+import org.sflphone.service.StringVect;
import org.sflphone.service.VectMap;
public class SwigNativeConverter {
@@ -179,4 +180,11 @@
return toReturn;
}
+ public static ArrayList<String> convertSwigToNative(StringVect vector) {
+ ArrayList<String> toReturn = new ArrayList<String>();
+ for (int i = 0; i < vector.size(); ++i) {
+ toReturn.add(vector.get(i));
+ }
+ return toReturn;
+ }
}