* #31377: partial implementation of new interface
diff --git a/src/org/sflphone/model/Bubble.java b/src/org/sflphone/model/Bubble.java
index e6ad794..efc4ace 100644
--- a/src/org/sflphone/model/Bubble.java
+++ b/src/org/sflphone/model/Bubble.java
@@ -2,6 +2,7 @@
 
 import org.sflphone.R;
 import org.sflphone.adapters.ContactPictureTask;
+import org.sflphone.model.BubbleUser.ActionDrawer;
 
 import android.content.Context;
 import android.graphics.Bitmap;
@@ -13,55 +14,67 @@
 import android.graphics.PointF;
 import android.graphics.RectF;
 import android.graphics.Shader;
-import android.util.Log;
 
-public class Bubble {
+public abstract class Bubble {
 
     // A Bitmap object that is going to be passed to the BitmapShader
-    private Bitmap externalBMP;
+    protected Bitmap externalBMP;
 
-    public SipCall associated_call;
-    private PointF pos = new PointF();
-    private RectF bounds;
+    protected PointF pos = new PointF();
+    protected RectF bounds;
     public float target_scale = 1.f;
-    private float radius;
-    private float scale = 1.f;
-    private float density = 1.f;
+    protected float radius;
+    protected float scale = 1.f;
+    protected float density = 1.f;
     public PointF speed = new PointF(0, 0);
     public PointF last_speed = new PointF();
     public PointF attractor = null;
+    ActionDrawer act;
+    
+
+    boolean isUser;
 
     public boolean dragged = false;
 
     public boolean markedToDie = false;
     public long last_drag;
     public boolean expanded; // determine if we draw the buttons around the bubble
-    private Bitmap saved_photo;
-    private float expanded_radius;
+    protected Bitmap saved_photo;
 
-    ActionDrawer act = new ActionDrawer(0, 0, false, false);
+    public interface actions {
+        int NOTHING = 0;
+        int HOLD = 1;
+        int RECORD = 2;
+        int HANGUP = 3;
+        int MESSAGE = 4;
+        int TRANSFER = 5;
+        int MUTE = 6;
+    }
+
+    protected Context mContext;
 
     public void setAttractor(PointF attractor) {
         this.attractor = attractor;
     }
 
-    public Bubble(Context context, SipCall call, float x, float y, float size) {
-
-        saved_photo = getContactPhoto(context, call, (int) size);
-        associated_call = call;
+    public Bubble(Context context, CallContact contact, float x, float y, float size) {
+        mContext = context;
         pos.set(x, y);
         radius = size / 2;
-        expanded_radius = (float) (size * 1.5);
+        saved_photo = getContactPhoto(context, contact, (int) size);
+        generateBitmap();
+        attractor = new PointF(x, y);
+    }
 
+    protected void generateBitmap() {
+        
         int w = saved_photo.getWidth(), h = saved_photo.getHeight();
         if (w > h) {
             w = h;
         } else if (h > w) {
             h = w;
         }
-
-        externalBMP = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
-
+        externalBMP = Bitmap.createBitmap(w + 10, h + 10, Bitmap.Config.ARGB_8888);
         BitmapShader shader;
         shader = new BitmapShader(saved_photo, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
 
@@ -69,16 +82,21 @@
         paint.setAntiAlias(true);
         paint.setShader(shader);
         Canvas internalCanvas = new Canvas(externalBMP);
-        internalCanvas.drawOval(new RectF(0, 0, w, h), paint);
+        internalCanvas.drawOval(new RectF(5, 5, w, h), paint);
+
+        Paint whiteStroke = new Paint();
+        whiteStroke.setStyle(Style.STROKE);
+        whiteStroke.setStrokeWidth(5);
+        whiteStroke.setColor(Color.WHITE);
+        internalCanvas.drawCircle(w / 2, h / 2, w / 2, whiteStroke);
 
         bounds = new RectF(pos.x - getRadius(), pos.y - getRadius(), pos.x + getRadius(), pos.y + getRadius());
-        attractor = new PointF(x, y);
-
+        
     }
 
-    private Bitmap getContactPhoto(Context context, SipCall call, int size) {
-        if (call.getContact().getPhoto_id() > 0) {
-            return ContactPictureTask.loadContactPhoto(context.getContentResolver(), call.getContact().getId());
+    protected Bitmap getContactPhoto(Context context, CallContact contact, int size) {
+        if (contact.getPhoto_id() > 0) {
+            return ContactPictureTask.loadContactPhoto(context.getContentResolver(), contact.getId());
         } else {
             return ContactPictureTask.decodeSampledBitmapFromResource(context.getResources(), R.drawable.ic_contact_picture, (int) size, (int) size);
         }
@@ -92,16 +110,7 @@
         return bounds;
     }
 
-    public void set(float x, float y, float s) {
-        scale = s;
-        pos.x = x;
-        pos.y = y;
-        if (!expanded) {
-            bounds.set(pos.x - getRadius(), pos.y - getRadius(), pos.x + getRadius(), pos.y + getRadius());
-        } else {
-            bounds.set(pos.x - getRadius(), pos.y - getRadius(), pos.x + getRadius(), pos.y + getRadius());
-        }
-    }
+    public abstract void set(float x, float y, float s);
 
     public float getPosX() {
         return pos.x;
@@ -127,12 +136,7 @@
         set(pos.x, pos.y, s);
     }
 
-    public int getRadius() {
-        if (expanded)
-            return (int) (expanded_radius * scale * density);
-
-        return (int) (radius * scale * density);
-    }
+    public abstract int getRadius();
 
     /**
      * Point intersection test.
@@ -157,210 +161,14 @@
         this.density = density;
     }
 
-    public void expand(int width, int height) {
-
-        expanded = true;
-
-//        if (associated_call.getContact().isUser()) {
-            createCircularExpandedBubble();
-//        } else {
-//            createRectangularExpandedBubble(width, height);
-//        }
-
-    }
-
-    private void createRectangularExpandedBubble(int width, int height) {
-
-        // int w = saved_photo.getWidth(), h = saved_photo.getHeight();
-        // if (w > h) {
-        // w = h;
-        // } else if (h > w) {
-        // h = w;
-        // }
-        // externalBMP = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
-        //
-        // BitmapShader shader;
-        // shader = new BitmapShader(saved_photo, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
-        //
-        // Paint paint = new Paint();
-        // paint.setAntiAlias(true);
-        // paint.setShader(shader);
-        // Canvas internalCanvas = new Canvas(externalBMP);
-        // internalCanvas.drawOval(new RectF(0, 0, w, h), paint);
-        //
-        // bounds = new RectF(pos.x - getRadius(), pos.y - getRadius(), pos.x + getRadius(), pos.y + getRadius());
-
-        int w = saved_photo.getWidth(), h = saved_photo.getHeight();
-        if (w > h) {
-            w = h;
-        } else if (h > w) {
-            h = w;
-        }
-
-        BitmapShader shader;
-        shader = new BitmapShader(saved_photo, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
-
-        Paint paint = new Paint();
-        paint.setAntiAlias(true);
-        paint.setShader(shader);
-
-        Paint test = new Paint();
-        test.setColor(Color.CYAN);
-        test.setStyle(Style.FILL);
-
-        if (pos.x < width / 3) {
-            // Open on the right
-            bounds = new RectF(pos.x - getRadius(), pos.y - getRadius(), pos.x + 300, pos.y + getRadius());
-            externalBMP = Bitmap.createBitmap(w + 300, h, Bitmap.Config.ARGB_8888);
-            Canvas internalCanvas = new Canvas(externalBMP);
-            internalCanvas.drawRect(new RectF(0, 0, w + 300, h), test);
-            internalCanvas.drawOval(new RectF(0, 0, w, h), paint);
-        } else if (pos.x > 2 * width / 3) {
-            // Open on the left
-            bounds = new RectF(pos.x - getRadius() - 300, pos.y - getRadius(), pos.x + getRadius(), pos.y + getRadius());
-            externalBMP = Bitmap.createBitmap(w + 300, h, Bitmap.Config.ARGB_8888);
-            Canvas internalCanvas = new Canvas(externalBMP);
-            internalCanvas.drawRect(new RectF(0, 0, w + 300, h), test);
-            internalCanvas.drawOval(new RectF(300, 0, 300 + w, h), paint);
-        } else {
-            // Middle of the screen
-            if (pos.y < height / 3) {
-
-                // Middle Top
-
-                Log.i("Bubble", "Middle Top screen");
-                Log.i("Bubble", "Bounds:" + bounds.toShortString());
-                Log.i("Bubble", "w:" + w);
-                Log.i("Bubble", "h:" + h);
-
-                act = new ActionDrawer(w - 200, 4 * h, false, true);
-                act.setBounds(new RectF(pos.x - act.getWidth() / 2, pos.y, pos.x + act.getWidth() / 2, pos.y + act.getHeight()));
-                
-                
-
-                externalBMP = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
-
-                Canvas internalCanvas = new Canvas(externalBMP);
-                internalCanvas.drawOval(new RectF(0, 0, w, h), paint);
-//                internalCanvas.drawRect(new RectF(0, h, w, h + act.getHeight()), test);
-
-                bounds = new RectF(pos.x - getRadius(), pos.y - getRadius(), pos.x + getRadius(), pos.y + getRadius());
-
-            } else if (pos.y > 2 * height / 3) {
-                // Middle Bottom
-                bounds = new RectF(pos.x - getRadius(), pos.y - 300 - getRadius(), pos.x + getRadius(), pos.y + getRadius());
-                externalBMP = Bitmap.createBitmap(w, h + 300, Bitmap.Config.ARGB_8888);
-                Canvas internalCanvas = new Canvas(externalBMP);
-                internalCanvas.drawRect(new RectF(0, 0, w, h + 300), test);
-                internalCanvas.drawOval(new RectF(0, 300, w, h + 300), paint);
-            }
-        }
-
-    }
-
-    private void createCircularExpandedBubble() {
-
-        int w = saved_photo.getWidth(), h = saved_photo.getHeight();
-        if (w > h) {
-            w = h;
-        } else if (h > w) {
-            h = w;
-        }
-
-        externalBMP = Bitmap.createBitmap((int) (w * expanded_radius / radius), (int) (h * expanded_radius / radius), Bitmap.Config.ARGB_8888);
-        BitmapShader shader;
-        shader = new BitmapShader(saved_photo, Shader.TileMode.REPEAT, Shader.TileMode.REPEAT);
-
-        Paint paint = new Paint();
-        paint.setAntiAlias(true);
-        paint.setShader(shader);
-        Canvas internalCanvas = new Canvas(externalBMP);
-
-        Paint paint2 = new Paint();
-        paint2.setColor(0xAA000000);
-
-        internalCanvas.drawOval(new RectF(0, 0, (int) (w * expanded_radius / radius), (int) (h * expanded_radius / radius)), paint2);
-        internalCanvas.drawOval(new RectF(externalBMP.getWidth() / 2 - w / 2, externalBMP.getHeight() / 2 - h / 2,
-                externalBMP.getWidth() / 2 + w / 2, externalBMP.getHeight() / 2 + h / 2), paint);
-
-        bounds.set(pos.x - getRadius(), pos.y - getRadius(), pos.x + getRadius(), pos.y + getRadius());
-
-    }
+    public abstract void expand(int width, int height);
 
     public void retract() {
         expanded = false;
-
-        int w = saved_photo.getWidth(), h = saved_photo.getHeight();
-        if (w > h) {
-            w = h;
-        } else if (h > w) {
-            h = w;
-        }
-        externalBMP = Bitmap.createBitmap(w, h, Bitmap.Config.ARGB_8888);
-
-        BitmapShader shader;
-        shader = new BitmapShader(saved_photo, Shader.TileMode.CLAMP, Shader.TileMode.CLAMP);
-
-        Paint paint = new Paint();
-        paint.setAntiAlias(true);
-        paint.setShader(shader);
-        Canvas internalCanvas = new Canvas(externalBMP);
-        internalCanvas.drawOval(new RectF(0, 0, w, h), paint);
-
-        bounds = new RectF(pos.x - getRadius(), pos.y - getRadius(), pos.x + getRadius(), pos.y + getRadius());
+        generateBitmap();
     }
 
-    /**
-     * 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 the bubble is expanded we need to check on wich action button the user tap
-     * 
-     * @param x
-     * @param y
-     * @return
-     */
-    public int getAction(float x, float y) {
-        float relativeX = x - pos.x + bounds.width()/2;
-        float relativeY = y - pos.y + bounds.height() / 2;
-
-        // Log.i("Bubble", "relativeX:" + relativeX);
-        // Log.i("Bubble", "relativeY:" + relativeY);
-        //
-        // Log.i("Bubble", "pos.x:" + pos.x);
-        // Log.i("Bubble", "pos.y:" + pos.y);
-        //
-        // Log.i("Bubble", "externalBMP.getWidth():" + externalBMP.getWidth());
-        // Log.i("Bubble", "externalBMP.getHeight():" + externalBMP.getHeight());
-
-        // Hold - Left
-        if (relativeX < bounds.width()/2 / 3 && relativeY > bounds.height() / 3) {
-            Log.i("Bubble", "Holding");
-            return 1;
-        }
-
-        // Record - Right
-        if (relativeX > bounds.width()/2 * 2 / 3 && relativeY > bounds.height() / 3) {
-            Log.i("Bubble", "Record");
-            return 2;
-        }
-
-        // Transfer - Bottom
-        if (relativeY > bounds.height() * 2 / 3) {
-            Log.i("Bubble", "Transfer");
-            return 3;
-        }
-        return 0;
-    }
+    
 
     public boolean isOnBorder(float w, float h) {
         return (bounds.left < 0 || bounds.right > w || bounds.top < 0 || bounds.bottom > h);
@@ -375,41 +183,45 @@
         return radius;
     }
 
-    public int getHoldStatus() {
-        if (associated_call.isOnHold())
-            return R.string.action_call_unhold;
-        else
-            return R.string.action_call_hold;
-    }
+    public abstract boolean getHoldStatus();
 
-    public int getRecordStatus() {
-        if (associated_call.isRecording())
-            return R.string.action_call_stop_record;
-        else
-            return R.string.action_call_record;
-    }
+    public abstract boolean getRecordStatus();
 
-    // Calculate the position of this Bubble depending on its coordinates
-    // It will open the actions drawer differently depending on it
-    public int getPosition(int width, int height) {
+    public abstract SipCall getCall();
 
-        return 0;
-    }
+    public abstract Bitmap getDrawerBitmap();
 
-    protected class ActionDrawer {
-
+    public abstract RectF getDrawerBounds();
+    
+    protected abstract class ActionDrawer{
+        
         int mWidth, mHeight;
-        boolean isLeft, isTop;
         RectF bounds;
+        Bitmap img;
 
-        public ActionDrawer(int w, int h, boolean left, boolean top) {
-            isLeft = left;
-            isTop = top;
+        public ActionDrawer(int w, int h) {
+
             mWidth = w;
             mHeight = h;
             bounds = new RectF(0, 0, 0, 0);
-        }
 
+        }
+        
+        /**
+         * When the bubble is expanded we need to check on wich action button the user tap
+         * 
+         * @param x
+         * @param y
+         * @return
+         */
+        public abstract int getAction(float x, float y);
+        
+        public void setBounds(float f, float y, float g, float h) {
+            bounds.set(f, y, g, h);
+        }
+        
+        public abstract void generateBitmap();
+        
         public RectF getBounds() {
             return bounds;
         }
@@ -418,6 +230,10 @@
             this.bounds = bounds;
         }
 
+        public Bitmap getBitmap() {
+            return img;
+        }
+
         public int getWidth() {
             return mWidth;
         }
@@ -425,6 +241,14 @@
         public int getHeight() {
             return mHeight;
         }
-
     }
+
+    public ActionDrawer getDrawer() {
+        return act;
+    }
+    
+    public void setDrawer(ActionDrawer a) {
+        act = a;
+    }
+
 }
diff --git a/src/org/sflphone/model/BubbleContact.java b/src/org/sflphone/model/BubbleContact.java
new file mode 100644
index 0000000..06e7f6e
--- /dev/null
+++ b/src/org/sflphone/model/BubbleContact.java
@@ -0,0 +1,222 @@
+package org.sflphone.model;
+
+import org.sflphone.R;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.Rect;
+import android.graphics.RectF;
+import android.util.Log;
+
+public class BubbleContact extends Bubble {
+
+    public SipCall associated_call;
+    Bitmap buttonMsg, buttonHold, buttonTransfer, buttonHangUp;
+
+    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, false, false));
+        buttonMsg = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_action_chat);
+        buttonHold = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_action_pause_over_video);
+        buttonTransfer = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_action_forward);
+        buttonHangUp = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_action_end_call);
+
+    }
+
+    @Override
+    public void expand(int width, int height) {
+
+        expanded = true;
+        generateBitmap();
+        if (pos.x < width / 3) {
+
+            // Open on the right
+            act = new ActionDrawer(width * 2 / 3, getRadius() * 2, false, false);
+            act.setBounds(pos.x, pos.y - getRadius(), pos.x + act.getWidth(), pos.y + getRadius());
+            act.generateBitmap();
+
+
+        } else if (pos.x > 2 * width / 3) {
+            // Open on the left
+            act = new ActionDrawer(width * 2 / 3, getRadius() * 2, true, false);
+            act.setBounds(pos.x - act.getWidth(), pos.y - getRadius(), pos.x, pos.y + +getRadius());
+            act.generateBitmap();
+
+        } else {
+            // Middle of the screen
+            if (pos.y < height / 3) {
+                // Middle Top
+
+                act = new ActionDrawer((int) (getRadius() * 1.5f), height / 2, false, true);
+                int margin = (int) (0.5f * getRadius()) / 2;
+                act.setBounds(pos.x - getRadius() + margin, pos.y, pos.x + getRadius() - margin, pos.y + act.getHeight());
+                act.generateBitmap();
+
+            } else if (pos.y > 2 * height / 3) {
+                // Middle Bottom
+
+                act = new ActionDrawer(getRadius() * 2, height / 2, false, true);
+                act.setBounds(pos.x - getRadius(), pos.y - act.getHeight(), pos.x + getRadius(), pos.y);
+                act.generateBitmap();
+
+                
+            }
+        }
+
+    }
+
+    protected class ActionDrawer extends Bubble.ActionDrawer{
+
+        boolean isLeft, isTop;
+        RectF boundsHoldButton, boundsMsgButton, boundsTransferButton, boundsHangUpButton;
+
+        public ActionDrawer(int w, int h, boolean left, boolean top) {
+            super(w, h);
+            isLeft = left;
+            isTop = top;
+        }
+        
+        @Override
+        public int getAction(float x, float y) {
+
+            float relativeX = x - getBounds().left;
+            float relativeY = y - getBounds().top;
+
+            if (boundsHoldButton.contains(relativeX, relativeY)) {
+                Log.i("Bubble", "Holding");
+                return actions.HOLD;
+            }
+
+            if (boundsMsgButton.contains(relativeX, relativeY)) {
+                Log.i("Bubble", "Msg");
+                return actions.MESSAGE;
+            }
+
+            if (boundsHangUpButton.contains(relativeX, relativeY)) {
+                Log.i("Bubble", "hangUp");
+                return actions.HANGUP;
+            }
+
+            if (boundsTransferButton.contains(relativeX, relativeY)) {
+                Log.i("Bubble", "Transfer");
+                return actions.TRANSFER;
+            }
+            return 0;
+
+        }
+
+        public void generateBitmap() {
+
+            img = Bitmap.createBitmap(mWidth, mHeight, Config.ARGB_8888);
+            Paint paint = new Paint();
+            paint.setColor(mContext.getResources().getColor(R.color.sfl_action_blue));
+            Canvas c = new Canvas(img);
+            c.drawRect(new RectF(0, 0, mWidth, mHeight), paint);
+
+            Paint pButtons = new Paint();
+            if (isTop) {
+                float rHeight = bounds.height() - getRadius();
+                boundsHoldButton = new RectF(0, getRadius(), mWidth, getRadius() + rHeight / 4);
+                boundsMsgButton = new RectF(0, getRadius() + rHeight / 4, mWidth, getRadius() + 2 * rHeight / 4);
+                boundsTransferButton = new RectF(0, getRadius() + 2 * rHeight / 4, mWidth, getRadius() + 3 * rHeight / 4);
+                boundsHangUpButton = new RectF(0, getRadius() + 3 * rHeight / 4, mWidth, getRadius() + rHeight);
+
+                int wHang = buttonHangUp.getWidth();
+                int hHang = buttonHangUp.getHeight();
+                c.drawBitmap(buttonHangUp, null, new RectF(
+                        (int) boundsHangUpButton.centerX() - wHang / 2,
+                        (int) boundsHangUpButton.centerY() - hHang / 2, 
+                        (int) boundsHangUpButton.centerX() + wHang / 2,
+                        (int) boundsHangUpButton.centerY() + hHang / 2), 
+                        pButtons);
+                
+                int wHold = buttonHold.getWidth();
+                int hHold = buttonHold.getHeight();
+                c.drawBitmap(buttonHold, null, new RectF(
+                        (int) boundsHoldButton.centerX() - wHold / 2,
+                        (int) boundsHoldButton.centerY() - hHold / 2, 
+                        (int) boundsHoldButton.centerX() + wHold / 2,
+                        (int) boundsHoldButton.centerY() + hHold / 2)
+                        , pButtons);
+                
+                int wMsg = buttonMsg.getWidth();
+                int hMsg = buttonMsg.getHeight();
+                
+                c.drawBitmap(buttonMsg, null, new RectF(
+                        (int) boundsMsgButton.centerX() - wMsg / 2,
+                        (int) boundsMsgButton.centerY() - hMsg / 2, 
+                        (int) boundsMsgButton.centerX() + wMsg / 2,
+                        (int) boundsMsgButton.centerY() + hMsg / 2),
+                        pButtons);
+                
+                int wTrans = buttonTransfer.getWidth();
+                int hTrans = buttonTransfer.getHeight();
+
+                c.drawBitmap(buttonTransfer, null, new RectF(
+                        (int) boundsTransferButton.centerX() - wTrans / 2,
+                        (int) boundsTransferButton.centerY() - hTrans / 2, 
+                        (int) boundsTransferButton.centerX() + wTrans / 2,
+                        (int) boundsTransferButton.centerY() + hTrans / 2),
+                        pButtons);
+            }
+
+        }
+
+    }
+
+    public Bitmap getDrawerBitmap() {
+        return act.getBitmap();
+    }
+
+    public RectF getDrawerBounds() {
+        return act.getBounds();
+    }
+
+    @Override
+    public void set(float x, float y, float s) {
+        scale = s;
+        pos.x = x;
+        pos.y = y;
+        if (!expanded) {
+            bounds.set(pos.x - getRadius(), pos.y - getRadius(), pos.x + getRadius(), pos.y + getRadius());
+        } else {
+            bounds.set(pos.x - getRadius(), pos.y - getRadius(), pos.x + getRadius(), pos.y + getRadius());
+            act.setBounds(pos.x - getRadius(), pos.y, pos.x + getRadius(), pos.y + act.getHeight());
+        }
+    }
+
+    @Override
+    public int getRadius() {
+        return (int) (radius * scale * density);
+    }
+
+    
+
+    @Override
+    public boolean getHoldStatus() {
+        if (associated_call.isOnHold())
+            return true;
+        else
+            return false;
+    }
+
+    @Override
+    public boolean getRecordStatus() {
+        if (associated_call.isRecording())
+            return true;
+        else
+            return false;
+    }
+
+    @Override
+    public SipCall getCall() {
+        return associated_call;
+    }
+
+}
diff --git a/src/org/sflphone/model/BubbleModel.java b/src/org/sflphone/model/BubbleModel.java
index 5880fd7..0caa1d6 100644
--- a/src/org/sflphone/model/BubbleModel.java
+++ b/src/org/sflphone/model/BubbleModel.java
@@ -191,7 +191,7 @@
 
     public Bubble getBubble(SipCall call) {
         for(Bubble b : bubbles){
-            if(b.associated_call.getCallId().contentEquals(call.getCallId()))
+            if(b.getCall().getCallId().contentEquals(call.getCallId()))
                 return b;
         }
         return null;
diff --git a/src/org/sflphone/model/BubbleUser.java b/src/org/sflphone/model/BubbleUser.java
new file mode 100644
index 0000000..ef913be
--- /dev/null
+++ b/src/org/sflphone/model/BubbleUser.java
@@ -0,0 +1,179 @@
+package org.sflphone.model;
+
+import org.sflphone.R;
+
+import android.content.Context;
+import android.graphics.Bitmap;
+import android.graphics.Bitmap.Config;
+import android.graphics.BitmapFactory;
+import android.graphics.Canvas;
+import android.graphics.Paint;
+import android.graphics.RectF;
+import android.util.Log;
+
+public class BubbleUser extends Bubble {
+
+    public Conference associated_call;
+    SipCall myself;
+    Bitmap buttonMic, buttonHold, buttonRecord, buttonHangUp;
+    float expanded_radius;
+
+    public BubbleUser(Context context, SipCall m, Conference conf, float x, float y, float size) {
+        super(context, m.getContact(), x, y, size);
+        myself = m;
+        isUser = true;
+        associated_call = conf;
+        setDrawer(new ActionDrawer(0, 0));
+        expanded_radius = (float) (size * 1.5);
+
+        buttonMic = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_action_mic);
+        buttonHold = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_action_pause_over_video);
+        // buttonRecord = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_action_);
+        buttonHangUp = BitmapFactory.decodeResource(mContext.getResources(), R.drawable.ic_action_end_call);
+    }
+
+    @Override
+    public void set(float x, float y, float s) {
+        scale = s;
+        pos.x = x;
+        pos.y = y;
+        bounds.set(pos.x - getRadius(), pos.y - getRadius(), pos.x + getRadius(), pos.y + getRadius());
+        if (!expanded) {
+            bounds.set(pos.x - getRadius(), pos.y - getRadius(), pos.x + getRadius(), pos.y + getRadius());
+        } else {
+            bounds.set(pos.x - getRadius(), pos.y - getRadius(), pos.x + getRadius(), pos.y + getRadius());
+            act.setBounds(pos.x - getExpandedRadius(), pos.y - getExpandedRadius(), pos.x + getExpandedRadius(), pos.y + getExpandedRadius());
+        }
+    }
+
+    @Override
+    public void expand(int width, int height) {
+
+        expanded = true;
+        generateBitmap();
+        setDrawer(new ActionDrawer((int) getExpandedRadius() * 2, (int) getExpandedRadius() * 2));
+
+        act.setBounds(pos.x - getExpandedRadius(), pos.y - getExpandedRadius(), pos.x + getExpandedRadius(), pos.y + getExpandedRadius());
+        act.generateBitmap();
+
+    }
+
+    @Override
+    public int getRadius() {
+        return (int) (radius * scale * density);
+    }
+
+    public int getExpandedRadius() {
+        return (int) (expanded_radius * scale * density);
+    }
+
+    @Override
+    public boolean getHoldStatus() {
+        if (associated_call.isOnHold())
+            return true;
+        else
+            return false;
+    }
+
+    @Override
+    public boolean getRecordStatus() {
+        if (associated_call.isRecording())
+            return true;
+        else
+            return false;
+    }
+
+    @Override
+    public SipCall getCall() {
+        return myself;
+    }
+
+    protected class ActionDrawer extends Bubble.ActionDrawer {
+
+        RectF boundsHoldButton, boundsMicButton, boundsRecordButton, boundsHangUpButton;
+
+        public ActionDrawer(int w, int h) {
+            super(w, h);
+        }
+
+        @Override
+        public void generateBitmap() {
+            img = Bitmap.createBitmap(mWidth, mHeight, Config.ARGB_8888);
+            Paint paint = new Paint();
+            paint.setColor(mContext.getResources().getColor(R.color.sfl_action_blue));
+            paint.setDither(true);
+            Canvas c = new Canvas(img);
+            c.drawOval(new RectF(0, 0, mWidth, mHeight), paint);
+            Log.i("Bubble", "mWidth:" + mWidth);
+            Log.i("Bubble", "mHeight:" + mHeight);
+
+            Paint test4 = new Paint();
+            boundsHangUpButton = new RectF(mWidth / 2 - getRadius(), 0, mWidth / 2 + getRadius(), mHeight / 2 - getRadius());
+            c.drawBitmap(buttonHangUp, null, boundsHangUpButton, test4);
+
+            boundsHoldButton = new RectF(0, mHeight / 2 - getRadius(), mWidth / 2 - getRadius(), mHeight / 2 + getRadius());
+            c.drawBitmap(buttonHold, null, boundsHoldButton, test4);
+
+            boundsMicButton = new RectF(mWidth / 2 + getRadius(), mHeight / 2 - getRadius(), mWidth, mHeight / 2 + getRadius());
+            c.drawBitmap(buttonMic, null, boundsMicButton, test4);
+            // //
+            // boundsRecordButton = new RectF(externalBMP.getWidth() / 2 - w / 2, 0, externalBMP.getWidth() / 2 + w / 2, externalBMP.getHeight() / 2 -
+            // h / 2);
+            // c.drawBitmap(buttonRecord, null, boundsRecordButton, test4);
+        }
+
+        @Override
+        public int getAction(float x, float y) {
+
+            float relativeX = x - getBounds().left;
+            float relativeY = y - getBounds().top;
+
+            Log.i("Bubble", "relativeX:" + relativeX);
+            Log.i("Bubble", "relativeY:" + relativeY);
+
+            Log.i("Bubble", "pos.x:" + pos.x);
+            Log.i("Bubble", "pos.y:" + pos.y);
+            //
+            // Log.i("Bubble", getBounds().toShortString());
+            //
+            Log.i("boundsHoldButton", boundsHoldButton.toShortString());
+            Log.i("boundsMicButton", boundsMicButton.toShortString());
+            Log.i("boundsHangUpButton", boundsHangUpButton.toShortString());
+
+            if (boundsHoldButton.contains(relativeX, relativeY)) {
+                Log.i("Bubble", "Holding");
+                return actions.HOLD;
+            }
+
+            // if (boundsRecordButton.contains(x, y)) {
+            // Log.i("Bubble", "Record");
+            // return actions.RECORD;
+            // }
+
+            if (boundsMicButton.contains(x, y)) {
+                Log.i("Bubble", "Muting");
+                return actions.MUTE;
+            }
+
+            if (boundsHangUpButton.contains(x, y)) {
+                Log.i("Bubble", "hangup");
+                return actions.HANGUP;
+            }
+
+            return 0;
+
+        }
+
+    }
+
+    @Override
+    public Bitmap getDrawerBitmap() {
+        return act.img;
+    }
+
+    @Override
+    public RectF getDrawerBounds() {
+        return act.bounds;
+    }
+
+}
diff --git a/src/org/sflphone/model/BubblesView.java b/src/org/sflphone/model/BubblesView.java
index 660eb9a..7920bbb 100644
--- a/src/org/sflphone/model/BubblesView.java
+++ b/src/org/sflphone/model/BubblesView.java
@@ -265,7 +265,7 @@
 

                 Paint tryMe = new Paint();

 

