#16923: Implement factory method in CallList to create new calls
diff --git a/src/com/savoirfairelinux/sflphone/client/CallActivity.java b/src/com/savoirfairelinux/sflphone/client/CallActivity.java
index 51a6cb4..d032e8d 100644
--- a/src/com/savoirfairelinux/sflphone/client/CallActivity.java
+++ b/src/com/savoirfairelinux/sflphone/client/CallActivity.java
@@ -64,9 +64,13 @@
         // Parcelable value = b.getParcelable("CallInfo");
         SipCall.CallInfo info = b.getParcelable("CallInfo"); // new SipCall.CallInfo.CREATOR.createFromParcel
         Log.i(TAG, "Starting activity for call " + info.mCallID);
+        mCall = new SipCall(info); 
 
         Intent intent = new Intent(this, SipService.class);
         bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+
+        findViewById(R.id.buttonhangup).setOnClickListener(this);
+        
     }
 
     @Override
@@ -90,12 +94,11 @@
     @Override
     public void onClick(View view)
     {
+        Log.i(TAG, "On click action");
         if(view.getId() == R.id.buttonhangup) {
-            try {
-                service.hangUp(mCall.mCallInfo.mCallID);
-            } catch (RemoteException e) {
-                Log.e(TAG, "Cannot call service method", e);
-            }
+            mCall.hangup(service);
+            // terminate this activity
+            finish();
         }
     }
 }
diff --git a/src/com/savoirfairelinux/sflphone/client/CallElementList.java b/src/com/savoirfairelinux/sflphone/client/CallElementList.java
index 47f6af0..cbbe17a 100644
--- a/src/com/savoirfairelinux/sflphone/client/CallElementList.java
+++ b/src/com/savoirfairelinux/sflphone/client/CallElementList.java
@@ -289,17 +289,17 @@
                               Log.i(TAG, "Selected " + items[item]);
                               switch (item) {
                                   case 0:
-                                      call.hangup();
+                                      call.hangup(service);
                                       break;
                                   case 1:
                                       call.sendTextMessage();
                                       // Need to hangup this call immediately since no way to do it after this action
-                                      call.hangup();
+                                      call.hangup(service);
                                       break;
                                   case 2:
                                       call.addToConference();
                                       // Need to hangup this call immediately since no way to do it after this action
-                                      call.hangup();
+                                      call.hangup(service);
                                       break;
                                   default:
                                       break; 
@@ -354,7 +354,7 @@
         // Insert desired behavior here.
         Log.i(TAG, "Item clicked: " + id);
         SipCall call = (SipCall) mAdapter.getItem(position);
-        call.hangup(); 
+        call.hangup(service); 
     }
 
 	@Override
diff --git a/src/com/savoirfairelinux/sflphone/client/ContactListFragment.java b/src/com/savoirfairelinux/sflphone/client/ContactListFragment.java
index d7a8d6f..0cf95b4 100644
--- a/src/com/savoirfairelinux/sflphone/client/ContactListFragment.java
+++ b/src/com/savoirfairelinux/sflphone/client/ContactListFragment.java
@@ -232,12 +232,12 @@
                                   case 1:
                                       call.sendTextMessage();
                                       // Need to hangup this call immediately since no way to do it after this action
-                                      call.hangup();
+                                      call.hangup(service);
                                       break;
                                   case 2:
                                       call.addToConference();
                                       // Need to hangup this call immediately since no way to do it after this action
-                                      call.hangup();
+                                      call.hangup(service);
                                       break;
                                   default:
                                       break; 
diff --git a/src/com/savoirfairelinux/sflphone/client/SFLPhoneHome.java b/src/com/savoirfairelinux/sflphone/client/SFLPhoneHome.java
index df4ac8a..7d7a863 100644
--- a/src/com/savoirfairelinux/sflphone/client/SFLPhoneHome.java
+++ b/src/com/savoirfairelinux/sflphone/client/SFLPhoneHome.java
@@ -41,6 +41,7 @@
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.ServiceConnection;
 import android.os.Bundle;
 import android.os.Handler;
