* #33708: im working for calls (conference untested)
diff --git a/res/layout/frag_imessaging.xml b/res/layout/frag_imessaging.xml
index ab75024..e7d69ba 100644
--- a/res/layout/frag_imessaging.xml
+++ b/res/layout/frag_imessaging.xml
@@ -1,33 +1,41 @@
 <?xml version="1.0" encoding="utf-8"?>
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
-    android:layout_height="fill_parent"
-    android:orientation="vertical" >
+    android:layout_width="match_parent"
+    android:layout_height="match_parent" >
 
     <ListView
         android:id="@+id/message_list"
         android:layout_width="match_parent"
-        android:layout_height="wrap_content"
+        android:layout_height="match_parent"
         android:layout_above="@+id/form"
+        android:background="@color/sfl_dark_blue"
         android:layout_alignParentTop="true" >
     </ListView>
 
-    <RelativeLayout
+    <LinearLayout
         android:id="@+id/form"
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content"
         android:layout_alignParentBottom="true"
-        android:layout_alignParentLeft="true"
-        android:orientation="vertical" >
+        android:background="@color/darker_gray"
+        android:weightSum="4" >
 
         <EditText
-            android:id="@+id/editText1"
-            android:layout_width="wrap_content"
+            android:id="@+id/send_im_edittext"
+            android:layout_width="0dp"
+            android:layout_weight="3"
             android:layout_height="wrap_content"
-            android:layout_alignParentLeft="true"
-            android:layout_alignParentRight="true"
+            android:imeOptions="actionSend"
             android:ems="10"
-            android:inputType="text" />
-    </RelativeLayout>
+            android:inputType="textCapSentences|textImeMultiLine" />
+        
+        <Button 
+            android:id="@+id/send_im_button"
+             android:layout_width="0dp"
+            android:layout_weight="1"
+            android:layout_height="wrap_content"
+            android:text="Send"
+            android:background="@drawable/item_generic_selector"/>
+    </LinearLayout>
 
 </RelativeLayout>
\ No newline at end of file
diff --git a/res/layout/item_message.xml b/res/layout/item_message.xml
index da513cc..a9042a3 100644
--- a/res/layout/item_message.xml
+++ b/res/layout/item_message.xml
@@ -1,11 +1,11 @@
 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="fill_parent"
+    android:layout_width="match_parent"
     android:layout_height="wrap_content" >
 
     <LinearLayout
         android:id="@+id/wrapper"
-        android:layout_width="fill_parent"
+        android:layout_width="match_parent"
         android:layout_height="wrap_content" >
 
         <TextView
@@ -16,7 +16,7 @@
             android:layout_margin="5dip"
             android:background="@drawable/item_generic_selector"
             android:paddingLeft="10dip"
-            android:text="Hello bubbles!"
+            android:autoLink="all"
             android:textColor="@android:color/primary_text_light" />
     </LinearLayout>
 
diff --git a/src/org/sflphone/adapters/DiscussArrayAdapter.java b/src/org/sflphone/adapters/DiscussArrayAdapter.java
index 8312c2a..9dc1730 100644
--- a/src/org/sflphone/adapters/DiscussArrayAdapter.java
+++ b/src/org/sflphone/adapters/DiscussArrayAdapter.java
@@ -6,10 +6,10 @@
 import org.sflphone.R;
 import org.sflphone.model.SipMessage;
 
-import android.app.Activity;
 import android.content.Context;
 import android.graphics.Bitmap;
 import android.graphics.BitmapFactory;
+import android.os.Bundle;
 import android.view.Gravity;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -25,8 +25,14 @@
     private LinearLayout wrapper;
     private Context mContext;
 