-                canvas.drawColor(Color.WHITE);

+                canvas.drawColor(getResources().getColor(R.color.sfl_light_blue));

 

                 if (dragging_bubble) {

                     Paint p = new Paint();

@@ -295,29 +295,19 @@
                             continue;

                         }

                         canvas.drawBitmap(b.getBitmap(), null, b.getBounds(), null);

-                        canvas.drawText(b.associated_call.getContact().getmDisplayName(), b.getPosX(), (float) (b.getPosY() - b.getRetractedRadius()

-                                * 1.2 * density), getNamePaint(b));

+                        canvas.drawText(b.getCall().getContact().getmDisplayName(), b.getPosX(), (float) (b.getPosY() - b.getRetractedRadius() * 1.2

+                                * density), getNamePaint(b));

                     }

 

                     Bubble first_plan = getExpandedBubble();

                     if (first_plan != null) {

 

+                        if (first_plan.getDrawerBitmap() != null) {

+                            canvas.drawBitmap(first_plan.getDrawerBitmap(), null, first_plan.getDrawerBounds(), null);

+                        } 

                         canvas.drawBitmap(first_plan.getBitmap(), null, first_plan.getBounds(), null);

-                        Log.i(TAG, first_plan.getBounds().toShortString());

-

-                        canvas.drawText(first_plan.associated_call.getContact().getmDisplayName(), first_plan.getPosX(),

-                                (float) (first_plan.getPosY() - first_plan.getRetractedRadius() * 1.2 * density), getNamePaint(first_plan));

-

-                        canvas.drawText(getResources().getString(R.string.action_call_general_transfer), first_plan.getPosX(),

-                                (float) (first_plan.getPosY() + first_plan.getRetractedRadius() * 1.5 * density), getNamePaint(first_plan));

-

-                        canvas.drawText(getResources().getString(first_plan.getHoldStatus()),

-                                (float) (first_plan.getPosX() - first_plan.getRetractedRadius() * 1.5 * density - 15), first_plan.getPosY(),

-                                getNamePaint(first_plan));

-

-                        canvas.drawText(getResources().getString(first_plan.getRecordStatus()),

-                                (float) (first_plan.getPosX() + first_plan.getRetractedRadius() * 1.5 * density + 15), first_plan.getPosY(),

-                                getNamePaint(first_plan));

+                        // canvas.drawText(first_plan.associated_call.getContact().getmDisplayName(), first_plan.getPosX(),

+                        // (float) (first_plan.getPosY() - first_plan.getRetractedRadius() * 1.2 * density), getNamePaint(first_plan));

 

                     }

 

