* #38608: first implementation of history database

History is now stored in a lightweight ORM database.
Corners cases are still not treated, but simple calls are saved properly.
diff --git a/src/org/sflphone/client/CallActivity.java b/src/org/sflphone/client/CallActivity.java
index 107fbfa..44e55d8 100644
--- a/src/org/sflphone/client/CallActivity.java
+++ b/src/org/sflphone/client/CallActivity.java
@@ -371,18 +371,6 @@
         mHandler.postDelayed(mUpdateTimeTask, 0);
     }
 
-    public void onCallSuspended() {
-        try {
-            if (mCurrentCallFragment.getConference().hasMultipleParticipants()) {
-                mService.holdConference(mCurrentCallFragment.getConference().getId());
-            } else {
-                mService.hold(mCurrentCallFragment.getConference().getParticipants().get(0).getCallId());
-            }
-        } catch (RemoteException e) {
-            e.printStackTrace();
-        }
-    }
-
     @Override
     public void slideChatScreen() {
 
diff --git a/src/org/sflphone/fragments/CallFragment.java b/src/org/sflphone/fragments/CallFragment.java
index 60f33a7..71be78c 100644
--- a/src/org/sflphone/fragments/CallFragment.java
+++ b/src/org/sflphone/fragments/CallFragment.java
@@ -565,7 +565,7 @@
     }
 
     public void updateTime() {
-        long duration = System.currentTimeMillis() / 1000 - this.conf.getParticipants().get(0).getTimestamp_start();
+        long duration = System.currentTimeMillis() / 1000 - this.conf.getParticipants().get(0).getTimestampStart_();
         if (conf.isOnGoing())
             callStatusTxt.setText(String.format("%d:%02d:%02d", duration / 3600, duration % 3600 / 60, duration % 60));
     }
diff --git a/src/org/sflphone/fragments/CallListFragment.java b/src/org/sflphone/fragments/CallListFragment.java
index 1264e54..259f7d1 100644
--- a/src/org/sflphone/fragments/CallListFragment.java
+++ b/src/org/sflphone/fragments/CallListFragment.java
@@ -232,7 +232,7 @@
 
         nb_confs.setText("" + multiConfs.size());
         nb_calls.setText("" + oneToOneConfs.size());
-        confs_adapter.updateDataset(new ArrayList<Conference>(multiConfs));
+        confs_adapter.updateDataset(multiConfs);
         calls_adapter.updateDataset(oneToOneConfs);
     }
 