-    public DiscussArrayAdapter(Context context) {
+    public DiscussArrayAdapter(Context context, Bundle args) {
         mContext = context;
+        
+        if(args == null)
+            messages = new ArrayList<SipMessage>();
+        else
+            messages = args.getParcelableArrayList("messages");
+        
     }
 
     public void add(SipMessage object) {
diff --git a/src/org/sflphone/client/CallActivity.java b/src/org/sflphone/client/CallActivity.java
index 955b584..fa1e6fa 100644
--- a/src/org/sflphone/client/CallActivity.java
+++ b/src/org/sflphone/client/CallActivity.java
@@ -33,6 +33,7 @@
 
 package org.sflphone.client;
 
+import java.util.ArrayList;
 import java.util.HashMap;
 
 import org.sflphone.R;
@@ -191,6 +192,7 @@
             service = ISipService.Stub.asInterface(binder);
 
             mCurrentCallFragment = new CallFragment();
+            mIMFragment = new IMFragment();
 
             Uri u = getIntent().getData();
             if (u != null) {
@@ -198,7 +200,7 @@
                 try {
                     service.destroyNotification();
 
-                    String accountID = (String) service.getAccountList().get(1);
+                    String accountID = (String) service.getAccountList().get(1); // We use the first account to place outgoing calls
                     Account acc = new Account(accountID, (HashMap<String, String>) service.getAccountDetails(accountID));
 
                     SipCall call = SipCall.SipCallBuilder.getInstance().startCallCreation().setContact(c).setAccount(acc)
@@ -217,15 +219,24 @@
                 if (getIntent().getBooleanExtra("resuming", false)) {
 
                     Bundle b = new Bundle();
+                    Conference resumed = getIntent().getParcelableExtra("conference");
                     b.putParcelable("conference", getIntent().getParcelableExtra("conference"));
                     mCurrentCallFragment.setArguments(b);
 
+                    Bundle IMBundle = new Bundle();
+                    IMBundle.putParcelableArrayList("messages", resumed.getMessages());
+                    mIMFragment.setArguments(IMBundle);
+
                 } else {
                     mCurrentCallFragment.setArguments(getIntent().getExtras());
+                    
+                    Bundle IMBundle = new Bundle();
+                    IMBundle.putParcelableArrayList("messages", new ArrayList<SipMessage>());
+                    mIMFragment.setArguments(IMBundle);
                 }
 
             }
-            mIMFragment = new IMFragment();
+
             slidingPaneLayout.setCurFragment(mCurrentCallFragment);
             getIntent().getExtras();
             // mCallsFragment.update();
@@ -249,7 +260,6 @@
         mCurrentCallFragment.setArguments(b);
         getFragmentManager().beginTransaction().replace(R.id.ongoingcall_pane, mCurrentCallFragment).commit();
         slidingPaneLayout.setCurFragment(mCurrentCallFragment);
-        // mCallsFragment.update();
 
     }
 
@@ -264,13 +274,6 @@
     @SuppressWarnings("unchecked")
     // No proper solution with HashMap runtime cast
     public void processCallStateChangedSignal(String callID, String newState) {
-        /*
-         * Bundle bundle = intent.getBundleExtra("com.savoirfairelinux.sflphone.service.newstate"); String callID = bundle.getString("CallID"); String
-         * newState = bundle.getString("State");
-         */
-        // CallFragment fr = mCurrentCallFragment;
-
-        // mCallsFragment.update();
 
         if (mCurrentCallFragment != null) {
             mCurrentCallFragment.changeCallState(callID, newState);
@@ -282,17 +285,6 @@
             HashMap<String, SipCall> callMap = (HashMap<String, SipCall>) service.getCallList();
             HashMap<String, Conference> confMap = (HashMap<String, Conference>) service.getConferenceList();
 
-            // Log.i(TAG, "call size"+callMap.size());
-            // Log.i(TAG, "call size"+confMap.size());
-            // if (callMap.size() == 0 && confMap.size() == 0) {
-            // finish();
-            // }
-            //
-            // if (callMap.size() > 0) {
-            // // ArrayList<SipCall> calls = new ArrayList<SipCall>(callMap.values());
-            // // HashMap<String, String> details = (HashMap<String, String>) service.getCallDetails(calls.get(0).getCallId());
-            //
-            // }
         } catch (RemoteException e) {
 
             Log.e(TAG, e.toString());
@@ -305,8 +297,8 @@
     @Override
     public void incomingText(Intent in) {
         Bundle b = in.getBundleExtra("com.savoirfairelinux.sflphone.service.newtext");
-        
-        if(mIMFragment != null){
+
+        if (mIMFragment != null) {
             SipMessage msg = new SipMessage(true, b.getString("Msg"));
             mIMFragment.putMessage(msg);
         }
@@ -318,30 +310,6 @@
         return service;
     }
 
-    // @Override
-    // public void {
-    //
-    // if (mCurrentCallFragment == null || mCurrentCallFragment.getBubbleView() == null) {
-    // return;
-    // }
-    // mHandler.removeCallbacks(mUpdateTimeTask);
-    // mCurrentCallFragment.getBubbleView().stopThread();
-    // mCurrentCallFragment = new CallFragment();
-    // Bundle b = new Bundle();
-    //
-    // b.putParcelable("conference", conf);
-    // mCurrentCallFragment.setArguments(b);
-    //
-    // // if (calls.size() == 1) {
-    // // onCallResumed(calls.get(0));
-    // // }
-    //
-    // // slidingPaneLayout.setCurFragment(mCurrentCallFragment);
-    // slidingPaneLayout.closePane();
-    // // fragIsChanging = true;
-    //
-    // }
-
     @Override
     public void onBackPressed() {
         super.onBackPressed();
@@ -383,6 +351,19 @@
     }
 
     @Override
+    public boolean sendIM(SipMessage msg) {
+
+        try {
+            service.sendTextMessage(mCurrentCallFragment.getConference().getId(), msg);
+        } catch (RemoteException e) {
+            e.printStackTrace();
+            return false;
+        }
+
+        return true;
+    }
+
+    @Override
     public void startTimer() {
         mHandler.postDelayed(mUpdateTimeTask, 0);
     }
diff --git a/src/org/sflphone/fragments/CallFragment.java b/src/org/sflphone/fragments/CallFragment.java
index c738e6d..beaf2ad 100644
--- a/src/org/sflphone/fragments/CallFragment.java
+++ b/src/org/sflphone/fragments/CallFragment.java
@@ -357,7 +357,7 @@
     }
 
     private Bubble getBubbleForUser(Conference conf, float x, float y) {
-        Bubble contact_bubble = model.getBubble(conf.getId());
+        Bubble contact_bubble = model.getUser();
         if (contact_bubble != null) {
             contact_bubble.attractor.set(x, y);
             ((BubbleUser) contact_bubble).setConference(conf);
diff --git a/src/org/sflphone/fragments/IMFragment.java b/src/org/sflphone/fragments/IMFragment.java
index 2cf02ea..6f6ddb2 100644
--- a/src/org/sflphone/fragments/IMFragment.java
+++ b/src/org/sflphone/fragments/IMFragment.java
@@ -1,8 +1,9 @@
 package org.sflphone.fragments;
 
+import java.util.ArrayList;
+
 import org.sflphone.R;
 import org.sflphone.adapters.DiscussArrayAdapter;
-import org.sflphone.model.Conference;
 import org.sflphone.model.SipMessage;
 import org.sflphone.service.ISipService;
 
@@ -10,10 +11,18 @@
 import android.app.Fragment;
 import android.content.Intent;
 import android.os.Bundle;
+import android.util.Log;
+import android.view.KeyEvent;
 import android.view.LayoutInflater;
 import android.view.View;
+import android.view.View.OnClickListener;
 import android.view.ViewGroup;
+import android.view.inputmethod.EditorInfo;
+import android.widget.Button;
+import android.widget.EditText;
 import android.widget.ListView;
+import android.widget.TextView;
+import android.widget.TextView.OnEditorActionListener;
 
 public class IMFragment extends Fragment {
     static final String TAG = CallListFragment.class.getSimpleName();
@@ -23,6 +32,8 @@
     DiscussArrayAdapter mAdapter;
     ListView list;
 
+    private EditText sendTextField;
+
     public static final int REQUEST_TRANSFER = 10;
     public static final int REQUEST_CONF = 20;
 
@@ -30,7 +41,7 @@
     public void onCreate(Bundle savedBundle) {
         super.onCreate(savedBundle);
 
-        mAdapter = new DiscussArrayAdapter(getActivity());
+        mAdapter = new DiscussArrayAdapter(getActivity(), getArguments());
 
     }
 
@@ -44,6 +55,11 @@
             return null;
         }
 
+        @Override
+        public boolean sendIM(SipMessage msg) {
+            return false;
+        }
+
     };
 
     /**
@@ -53,6 +69,7 @@
     public interface Callbacks {
         public ISipService getService();
 
+        public boolean sendIM(SipMessage msg);
     }
 
     @Override
@@ -72,8 +89,6 @@
         mCallbacks = sDummyCallbacks;
     }
 
-    
-
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
         ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.frag_imessaging, container, false);
@@ -81,15 +96,48 @@
         list = (ListView) rootView.findViewById(R.id.message_list);
         list.setAdapter(mAdapter);
 
+        sendTextField = (EditText) rootView.findViewById(R.id.send_im_edittext);
+
+        sendTextField.setOnEditorActionListener(new OnEditorActionListener() {
+
+            @Override
+            public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+
+                if (actionId == EditorInfo.IME_ACTION_SEND) {
+                    if (sendTextField.getText().toString().length() > 0) {
+                        SipMessage toSend = new SipMessage(false, sendTextField.getText().toString());
+                        putMessage(toSend);
+                        sendTextField.setText("");
+                        mCallbacks.sendIM(toSend);
+                    }
+                }
+                return true;
+            }
+        });
+
+        ((Button) rootView.findViewById(R.id.send_im_button)).setOnClickListener(new OnClickListener() {
+
+            @Override
+            public void onClick(View v) {
+                if (sendTextField.getText().toString().length() > 0) {
+                    SipMessage toSend = new SipMessage(false, sendTextField.getText().toString());
+                    putMessage(toSend);
+                    sendTextField.setText("");
+                    mCallbacks.sendIM(toSend);
+                }
+            }
+        });
+
         return rootView;
     }
-    
+
     @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
-        super.onActivityResult(requestCode, resultCode, data);       
+        super.onActivityResult(requestCode, resultCode, data);
     }
 
     public void putMessage(SipMessage msg) {
         mAdapter.add(msg);
+        Log.i(TAG, "Messages" + mAdapter.getCount());
     }
 }
diff --git a/src/org/sflphone/model/Bubble.java b/src/org/sflphone/model/Bubble.java
index b76feca..1f8c405 100644
--- a/src/org/sflphone/model/Bubble.java
+++ b/src/org/sflphone/model/Bubble.java
@@ -62,6 +62,7 @@
         saved_photo = getContactPhoto(context, contact, (int) size);
         generateBitmap();
         attractor = new PointF(x, y);
+        isUser = false;
     }
 
     protected void generateBitmap() {
diff --git a/src/org/sflphone/model/BubbleContact.java b/src/org/sflphone/model/BubbleContact.java
index 3670f3c..1650a93 100644
--- a/src/org/sflphone/model/BubbleContact.java
+++ b/src/org/sflphone/model/BubbleContact.java
@@ -27,7 +27,6 @@
     public BubbleContact(Context context, SipCall call, float x, float y, float size) {
         super(context, call.getContact(), x, y, size);
         associated_call = call;
-        isUser = false;
         setDrawer(new ActionDrawer(0, 0, drawerPosition.UNDEFINED));
         buttonMsg = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_action_chat);
         buttonHold = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_action_pause_over_video);
diff --git a/src/org/sflphone/model/BubbleModel.java b/src/org/sflphone/model/BubbleModel.java
index ee5cb30..ff69792 100644
--- a/src/org/sflphone/model/BubbleModel.java
+++ b/src/org/sflphone/model/BubbleModel.java
@@ -6,192 +6,188 @@
 import android.graphics.PointF;
 import android.util.Log;
 
-public class BubbleModel
-{
-	private static final String TAG = BubbleModel.class.getSimpleName();
+public class BubbleModel {
+    private static final String TAG = BubbleModel.class.getSimpleName();
 
-	private long lastUpdate = 0;
-	public int width, height;
-	private ArrayList<Bubble> bubbles = new ArrayList<Bubble>();
-	private ArrayList<Attractor> attractors = new ArrayList<Attractor>();
+    private long lastUpdate = 0;
+    public int width, height;
+    private ArrayList<Bubble> bubbles = new ArrayList<Bubble>();
+    private ArrayList<Attractor> attractors = new ArrayList<Attractor>();
 
-	private static final double BUBBLE_RETURN_TIME_HALF_LIFE = .3;
-	private static final double BUBBLE_RETURN_TIME_LAMBDA = Math.log(2)/BUBBLE_RETURN_TIME_HALF_LIFE;
+    private static final double BUBBLE_RETURN_TIME_HALF_LIFE = .3;
+    private static final double BUBBLE_RETURN_TIME_LAMBDA = Math.log(2) / BUBBLE_RETURN_TIME_HALF_LIFE;
 
-	private static final double FRICTION_VISCOUS = Math.log(2)/.2f;		// Viscous friction factor
+    private static final double FRICTION_VISCOUS = Math.log(2) / .2f; // Viscous friction factor
 
-	private static final float BUBBLE_MAX_SPEED = 2500.f;	// px.s-1 : Max target speed in px/sec
-	private static final float ATTRACTOR_SMOOTH_DIST = 50.f; // px : Size of the "gravity hole" around the attractor
-	private static final float ATTRACTOR_STALL_DIST = 15.f; // px : Size of the "gravity hole" flat bottom
-	private static final float ATTRACTOR_DIST_SUCK = 20.f; // px
+    private static final float BUBBLE_MAX_SPEED = 2500.f; // px.s-1 : Max target speed in px/sec
+    private static final float ATTRACTOR_SMOOTH_DIST = 50.f; // px : Size of the "gravity hole" around the attractor
+    private static final float ATTRACTOR_STALL_DIST = 15.f; // px : Size of the "gravity hole" flat bottom
+    private static final float ATTRACTOR_DIST_SUCK = 20.f; // px
 
-	private static final float BORDER_REPULSION = 60000; // px.s^-2
+    private static final float BORDER_REPULSION = 60000; // px.s^-2
 
-	private final float border_repulsion;
-	private final float bubble_max_speed;
-	private final float attractor_smooth_dist;
-	private final float attractor_stall_dist;
-	private final float attractor_dist_suck;
+    private final float border_repulsion;
+    private final float bubble_max_speed;
+    private final float attractor_smooth_dist;
+    private final float attractor_stall_dist;
+    private final float attractor_dist_suck;
 
-	private float density = 1.f;
+    private float density = 1.f;
 
-	public BubbleModel(float screen_density) {
-	    Log.d(TAG, "Creating BubbleModel");
-		this.density = screen_density;
-		attractor_dist_suck = ATTRACTOR_DIST_SUCK*density;
-		bubble_max_speed = BUBBLE_MAX_SPEED*density;
-		attractor_smooth_dist = ATTRACTOR_SMOOTH_DIST*density;
-		attractor_stall_dist = ATTRACTOR_STALL_DIST*density;
-		border_repulsion = BORDER_REPULSION*density;
-	}
+    public BubbleModel(float screen_density) {
+        Log.d(TAG, "Creating BubbleModel");
+        this.density = screen_density;
+        attractor_dist_suck = ATTRACTOR_DIST_SUCK * density;
+        bubble_max_speed = BUBBLE_MAX_SPEED * density;
+        attractor_smooth_dist = ATTRACTOR_SMOOTH_DIST * density;
+        attractor_stall_dist = ATTRACTOR_STALL_DIST * density;
+        border_repulsion = BORDER_REPULSION * density;
+    }
 
-	public void addBubble(Bubble b) {
-		b.setDensity(density);
-		bubbles.add(b);
-	}
+    public void addBubble(Bubble b) {
+        b.setDensity(density);
+        bubbles.add(b);
+    }
 
-	public List<Bubble> getBubbles()
-	{
-		return bubbles;
-	}
+    public List<Bubble> getBubbles() {
+        return bubbles;
+    }
 
-	public void addAttractor(Attractor a) {
-		a.setDensity(density);
-		attractors.add(a);
-	}
+    public void addAttractor(Attractor a) {
+        a.setDensity(density);
+        attractors.add(a);
+    }
 
-	public List<Attractor> getAttractors()
-	{
-		return attractors;
-	}
+    public List<Attractor> getAttractors() {
+        return attractors;
+    }
 
-	public void clearAttractors() {
-		attractors.clear();
-	}
+    public void clearAttractors() {
+        attractors.clear();
+    }
 
-	public void clear() {
-		clearAttractors();
-		bubbles.clear();
-	}
+    public void clear() {
+        clearAttractors();
+        bubbles.clear();
+    }
 
-	public void update()
-	{
-		long now = System.nanoTime();
+    public void update() {
+        long now = System.nanoTime();
 
-		// Do nothing if lastUpdate is in the future.
-		if (lastUpdate > now)
-			return;
+        // Do nothing if lastUpdate is in the future.
+        if (lastUpdate > now)
+            return;
 
-		double ddt = Math.min((now - lastUpdate) / 1000000000.0, .2);
-		lastUpdate = now;
+        double ddt = Math.min((now - lastUpdate) / 1000000000.0, .2);
+        lastUpdate = now;
 
-		float dt = (float)ddt;
-		//Log.w(TAG, "update dt="+dt);
+        float dt = (float) ddt;
+        // Log.w(TAG, "update dt="+dt);
 
-		int attr_n = attractors.size();
+        int attr_n = attractors.size();
 
-		// Iterators should not be used in frequently called methods
-		// to avoid garbage collection glitches caused by iterator objects.
-		for(int i=0, n=bubbles.size(); i<n; i++) {
-			Bubble b = bubbles.get(i);
-			
-            if (b.markedToDie){
-			    continue;
-			}
+        // Iterators should not be used in frequently called methods
+        // to avoid garbage collection glitches caused by iterator objects.
+        for (int i = 0, n = bubbles.size(); i < n; i++) {
+            Bubble b = bubbles.get(i);
 
-			if(!b.dragged) {
-			    
-				float bx=b.getPosX(), by=b.getPosY();
+            if (b.markedToDie) {
+                continue;
+            }
 
-				Attractor attractor = null;
-				PointF attractor_pos = b.attractor;
-				float attractor_dist = (attractor_pos.x-bx)*(attractor_pos.x-bx) + (attractor_pos.y-by)*(attractor_pos.x-by);
+            if (!b.dragged) {
 
-				for(int j=0; j<attr_n; j++) {
-				    try{
-					Attractor t = attractors.get(j);
-				    
-					float dx = t.pos.x-bx, dy = t.pos.y-by;
-					float adist = dx*dx + dy*dy;
-					if(adist < attractor_dist) {
-						attractor = t;
-						attractor_pos = t.pos;
-						attractor_dist = adist;
-					}
-				    } catch (IndexOutOfBoundsException e){
+                float bx = b.getPosX(), by = b.getPosY();
+
+                Attractor attractor = null;
+                PointF attractor_pos = b.attractor;
+                float attractor_dist = (attractor_pos.x - bx) * (attractor_pos.x - bx) + (attractor_pos.y - by) * (attractor_pos.x - by);
+
+                for (int j = 0; j < attr_n; j++) {
+                    try {
+                        Attractor t = attractors.get(j);
+
+                        float dx = t.pos.x - bx, dy = t.pos.y - by;
+                        float adist = dx * dx + dy * dy;
+                        if (adist < attractor_dist) {
+                            attractor = t;
+                            attractor_pos = t.pos;
+                            attractor_dist = adist;
+                        }
+                    } catch (IndexOutOfBoundsException e) {
                         // Try to update when layout was changing
                     }
-				}
+                }
 
-				//float friction_coef = 1.f-FRICTION_VISCOUS*dt;
-				double friction_coef = 1+Math.expm1(-FRICTION_VISCOUS*ddt);
-				b.speed.x *= friction_coef;
-				b.speed.y *= friction_coef;
+                // float friction_coef = 1.f-FRICTION_VISCOUS*dt;
+                double friction_coef = 1 + Math.expm1(-FRICTION_VISCOUS * ddt);
+                b.speed.x *= friction_coef;
+                b.speed.y *= friction_coef;
 
-				//if(attractor != null) {
-				float target_speed;
-				float tdx = attractor_pos.x - bx, tdy = attractor_pos.y - by;
-				float dist = Math.max(1.f, (float) Math.sqrt(tdx*tdx + tdy*tdy));
-				if(dist > attractor_smooth_dist)
-					target_speed = bubble_max_speed;
-				else if(dist < attractor_stall_dist)
-					target_speed = 0;
-				else {
-					float a = (dist-attractor_stall_dist)/(attractor_smooth_dist-attractor_stall_dist);
-					target_speed = bubble_max_speed*a;
-				}
-				if(attractor != null) {
-					if(dist > attractor_smooth_dist)
-						b.target_scale = 1.f;
-					else if(dist < attractor_stall_dist)
-						b.target_scale = .2f;
-					else {
-						float a = (dist-attractor_stall_dist)/(attractor_smooth_dist-attractor_stall_dist);
-						b.target_scale = a*.8f+.2f;
-					}
-				}
+                // if(attractor != null) {
+                float target_speed;
+                float tdx = attractor_pos.x - bx, tdy = attractor_pos.y - by;
+                float dist = Math.max(1.f, (float) Math.sqrt(tdx * tdx + tdy * tdy));
+                if (dist > attractor_smooth_dist)
+                    target_speed = bubble_max_speed;
+                else if (dist < attractor_stall_dist)
+                    target_speed = 0;
+                else {
+                    float a = (dist - attractor_stall_dist) / (attractor_smooth_dist - attractor_stall_dist);
+                    target_speed = bubble_max_speed * a;
+                }
+                if (attractor != null) {
+                    if (dist > attractor_smooth_dist)
+                        b.target_scale = 1.f;
+                    else if (dist < attractor_stall_dist)
+                        b.target_scale = .2f;
+                    else {
+                        float a = (dist - attractor_stall_dist) / (attractor_smooth_dist - attractor_stall_dist);
+                        b.target_scale = a * .8f + .2f;
+                    }
+                }
 
-				// border repulsion
-				if(bx < 0 && b.speed.x < 0) {
-					b.speed.x += dt * border_repulsion;
-				} else if(bx > width && b.speed.x > 0) {
-					b.speed.x -= dt * border_repulsion;
-				}
-				if(by < 0 && b.speed.y < 0) {
-					b.speed.y += dt * border_repulsion;
-				} else if(by > height && b.speed.y > 0) {
-					b.speed.y -= dt * border_repulsion;
-				}
+                // border repulsion
+                if (bx < 0 && b.speed.x < 0) {
+                    b.speed.x += dt * border_repulsion;
+                } else if (bx > width && b.speed.x > 0) {
+                    b.speed.x -= dt * border_repulsion;
+                }
+                if (by < 0 && b.speed.y < 0) {
+                    b.speed.y += dt * border_repulsion;
+                } else if (by > height && b.speed.y > 0) {
+                    b.speed.y -= dt * border_repulsion;
+                }
 
-				b.speed.x += dt * target_speed * tdx/dist;
-				b.speed.y += dt * target_speed * tdy/dist;
+                b.speed.x += dt * target_speed * tdx / dist;
+                b.speed.y += dt * target_speed * tdy / dist;
 
-				double edt = -Math.expm1(-BUBBLE_RETURN_TIME_LAMBDA*ddt);
-				double dx = (attractor_pos.x - bx) * edt + Math.min(bubble_max_speed, b.speed.x) * dt;
-				double dy = (attractor_pos.y - by) * edt + Math.min(bubble_max_speed, b.speed.y) * dt;
-				//	Log.w(TAG, "update dx="+dt+" dy="+dy);
-				b.setPos((float)(bx+dx), (float)(by+dy));
+                double edt = -Math.expm1(-BUBBLE_RETURN_TIME_LAMBDA * ddt);
+                double dx = (attractor_pos.x - bx) * edt + Math.min(bubble_max_speed, b.speed.x) * dt;
+                double dy = (attractor_pos.y - by) * edt + Math.min(bubble_max_speed, b.speed.y) * dt;
+                // Log.w(TAG, "update dx="+dt+" dy="+dy);
+                b.setPos((float) (bx + dx), (float) (by + dy));
 
-//				Log.i(TAG,"Model:");
-				if(attractor != null && attractor_dist < attractor_dist_suck*attractor_dist_suck) {
-					b.dragged = false;
-					if(attractor.callback.onBubbleSucked(b)) {
-						bubbles.remove(b);
-						n--;
-					} else {
-						b.target_scale = 1.f;
-					}
-				}
-			}
+                // Log.i(TAG,"Model:");
+                if (attractor != null && attractor_dist < attractor_dist_suck * attractor_dist_suck) {
+                    b.dragged = false;
+                    if (attractor.callback.onBubbleSucked(b)) {
+                        bubbles.remove(b);
+                        n--;
+                    } else {
+                        b.target_scale = 1.f;
+                    }
+                }
+            }
 
-			b.setScale(b.getScale() + (b.target_scale-b.getScale())*dt*10.f);
+            b.setScale(b.getScale() + (b.target_scale - b.getScale()) * dt * 10.f);
 
-		}
-	}
+        }
+    }
 
     public Bubble getBubble(String call) {
-        for(Bubble b : bubbles){
-            if(b.callIDEquals(call))
+        for (Bubble b : bubbles) {
+            if (!b.isUser && b.callIDEquals(call))
                 return b;
         }
         return null;
@@ -199,8 +195,15 @@
 
     public void removeBubble(SipCall sipCall) {
         bubbles.remove(getBubble(sipCall.getCallId()));
-        
+
     }
 
+    public Bubble getUser() {
+        for (Bubble b : bubbles) {
+            if (b.isUser)
+                return b;
+        }
+        return null;
+    }
 
 }
diff --git a/src/org/sflphone/model/Conference.java b/src/org/sflphone/model/Conference.java
index 08cb850..465a307 100644
--- a/src/org/sflphone/model/Conference.java
+++ b/src/org/sflphone/model/Conference.java
@@ -11,6 +11,7 @@
     private String state = "";
     private ArrayList<SipCall> participants;
     private boolean recording;
+    private ArrayList<SipMessage> messages;
 
     public interface state {
         int ACTIVE_ATTACHED = 0;
@@ -31,6 +32,8 @@
         out.writeString(id);
         out.writeString(state);
         out.writeTypedList(participants);
+        out.writeByte((byte) (recording ? 1 : 0));
+        out.writeTypedList(messages);
     }
 
     public static final Parcelable.Creator<Conference> CREATOR = new Parcelable.Creator<Conference>() {
@@ -48,6 +51,9 @@
         id = in.readString();
         state = in.readString();
         in.readTypedList(participants, SipCall.CREATOR);
+        recording = in.readByte() == 1 ? true : false;
+        messages = new ArrayList<SipMessage>();
+        in.readTypedList(messages, SipMessage.CREATOR);
     }
 
     public Conference(String cID) {
@@ -63,11 +69,10 @@
     }
 
     public String getId() {
-        return id;
-    }
-
-    public void setId(String id) {
-        this.id = id;
+        if(hasMultipleParticipants())
+            return id;
+        else
+            return participants.get(0).getCallId();
     }
 
     public String getState() {
@@ -100,17 +105,17 @@
         }
         return null;
     }
-    
+
     /**
      * Compare conferences based on confID/participants
      */
     @Override
     public boolean equals(Object c) {
         if (c instanceof Conference) {
-            if(((Conference) c).id.contentEquals(id) && !id.contentEquals("-1")){
+            if (((Conference) c).id.contentEquals(id) && !id.contentEquals("-1")) {
                 return true;
             } else {
-                if(((Conference) c).id.contentEquals(id)){
+                if (((Conference) c).id.contentEquals(id)) {
                     for (int i = 0; i < participants.size(); ++i) {
                         if (!((Conference) c).contains(participants.get(i).getCallId()))
                             return false;
@@ -151,4 +156,12 @@
         return false;
     }
 
+    public ArrayList<SipMessage> getMessages() {
+        if (hasMultipleParticipants())
+            return messages;
+        else
+            return participants.get(0).getMessages();
+
+    }
+
 }
diff --git a/src/org/sflphone/model/SipCall.java b/src/org/sflphone/model/SipCall.java
index 8aa381c..63989f5 100644
--- a/src/org/sflphone/model/SipCall.java
+++ b/src/org/sflphone/model/SipCall.java
@@ -52,20 +52,20 @@
     private boolean isRecording = false;
     private long timestamp_start = 0;
 
-    public static final String USER_ID = "user_id";
 
     private int mCallType = state.CALL_TYPE_UNDETERMINED;
     private int mCallState = state.CALL_STATE_NONE;
     private int mMediaState = state.MEDIA_STATE_NONE;
+    
+    ArrayList<SipMessage> messages;
 
     /************************
      * Construtors
      ***********************/
 
     private SipCall(Parcel in) {
-        ArrayList<String> list = in.createStringArrayList();
 
-        mCallID = list.get(0);
+        mCallID = in.readString();
         mAccount = in.readParcelable(Account.class.getClassLoader());
         contact = in.readParcelable(CallContact.class.getClassLoader());
         isRecording = in.readByte() == 1;
@@ -73,6 +73,9 @@
         mCallState = in.readInt();
         mMediaState = in.readInt();
         timestamp_start = in.readLong();
+        
+        messages = new ArrayList<SipMessage>();
+        in.readTypedList(messages, SipMessage.CREATOR);
     }
 
     public SipCall(String id, Account account, int call_type, int call_state, int media_state, CallContact c) {
@@ -82,6 +85,7 @@
         mCallState = call_state;
         mMediaState = media_state;
         contact = c;
+        messages = new ArrayList<SipMessage>();
     }
 
     public interface state {
@@ -113,11 +117,8 @@
 
     @Override
     public void writeToParcel(Parcel out, int flags) {
-        ArrayList<String> list = new ArrayList<String>();
 
-        list.add(mCallID);
-
-        out.writeStringList(list);
+        out.writeString(mCallID);
         out.writeParcelable(mAccount, 0);
 
         out.writeParcelable(contact, 0);
@@ -126,6 +127,8 @@
         out.writeInt(mCallState);
         out.writeInt(mMediaState);
         out.writeLong(timestamp_start);
+        
+        out.writeTypedList(messages);
     }
 
     public static final Parcelable.Creator<SipCall> CREATOR = new Parcelable.Creator<SipCall>() {
@@ -420,4 +423,12 @@
         return mCallState == state.CALL_STATE_CURRENT;
     }
 
+    public void addSipMessage(SipMessage message) {
+        messages.add(message);
+    }
+
+    public ArrayList<SipMessage> getMessages() {
+        return messages;
+    }
+
 }
diff --git a/src/org/sflphone/model/SipMessage.aidl b/src/org/sflphone/model/SipMessage.aidl
new file mode 100644
index 0000000..467cf80
--- /dev/null
+++ b/src/org/sflphone/model/SipMessage.aidl
@@ -0,0 +1,4 @@
+package org.sflphone.model;
+
+
+parcelable SipMessage;
\ No newline at end of file
diff --git a/src/org/sflphone/model/SipMessage.java b/src/org/sflphone/model/SipMessage.java
index 5d1c188..63609ea 100644
--- a/src/org/sflphone/model/SipMessage.java
+++ b/src/org/sflphone/model/SipMessage.java
@@ -1,13 +1,44 @@
 package org.sflphone.model;
 
-public class SipMessage {
-	public boolean left;
-	public String comment;
+import java.util.ArrayList;
 
-	public SipMessage(boolean left, String comment) {
-		super();
-		this.left = left;
-		this.comment = comment;
-	}
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class SipMessage implements Parcelable {
+    public boolean left;
+    public String comment;
+
+    public SipMessage(boolean left, String comment) {
+        super();
+        this.left = left;
+        this.comment = comment;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeByte((byte) (left ? 1 : 0));
+        out.writeString(comment);
+    }
+
+    public static final Parcelable.Creator<SipMessage> CREATOR = new Parcelable.Creator<SipMessage>() {
+        public SipMessage createFromParcel(Parcel in) {
+            return new SipMessage(in);
+        }
+
+        public SipMessage[] newArray(int size) {
+            return new SipMessage[size];
+        }
+    };
+
+    private SipMessage(Parcel in) {
+        left = (in.readByte() == 1) ? true : false;
+        comment = in.readString();
+    }
 
 }
\ No newline at end of file
diff --git a/src/org/sflphone/receivers/IncomingReceiver.java b/src/org/sflphone/receivers/IncomingReceiver.java
index 1c81e82..2734da2 100644
--- a/src/org/sflphone/receivers/IncomingReceiver.java
+++ b/src/org/sflphone/receivers/IncomingReceiver.java
@@ -9,6 +9,7 @@
 import org.sflphone.model.CallContact;
 import org.sflphone.model.Conference;
 import org.sflphone.model.SipCall;
+import org.sflphone.model.SipMessage;
 import org.sflphone.service.CallManagerCallBack;
 import org.sflphone.service.ConfigurationManagerCallback;
 import org.sflphone.service.ServiceConstants;
@@ -53,7 +54,9 @@
 
         } else if (intent.getAction().contentEquals(CallManagerCallBack.INCOMING_TEXT)) {
 
+            Bundle extra = intent.getBundleExtra("com.savoirfairelinux.sflphone.service.newtext");
             Log.i(TAG, "Received" + intent.getAction());
+            callback.getCurrent_calls().get(extra.get("CallID")).addSipMessage(new SipMessage(true, extra.getString("Msg")));
             callback.sendBroadcast(intent);
 
         } else if (intent.getAction().contentEquals(CallManagerCallBack.INCOMING_CALL)) {
diff --git a/src/org/sflphone/service/ISipService.aidl b/src/org/sflphone/service/ISipService.aidl
index 1ebfc8d..572bf55 100644
--- a/src/org/sflphone/service/ISipService.aidl
+++ b/src/org/sflphone/service/ISipService.aidl
@@ -2,6 +2,7 @@
 
 import org.sflphone.model.SipCall;
 import org.sflphone.model.Conference;
+import org.sflphone.model.SipMessage;
 
 interface ISipService {
     
@@ -46,7 +47,7 @@
 	void playDtmf(in String key);
     
     /* IM */
-    void sendTextMessage(in String callID, in String message, in String from);
+    void sendTextMessage(in String callID, in SipMessage message);
         
     void transfer(in String callID, in String to);
     void attendedTransfer(in String transferID, in String targetID);
diff --git a/src/org/sflphone/service/SipService.java b/src/org/sflphone/service/SipService.java
index 0eb71ac..29f8df6 100644
--- a/src/org/sflphone/service/SipService.java
+++ b/src/org/sflphone/service/SipService.java
@@ -42,6 +42,7 @@
 import org.sflphone.model.Codec;
 import org.sflphone.model.Conference;
 import org.sflphone.model.SipCall;
+import org.sflphone.model.SipMessage;
 import org.sflphone.receivers.IncomingReceiver;
 import org.sflphone.utils.MediaManager;
 import org.sflphone.utils.SipNotifications;
@@ -1015,12 +1016,13 @@
         }
 
         @Override
-        public void sendTextMessage(final String callID, final String message, final String from) throws RemoteException {
+        public void sendTextMessage(final String callID, final SipMessage message) throws RemoteException {
             getExecutor().execute(new SipRunnable() {
                 @Override
                 protected void doRun() throws SameThreadException, RemoteException {
                     Log.i(TAG, "SipService.sendTextMessage() thread running...");
-                    callManagerJNI.sendTextMessage(callID, message);
+                    callManagerJNI.sendTextMessage(callID, message.comment);
+                    getCurrent_calls().get(callID).addSipMessage(message);
                 }
             });