@@ -359,7 +349,7 @@
                     b.target_scale = 1.f;

                     if (b.isOnBorder(model.width, model.height) && !b.expanded) {

                         b.markedToDie = true;

-                        ((CallActivity) callback.getActivity()).onCallEnded(b.associated_call);

+                        ((CallActivity) callback.getActivity()).onCallEnded(b.getCall());

                     }

                 }

             }

@@ -413,34 +403,42 @@
             List<Bubble> bubbles = model.getBubbles();

             final int n_bubbles = bubbles.size();

             Bubble expand = getExpandedBubble();

+            Log.d("Main", "onDown");

             if (expand != null) {

-                if (!expand.intersects(event.getX(), event.getY())) {

+                 Log.d("Main", "getAction");

+                switch (expand.getDrawer().getAction(event.getX(), event.getY())) {

+                case Bubble.actions.NOTHING:

                     expand.retract();

-                } else {

-                    // Log.d("Main", "getAction");

-                    switch (expand.getAction(event.getX(), event.getY())) {

-                    case 0:

-                        expand.retract();

-                        break;

-                    case 1:

-                        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");

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

-                        break;

-                    case 3:

-                        callback.makeTransfer(expand);

-                        break;

+                    break;

+                case Bubble.actions.HOLD:

+                    // if(expand.isUser){

+                    // ((CallActivity) callback.getActivity()).onCallSuspended();

+                    // }

+                    if (expand.getHoldStatus()) {

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

+                    } else {

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

                     }

+

+                    break;

+                case Bubble.actions.RECORD:

+                    ((CallActivity) callback.getActivity()).onRecordCall(expand.getCall());

+                    break;

+                case Bubble.actions.MESSAGE:

+                    // TODO

+                    break;

+

+                case Bubble.actions.HANGUP:

+                    ((CallActivity) callback.getActivity()).onCallEnded(expand.getCall());

+                    break;

+

+                case Bubble.actions.TRANSFER:

+                    callback.makeTransfer((BubbleContact) expand);

+                    break;

                 }

                 return true;

             }

+

             // Log.d("Main", "onDown");

             for (int i = 0; i < n_bubbles; i++) {

                 Bubble b = bubbles.get(i);