@@ -49,6 +50,7 @@
 import android.os.RemoteException;
 import android.support.v13.app.FragmentStatePagerAdapter;
 import android.support.v4.view.ViewPager;
+import android.support.v4.content.LocalBroadcastManager;
 import android.util.Log;
 import android.view.Gravity;
 import android.view.LayoutInflater;
@@ -69,6 +71,7 @@
 import com.savoirfairelinux.sflphone.service.ISipService;
 import com.savoirfairelinux.sflphone.service.SipService;
 import com.savoirfairelinux.sflphone.utils.AccountList;
+import com.savoirfairelinux.sflphone.utils.CallList;
 
 import java.util.HashMap;
 
@@ -91,6 +94,7 @@
     private boolean mBound = false;
     private ISipService service;
     public AccountList mAccountList = new AccountList();
+    public CallList mCallList = new CallList();
 
     /**
      * The {@link ViewPager} that will host the section contents.
@@ -164,6 +168,10 @@
         animation.setRepeatCount(Animation.INFINITE);
         // Reverse
         animation.setRepeatMode(Animation.REVERSE);
+
+        LocalBroadcastManager.getInstance(this).registerReceiver(mCallList, new IntentFilter("new-call-created"));
+        LocalBroadcastManager.getInstance(this).registerReceiver(mCallList, new IntentFilter("call-state-changed"));
+        LocalBroadcastManager.getInstance(this).registerReceiver(mCallList, new IntentFilter("incoming-call"));
     }
 
     @Override
@@ -484,12 +492,19 @@
             Log.e(TAG, "Cannot call service method", e);
         }
         */