@@ -361,7 +361,7 @@
             if (call.getParticipants().size() == 1) {
                 ((TextView) convertView.findViewById(R.id.call_title)).setText(call.getParticipants().get(0).getContact().getmDisplayName());
 
-                long duration = System.currentTimeMillis() / 1000 - (call.getParticipants().get(0).getTimestamp_start());
+                long duration = System.currentTimeMillis() / 1000 - (call.getParticipants().get(0).getTimestampStart_());
 
                 ((TextView) convertView.findViewById(R.id.call_time)).setText(String.format("%d:%02d:%02d", duration / 3600, (duration % 3600) / 60,
                         (duration % 60)));
diff --git a/src/org/sflphone/fragments/HistoryFragment.java b/src/org/sflphone/fragments/HistoryFragment.java
index 0ab1712..4030c6d 100644
--- a/src/org/sflphone/fragments/HistoryFragment.java
+++ b/src/org/sflphone/fragments/HistoryFragment.java
@@ -166,7 +166,7 @@
     public void onStart() {
         super.onStart();
         Log.w(TAG, "onStart");
-        //getLoaderManager().restartLoader(LoaderConstants.HISTORY_LOADER, null, this);
+        getLoaderManager().restartLoader(LoaderConstants.HISTORY_LOADER, null, this);
     }
 
     public void makeNewCall(int position) {
@@ -218,7 +218,7 @@
             entryView.incoming.setText(getString(R.string.hist_in_calls, dataset.get(pos).getIncoming_sum()));
             entryView.outgoing.setText(getString(R.string.hist_out_calls, dataset.get(pos).getOutgoing_sum()));
 
-            if (dataset.get(pos).getCalls().lastEntry().getValue().getRecordPath().length() > 0) {
+            /*if (dataset.get(pos).getCalls().lastEntry().getValue().getRecordPath().length() > 0) {
                 entryView.replay.setVisibility(View.VISIBLE);
                 entryView.replay.setTag(R.id.replay, true);
                 entryView.replay.setOnClickListener(new OnClickListener() {
@@ -241,9 +241,9 @@
                         }
                     }
                 });
-            }
+            }*/
 
-            entryView.date.setText(dataset.get(pos).getCalls().lastEntry().getValue().getDate());
+            /*entryView.date.setText(dataset.get(pos).getCalls().lastEntry().getValue().getDate());*/
             entryView.photo.setOnClickListener(new OnClickListener() {
 
                 @Override
diff --git a/src/org/sflphone/history/HistoryCall.java b/src/org/sflphone/history/HistoryCall.java
index 05d3591..a77f3a3 100644
--- a/src/org/sflphone/history/HistoryCall.java
+++ b/src/org/sflphone/history/HistoryCall.java
@@ -35,6 +35,7 @@
 import android.os.Parcel;
 import android.os.Parcelable;
 import com.j256.ormlite.field.DatabaseField;
+import org.sflphone.model.SipCall;
 import org.sflphone.service.ServiceConstants;
 
 import java.sql.Timestamp;
@@ -62,8 +63,6 @@
     String direction;
     @DatabaseField
     String recordPath;
-    @DatabaseField
-    String timeFormatted;
 
     public String getAccountID() {
         return accountID;
@@ -81,6 +80,15 @@
     @DatabaseField
     long callID;
 
+    public HistoryCall(SipCall call) {
+        call_start = call.getTimestampStart_();
+        call_end = call.getTimestampEnd_();
+        number = call.getContact().getPhones().get(0).getNumber();
+        missed = call.isRinging();
+        direction = call.getCallTypeString();
+        recordPath = call.getRecordPath();
+    }
+
     /* Needed by ORMLite */
     public HistoryCall() {
     }
@@ -90,7 +98,7 @@
     }
 
     public String getDate() {
-        return timeFormatted;
+        return HistoryTimeModel.timeToHistoryConst(call_start);
     }
 
     public String getStartString(String format) {
@@ -142,7 +150,6 @@
         dest.writeByte((byte) (missed ? 1 : 0));
         dest.writeString(direction);
         dest.writeString(recordPath);
-        dest.writeString(timeFormatted);
         dest.writeLong(contactID);
         dest.writeLong(callID);
     }
@@ -165,7 +172,6 @@
         missed = in.readByte() == 1 ? true : false;
         direction = in.readString();
         recordPath = in.readString();
-        timeFormatted = in.readString();
         contactID = in.readLong();
         callID = in.readLong();
     }
diff --git a/src/org/sflphone/history/HistoryManager.java b/src/org/sflphone/history/HistoryManager.java
index 25aa853..69b8154 100644
--- a/src/org/sflphone/history/HistoryManager.java
+++ b/src/org/sflphone/history/HistoryManager.java
@@ -33,14 +33,11 @@
 
 import android.content.Context;
 import com.j256.ormlite.android.apptools.OpenHelperManager;
-import com.j256.ormlite.dao.Dao;
+import org.sflphone.model.Conference;
+import org.sflphone.model.SipCall;
 
 import java.sql.SQLException;
-import java.text.SimpleDateFormat;
-import java.util.ArrayList;
-import java.util.Calendar;
 import java.util.List;
-import java.util.Locale;
 
 public class HistoryManager {
 
@@ -48,8 +45,26 @@
     private DatabaseHelper historyDBHelper = null;
 
     public HistoryManager(Context context) {
-        getHelper();
         mContext = context;
+        getHelper();
+    }
+
+    public boolean insertNewEntry(Conference toInsert){
+        for (SipCall call : toInsert.getParticipants()) {
+            call.setTimestampEnd_(System.currentTimeMillis() * 1000);
+            HistoryCall persistent = new HistoryCall(call);
+            try {
+                getHelper().getHistoryDao().create(persistent);
+            } catch (SQLException e) {
+                e.printStackTrace();
+                return false;
+            }
+        }
+        return true;
+    }
+
+    public boolean insertNewEntry(SipCall toInsert){
+        return true;
     }
 
     /**
diff --git a/src/org/sflphone/model/SipCall.java b/src/org/sflphone/model/SipCall.java
index a8574a4..fdbcf03 100644
--- a/src/org/sflphone/model/SipCall.java
+++ b/src/org/sflphone/model/SipCall.java
@@ -32,7 +32,6 @@
 package org.sflphone.model;
 
 import java.io.InvalidObjectException;
-import java.util.ArrayList;
 import java.util.Random;
 
 import android.content.ContentResolver;
@@ -48,16 +47,19 @@
     private Account mAccount = null;
     private CallContact contact = null;
     private boolean isRecording = false;
-    private long timestamp_start = 0;
-    
+    private long timestampStart_ = 0;
+    private long timestampEnd_ = 0;
+
 
     private int mCallType = state.CALL_TYPE_UNDETERMINED;
     private int mCallState = state.CALL_STATE_NONE;
     private int mMediaState = state.MEDIA_STATE_NONE;
 
-    /************************
+    /**
+     * *********************
      * Construtors
-     ***********************/
+     * *********************
+     */
 
     private SipCall(Parcel in) {
 
@@ -68,8 +70,9 @@
         mCallType = in.readInt();
         mCallState = in.readInt();
         mMediaState = in.readInt();
-        timestamp_start = in.readLong();
-            }
+        timestampStart_ = in.readLong();
+        timestampEnd_ = in.readLong();
+    }
 
     public SipCall(String id, Account account, int call_type, int call_state, int media_state, CallContact c) {
         mCallID = id;
@@ -80,6 +83,14 @@
         contact = c;
     }
 
+    public long getTimestampEnd_() {
+        return timestampEnd_;
+    }
+
+    public String getRecordPath() {
+        return "";
+    }
+
     public interface state {
         public static final int CALL_TYPE_UNDETERMINED = 0;
         public static final int CALL_TYPE_INCOMING = 1;
@@ -118,7 +129,8 @@
         out.writeInt(mCallType);
         out.writeInt(mCallState);
         out.writeInt(mMediaState);
-        out.writeLong(timestamp_start);
+        out.writeLong(timestampStart_);
+        out.writeLong(timestampEnd_);
     }
 
     public static final Parcelable.Creator<SipCall> CREATOR = new Parcelable.Creator<SipCall>() {
@@ -139,12 +151,16 @@
         return mCallID;
     }
 
-    public long getTimestamp_start() {
-        return timestamp_start;
+    public long getTimestampStart_() {
+        return timestampStart_;
     }
 
-    public void setTimestamp_start(long timestamp_start) {
-        this.timestamp_start = timestamp_start;
+    public void setTimestampStart_(long timestampStart_) {
+        this.timestampStart_ = timestampStart_;
+    }
+
+    public void setTimestampEnd_(long timestampEnd_) {
+        this.timestampEnd_ = timestampEnd_;
     }
 
     public void setAccount(Account account) {
@@ -165,12 +181,12 @@
 
     public String getCallTypeString() {
         switch (mCallType) {
-        case state.CALL_TYPE_INCOMING:
-            return "CALL_TYPE_INCOMING";
-        case state.CALL_TYPE_OUTGOING:
-            return "CALL_TYPE_OUTGOING";
-        default:
-            return "CALL_TYPE_UNDETERMINED";
+            case state.CALL_TYPE_INCOMING:
+                return "CALL_TYPE_INCOMING";
+            case state.CALL_TYPE_OUTGOING:
+                return "CALL_TYPE_OUTGOING";
+            default:
+                return "CALL_TYPE_UNDETERMINED";
         }
     }
 
@@ -178,18 +194,6 @@
         mCallState = callState;
     }
 
-    public int getCallStateInt() {
-        return mCallState;
-    }
-
-    public String getmCallID() {
-        return mCallID;
-    }
-
-    public void setmCallID(String mCallID) {
-        this.mCallID = mCallID;
-    }
-
     public CallContact getContact() {
         return contact;
     }
@@ -198,66 +202,42 @@
         contact = contacts;
     }
 
-    public int getmCallType() {
-        return mCallType;
-    }
-
-    public void setmCallType(int mCallType) {
-        this.mCallType = mCallType;
-    }
-
-    public int getmMediaState() {
-        return mMediaState;
-    }
-
-    public void setmMediaState(int mMediaState) {
-        this.mMediaState = mMediaState;
-    }
-
     public String getCallStateString() {
 
         String text_state;
 
         switch (mCallState) {
-        case state.CALL_STATE_INCOMING:
-            text_state = "INCOMING";
-            break;
-        case state.CALL_STATE_RINGING:
-            text_state = "RINGING";
-            break;
-        case state.CALL_STATE_CURRENT:
-            text_state = "CURRENT";
-            break;
-        case state.CALL_STATE_HUNGUP:
-            text_state = "HUNGUP";
-            break;
-        case state.CALL_STATE_BUSY:
-            text_state = "BUSY";
-            break;
-        case state.CALL_STATE_FAILURE:
-            text_state = "FAILURE";
-            break;
-        case state.CALL_STATE_HOLD:
-            text_state = "HOLD";
-            break;
-        case state.CALL_STATE_UNHOLD:
-            text_state = "UNHOLD";
-            break;
-        default:
-            text_state = "NULL";
+            case state.CALL_STATE_INCOMING:
+                text_state = "INCOMING";
+                break;
+            case state.CALL_STATE_RINGING:
+                text_state = "RINGING";
+                break;
+            case state.CALL_STATE_CURRENT:
+                text_state = "CURRENT";
+                break;
+            case state.CALL_STATE_HUNGUP:
+                text_state = "HUNGUP";
+                break;
+            case state.CALL_STATE_BUSY:
+                text_state = "BUSY";
+                break;
+            case state.CALL_STATE_FAILURE:
+                text_state = "FAILURE";
+                break;
+            case state.CALL_STATE_HOLD:
+                text_state = "HOLD";
+                break;
+            case state.CALL_STATE_UNHOLD:
+                text_state = "UNHOLD";
+                break;
+            default:
+                text_state = "NULL";
         }
 
         return text_state;
     }
 
-    public void setMediaState(int mediaState) {
-        mMediaState = mediaState;
-    }
-
-    public int getMediaState() {
-        return mMediaState;
-    }
-
     public boolean isRecording() {
         return isRecording;
     }
diff --git a/src/org/sflphone/service/CallManagerCallBack.java b/src/org/sflphone/service/CallManagerCallBack.java
index 5ba0d67..0aeb137 100644
--- a/src/org/sflphone/service/CallManagerCallBack.java
+++ b/src/org/sflphone/service/CallManagerCallBack.java
@@ -2,7 +2,6 @@
 
 import android.content.Intent;
 import android.os.Bundle;
-import android.support.v4.content.LocalBroadcastManager;
 import android.util.Log;
 import org.sflphone.client.CallActivity;
 import org.sflphone.model.*;
@@ -39,36 +38,28 @@
         Intent intent = new Intent(CALL_STATE_CHANGED);
         intent.putExtra("com.savoirfairelinux.sflphone.service.newstate", bundle);
 
-        /*try {
-            if (mService.getCurrentCalls().get(callID) != null && mBinder.isConferenceParticipant(callID)) {
-                mService.getCurrentCalls().remove(callID);
-            }
-        } catch (RemoteException e1) {
-            e1.printStackTrace();
-        }*/
-
 
         if (newState.equals("INCOMING")) {
-            mService.getCurrentConfs().get(callID).setCallState(callID, SipCall.state.CALL_STATE_INCOMING);
+            mService.getConferences().get(callID).setCallState(callID, SipCall.state.CALL_STATE_INCOMING);
         } else if (newState.equals("RINGING")) {
             try {
-                mService.getCurrentConfs().get(callID).setCallState(callID, SipCall.state.CALL_STATE_RINGING);
+                mService.getConferences().get(callID).setCallState(callID, SipCall.state.CALL_STATE_RINGING);
             } catch (NullPointerException e) {
-                if (mService.getCurrentConfs() == null) {
+                if (mService.getConferences() == null) {
                     return;
                 }
-                if (mService.getCurrentConfs().get(callID) == null) {
+                if (mService.getConferences().get(callID) == null) {
                     Log.e(TAG, "call for " + callID + " is null");
                     return;
                 }
             }
 
         } else if (newState.equals("CURRENT")) {
-            if (mService.getCurrentConfs().get(callID) != null) {
-                mService.getCurrentConfs().get(callID).setCallState(callID, SipCall.state.CALL_STATE_CURRENT);
+            if (mService.getConferences().get(callID) != null) {
+                mService.getConferences().get(callID).setCallState(callID, SipCall.state.CALL_STATE_CURRENT);
             } else {
                 // Check if call is in a conference
-                Iterator<Map.Entry<String, Conference>> it = mService.getCurrentConfs().entrySet().iterator();
+                Iterator<Map.Entry<String, Conference>> it = mService.getConferences().entrySet().iterator();
                 while (it.hasNext()) {
                     Conference tmp = it.next().getValue();
                     for (SipCall c : tmp.getParticipants()) {
@@ -79,43 +70,43 @@
             }
 
         } else if (newState.equals("HUNGUP")) {
-
             Log.d(TAG, "Hanging up " + callID);
-            if (mService.getCurrentConfs().get(callID) != null) {
-                if (mService.getCurrentConfs().get(callID).isRinging()
-                        && mService.getCurrentConfs().get(callID).isIncoming())
-                    mService.notificationManager.publishMissedCallNotification(mService.getCurrentConfs().get(callID));
-                mService.getCurrentConfs().remove(callID);
+            if (mService.getConferences().get(callID) != null) {
+                if (mService.getConferences().get(callID).isRinging()
+                        && mService.getConferences().get(callID).isIncoming())
+                    mService.mNotificationManager.publishMissedCallNotification(mService.getConferences().get(callID));
+
+                mService.mHistoryManager.insertNewEntry(mService.getConferences().get(callID));
+                mService.getConferences().remove(callID);
             } else {
-                ArrayList<Conference> it = new ArrayList<Conference>(mService.getCurrentConfs().values());
+                ArrayList<Conference> it = new ArrayList<Conference>(mService.getConferences().values());
 
                 boolean found = false;
                 int i = 0;
                 while (!found && i < it.size()) {
                     Conference tmp = it.get(i);
 
-                    for (int j = 0; j < tmp.getParticipants().size(); ++j) {
-                        if (tmp.getParticipants().get(j).getCallId().contentEquals(callID)) {
-                            mService.getCurrentConfs().get(tmp.getId()).getParticipants().remove(tmp.getParticipants().get(j));
+                    for (SipCall call : tmp.getParticipants()) {
+                        if (call.getCallId().contentEquals(callID)) {
+                            mService.mHistoryManager.insertNewEntry(call);
+                            mService.getConferences().get(tmp.getId()).removeParticipant(call.getCallId());
                             found = true;
                         }
-
                     }
                     ++i;
-
                 }
             }
 
         } else if (newState.equals("BUSY")) {
-            mService.getCurrentConfs().remove(callID);
+            mService.getConferences().remove(callID);
         } else if (newState.equals("FAILURE")) {
-            mService.getCurrentConfs().remove(callID);
+            mService.getConferences().remove(callID);
         } else if (newState.equals("HOLD")) {
-            if (mService.getCurrentConfs().get(callID) != null) {
-                mService.getCurrentConfs().get(callID).setCallState(callID, SipCall.state.CALL_STATE_HOLD);
+            if (mService.getConferences().get(callID) != null) {
+                mService.getConferences().get(callID).setCallState(callID, SipCall.state.CALL_STATE_HOLD);
             } else {
                 // Check if call is in a conference
-                Iterator<Map.Entry<String, Conference>> it = mService.getCurrentConfs().entrySet().iterator();
+                Iterator<Map.Entry<String, Conference>> it = mService.getConferences().entrySet().iterator();
                 while (it.hasNext()) {
                     Conference tmp = it.next().getValue();
                     for (SipCall c : tmp.getParticipants()) {
@@ -126,11 +117,11 @@
             }
         } else if (newState.equals("UNHOLD")) {
 
-            if (mService.getCurrentConfs().get(callID) != null) {
-                mService.getCurrentConfs().get(callID).setCallState(callID, SipCall.state.CALL_STATE_CURRENT);
+            if (mService.getConferences().get(callID) != null) {
+                mService.getConferences().get(callID).setCallState(callID, SipCall.state.CALL_STATE_CURRENT);
             } else {
                 // Check if call is in a conference
-                Iterator<Map.Entry<String, Conference>> it = mService.getCurrentConfs().entrySet().iterator();
+                Iterator<Map.Entry<String, Conference>> it = mService.getConferences().entrySet().iterator();
                 while (it.hasNext()) {
                     Conference tmp = it.next().getValue();
                     for (SipCall c : tmp.getParticipants()) {
@@ -140,13 +131,9 @@
                 }
             }
         } else {
-            mService.getCurrentConfs().get(callID).setCallState(callID, SipCall.state.CALL_STATE_NONE);
+            mService.getConferences().get(callID).setCallState(callID, SipCall.state.CALL_STATE_NONE);
         }
-
-
-        Log.d(TAG, "Hanging up " + callID);
         mService.sendBroadcast(intent);
-
     }
 
     @Override
@@ -170,11 +157,11 @@
             toSend.putExtra("newcall", newCall);
             StringMap callDetails = mService.getCallManagerJNI().getCallDetails(callID);
 
-            newCall.setTimestamp_start(Long.parseLong(callDetails.get(ServiceConstants.call.TIMESTAMP_START)));
+            newCall.setTimestampStart_(Long.parseLong(callDetails.get(ServiceConstants.call.TIMESTAMP_START)));
 
             Conference toAdd = new Conference(newCall);
 
-            mService.getCurrentConfs().put(toAdd.getId(), toAdd);
+            mService.getConferences().put(toAdd.getId(), toAdd);
 
             Bundle bundle = new Bundle();
 
@@ -182,8 +169,8 @@
             toSend.putExtra("resuming", false);
             toSend.putExtras(bundle);
             mService.startActivity(toSend);
-            mService.mediaManager.startRing("");
-            mService.mediaManager.obtainAudioFocus(true);
+            mService.mMediaManager.startRing("");
+            mService.mMediaManager.obtainAudioFocus(true);
         } catch (Exception e) {
             e.printStackTrace();
         }
@@ -203,24 +190,24 @@
         StringVect all_participants = mService.getCallManagerJNI().getParticipantList(confID);
         Log.w(TAG, "all_participants:" + all_participants.size());
         for (int i = 0; i < all_participants.size(); ++i) {
-            if (mService.getCurrentConfs().get(all_participants.get(i)) != null) {
-                created.addParticipant(mService.getCurrentConfs().get(all_participants.get(i)).getCallById(all_participants.get(i)));
-                mService.getCurrentConfs().remove(all_participants.get(i));
+            if (mService.getConferences().get(all_participants.get(i)) != null) {
+                created.addParticipant(mService.getConferences().get(all_participants.get(i)).getCallById(all_participants.get(i)));
+                mService.getConferences().remove(all_participants.get(i));
             } else {
-                Iterator<Map.Entry<String, Conference>> it = mService.getCurrentConfs().entrySet().iterator();
+                Iterator<Map.Entry<String, Conference>> it = mService.getConferences().entrySet().iterator();
                 while (it.hasNext()) {
                     Conference tmp = it.next().getValue();
                     for (SipCall c : tmp.getParticipants()) {
                         if (c.getCallId().contentEquals(all_participants.get(i))) {
                             created.addParticipant(c);
-                            mService.getCurrentConfs().get(tmp.getId()).removeParticipant(c.getCallId());
+                            mService.getConferences().get(tmp.getId()).removeParticipant(c.getCallId());
                         }
                     }
                 }
             }
         }
         intent.putExtra("newconf", created);
-        mService.getCurrentConfs().put(created.getId(), created);
+        mService.getConferences().put(created.getId(), created);
         mService.sendBroadcast(intent);
     }
 
@@ -236,15 +223,15 @@
         intent.putExtra("com.savoirfairelinux.sflphone.service.newtext", bundle);
 
 
-        if (mService.getCurrentConfs().get(ID) != null) {
-            mService.getCurrentConfs().get(ID).addSipMessage(new SipMessage(true, msg));
+        if (mService.getConferences().get(ID) != null) {
+            mService.getConferences().get(ID).addSipMessage(new SipMessage(true, msg));
         } else {
-            Iterator<Map.Entry<String, Conference>> it = mService.getCurrentConfs().entrySet().iterator();
+            Iterator<Map.Entry<String, Conference>> it = mService.getConferences().entrySet().iterator();
             while (it.hasNext()) {
                 Conference tmp = it.next().getValue();
                 for (SipCall c : tmp.getParticipants()) {
                     if (c.getCallId().contentEquals(ID)) {
-                        mService.getCurrentConfs().get(tmp.getId()).addSipMessage(new SipMessage(true, msg));
+                        mService.getConferences().get(tmp.getId()).addSipMessage(new SipMessage(true, msg));
                     }
                 }
             }
@@ -259,12 +246,12 @@
         Intent intent = new Intent(CONF_REMOVED);
         intent.putExtra("confID", confID);
 
-        Conference toReInsert = mService.getCurrentConfs().get(confID);
+        Conference toReInsert = mService.getConferences().get(confID);
         /*for (int i = 0; i < toDestroy.getParticipants().size(); ++i) {
             mService.getCurrentCalls().put(toDestroy.getParticipants().get(i).getCallId(), toDestroy.getParticipants().get(i));
         }*/
-        mService.getCurrentConfs().remove(confID);
-        mService.getCurrentConfs().put(toReInsert.getId(), toReInsert);
+        mService.getConferences().remove(confID);
+        mService.getConferences().put(toReInsert.getId(), toReInsert);
         mService.sendBroadcast(intent);
 
     }
@@ -275,28 +262,22 @@
         Intent intent = new Intent(CONF_CHANGED);
         intent.putExtra("confID", confID);
         intent.putExtra("State", state);
-        ArrayList<String> all_participants;
 
-/*        try {
-            all_participants = (ArrayList<String>) mBinder.getParticipantList(intent.getStringExtra("confID"));
-            for (String participant : all_participants) {
-                if (mService.getCurrentConfs().get(confID).getParticipants().size() < all_participants.size()
-                        && mService.getCurrentCalls().get(participant) != null) { // We need to add the new participant to the conf
-                    mService.getCurrentConfs().get(confID).getParticipants()
-                            .add(mService.getCurrentCalls().get(participant));
-                    mService.getCurrentCalls().remove(participant);
-                    mService.getCurrentConfs().get(confID).setState(intent.getStringExtra("State"));
-                    mService.sendBroadcast(intent);
-                    return;
-                }
+        StringVect all_participants = mService.getCallManagerJNI().getParticipantList(intent.getStringExtra("confID"));
+        for (int i = 0; i < all_participants.size(); ++i) {
+            if (mService.getConferences().get(confID).getParticipants().size() < all_participants.size()
+                    && mService.getConferences().get(all_participants.get(i)) != null) { // We need to add the new participant to the conf
+                mService.getConferences().get(confID).addParticipant(mService.getConferences().get(all_participants.get(i)).getCallById(all_participants.get(i)));
+                mService.getConferences().remove(all_participants.get(i));
+                mService.getConferences().get(confID).setCallState(confID, intent.getStringExtra("State"));
+                mService.sendBroadcast(intent);
+                return;
             }
-        } catch (RemoteException e) {
-            e.printStackTrace();
-        }*/
+        }
 
         Log.i(TAG, "Received" + intent.getAction());
-        if (mService.getCurrentConfs().get(confID) != null) {
-            mService.getCurrentConfs().get(confID).setCallState(confID, state);
+        if (mService.getConferences().get(confID) != null) {
+            mService.getConferences().get(confID).setCallState(confID, state);
             mService.sendBroadcast(intent);
         }
     }
@@ -306,7 +287,7 @@
         Intent intent = new Intent(RECORD_STATE_CHANGED);
         intent.putExtra("id", id);
         intent.putExtra("file", filename);
-        LocalBroadcastManager.getInstance(mService).sendBroadcast(intent);
+        mService.sendBroadcast(intent);
     }
 
 }
diff --git a/src/org/sflphone/service/SipService.java b/src/org/sflphone/service/SipService.java
index bfc6ac2..78221ba 100644
--- a/src/org/sflphone/service/SipService.java
+++ b/src/org/sflphone/service/SipService.java
@@ -24,7 +24,6 @@
  */
 package org.sflphone.service;
 
-import java.lang.ref.WeakReference;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.Iterator;
@@ -32,6 +31,7 @@
 import java.util.Map;
 import java.util.Map.Entry;
 
+import org.sflphone.history.HistoryManager;
 import org.sflphone.model.Codec;
 import org.sflphone.model.Conference;
 import org.sflphone.model.SipCall;
@@ -73,20 +73,16 @@
     private ConfigurationManagerCallback configurationManagerCallback;
     private boolean isPjSipStackStarted = false;
 
-    public SipNotifications notificationManager;
-    public MediaManager mediaManager;
+    protected SipNotifications mNotificationManager;
+    protected HistoryManager mHistoryManager;
+    protected MediaManager mMediaManager;
 
-    /*private HashMap<String, SipCall> current_calls = new HashMap<String, SipCall>();*/
-    private HashMap<String, Conference> current_confs = new HashMap<String, Conference>();
+    private HashMap<String, Conference> mConferences = new HashMap<String, Conference>();
 
-    public HashMap<String, Conference> getCurrentConfs() {
-        return current_confs;
+    public HashMap<String, Conference> getConferences() {
+        return mConferences;
     }
 
-    /*public HashMap<String, SipCall> getCurrentCalls() {
-        return current_calls;
-    }*/
-
     @Override
     public boolean onUnbind(Intent i) {
         super.onUnbind(i);
@@ -107,11 +103,12 @@
 
         getExecutor().execute(new StartRunnable());
 
-        notificationManager = new SipNotifications(this);
-        mediaManager = new MediaManager(this);
+        mNotificationManager = new SipNotifications(this);
+        mMediaManager = new MediaManager(this);
+        mHistoryManager = new HistoryManager(this);
 
-        notificationManager.onServiceCreate();
-        mediaManager.startService();
+        mNotificationManager.onServiceCreate();
+        mMediaManager.startService();
 
     }
 
@@ -127,7 +124,7 @@
     public void onDestroy() {
         Log.i(TAG, "onDestroy");
         /* called once by stopService() */
-        notificationManager.onServiceDestroy();
+        mNotificationManager.onServiceDestroy();
 
         getExecutor().execute(new FinalizeRunnable());
         super.onDestroy();
@@ -320,10 +317,10 @@
 
                     HashMap<String, String> details = SwigNativeConverter.convertCallDetailsToNative(callManagerJNI.getCallDetails(call.getCallId()));
                     // watchout timestamp stored by sflphone is in seconds
-                    call.setTimestamp_start(Long.parseLong(details.get(ServiceConstants.call.TIMESTAMP_START)));
+                    call.setTimestampStart_(Long.parseLong(details.get(ServiceConstants.call.TIMESTAMP_START)));
                     Conference toAdd = new Conference(call);
-                    current_confs.put(toAdd.getId(), toAdd);
-                    mediaManager.obtainAudioFocus(false);
+                    mConferences.put(toAdd.getId(), toAdd);
+                    mMediaManager.obtainAudioFocus(false);
                 }
             });
         }
@@ -342,26 +339,26 @@
 
         @Override
         public void accept(final String callID) {
-            mediaManager.stopRing();
+            mMediaManager.stopRing();
             getExecutor().execute(new SipRunnable() {
                 @Override
                 protected void doRun() throws SameThreadException {
                     Log.i(TAG, "SipService.accept() thread running...");
                     callManagerJNI.accept(callID);
-                    mediaManager.RouteToInternalSpeaker();
+                    mMediaManager.RouteToInternalSpeaker();
                 }
             });
         }
 
         @Override
         public void hangUp(final String callID) {
-            mediaManager.stopRing();
+            mMediaManager.stopRing();
             getExecutor().execute(new SipRunnable() {
                 @Override
                 protected void doRun() throws SameThreadException {
                     Log.i(TAG, "SipService.hangUp() thread running...");
                     callManagerJNI.hangUp(callID);
-                    mediaManager.abandonAudioFocus();
+                    mMediaManager.abandonAudioFocus();
                 }
             });
         }
@@ -668,7 +665,7 @@
                 protected void doRun() throws SameThreadException, RemoteException {
                     Log.i(TAG, "SipService.addParticipant() thread running...");
                     callManagerJNI.addParticipant(call.getCallId(), confID);
-                    current_confs.get(confID).getParticipants().add(call);
+                    mConferences.get(confID).getParticipants().add(call);
                 }
             });
 
@@ -693,14 +690,14 @@
                 protected void doRun() throws SameThreadException, RemoteException {
                     Log.i(TAG, "SipService.detachParticipant() thread running...");
                     Log.i(TAG, "Detaching " + callID);
-                    Iterator<Entry<String, Conference>> it = current_confs.entrySet().iterator();
-                    Log.i(TAG, "current_confs size " + current_confs.size());
+                    Iterator<Entry<String, Conference>> it = mConferences.entrySet().iterator();
+                    Log.i(TAG, "mConferences size " + mConferences.size());
                     while (it.hasNext()) {
                         Conference tmp = it.next().getValue();
                         Log.i(TAG, "conf has " + tmp.getParticipants().size() + " participants");
                         if (tmp.contains(callID)) {
                             Conference toDetach = new Conference(tmp.getCallById(callID));
-                            current_confs.put(toDetach.getId(), toDetach);
+                            mConferences.put(toDetach.getId(), toDetach);
                             Log.i(TAG, "Call found and put in current_calls");
                         }
                     }
@@ -800,7 +797,7 @@
             // nativelist.add(swigvect.get(i));
             //
             // return nativelist;
-            return current_confs;
+            return mConferences;
         }
 
         @Override
@@ -885,10 +882,10 @@
                     Log.i(TAG, "SipService.toggleRecordingCall() thread running...");
                     boolean result = callManagerJNI.toggleRecording(id);
 
-                    if (getCurrentConfs().containsKey(id)) {
-                        getCurrentConfs().get(id).setRecording(result);
+                    if (getConferences().containsKey(id)) {
+                        getConferences().get(id).setRecording(result);
                     } else {
-                        Iterator<Conference> it = getCurrentConfs().values().iterator();
+                        Iterator<Conference> it = getConferences().values().iterator();
                         while (it.hasNext()) {
                             Conference c = it.next();
                             if (c.getCallById(id) != null)
@@ -949,8 +946,8 @@
                 protected void doRun() throws SameThreadException, RemoteException {
                     Log.i(TAG, "SipService.sendTextMessage() thread running...");
                     callManagerJNI.sendTextMessage(callID, message.comment);
-                    if (getCurrentConfs().get(callID) != null)
-                        getCurrentConfs().get(callID).addSipMessage(message);
+                    if (getConferences().get(callID) != null)
+                        getConferences().get(callID).addSipMessage(message);
                 }
             });
 
@@ -1040,10 +1037,10 @@
 
 /*        @Override
         public Conference getCallById(String callID) throws RemoteException {
-            if(current_confs.containsKey(callID))
-                return current_confs.get(callID);
+            if(mConferences.containsKey(callID))
+                return mConferences.get(callID);
             else{
-                Iterator<Conference> it = getCurrentConfs().values().iterator();
+                Iterator<Conference> it = getConferences().values().iterator();
                 while (it.hasNext()) {
                     Conference c = it.next();
                     if (c.getCallById(callID) != null)
@@ -1068,12 +1065,12 @@
 
         @Override
         public Conference getCurrentCall() throws RemoteException {
-            for (Conference conf : current_confs.values()) {
+            for (Conference conf : mConferences.values()) {
                 if (conf.isIncoming())
                     return conf;
             }
 
-            for (Conference conf : current_confs.values()) {
+            for (Conference conf : mConferences.values()) {
                 if (conf.isOnGoing())
                     return conf;
             }
@@ -1094,12 +1091,12 @@
 
         @Override
         public List getConcurrentCalls() throws RemoteException {
-            return new ArrayList(current_confs.values());
+            return new ArrayList(mConferences.values());
         }
 
         @Override
         public Conference getConference(String id) throws RemoteException {
-            return current_confs.get(id);
+            return mConferences.get(id);
         }
 
         @Override
@@ -1183,9 +1180,9 @@
         @Override
         public void toggleSpeakerPhone(boolean toggle) throws RemoteException {
             if (toggle)
-                mediaManager.RouteToSpeaker();
+                mMediaManager.RouteToSpeaker();
             else
-                mediaManager.RouteToInternalSpeaker();
+                mMediaManager.RouteToInternalSpeaker();
         }
 
     };