* #25270 Overall improvements of transitions between calls and call actions
* #25117 Refactor and stability
diff --git a/src/com/savoirfairelinux/sflphone/model/Bubble.java b/src/com/savoirfairelinux/sflphone/model/Bubble.java
index 420fb6a..7d9bf2c 100644
--- a/src/com/savoirfairelinux/sflphone/model/Bubble.java
+++ b/src/com/savoirfairelinux/sflphone/model/Bubble.java
@@ -210,6 +210,19 @@
         canvas.drawBitmap(circle, 0, 0, circlePaint);
 
     }
+    
+
+    /**
+     * Compare bubbles based on call ID
+     */
+    @Override
+    public boolean equals(Object c) {
+        if (c instanceof Bubble && ((Bubble) c).associated_call.getCallId().contentEquals(associated_call.getCallId())) {
+            return true;
+        }
+        return false;
+
+    }
 
     /**
      * When bubble is expanded we need to check on wich action button the user tap
diff --git a/src/com/savoirfairelinux/sflphone/model/BubbleModel.java b/src/com/savoirfairelinux/sflphone/model/BubbleModel.java
index 8650230..c1a87cb 100644
--- a/src/com/savoirfairelinux/sflphone/model/BubbleModel.java
+++ b/src/com/savoirfairelinux/sflphone/model/BubbleModel.java
@@ -4,6 +4,7 @@
 import java.util.List;
 
 import android.graphics.PointF;
+import android.util.Log;
 
 public class BubbleModel
 {
@@ -182,5 +183,25 @@
 		}
 	}
 
+    public Bubble getBubble(SipCall call) {
+        for(Bubble b : bubbles){
+            if(call == null){
+                Log.e(TAG, "call null");
+            } 
+            if(b.associated_call.getCallId() == null){
+                Log.e(TAG, "id null");
+            }
+            if(b.associated_call.getCallId().contentEquals(call.getCallId()))
+                return b;
+        }
+        return null;
+    }
+
+    public void removeBubble(SipCall sipCall) {
+        
+        bubbles.remove(getBubble(sipCall));
+        
+    }
+
 
 }
diff --git a/src/com/savoirfairelinux/sflphone/model/BubblesView.java b/src/com/savoirfairelinux/sflphone/model/BubblesView.java
index f365ec2..0e3864a 100644
--- a/src/com/savoirfairelinux/sflphone/model/BubblesView.java
+++ b/src/com/savoirfairelinux/sflphone/model/BubblesView.java
@@ -34,13 +34,11 @@
 

 import java.util.List;

 

-import android.app.FragmentManager;

 import android.content.Context;

 import android.graphics.Canvas;

 import android.graphics.Color;

 import android.graphics.Paint;

 import android.graphics.Paint.Align;

-import android.os.Bundle;

 import android.os.Handler;

 import android.os.Message;

 import android.util.AttributeSet;

@@ -56,7 +54,6 @@
 

 import com.savoirfairelinux.sflphone.client.CallActivity;

 import com.savoirfairelinux.sflphone.fragments.CallFragment;

-import com.savoirfairelinux.sflphone.fragments.TransferDFragment;

 

 public class BubblesView extends SurfaceView implements SurfaceHolder.Callback, OnTouchListener {

     private static final String TAG = BubblesView.class.getSimpleName();

@@ -279,8 +276,18 @@
                         canvas.drawText(first_plan.associated_call.getContact().getmDisplayName(), first_plan.getPosX(), first_plan.getPosY() - 50

                                 * density, getNamePaint(first_plan));

                         canvas.drawText("Transfer", first_plan.getPosX(), first_plan.getPosY() + 70 * density, getNamePaint(first_plan));

-                        canvas.drawText("Hold", first_plan.getPosX() - 70 * density, first_plan.getPosY(), getNamePaint(first_plan));

-                        canvas.drawText("Record", first_plan.getPosX() + 70 * density, first_plan.getPosY(), getNamePaint(first_plan));

+                        if (first_plan.associated_call.isOnHold()) {

+                            canvas.drawText("Unhold", first_plan.getPosX() - 70 * density, first_plan.getPosY(), getNamePaint(first_plan));

+                        } else {

+                            canvas.drawText("Hold", first_plan.getPosX() - 70 * density, first_plan.getPosY(), getNamePaint(first_plan));

+                        }

+                        if (first_plan.associated_call.isRecording()) {

+                            canvas.drawText("Stop\nRecording", first_plan.getPosX() + 70 * density, first_plan.getPosY(), getNamePaint(first_plan));

+                        } else {

+                            canvas.drawText("Record", first_plan.getPosX() + 70 * density, first_plan.getPosY(), getNamePaint(first_plan));

+

+                        }

+

                     }

 

                 } catch (IndexOutOfBoundsException e) {

@@ -344,6 +351,27 @@
         return null;

     }

 

+    public void restartDrawing() {

+        if (thread != null && thread.suspendFlag) {

+            Log.i(TAG, "Relaunch drawing thread");

+            thread.setPaused(false);

+        }

+    }

+

+    public void setFragment(CallFragment callFragment) {

+        callback = callFragment;

+

+    }

+

+    public void stopThread() {

+        if (thread != null && thread.suspendFlag) {

+            Log.i(TAG, "Stop drawing thread");

+            thread.setRunning(false);

+            thread.setPaused(false);

+        }

+

+    }

+

     class MyOnGestureListener implements OnGestureListener {

         @Override

         public boolean onDown(MotionEvent event) {

@@ -360,8 +388,12 @@
                         expand.retract();

                         break;

                     case 1:

-                        Log.d("Main", "onCallSuspended");

-                        ((CallActivity) callback.getActivity()).onCallSuspended(expand.associated_call);

+                        if (expand.associated_call.isOnHold()) {

+                            ((CallActivity) callback.getActivity()).onCallResumed(expand.associated_call);

+                        } else {

+                            ((CallActivity) callback.getActivity()).onCallSuspended(expand.associated_call);

+                        }

+

                         break;

                     case 2:

                         Log.d("Main", "onRecordCall");

@@ -450,17 +482,4 @@
             return true;

         }

     }

-

-    public void restartDrawing() {

-        if (thread != null && thread.suspendFlag) {

-            Log.i(TAG, "Relaunch drawing thread");

-            thread.setPaused(false);

-        }

-    }

-

-    public void setFragment(CallFragment callFragment) {

-        callback = callFragment;

-

-    }

-

 }

diff --git a/src/com/savoirfairelinux/sflphone/model/CallContact.java b/src/com/savoirfairelinux/sflphone/model/CallContact.java
index 75c8b6b..4e3ae1a 100644
--- a/src/com/savoirfairelinux/sflphone/model/CallContact.java
+++ b/src/com/savoirfairelinux/sflphone/model/CallContact.java
@@ -37,7 +37,6 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.provider.ContactsContract.Profile;
-import android.util.Log;
 
 public class CallContact implements Parcelable {
 
@@ -49,7 +48,7 @@
 
     private CallContact(long cID, String displayName, long photoID, ArrayList<Phone> p, ArrayList<Phone> sip, String mail) {
         id = cID;
-        mDisplayName = displayName;
+        mDisplayName = displayName.substring(0, displayName.length() > 10 ? 10 : displayName.length());;
         phones = p;
         sip_phones = sip;
         mEmail = mail;
@@ -68,10 +67,6 @@
         return mDisplayName;
     }
 
-    public void setmDisplayName(String mDisplayName) {
-        this.mDisplayName = mDisplayName;
-    }
-
     public long getPhoto_id() {
         return photo_id;
     }
@@ -131,6 +126,7 @@
 
         public ContactBuilder startNewContact(long id, String displayName, long photo_id) {
             contactID = id;
+            
             contactName = displayName;
             contactPhoto = photo_id;
             phones = new ArrayList<Phone>();
@@ -169,7 +165,6 @@
             CallContact result = null;
             if (mProfileCursor.getCount() > 0) {
                 mProfileCursor.moveToFirst();
-                Log.i("CallContact", "THERE IS AN ENTRY");
                 result = new CallContact(mProfileCursor.getLong(mProfileCursor.getColumnIndex(Profile._ID)), displayName,
                         mProfileCursor.getLong(mProfileCursor.getColumnIndex(Profile.PHOTO_ID)), new ArrayList<Phone>(),
                         new ArrayList<CallContact.Phone>(), "");
diff --git a/src/com/savoirfairelinux/sflphone/model/Conference.aidl b/src/com/savoirfairelinux/sflphone/model/Conference.aidl
new file mode 100644
index 0000000..a959fe3
--- /dev/null
+++ b/src/com/savoirfairelinux/sflphone/model/Conference.aidl
@@ -0,0 +1,4 @@
+package com.savoirfairelinux.sflphone.model;
+
+
+parcelable Conference;
\ No newline at end of file
diff --git a/src/com/savoirfairelinux/sflphone/model/Conference.java b/src/com/savoirfairelinux/sflphone/model/Conference.java
index 26ddf63..02d06c7 100644
--- a/src/com/savoirfairelinux/sflphone/model/Conference.java
+++ b/src/com/savoirfairelinux/sflphone/model/Conference.java
@@ -9,8 +9,9 @@
 public class Conference implements Parcelable {
 
     private String id;
-    private String state;
+    private String state = "";
     private ArrayList<SipCall> participants;
+    private boolean recording;
 
     public interface state {
         int ACTIVE_ATTACHED = 0;
@@ -68,6 +69,9 @@
     }
 
     public String getState() {
+        if(participants.size() == 1){
+            return participants.get(0).getCallStateString();
+        }
         return state;
     }
 
@@ -95,4 +99,32 @@
         return null;
     }
 
+    public boolean hasMultipleParticipants() {
+        return participants.size() > 1;
+    }
+
+    public boolean isOnHold() {
+        if(participants.size() == 1 && participants.get(0).isOnHold())
+            return true;
+        return state.contentEquals("HOLD");
+    }
+
+    public void setRecording(boolean b) {
+        recording = b;
+    }
+
+    public boolean isRecording() {
+        return recording;
+    }
+
+    public boolean 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/model/SipCall.java b/src/com/savoirfairelinux/sflphone/model/SipCall.java
index 2e7018d..3f38733 100644
--- a/src/com/savoirfairelinux/sflphone/model/SipCall.java
+++ b/src/com/savoirfairelinux/sflphone/model/SipCall.java
@@ -45,7 +45,8 @@
     private String mCallID = "";
     private String mAccountID = "";
     private CallContact contact = null;
-    
+    private boolean isRecording = false;
+
     public static final String USER_ID = "user_id";
 
     private int mCallType = state.CALL_TYPE_UNDETERMINED;
@@ -59,24 +60,15 @@
     private SipCall(Parcel in) {
         ArrayList<String> list = in.createStringArrayList();
 
-        // Don't mess with this order!!!
         mCallID = list.get(0);
         mAccountID = list.get(1);
-        // mDisplayName = list.get(2);
-        // mPhone = list.get(3);
-        // mEmail = list.get(4);
-        // mRemoteContact = list.get(5);
-
         contact = in.readParcelable(CallContact.class.getClassLoader());
-
+        isRecording = in.readByte() == 1;
         mCallType = in.readInt();
         mCallState = in.readInt();
         mMediaState = in.readInt();
     }
 
-    // public SipCall(Intent call) {
-
-    // }
 
     public SipCall(String id, String account, int call_type, int call_state, int media_state, CallContact c) {
         mCallID = id;
@@ -87,8 +79,6 @@
         contact = c;
     }
 
-    // public SipCall() {
-    // }
 
     public interface state {
         public static final int CALL_TYPE_UNDETERMINED = 0;
@@ -127,6 +117,7 @@
 
         out.writeStringList(list);
         out.writeParcelable(contact, 0);
+        out.writeByte((byte) (isRecording ? 1 : 0));
         out.writeInt(mCallType);
         out.writeInt(mCallState);
         out.writeInt(mMediaState);
@@ -269,6 +260,14 @@
         return mMediaState;
     }
 
+    public boolean isRecording() {
+        return isRecording;
+    }
+
+    public void setRecording(boolean isRecording) {
+        this.isRecording = isRecording;
+    }
+
     public static class SipCallBuilder {
 
         private String bCallID = "";
@@ -332,7 +331,7 @@
 
         public static SipCall buildMyselfCall(ContentResolver cr, String displayName) {
             return new SipCall("default", "default", SipCall.state.CALL_TYPE_UNDETERMINED, state.CALL_STATE_NONE, state.MEDIA_STATE_NONE,
-                    CallContact.ContactBuilder.buildUserContact(cr, ""));
+                    CallContact.ContactBuilder.buildUserContact(cr, displayName));
 
         }
 
@@ -401,6 +400,7 @@
 
     }
 
+
     public boolean isOngoing() {
         if (mCallState == state.CALL_STATE_RINGING || mCallState == state.CALL_STATE_NONE || mCallState == state.CALL_STATE_FAILURE
                 || mCallState == state.CALL_STATE_BUSY || mCallState == state.CALL_STATE_HUNGUP)
@@ -409,4 +409,8 @@
         return true;
     }
 
+    public boolean isOnHold() {
+        return mCallState == state.CALL_STATE_HOLD;
+    }
+
 }