-        SipCall call = new SipCall();
+        
+        Random random = new Random();
+        String callID = Integer.toString(random.nextInt());
+        SipCall.CallInfo info = new SipCall.CallInfo();
+        info.mCallID = callID;
+
+        SipCall call = CallList.getCallInstance(info);
+
         launchCallActivity(call);
     }
 
     public void processingHangUpAction() {
-       try {
+        try {
             if (incomingCallID != "") {
                 buttonCall.clearAnimation();
                 Log.d(TAG, "service.refuse(" + incomingCallID + ");");
diff --git a/src/com/savoirfairelinux/sflphone/client/SipCall.java b/src/com/savoirfairelinux/sflphone/client/SipCall.java
index caf9c9a..ed1aee8 100644
--- a/src/com/savoirfairelinux/sflphone/client/SipCall.java
+++ b/src/com/savoirfairelinux/sflphone/client/SipCall.java
@@ -32,13 +32,16 @@
 
 import android.os.Parcelable;
 import android.os.Parcel;
+import android.os.RemoteException;
 import android.util.Log;
 import java.util.ArrayList;
 
+import com.savoirfairelinux.sflphone.service.ISipService;
+
 public class SipCall
 {
     final static String TAG = "SipCall";
-    public static CallElementList mCallElementList;
+    public static CallElementList mCallElementList = null;
     public CallInfo mCallInfo;
 
     public static int CALL_STATE_INVALID = 0;      // The call is not existent in SFLphone service
@@ -74,6 +77,8 @@
         @Override
         public void writeToParcel(Parcel out, int flags) {
             ArrayList<String> list = new ArrayList<String>();
+
+            // Don't mess with this order!!!
             list.add(mCallID);
             list.add(mDisplayName);
             list.add(mPhone);
@@ -100,6 +105,8 @@
 
         private CallInfo(Parcel in) {
             ArrayList<String> list = in.createStringArrayList();
+
+            // Don't mess with this order!!!
             mCallID = list.get(0);
             mDisplayName = list.get(1);
             mPhone = list.get(2);
@@ -126,27 +133,10 @@
         mCallElementList = list;
     }
 
-    /** TODO factory method that should be moved in CallList 
-    public static SipCall getCallInstance(CallInfo info)
-    {
-        if(CallList.isEmpty())
-            return new SipCall(info);
-       
-        for(SipCall sipcall : CallList) {
-            if(sipcall.mCallInfo.mDisplayName.equals(info.mDisplayName)) {
-                if(sipcall.mCallInfo.mPhone.equals(info.mPhone)) {
-                    return sipcall;
-                }
-            }
-        }
-
-        return new SipCall(info);
-    }
-    */
-
     public void placeCall()
     {
-        mCallElementList.addCall(this); 
+        if(mCallElementList != null)
+            mCallElementList.addCall(this); 
         // mManager.callmanagerJNI.placeCall("IP2IP", "CALL1234", "192.168.40.35");
     }
 
@@ -155,10 +145,18 @@
 
     }
 
-    public void hangup()
+    public void hangup(ISipService service)
     {
-        mCallElementList.removeCall(this);
-        // mManager.callmanagerJNI.hangup("IP2IP", "CALL1234", "192.168.40.35");
+        Log.i(TAG, "Hangup call " + mCallInfo.mCallID);
+
+        if(mCallElementList != null)
+            mCallElementList.removeCall(this);
+
+        try {
+            service.hangUp(mCallInfo.mCallID);
+        } catch (RemoteException e) {
+            Log.e(TAG, "Cannot call service method", e);
+        }
     }
 
     public void addToConference()
diff --git a/src/com/savoirfairelinux/sflphone/service/CallManagerCallBack.java b/src/com/savoirfairelinux/sflphone/service/CallManagerCallBack.java
index 602eaa9..4ef7cc4 100644
--- a/src/com/savoirfairelinux/sflphone/service/CallManagerCallBack.java
+++ b/src/com/savoirfairelinux/sflphone/service/CallManagerCallBack.java
@@ -1,23 +1,67 @@
 package com.savoirfairelinux.sflphone.service;
 
+import android.content.Context;
+import android.content.Intent;
 import android.util.Log;
+import android.os.Bundle;
+import android.support.v4.content.LocalBroadcastManager;
 
 public class CallManagerCallBack extends Callback {
     
     private static final String TAG = "CallManagerCallBack";
+    private Context mContext; 
+
+    public CallManagerCallBack(Context context) {
+        mContext = context;
+    }
 
     @Override
     public void on_new_call_created(String accountID, String callID, String to) {
         Log.d(TAG, "on_new_call_created(" + accountID + ", " + callID + ", " + to + ")");
+        sendNewCallCreatedMessage(accountID, callID, to);
     }
 
     @Override
     public void on_call_state_changed(String callID, String state) {
         Log.d(TAG, "on_call_state_changed(" + callID + ", " + state + ")");
+        sendCallStateChangedMessage(callID, state);
     }
 
     @Override
     public void on_incoming_call(String accountID, String callID, String from) {
         Log.d(TAG, "on_incoming_call(" + accountID + ", " + callID + ", " + from + ")");
+        sendIncomingCallMessage(accountID, callID, from);
+    }
+
+    private void sendNewCallCreatedMessage(String accountID, String callID, String to) {
+        Bundle bundle = new Bundle();
+        bundle.putString("AccountID", accountID);
+        bundle.putString("CallID", callID);
+        bundle.putString("To", to);
+        Intent intent = new Intent("new-call-created");
+        intent.putExtra("signal-name", "new-call-created");
+        intent.putExtra("newcall", bundle);
+        LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
+    }
+
+    private void sendCallStateChangedMessage(String callID, String state) {
+        Bundle bundle = new Bundle();
+        bundle.putString("CallID", callID);
+        bundle.putString("State", state);
+        Intent intent = new Intent("call-state-changed");
+        intent.putExtra("signal-name", "call-state-changed"); 
+        intent.putExtra("newstate", bundle);
+        LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
+    }
+
+    private void sendIncomingCallMessage(String accountID, String callID, String from) {
+        Bundle bundle = new Bundle();
+        bundle.putString("AccountID", accountID);
+        bundle.putString("CallID", callID);
+        bundle.putString("From", from);
+        Intent intent = new Intent("incoming-call");
+        intent.putExtra("signal-name", "incoming-call"); 
+        intent.putExtra("newcall", bundle);
+        LocalBroadcastManager.getInstance(mContext).sendBroadcast(intent);
     }
 }
diff --git a/src/com/savoirfairelinux/sflphone/service/ConfigurationManagerCallback.java b/src/com/savoirfairelinux/sflphone/service/ConfigurationManagerCallback.java
index 787447b..3bfcafc 100644
--- a/src/com/savoirfairelinux/sflphone/service/ConfigurationManagerCallback.java
+++ b/src/com/savoirfairelinux/sflphone/service/ConfigurationManagerCallback.java
@@ -29,9 +29,9 @@
 
 public class ConfigurationManagerCallback extends ConfigurationCallback {
     private static final String TAG = "ConfigurationManagerCallback";
-    Context mContext; 
+    private Context mContext; 
 
-    ConfigurationManagerCallback(Context context) {
+    public ConfigurationManagerCallback(Context context) {
         mContext = context;
     }
 
diff --git a/src/com/savoirfairelinux/sflphone/service/SipService.java b/src/com/savoirfairelinux/sflphone/service/SipService.java
index 14c39bf..3eb2758 100644
--- a/src/com/savoirfairelinux/sflphone/service/SipService.java
+++ b/src/com/savoirfairelinux/sflphone/service/SipService.java
@@ -369,7 +369,7 @@
         managerImpl.setPath(sflphoneApp.getAppPath());
 
         callManagerJNI = new CallManagerJNI();
-        callManagerCallBack = new CallManagerCallBack();
+        callManagerCallBack = new CallManagerCallBack(this);
         SFLPhoneservice.setCallbackObject(callManagerCallBack);
 
         configurationManagerJNI = new ConfigurationManagerJNI();
diff --git a/src/com/savoirfairelinux/sflphone/utils/CallList.java b/src/com/savoirfairelinux/sflphone/utils/CallList.java
index 20d3dae..0afa0ed 100644
--- a/src/com/savoirfairelinux/sflphone/utils/CallList.java
+++ b/src/com/savoirfairelinux/sflphone/utils/CallList.java
@@ -43,7 +43,7 @@
 public class CallList extends BroadcastReceiver
 {
     static final String TAG = "CallList";
-    ArrayList<SipCall> mList = new ArrayList<SipCall>();
+    static ArrayList<SipCall> mList = new ArrayList<SipCall>();
 
     private enum Signals {
         NEW_CALL_CREATED,
@@ -52,22 +52,35 @@
         CALL_STATE_CHANGED
     }
 
+    /**
+     * Factory method to create/retreive call instance
+     */
+    public static SipCall getCallInstance(SipCall.CallInfo info)
+    {
+        if(mList.isEmpty())
+            return new SipCall(info);
+
+        for(SipCall sipcall : mList) {
+            if(sipcall.mCallInfo.mCallID.equals(info.mCallID)) {
+                return sipcall;
+            }
+        }
+
+        SipCall call = new SipCall(info);
+        mList.add(call);
+
+        return call;
+    }
+
     @Override
     public void onReceive(Context context, Intent intent)
     {
         String signalName = intent.getStringExtra("signal-name");
         Log.d(TAG, "Signal received: " + signalName);
 
-        Signals signalReceived = Signals.valueOf(signalName.toUpperCase());
-        switch(signalReceived) {
-            case NEW_CALL_CREATED:
-                break;
-            case INCOMING_CALL:
-                break;
-            case INCOMING_MESSAGE:
-                break;
-            case CALL_STATE_CHANGED:
-                break;
+        if(signalName.equals("new-call-created")) {
+        } else if(signalName.equals("call-state-changed")) {
+        } else if(signalName.equals("incoming-call")) {
         }
     }
 }