From b179bab0620a323581f52cf6ad2d7913ac3e1368 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Adrien=20B=C3=A9raud?= <adrien.beraud@savoirfairelinux.com>
Date: Thu, 8 Oct 2015 12:04:22 -0400
Subject: [PATCH] android: first publishable implementation of Ring on Android

Change-Id: I6d65993a0bbed0ac680d6fe5980aae0fb931116e
---
 compile.sh                                    |  12 +-
 configure.sh                                  |   2 +-
 ring-android/.idea/misc.xml                   |  26 +-
 ring-android/app/app.iml                      |  37 +-
 ring-android/app/build.gradle                 |  16 +-
 ring-android/app/src/main/AndroidManifest.xml |  62 +-
 .../adapters/AccountSelectionAdapter.java     |  23 +-
 .../cx/ring/adapters/ContactPictureTask.java  |  94 +-
 .../cx/ring/adapters/ContactsAdapter.java     | 115 +-
 .../cx/ring/adapters/DiscussArrayAdapter.java | 106 --
 .../ring/adapters/SectionsPagerAdapter.java   |   3 +-
 .../ring/adapters/StarredContactsAdapter.java |   7 +-
 .../ring/client/AccountEditionActivity.java   |  83 +-
 .../java/cx/ring/client/CallActivity.java     | 194 ++--
 .../cx/ring/client/ConversationActivity.java  | 386 +++++++
 .../java/cx/ring/client/HomeActivity.java     | 201 ++--
 .../ring/client/NewConversationActivity.java  | 141 +++
 .../fragments/AccountWrapperFragment.java     | 100 --
 .../fragments/AccountsManagementFragment.java | 187 ++--
 .../fragments/AudioManagementFragment.java    |  26 +-
 .../java/cx/ring/fragments/CallFragment.java  | 436 +++++---
 .../cx/ring/fragments/CallListFragment.java   | 350 ++++--
 .../fragments/CallableWrapperFragment.java    |  15 +-
 .../ring/fragments/ConferenceDFragment.java   |  12 +-
 .../ring/fragments/ContactListFragment.java   | 154 +--
 .../DetailsHistoryEntryFragment.java          |   7 +-
 .../cx/ring/fragments/DialingFragment.java    |  32 +-
 .../fragments/GeneralAccountFragment.java     |  21 +-
 .../cx/ring/fragments/HistoryFragment.java    |  28 +-
 .../java/cx/ring/fragments/IMFragment.java    | 193 ----
 .../java/cx/ring/fragments/MenuFragment.java  |  80 +-
 .../fragments/NestedSettingsFragment.java     |  22 +-
 .../fragments/SecurityAccountFragment.java    |  17 +-
 .../cx/ring/fragments/TransferDFragment.java  |  12 +-
 .../java/cx/ring/history/DatabaseHelper.java  |  15 +-
 .../java/cx/ring/history/HistoryCall.java     |  45 +-
 .../java/cx/ring/history/HistoryEntry.java    |  94 +-
 .../java/cx/ring/history/HistoryManager.java  |  25 +-
 .../java/cx/ring/history/HistoryText.java     | 187 ++++
 .../java/cx/ring/loaders/AccountsLoader.java  |  13 +-
 .../java/cx/ring/loaders/ContactsLoader.java  |  89 +-
 .../java/cx/ring/loaders/HistoryLoader.java   |   5 +-
 .../src/main/java/cx/ring/model/Bubble.java   |   2 +-
 .../java/cx/ring/model/BubbleContact.java     |   4 +-
 .../main/java/cx/ring/model/BubblesView.java  |  12 +-
 .../main/java/cx/ring/model/CallContact.java  | 214 ++--
 .../main/java/cx/ring/model/Conference.java   |  40 +-
 .../main/java/cx/ring/model/Conversation.java | 232 ++++
 .../java/cx/ring/model/SecureSipCall.java     |   6 +-
 .../src/main/java/cx/ring/model/SipCall.java  | 135 ++-
 .../main/java/cx/ring/model/SipMessage.java   |  72 --
 .../{SipMessage.aidl => TextMessage.aidl}     |   2 +-
 .../main/java/cx/ring/model/TextMessage.java  | 294 ++++++
 .../java/cx/ring/model/account/Account.java   |  19 +-
 .../cx/ring/model/account/AccountDetail.java  |  21 +-
 .../model/account/AccountDetailAdvanced.java  |  21 +-
 .../model/account/AccountDetailBasic.java     |  30 +-
 .../ring/model/account/AccountDetailSrtp.java |   2 +-
 .../ring/model/account/AccountDetailTls.java  |   2 +-
 .../cx/ring/service/CallManagerCallBack.java  | 187 ++--
 .../service/ConfigurationManagerCallback.java |  23 +-
 .../java/cx/ring/service/ISipService.aidl     |   4 +-
 .../java/cx/ring/service/LocalService.java    | 813 ++++++++++++++
 .../main/java/cx/ring/service/SipService.java | 151 ++-
 .../main/java/cx/ring/utils/MediaManager.java |   2 +-
 .../java/cx/ring/utils/SipNotifications.java  |  24 +-
 .../main/java/cx/ring/utils/Utilities.java    |  35 +
 .../java/cx/ring/views/CallPaneLayout.java    |   3 +-
 .../cx/ring/views/HalfCircleImageView.java    |   2 +-
 .../cx/ring/views/NumberPickerPreference.java |   2 +-
 .../views/QuadNumberPickerPreference.java     |   2 +-
 .../views/SwipeListViewTouchListener.java     | 409 --------
 .../stickylistheaders/AdapterWrapper.java     | 225 ----
 .../ApiLevelTooLowException.java              |  11 -
 .../CheckableWrapperView.java                 |  31 -
 .../SectionIndexerAdapterWrapper.java         |  32 -
 .../StickyListHeadersAdapter.java             |  38 -
 .../StickyListHeadersListView.java            | 993 ------------------
 .../views/stickylistheaders/WrapperView.java  | 150 ---
 .../stickylistheaders/WrapperViewList.java    | 176 ----
 ring-android/app/src/main/jni/Android.mk      |   7 +-
 ring-android/app/src/main/jni/Application.mk  |   2 +-
 .../res/drawable-hdpi/ic_action_end_call.png  | Bin 442 -> 0 bytes
 .../drawable-hdpi/ic_call_end_black_24dp.png  | Bin 0 -> 303 bytes
 .../drawable-hdpi/ic_call_end_black_36dp.png  | Bin 0 -> 403 bytes
 .../drawable-hdpi/ic_call_end_white_24dp.png  | Bin 0 -> 314 bytes
 .../res/drawable-hdpi/ic_call_white_24dp.png  | Bin 0 -> 340 bytes
 .../res/drawable-hdpi/ic_chat_white_24dp.png  | Bin 0 -> 168 bytes
 .../res/drawable-hdpi/ic_lock_white_24dp.png  | Bin 0 -> 309 bytes
 .../res/drawable-hdpi/ic_send_black_24dp.png  | Bin 0 -> 250 bytes
 .../res/drawable-hdpi/ic_share_white_24dp.png | Bin 0 -> 397 bytes
 .../drawable-hdpi/ic_videocam_white_24dp.png  | Bin 0 -> 173 bytes
 .../ic_send_black_24dp.png                    | Bin 0 -> 250 bytes
 .../ic_send_black_24dp.png                    | Bin 0 -> 204 bytes
 .../ic_send_black_24dp.png                    | Bin 0 -> 341 bytes
 .../ic_send_black_24dp.png                    | Bin 0 -> 414 bytes
 .../ic_send_black_24dp.png                    | Bin 0 -> 551 bytes
 .../res/drawable-mdpi/ic_action_end_call.png  | Bin 342 -> 0 bytes
 .../drawable-mdpi/ic_call_end_black_24dp.png  | Bin 0 -> 235 bytes
 .../drawable-mdpi/ic_call_end_black_36dp.png  | Bin 0 -> 303 bytes
 .../drawable-mdpi/ic_call_end_white_24dp.png  | Bin 0 -> 235 bytes
 .../res/drawable-mdpi/ic_call_white_24dp.png  | Bin 0 -> 246 bytes
 .../res/drawable-mdpi/ic_chat_white_24dp.png  | Bin 0 -> 133 bytes
 .../res/drawable-mdpi/ic_lock_white_24dp.png  | Bin 0 -> 208 bytes
 .../res/drawable-mdpi/ic_send_black_24dp.png  | Bin 0 -> 205 bytes
 .../res/drawable-mdpi/ic_share_white_24dp.png | Bin 0 -> 268 bytes
 .../drawable-mdpi/ic_videocam_white_24dp.png  | Bin 0 -> 131 bytes
 .../res/drawable-xhdpi/ic_action_end_call.png | Bin 552 -> 0 bytes
 .../drawable-xhdpi/ic_call_end_black_24dp.png | Bin 0 -> 371 bytes
 .../drawable-xhdpi/ic_call_end_black_36dp.png | Bin 0 -> 515 bytes
 .../drawable-xhdpi/ic_call_end_white_24dp.png | Bin 0 -> 389 bytes
 .../res/drawable-xhdpi/ic_call_white_24dp.png | Bin 0 -> 420 bytes
 .../res/drawable-xhdpi/ic_chat_white_24dp.png | Bin 0 -> 205 bytes
 .../res/drawable-xhdpi/ic_lock_white_24dp.png | Bin 0 -> 372 bytes
 .../res/drawable-xhdpi/ic_send_black_24dp.png | Bin 0 -> 333 bytes
 .../drawable-xhdpi/ic_share_white_24dp.png    | Bin 0 -> 496 bytes
 .../drawable-xhdpi/ic_videocam_white_24dp.png | Bin 0 -> 178 bytes
 .../drawable-xxhdpi/ic_action_end_call.png    | Bin 763 -> 0 bytes
 .../ic_call_end_black_24dp.png                | Bin 0 -> 515 bytes
 .../ic_call_end_black_36dp.png                | Bin 0 -> 721 bytes
 .../ic_call_end_white_24dp.png                | Bin 0 -> 553 bytes
 .../drawable-xxhdpi/ic_call_white_24dp.png    | Bin 0 -> 597 bytes
 .../drawable-xxhdpi/ic_chat_white_24dp.png    | Bin 0 -> 270 bytes
 .../drawable-xxhdpi/ic_lock_white_24dp.png    | Bin 0 -> 540 bytes
 .../drawable-xxhdpi/ic_send_black_24dp.png    | Bin 0 -> 412 bytes
 .../drawable-xxhdpi/ic_share_white_24dp.png   | Bin 0 -> 698 bytes
 .../ic_videocam_white_24dp.png                | Bin 0 -> 234 bytes
 .../ic_call_end_black_24dp.png                | Bin 0 -> 663 bytes
 .../ic_call_end_black_36dp.png                | Bin 0 -> 954 bytes
 .../ic_call_end_white_24dp.png                | Bin 0 -> 712 bytes
 .../drawable-xxxhdpi/ic_call_white_24dp.png   | Bin 0 -> 778 bytes
 .../drawable-xxxhdpi/ic_chat_white_24dp.png   | Bin 0 -> 344 bytes
 .../drawable-xxxhdpi/ic_lock_white_24dp.png   | Bin 0 -> 702 bytes
 .../drawable-xxxhdpi/ic_send_black_24dp.png   | Bin 0 -> 543 bytes
 .../drawable-xxxhdpi/ic_share_white_24dp.png  | Bin 0 -> 938 bytes
 .../ic_videocam_white_24dp.png                | Bin 0 -> 290 bytes
 .../app/src/main/res/drawable/call_button.xml |  14 +-
 .../main/res/drawable/drawer_disc_handle.xml  |  24 +-
 .../res/drawable/item_contact_selector.xml    |  27 +-
 .../res/drawable/item_generic_selector.xml    |   6 +-
 .../res/drawable/item_history_selector.xml    |  29 +-
 .../res/drawable/toggle_speaker_selector.xml  |   2 +-
 .../res/layout/activity_account_settings.xml  |  12 +-
 .../main/res/layout/activity_call_layout.xml  |  19 +-
 .../app/src/main/res/layout/activity_home.xml |  60 +-
 .../res/layout/activity_new_conversation.xml  |  16 +
 .../main/res/layout/frag_accounts_list.xml    |   6 +-
 .../src/main/res/layout/frag_audio_mgmt.xml   |   2 +-
 .../app/src/main/res/layout/frag_call.xml     | 229 ++--
 .../src/main/res/layout/frag_call_list.xml    |  50 +-
 .../src/main/res/layout/frag_contact_list.xml |  56 +-
 .../res/layout/frag_contact_list_header.xml   |  71 +-
 .../src/main/res/layout/frag_conversation.xml |  68 ++
 .../app/src/main/res/layout/frag_home.xml     |  11 +-
 .../src/main/res/layout/frag_imessaging.xml   |   2 +-
 .../src/main/res/layout/frag_menu_header.xml  |   2 +-
 .../app/src/main/res/layout/header.xml        |  27 +-
 .../app/src/main/res/layout/item_account.xml  |  10 +-
 .../src/main/res/layout/item_account_pref.xml |  12 +-
 .../main/res/layout/item_account_selected.xml |  11 +-
 .../app/src/main/res/layout/item_calllist.xml |  70 +-
 .../app/src/main/res/layout/item_codec.xml    |   6 +-
 .../app/src/main/res/layout/item_contact.xml  | 133 +--
 .../main/res/layout/item_contact_starred.xml  |  26 +-
 .../app/src/main/res/layout/item_history.xml  |  19 +-
 .../app/src/main/res/layout/item_textmsg.xml  | 155 +++
 .../app/src/main/res/menu/ac_call.xml         |   2 +-
 .../main/res/menu/conversation_actions.xml    |  15 +
 .../src/main/res/menu/newconv_option_menu.xml |   8 +
 .../app/src/main/res/values-land/dimens.xml   |  36 +
 .../src/main/res/values-sw600dp/dimens.xml    |  36 +
 .../app/src/main/res/values-v21/dimens.xml    |  37 +
 .../app/src/main/res/values-v21/styles.xml    |  13 +-
 .../app/src/main/res/values/colors.xml        |  30 +-
 .../app/src/main/res/values/dimens.xml        |   8 +-
 .../app/src/main/res/values/strings.xml       |   8 +-
 .../app/src/main/res/values/styles.xml        |  37 +-
 ring-android/build.gradle                     |   2 +-
 .../gradle/wrapper/gradle-wrapper.properties  |   4 +-
 ring-android/project.properties               |   2 +-
 ring-android/ring-android.iml                 |   4 +-
 181 files changed, 5258 insertions(+), 4262 deletions(-)
 delete mode 100644 ring-android/app/src/main/java/cx/ring/adapters/DiscussArrayAdapter.java
 create mode 100644 ring-android/app/src/main/java/cx/ring/client/ConversationActivity.java
 create mode 100644 ring-android/app/src/main/java/cx/ring/client/NewConversationActivity.java
 delete mode 100644 ring-android/app/src/main/java/cx/ring/fragments/AccountWrapperFragment.java
 delete mode 100644 ring-android/app/src/main/java/cx/ring/fragments/IMFragment.java
 create mode 100644 ring-android/app/src/main/java/cx/ring/history/HistoryText.java
 create mode 100644 ring-android/app/src/main/java/cx/ring/model/Conversation.java
 delete mode 100644 ring-android/app/src/main/java/cx/ring/model/SipMessage.java
 rename ring-android/app/src/main/java/cx/ring/model/{SipMessage.aidl => TextMessage.aidl} (52%)
 create mode 100644 ring-android/app/src/main/java/cx/ring/model/TextMessage.java
 create mode 100644 ring-android/app/src/main/java/cx/ring/service/LocalService.java
 create mode 100644 ring-android/app/src/main/java/cx/ring/utils/Utilities.java
 delete mode 100644 ring-android/app/src/main/java/cx/ring/views/SwipeListViewTouchListener.java
 delete mode 100644 ring-android/app/src/main/java/cx/ring/views/stickylistheaders/AdapterWrapper.java
 delete mode 100644 ring-android/app/src/main/java/cx/ring/views/stickylistheaders/ApiLevelTooLowException.java
 delete mode 100644 ring-android/app/src/main/java/cx/ring/views/stickylistheaders/CheckableWrapperView.java
 delete mode 100644 ring-android/app/src/main/java/cx/ring/views/stickylistheaders/SectionIndexerAdapterWrapper.java
 delete mode 100644 ring-android/app/src/main/java/cx/ring/views/stickylistheaders/StickyListHeadersAdapter.java
 delete mode 100644 ring-android/app/src/main/java/cx/ring/views/stickylistheaders/StickyListHeadersListView.java
 delete mode 100644 ring-android/app/src/main/java/cx/ring/views/stickylistheaders/WrapperView.java
 delete mode 100644 ring-android/app/src/main/java/cx/ring/views/stickylistheaders/WrapperViewList.java
 delete mode 100644 ring-android/app/src/main/res/drawable-hdpi/ic_action_end_call.png
 create mode 100644 ring-android/app/src/main/res/drawable-hdpi/ic_call_end_black_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-hdpi/ic_call_end_black_36dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-hdpi/ic_call_end_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-hdpi/ic_call_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-hdpi/ic_chat_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-hdpi/ic_lock_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-hdpi/ic_send_black_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-hdpi/ic_share_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-hdpi/ic_videocam_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-ldrtl-hdpi/ic_send_black_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-ldrtl-mdpi/ic_send_black_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-ldrtl-xhdpi/ic_send_black_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-ldrtl-xxhdpi/ic_send_black_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-ldrtl-xxxhdpi/ic_send_black_24dp.png
 delete mode 100644 ring-android/app/src/main/res/drawable-mdpi/ic_action_end_call.png
 create mode 100644 ring-android/app/src/main/res/drawable-mdpi/ic_call_end_black_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-mdpi/ic_call_end_black_36dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-mdpi/ic_call_end_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-mdpi/ic_call_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-mdpi/ic_chat_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-mdpi/ic_lock_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-mdpi/ic_send_black_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-mdpi/ic_share_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-mdpi/ic_videocam_white_24dp.png
 delete mode 100644 ring-android/app/src/main/res/drawable-xhdpi/ic_action_end_call.png
 create mode 100644 ring-android/app/src/main/res/drawable-xhdpi/ic_call_end_black_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xhdpi/ic_call_end_black_36dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xhdpi/ic_call_end_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xhdpi/ic_call_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xhdpi/ic_chat_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xhdpi/ic_lock_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xhdpi/ic_send_black_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xhdpi/ic_share_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xhdpi/ic_videocam_white_24dp.png
 delete mode 100644 ring-android/app/src/main/res/drawable-xxhdpi/ic_action_end_call.png
 create mode 100644 ring-android/app/src/main/res/drawable-xxhdpi/ic_call_end_black_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xxhdpi/ic_call_end_black_36dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xxhdpi/ic_call_end_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xxhdpi/ic_call_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xxhdpi/ic_chat_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xxhdpi/ic_lock_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xxhdpi/ic_send_black_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xxhdpi/ic_share_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xxhdpi/ic_videocam_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xxxhdpi/ic_call_end_black_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xxxhdpi/ic_call_end_black_36dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xxxhdpi/ic_call_end_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xxxhdpi/ic_call_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xxxhdpi/ic_chat_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xxxhdpi/ic_lock_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xxxhdpi/ic_send_black_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xxxhdpi/ic_share_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/drawable-xxxhdpi/ic_videocam_white_24dp.png
 create mode 100644 ring-android/app/src/main/res/layout/activity_new_conversation.xml
 create mode 100644 ring-android/app/src/main/res/layout/frag_conversation.xml
 create mode 100644 ring-android/app/src/main/res/layout/item_textmsg.xml
 create mode 100644 ring-android/app/src/main/res/menu/conversation_actions.xml
 create mode 100644 ring-android/app/src/main/res/menu/newconv_option_menu.xml
 create mode 100644 ring-android/app/src/main/res/values-land/dimens.xml
 create mode 100644 ring-android/app/src/main/res/values-sw600dp/dimens.xml
 create mode 100644 ring-android/app/src/main/res/values-v21/dimens.xml

diff --git a/compile.sh b/compile.sh
index 137f2c8f2..f2913d1e5 100755
--- a/compile.sh
+++ b/compile.sh
@@ -122,7 +122,7 @@ case "$REL" in
         if [ "${HAVE_64}" = 1 ];then
             ANDROID_API=android-21
         else
-            ANDROID_API=android-15
+            ANDROID_API=android-16
         fi
         CXXSTL="/"${GCCVER}
     ;;
@@ -131,7 +131,7 @@ case "$REL" in
             echo "You need the NDKv10 or later for 64 bits build"
             exit 1
         fi
-        ANDROID_API=android-15
+        ANDROID_API=android-16
         CXXSTL="/"${GCCVER}
     ;;
     7|8|*)
@@ -174,7 +174,7 @@ ANDROID_PATH="`pwd`"
 if [ "$FETCH" = 1 ]
 then
     # 1/ dring
-    TESTED_HASH=0012eab6f3bbc2df4461b85df788b86be1299f11
+    TESTED_HASH=6f868d66377a2305120986ce79cc03411080d196
     if [ ! -d "ring-daemon" ]; then
         echo "ring daemon source not found, cloning"
         git clone https://gerrit-ring.savoirfairelinux.com/ring-daemon.git
@@ -326,8 +326,8 @@ else
     RELEASE=0
 fi
 
-echo "EXTRA_CFLAGS= -g ${EXTRA_CFLAGS}" >> config.mak
-echo "EXTRA_CXXFLAGS= -g ${EXTRA_CXXFLAGS}" >> config.mak
+echo "EXTRA_CFLAGS= -g -fpic ${EXTRA_CFLAGS}" >> config.mak
+echo "EXTRA_CXXFLAGS= -g -fpic ${EXTRA_CXXFLAGS}" >> config.mak
 echo "EXTRA_LDFLAGS= ${EXTRA_LDFLAGS}" >> config.mak
 export RING_EXTRA_CFLAGS="${EXTRA_CFLAGS}"
 export RING_EXTRA_CXXFLAGS="${EXTRA_CXXFLAGS}"
@@ -413,7 +413,7 @@ cd ../..
 
 echo "Building Ring for Android ${PWD}" 
 make $CLEAN
-make -j1 TARGET_TUPLE=$TARGET_TUPLE PLATFORM_SHORT_ARCH=$PLATFORM_SHORT_ARCH CXXSTL=$CXXSTL RELEASE=$RELEASE $TARGET
+ANDROID_ABI="${ANDROID_ABI}" make -j1 TARGET_TUPLE=$TARGET_TUPLE PLATFORM_SHORT_ARCH=$PLATFORM_SHORT_ARCH CXXSTL=$CXXSTL RELEASE=$RELEASE $TARGET
 
 #
 # Exporting a environment script with all the necessary variables
diff --git a/configure.sh b/configure.sh
index ad3ee46d4..6fd1d3234 100755
--- a/configure.sh
+++ b/configure.sh
@@ -18,7 +18,7 @@ fi
 
 RING_SOURCEDIR=`cd ..; pwd`
 
-CFLAGS="-g -O2 -fstrict-aliasing -funsafe-math-optimizations"
+CFLAGS="-fpic -g -O2 -fstrict-aliasing -funsafe-math-optimizations"
 if [ -n "$HAVE_ARM" -a ! -n "$HAVE_64" ]; then
     CFLAGS="${CFLAGS} -mlong-calls"
 fi
diff --git a/ring-android/.idea/misc.xml b/ring-android/.idea/misc.xml
index 70b496f78..d7bb3975f 100644
--- a/ring-android/.idea/misc.xml
+++ b/ring-android/.idea/misc.xml
@@ -3,7 +3,31 @@
   <component name="EntryPointsManager">
     <entry_points version="2.0" />
   </component>
-  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="false" assert-keyword="true" jdk-15="true" project-jdk-name="Android API 22 Platform" project-jdk-type="Android SDK">
+  <component name="NullableNotNullManager">
+    <option name="myDefaultNullable" value="android.support.annotation.Nullable" />
+    <option name="myDefaultNotNull" value="android.support.annotation.NonNull" />
+    <option name="myNullables">
+      <value>
+        <list size="4">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.Nullable" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nullable" />
+          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.Nullable" />
+          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.Nullable" />
+        </list>
+      </value>
+    </option>
+    <option name="myNotNulls">
+      <value>
+        <list size="4">
+          <item index="0" class="java.lang.String" itemvalue="org.jetbrains.annotations.NotNull" />
+          <item index="1" class="java.lang.String" itemvalue="javax.annotation.Nonnull" />
+          <item index="2" class="java.lang.String" itemvalue="edu.umd.cs.findbugs.annotations.NonNull" />
+          <item index="3" class="java.lang.String" itemvalue="android.support.annotation.NonNull" />
+        </list>
+      </value>
+    </option>
+  </component>
+  <component name="ProjectRootManager" version="2" languageLevel="JDK_1_7" default="false" assert-keyword="true" jdk-15="true" project-jdk-name="1.7" project-jdk-type="JavaSDK">
     <output url="file://$PROJECT_DIR$/out" />
   </component>
 </project>
\ No newline at end of file
diff --git a/ring-android/app/app.iml b/ring-android/app/app.iml
index ece991d93..3502718a0 100644
--- a/ring-android/app/app.iml
+++ b/ring-android/app/app.iml
@@ -12,10 +12,12 @@
         <option name="SELECTED_TEST_ARTIFACT" value="_android_test_" />
         <option name="ASSEMBLE_TASK_NAME" value="assembleDebug" />
         <option name="COMPILE_JAVA_TASK_NAME" value="compileDebugSources" />
-        <option name="SOURCE_GEN_TASK_NAME" value="generateDebugSources" />
         <option name="ASSEMBLE_TEST_TASK_NAME" value="assembleDebugAndroidTest" />
         <option name="COMPILE_JAVA_TEST_TASK_NAME" value="compileDebugAndroidTestSources" />
-        <option name="TEST_SOURCE_GEN_TASK_NAME" value="generateDebugAndroidTestSources" />
+        <afterSyncTasks>
+          <task>generateDebugAndroidTestSources</task>
+          <task>generateDebugSources</task>
+        </afterSyncTasks>
         <option name="ALLOW_USER_CONFIGURATION" value="false" />
         <option name="MANIFEST_FILE_RELATIVE_PATH" value="/src/main/AndroidManifest.xml" />
         <option name="RES_FOLDER_RELATIVE_PATH" value="/src/main/res" />
@@ -24,7 +26,7 @@
       </configuration>
     </facet>
   </component>
-  <component name="NewModuleRootManager" inherit-compiler-output="false">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="false">
     <output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
     <output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
     <exclude-output />
@@ -34,13 +36,13 @@
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/debug" isTestSource="false" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/debug" isTestSource="false" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/debug" type="java-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/debug" type="java-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/debug" type="java-resource" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/r/androidTest/debug" isTestSource="true" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/aidl/androidTest/debug" isTestSource="true" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/buildConfig/androidTest/debug" isTestSource="true" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/source/rs/androidTest/debug" isTestSource="true" generated="true" />
       <sourceFolder url="file://$MODULE_DIR$/build/generated/res/rs/androidTest/debug" type="java-test-resource" />
-      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/generated/androidTest/debug" type="java-test-resource" />
+      <sourceFolder url="file://$MODULE_DIR$/build/generated/res/resValues/androidTest/debug" type="java-test-resource" />
       <sourceFolder url="file://$MODULE_DIR$/build-types/debug/res" type="java-resource" />
       <sourceFolder url="file://$MODULE_DIR$/build-types/debug/resources" type="java-resource" />
       <sourceFolder url="file://$MODULE_DIR$/build-types/debug/assets" type="java-resource" />
@@ -67,11 +69,12 @@
       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dependency-cache" />
       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex" />
       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/dex-cache" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/22.2.0/jars" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/design/22.2.0/jars" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v13/22.2.0/jars" />
-      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/22.2.0/jars" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/appcompat-v7/23.0.1/jars" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/design/23.0.1/jars" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v13/23.0.1/jars" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.android.support/support-v4/23.0.1/jars" />
       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/com.astuetz/pagerslidingtabstrip/1.0.1/jars" />
+      <excludeFolder url="file://$MODULE_DIR$/build/intermediates/exploded-aar/se.emilsjolander/stickylistheaders/2.7.0/jars" />
       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/incremental" />
       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/jacoco" />
       <excludeFolder url="file://$MODULE_DIR$/build/intermediates/javaResources" />
@@ -87,16 +90,18 @@
       <excludeFolder url="file://$MODULE_DIR$/build/outputs" />
       <excludeFolder url="file://$MODULE_DIR$/build/tmp" />
     </content>
-    <orderEntry type="jdk" jdkName="Android API 22 Platform" jdkType="Android SDK" />
+    <orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
     <orderEntry type="sourceFolder" forTests="false" />
     <orderEntry type="library" exported="" name="ormlite-android-4.48" level="project" />
+    <orderEntry type="library" exported="" name="libphonenumber-7.0.11" level="project" />
     <orderEntry type="library" exported="" name="pagerslidingtabstrip-1.0.1" level="project" />
     <orderEntry type="library" exported="" name="ormlite-core-4.48" level="project" />
-    <orderEntry type="library" exported="" name="robotium-solo-5.0.1" level="project" />
-    <orderEntry type="library" exported="" name="support-annotations-22.2.0" level="project" />
-    <orderEntry type="library" exported="" name="support-v13-22.2.0" level="project" />
-    <orderEntry type="library" exported="" name="support-v4-22.2.0" level="project" />
-    <orderEntry type="library" exported="" name="design-22.2.0" level="project" />
-    <orderEntry type="library" exported="" name="appcompat-v7-22.2.0" level="project" />
+    <orderEntry type="library" exported="" name="support-v13-23.0.1" level="project" />
+    <orderEntry type="library" exported="" name="stickylistheaders-2.7.0" level="project" />
+    <orderEntry type="library" exported="" name="support-v4-23.0.1" level="project" />
+    <orderEntry type="library" exported="" name="robotium-solo-5.4.1" level="project" />
+    <orderEntry type="library" exported="" name="design-23.0.1" level="project" />
+    <orderEntry type="library" exported="" name="appcompat-v7-23.0.1" level="project" />
+    <orderEntry type="library" exported="" name="support-annotations-23.0.1" level="project" />
   </component>
 </module>
\ No newline at end of file
diff --git a/ring-android/app/build.gradle b/ring-android/app/build.gradle
index e1bcbff06..2ca1c1988 100644
--- a/ring-android/app/build.gradle
+++ b/ring-android/app/build.gradle
@@ -1,18 +1,20 @@
 apply plugin: 'com.android.application'
 
 dependencies {
-    compile fileTree(dir: 'libs', include: '*.jar')
+    compile fileTree(include: '*.jar', dir: 'libs')
     compile 'com.j256.ormlite:ormlite-core:4.48'
     compile 'com.j256.ormlite:ormlite-android:4.48'
-    compile "com.android.support:support-v13:22.2.0"
-    compile 'com.android.support:design:22.2.0'
+    compile 'com.android.support:support-v13:23.0.+'
+    compile 'com.android.support:design:23.0.+'
     compile 'com.jayway.android.robotium:robotium-solo:5.4.1'
     compile 'com.astuetz:pagerslidingtabstrip:1.0.1'
+    compile 'com.googlecode.libphonenumber:libphonenumber:7.0.11'
+    compile 'se.emilsjolander:stickylistheaders:2.7.+'
 }
 
 android {
-    compileSdkVersion 22
-    buildToolsVersion "22.0.1"
+    compileSdkVersion 23
+    buildToolsVersion "23.0.1"
 
     sourceSets {
         main {
@@ -33,4 +35,8 @@ android {
         debug.setRoot('build-types/debug')
         release.setRoot('build-types/release')
     }
+    compileOptions {
+        sourceCompatibility JavaVersion.VERSION_1_7
+        targetCompatibility JavaVersion.VERSION_1_7
+    }
 }
\ No newline at end of file
diff --git a/ring-android/app/src/main/AndroidManifest.xml b/ring-android/app/src/main/AndroidManifest.xml
index ceb3bd83e..321aa6848 100644
--- a/ring-android/app/src/main/AndroidManifest.xml
+++ b/ring-android/app/src/main/AndroidManifest.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="utf-8"?>
 <!--
-Copyright (C) 2004-2014 Savoir-Faire Linux Inc.
+Copyright (C) 2004-2015 Savoir-Faire Linux Inc.
                                                                     
 Author: 	Alexandre Lision <alexandre.lision@savoirfairelinux.com>
 			Adrien Beraud <adrien.beraud@gmail.com>                     
@@ -36,6 +36,10 @@ as that of the covered work.
     android:versionCode="14"
     android:versionName="2.0.0" >
 
+    <uses-sdk
+        android:minSdkVersion="16"
+        android:targetSdkVersion="23" />
+
     <supports-screens
         android:anyDensity="true"
         android:largeScreens="true"
@@ -43,10 +47,6 @@ as that of the covered work.
         android:smallScreens="true"
         android:xlargeScreens="true" />
 
-    <uses-sdk
-        android:minSdkVersion="15"
-        android:targetSdkVersion="22" />
-
     <uses-permission android:name="android.permission.INTERNET" />
     <uses-permission android:name="android.permission.RECORD_AUDIO" />
     <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" />
@@ -67,6 +67,8 @@ as that of the covered work.
     <uses-permission android:name="android.permission.WAKE_LOCK" />
     <uses-permission android:name="android.permission.READ_LOGS" />
     <uses-permission android:name="android.permission.USE_SIP" />
+    <uses-permission android:name="android.permission.GET_TASKS" />
+    <uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
 
     <uses-feature
         android:name="android.hardware.wifi"
@@ -89,7 +91,7 @@ as that of the covered work.
         android:icon="@drawable/ic_launcher"
         android:label="@string/app_name" >
         <activity
-            android:name="cx.ring.client.HomeActivity"
+            android:name=".client.HomeActivity"
             android:label="@string/title_activity_sflphone_home"
             android:screenOrientation="portrait"
             android:theme="@style/AppThemeWithOverlay"
@@ -101,40 +103,74 @@ as that of the covered work.
             </intent-filter>
         </activity>
         <activity
-            android:name="cx.ring.client.AccountWizard"
+            android:name=".client.AccountWizard"
             android:screenOrientation="portrait"
             android:theme="@style/AppThemeWithoutOverlay" >
             <meta-data
                 android:name="android.support.PARENT_ACTIVITY"
-                android:value="cx.ring.client.AccountPreferenceActivity" />
+                android:value="cx.ring.client.AccountEditionActivity" />
         </activity>
         <activity
-            android:name="cx.ring.client.AccountEditionActivity"
+            android:name=".client.AccountEditionActivity"
             android:label="@string/app_name"
             android:screenOrientation="portrait"
             android:theme="@style/AppThemeWithoutOverlay" />
         <activity
-            android:name="cx.ring.client.DetailHistoryActivity"
+            android:name=".client.DetailHistoryActivity"
             android:label="@string/app_name"
             android:screenOrientation="portrait"
             android:theme="@style/AppThemeWithoutOverlay" />
+
+        <activity android:name=".client.NewConversationActivity" android:theme="@style/AppThemeWithoutOverlay" android:label="@string/app_name" >
+        </activity>
+
         <activity
-            android:name="cx.ring.client.CallActivity"
+            android:name=".client.CallActivity"
             android:label="@string/app_name"
             android:screenOrientation="portrait"
             android:theme="@style/AppThemeWithoutOverlay"
             android:windowSoftInputMode="adjustPan" >
             <intent-filter>
                 <action android:name="android.intent.action.CALL_PRIVILEGED" />
+                <action android:name="android.intent.action.CALL" />
+                <action android:name="android.intent.action.DIAL" />
+                <action android:name="android.intent.action.VIEW" />
 
                 <category android:name="android.intent.category.DEFAULT" />
 
                 <data android:scheme="tel" />
+                <data android:scheme="ring" />
+                <data android:scheme="sip" />
+            </intent-filter>
+            <intent-filter>
+                <action android:name="android.intent.action.CALL" />
+                <action android:name="android.intent.action.DIAL" />
+
+                <category android:name="android.intent.category.DEFAULT" />
+
+                <data android:mimeType="vnd.android.cursor.item/phone" />
+                <data android:mimeType="vnd.android.cursor.item/phone_v2" />
+                <data android:mimeType="vnd.android.cursor.item/person" />
             </intent-filter>
         </activity>
+        <activity
+            android:name=".client.ConversationActivity"
+            android:label="@string/app_name"
+            android:parentActivityName=".client.HomeActivity"
+            android:screenOrientation="portrait"
+            android:theme="@style/AppThemeWithoutOverlay"
+            android:windowSoftInputMode="adjustResize" >
+        </activity>
 
         <service
-            android:name="cx.ring.service.SipService"
+            android:name=".service.LocalService"
+            android:exported="false" >
+            <intent-filter>
+                <action android:name=".service.LocalService" />
+            </intent-filter>
+        </service>
+        <service
+            android:name=".service.SipService"
             android:exported="false" >
             <intent-filter>
                 <action android:name=".service.SipService" />
@@ -142,4 +178,4 @@ as that of the covered work.
         </service>
     </application>
 
-</manifest>
\ No newline at end of file
+</manifest>
diff --git a/ring-android/app/src/main/java/cx/ring/adapters/AccountSelectionAdapter.java b/ring-android/app/src/main/java/cx/ring/adapters/AccountSelectionAdapter.java
index 003f34737..6a2ab3172 100644
--- a/ring-android/app/src/main/java/cx/ring/adapters/AccountSelectionAdapter.java
+++ b/ring-android/app/src/main/java/cx/ring/adapters/AccountSelectionAdapter.java
@@ -32,12 +32,11 @@
 package cx.ring.adapters;
 
 import java.io.File;
-import java.util.ArrayList;
+import java.util.List;
 
 import cx.ring.R;
 
 import android.content.Context;
-import android.graphics.Color;
 import android.util.Log;
 import android.view.LayoutInflater;
 import android.view.View;
@@ -51,12 +50,12 @@ public class AccountSelectionAdapter extends BaseAdapter {
 
     private static final String TAG = AccountSelectionAdapter.class.getSimpleName();
 
-    ArrayList<Account> accounts;
+    List<Account> accounts;
     Context mContext;
     int selectedAccount = -1;
     static final String DEFAULT_ACCOUNT_ID = "IP2IP";
 
-    public AccountSelectionAdapter(Context cont, ArrayList<Account> newList) {
+    public AccountSelectionAdapter(Context cont, List<Account> newList) {
         super();
         accounts = newList;
         mContext = cont;
@@ -133,7 +132,11 @@ public class AccountSelectionAdapter extends BaseAdapter {
 
     private void updateAccountView(AccountView entryView, Account acc) {
         entryView.alias.setText(acc.getAlias());
-        entryView.host.setText(acc.getHost()/*+ " - " + acc.getRegistered_state()*/);
+        if (acc.isRing()) {
+            entryView.host.setText(acc.getBasicDetails().getUsername());
+        } else {
+            entryView.host.setText(acc.getBasicDetails().getUsername() + "@" + acc.getBasicDetails().getHostname());
+        }
         entryView.error.setVisibility(acc.isRegistered() ? View.GONE : View.VISIBLE);
     }
 
@@ -171,7 +174,13 @@ public class AccountSelectionAdapter extends BaseAdapter {
 
     }
 
-    public void addAll(ArrayList<Account> results) {
+    public void addAll(List<Account> results) {
+        accounts.addAll(results);
+        notifyDataSetChanged();
+    }
+
+    public void replaceAll(List<Account> results) {
+        accounts.clear();
         accounts.addAll(results);
         notifyDataSetChanged();
     }
@@ -184,7 +193,7 @@ public class AccountSelectionAdapter extends BaseAdapter {
 
         for (Account a : accounts) {
             if (a.getAccountID().contentEquals(accoundID)) {
-                a.setRegistered_state(state, code);
+                a.setRegistrationState(state, code);
                 Log.i(TAG, "updateAccount " + accoundID + " " + code);
                 notifyDataSetChanged();
                 return;
diff --git a/ring-android/app/src/main/java/cx/ring/adapters/ContactPictureTask.java b/ring-android/app/src/main/java/cx/ring/adapters/ContactPictureTask.java
index 5596a0636..0377dc7f5 100644
--- a/ring-android/app/src/main/java/cx/ring/adapters/ContactPictureTask.java
+++ b/ring-android/app/src/main/java/cx/ring/adapters/ContactPictureTask.java
@@ -32,6 +32,8 @@
 package cx.ring.adapters;
 
 import java.io.InputStream;
+import java.lang.ref.WeakReference;
+import java.util.ArrayList;
 
 import cx.ring.R;
 import cx.ring.model.CallContact;
@@ -51,20 +53,55 @@ import android.graphics.RectF;
 import android.graphics.Shader;
 import android.net.Uri;
 import android.provider.ContactsContract;
+import android.util.Log;
+import android.util.LruCache;
+import android.view.animation.AnimationUtils;
 import android.widget.ImageView;
 
 public class ContactPictureTask implements Runnable {
-    private ImageView view;
-    private CallContact contact;
+    static final String TAG = ContactPictureTask.class.getSimpleName();
+
+    private final WeakReference<ImageView> view;
+    private final CallContact contact;
+
     private ContentResolver cr;
-    private static int PADDING = 5;
+    private final Resources res;
+    //private PictureLoadedCallback cb;
+    private final ArrayList<PictureLoadedCallback> callbacks = new ArrayList<>(1);
+
+    //int w = photo_bmp.getWidth(), h = photo_bmp.getHeight();
+    private final int vw, vh;
+
+    public void addCallback(PictureLoadedCallback cb) {
+        //this.cb = callback;
+        synchronized (callbacks) {
+            view.clear();
+            callbacks.add(cb);
+        }
+    }
 
     // private final String TAG = ContactPictureTask.class.getSimpleName();
 
+    public interface PictureLoadedCallback {
+        void onPictureLoaded(Bitmap bmp);
+    };
+
     public ContactPictureTask(Context context, ImageView element, CallContact item) {
         contact = item;
         cr = context.getContentResolver();
-        view = element;
+        res = context.getResources();
+        view = new WeakReference<>(element);
+        vw = element.getWidth();
+        vh = element.getHeight();
+    }
+    public ContactPictureTask(Context context, ImageView element, CallContact item, PictureLoadedCallback cb) {
+        contact = item;
+        cr = context.getContentResolver();
+        res = context.getResources();
+        vw = element.getWidth();
+        vh = element.getHeight();
+        view = new WeakReference<>(element);
+        addCallback(cb);
     }
 
     public static Bitmap loadContactPhoto(ContentResolver cr, long id) {
@@ -80,17 +117,27 @@ public class ContactPictureTask implements Runnable {
 
     @Override
     public void run() {
+        Log.i(TAG, "ContactPictureTask run " + contact.getId());
+
         Bitmap photo_bmp;
         try {
             photo_bmp = loadContactPhoto(cr, contact.getId());
         } catch (IllegalArgumentException e) {
             photo_bmp = null;
         }
+        cr = null;
+
+        /*final ImageView v = view.get();
+        view.clear();
+        if (v == null) {
+            Log.i(TAG, "ContactPictureTask cancelling: view is now null");
+            return;
+        }*/
 
-        int dpiPadding = (int) (PADDING * view.getResources().getDisplayMetrics().density);
+        //int dpiPadding = (int) (PADDING * view.getResources().getDisplayMetrics().density);
 
         if (photo_bmp == null) {
-            photo_bmp = decodeSampledBitmapFromResource(view.getResources(), R.drawable.ic_contact_picture, view.getWidth(), view.getHeight());
+            photo_bmp = decodeSampledBitmapFromResource(res, R.drawable.ic_contact_picture, vw, vh);
         }
 
         int w = photo_bmp.getWidth(), h = photo_bmp.getHeight();
@@ -119,14 +166,41 @@ public class ContactPictureTask implements Runnable {
         // internalCanvas.drawOval(new RectF(PADDING, PADDING, externalBMP.getWidth() - dpiPadding, externalBMP.getHeight() - dpiPadding), paint);
         internalCanvas.drawOval(new RectF(0, 0, externalBMP.getWidth(), externalBMP.getHeight()), paint);
 
-        view.post(new Runnable() {
+        photo_bmp.recycle();
+
+        contact.setPhoto(externalBMP);
+        //v.invalidate();
+        synchronized (callbacks) {
+            final ImageView v = view.get();
+            view.clear();
+            if (v == null) {
+                for (PictureLoadedCallback cb : callbacks) {
+                    cb.onPictureLoaded(externalBMP);
+                }
+            } else {
+                v.post(new Runnable() {
+                    @Override
+                    public void run() {
+                        v.setImageBitmap(externalBMP);
+                    }
+                });
+            }
+            callbacks.clear();
+        }
+
+        /*v.post(new Runnable() {
             @Override
             public void run() {
-                view.setImageBitmap(externalBMP);
+                Log.w(TAG, "ContactPictureTask END " + contact.getId());
+                //v.setImageBitmap(externalBMP);
                 contact.setPhoto(externalBMP);
-                view.invalidate();
+                //v.invalidate();
+                for (PictureLoadedCallback cb : callbacks) {
+                    cb.onPictureLoaded(externalBMP);
+                }
+                callbacks.clear();
             }
-        });
+        });*/
     }
 
     public static Bitmap decodeSampledBitmapFromResource(Resources res, int resId, int reqWidth, int reqHeight) {
diff --git a/ring-android/app/src/main/java/cx/ring/adapters/ContactsAdapter.java b/ring-android/app/src/main/java/cx/ring/adapters/ContactsAdapter.java
index de47d94b4..1754589c0 100644
--- a/ring-android/app/src/main/java/cx/ring/adapters/ContactsAdapter.java
+++ b/ring-android/app/src/main/java/cx/ring/adapters/ContactsAdapter.java
@@ -33,28 +33,30 @@ package cx.ring.adapters;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.HashMap;
 import java.util.concurrent.ExecutorService;
 import java.util.concurrent.Executors;
 
 import cx.ring.R;
 import cx.ring.fragments.ContactListFragment;
 import cx.ring.model.CallContact;
-import cx.ring.views.stickylistheaders.StickyListHeadersAdapter;
+import se.emilsjolander.stickylistheaders.StickyListHeadersAdapter;
 
 import android.content.Context;
+import android.graphics.Bitmap;
+import android.util.LruCache;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.OnClickListener;
 import android.view.ViewGroup;
+import android.view.animation.AnimationUtils;
 import android.widget.BaseAdapter;
 import android.widget.ImageButton;
 import android.widget.ImageView;
 import android.widget.SectionIndexer;
 import android.widget.TextView;
-import android.widget.Toast;
 
 public class ContactsAdapter extends BaseAdapter implements StickyListHeadersAdapter, SectionIndexer {
-
     private ExecutorService infos_fetcher = Executors.newCachedThreadPool();
     Context mContext;
 
@@ -64,30 +66,41 @@ public class ContactsAdapter extends BaseAdapter implements StickyListHeadersAda
     WeakReference<ContactListFragment> parent;
     private LayoutInflater mInflater;
 
-    // private static final String TAG = ContactsAdapter.class.getSimpleName();
+    final private LruCache<Long, Bitmap> mMemoryCache;
+    final private HashMap<Long, WeakReference<ContactPictureTask>> running_tasks = new HashMap<>();
+
+    private static final String TAG = ContactsAdapter.class.getSimpleName();
 
     public ContactsAdapter(ContactListFragment contactListFragment) {
         super();
         mContext = contactListFragment.getActivity();
         mInflater = LayoutInflater.from(mContext);
-        parent = new WeakReference<ContactListFragment>(contactListFragment);
-        mContacts = new ArrayList<CallContact>();
+        parent = new WeakReference<>(contactListFragment);
+        mContacts = new ArrayList<>();
         mSectionIndices = getSectionIndices();
         mSectionLetters = getSectionLetters();
+        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
+        final int cacheSize = maxMemory / 8;
+        mMemoryCache = new LruCache<Long, Bitmap>(cacheSize){
+            @Override
+            protected int sizeOf(Long key, Bitmap bitmap) {
+                return bitmap.getByteCount() / 1024;
+            }
+        };
     }
 
     public static final int TYPE_HEADER = 0;
     public static final int TYPE_CONTACT = 1;
 
     private int[] getSectionIndices() {
-        ArrayList<Integer> sectionIndices = new ArrayList<Integer>();
+        ArrayList<Integer> sectionIndices = new ArrayList<>();
         if (mContacts.isEmpty())
             return new int[0];
-        char lastFirstChar = mContacts.get(0).getmDisplayName().charAt(0);
+        char lastFirstChar = mContacts.get(0).getDisplayName().charAt(0);
         sectionIndices.add(0);
         for (int i = 1; i < mContacts.size(); i++) {
-            if (mContacts.get(i).getmDisplayName().charAt(0) != lastFirstChar) {
-                lastFirstChar = mContacts.get(i).getmDisplayName().charAt(0);
+            if (mContacts.get(i).getDisplayName().charAt(0) != lastFirstChar) {
+                lastFirstChar = mContacts.get(i).getDisplayName().charAt(0);
                 sectionIndices.add(i);
             }
         }
@@ -101,26 +114,27 @@ public class ContactsAdapter extends BaseAdapter implements StickyListHeadersAda
     private Character[] getSectionLetters() {
         Character[] letters = new Character[mSectionIndices.length];
         for (int i = 0; i < mSectionIndices.length; i++) {
-            letters[i] = mContacts.get(mSectionIndices[i]).getmDisplayName().charAt(0);
+            letters[i] = mContacts.get(mSectionIndices[i]).getDisplayName().charAt(0);
         }
         return letters;
     }
 
     @Override
-    public View getView(int position, View convertView, ViewGroup root) {
+    public View getView(final int position, View convertView, ViewGroup root) {
         ContactView entryView;
 
         if (convertView == null) {
             convertView = mInflater.inflate(R.layout.item_contact, null);
 
             entryView = new ContactView();
-            entryView.quick_starred = (ImageButton) convertView.findViewById(R.id.quick_starred);
+            /*entryView.quick_starred = (ImageButton) convertView.findViewById(R.id.quick_starred);
             entryView.quick_edit = (ImageButton) convertView.findViewById(R.id.quick_edit);
             entryView.quick_discard = (ImageButton) convertView.findViewById(R.id.quick_discard);
             entryView.quick_call = (ImageButton) convertView.findViewById(R.id.quick_call);
-            entryView.quick_msg = (ImageButton) convertView.findViewById(R.id.quick_message);
+            entryView.quick_msg = (ImageButton) convertView.findViewById(R.id.quick_message);*/
             entryView.photo = (ImageView) convertView.findViewById(R.id.photo);
             entryView.display_name = (TextView) convertView.findViewById(R.id.display_name);
+            entryView.position = -1;
             convertView.setTag(entryView);
         } else {
             entryView = (ContactView) convertView.getTag();
@@ -128,14 +142,56 @@ public class ContactsAdapter extends BaseAdapter implements StickyListHeadersAda
 
         final CallContact item = mContacts.get(position);
 
-        entryView.display_name.setText(item.getmDisplayName());
+        if (entryView.position == position || (entryView.contact != null && entryView.contact.get() != null && item.getId() == entryView.contact.get().getId()))
+            return convertView;
+
+        entryView.display_name.setText(item.getDisplayName());
+        entryView.contact = new WeakReference<>(item);
+        entryView.position = position;
+        final Long cid = item.getId();
+        final Long pid = item.getPhotoId();
+        Bitmap bmp = item.getPhoto();
+        if (bmp == null) {
+            bmp = mMemoryCache.get(pid);
+            if (bmp != null) item.setPhoto(bmp);
+        }
 
-        if (item.hasPhoto()) {
-            entryView.photo.setImageBitmap(item.getPhoto());
+        if (bmp != null) {
+            entryView.photo.setImageBitmap(bmp);
         } else {
-            infos_fetcher.execute(new ContactPictureTask(mContext, entryView.photo, item));
+            entryView.photo.setImageBitmap(null);
+            final WeakReference<ContactView> wh = new WeakReference<>(entryView);
+            infos_fetcher.execute(new ContactPictureTask(mContext, entryView.photo, item, new ContactPictureTask.PictureLoadedCallback() {
+                @Override
+                public void onPictureLoaded(final Bitmap bmp) {
+                    mMemoryCache.put(pid, bmp);
+                    final ContactView fh = wh.get();
+                    if (fh == null || fh.photo.getParent() == null)
+                        return;
+                    if (fh.position == position)
+                        fh.photo.post(new Runnable() {
+                            @Override
+                            public void run() {
+                                final CallContact c = fh.contact.get();
+                                if (c.getId() == cid) {
+                                    c.setPhoto(bmp);
+                                    fh.photo.setImageBitmap(bmp);
+                                    fh.photo.startAnimation(AnimationUtils.loadAnimation(fh.photo.getContext(), R.anim.contact_fadein));
+                                }
+                            }
+                        });
+                }
+            }));
         }
 
+        convertView.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                parent.get().mCallbacks.onTextContact(item);
+            }
+        });
+
+/*
         entryView.quick_call.setOnClickListener(new OnClickListener() {
 
             @Override
@@ -182,7 +238,7 @@ public class ContactsAdapter extends BaseAdapter implements StickyListHeadersAda
         entryView.quick_edit.setClickable(false);
         entryView.quick_discard.setClickable(false);
         entryView.quick_starred.setClickable(false);
-
+*/
         return convertView;
     }
 
@@ -190,9 +246,11 @@ public class ContactsAdapter extends BaseAdapter implements StickyListHeadersAda
      * ViewHolder Pattern
      *********************/
     public class ContactView {
-        ImageButton quick_starred, quick_edit, quick_discard, quick_call, quick_msg;
+        ImageButton /*quick_starred, quick_edit, quick_discard, */quick_call, quick_msg;
         ImageView photo;
         TextView display_name;
+        WeakReference<CallContact> contact = new WeakReference<>(null);
+        int position;
     }
 
     @Override
@@ -224,7 +282,7 @@ public class ContactsAdapter extends BaseAdapter implements StickyListHeadersAda
         }
 
         // set header text as first char in name
-        char headerChar = mContacts.get(position).getmDisplayName().subSequence(0, 1).charAt(0);
+        char headerChar = mContacts.get(position).getDisplayName().subSequence(0, 1).charAt(0);
 
         holder.text.setText("" + headerChar);
 
@@ -240,7 +298,7 @@ public class ContactsAdapter extends BaseAdapter implements StickyListHeadersAda
     public long getHeaderId(int position) {
         // return the first character of the name as ID because this is what
         // headers are based upon
-        return mContacts.get(position).getmDisplayName().subSequence(0, 1).charAt(0);
+        return mContacts.get(position).getDisplayName().subSequence(0, 1).charAt(0);
     }
 
     @Override
@@ -274,14 +332,14 @@ public class ContactsAdapter extends BaseAdapter implements StickyListHeadersAda
     }
 
     public void clear() {
-        mContacts = new ArrayList<CallContact>();
+        mContacts = new ArrayList<>();
         mSectionIndices = new int[0];
         mSectionLetters = new Character[0];
         notifyDataSetChanged();
     }
-
+/*
     public void restore() {
-        mContacts = new ArrayList<CallContact>();
+        mContacts = new ArrayList<>();
         mSectionIndices = getSectionIndices();
         mSectionLetters = getSectionLetters();
         notifyDataSetChanged();
@@ -292,6 +350,13 @@ public class ContactsAdapter extends BaseAdapter implements StickyListHeadersAda
         mSectionIndices = getSectionIndices();
         mSectionLetters = getSectionLetters();
         notifyDataSetChanged();
+    }*/
+
+    public void setData(ArrayList<CallContact> contacts) {
+        mContacts = contacts;
+        mSectionIndices = getSectionIndices();
+        mSectionLetters = getSectionLetters();
+        notifyDataSetChanged();
     }
 
 }
diff --git a/ring-android/app/src/main/java/cx/ring/adapters/DiscussArrayAdapter.java b/ring-android/app/src/main/java/cx/ring/adapters/DiscussArrayAdapter.java
deleted file mode 100644
index 9cdfc411b..000000000
--- a/ring-android/app/src/main/java/cx/ring/adapters/DiscussArrayAdapter.java
+++ /dev/null
@@ -1,106 +0,0 @@
-/*
- *  Copyright (C) 2004-2014 Savoir-Faire Linux Inc.
- *
- *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  Additional permission under GNU GPL version 3 section 7:
- *
- *  If you modify this program, or any covered work, by linking or
- *  combining it with the OpenSSL project's OpenSSL library (or a
- *  modified version of that library), containing parts covered by the
- *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
- *  grants you additional permission to convey the resulting work.
- *  Corresponding Source for a non-source form of such a combination
- *  shall include the source code for the parts of OpenSSL used as well
- *  as that of the covered work.
- */
-
-package cx.ring.adapters;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import cx.ring.R;
-import cx.ring.model.SipMessage;
-
-import android.content.Context;
-import android.os.Bundle;
-import android.view.Gravity;
-import android.view.LayoutInflater;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.LinearLayout;
-import android.widget.TextView;
-
-public class DiscussArrayAdapter extends BaseAdapter {
-
-    private TextView countryName;
-    private List<SipMessage> messages = new ArrayList<SipMessage>();
-    private LinearLayout wrapper;
-    private Context mContext;
-
-    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) {
-        messages.add(object);
-        notifyDataSetChanged();
-    }
-
-    public int getCount() {
-        return this.messages.size();
-    }
-
-    public SipMessage getItem(int index) {
-        return this.messages.get(index);
-    }
-
-    public View getView(int position, View convertView, ViewGroup parent) {
-        View row = convertView;
-        if (row == null) {
-            LayoutInflater inflater = LayoutInflater.from(mContext);
-            row = inflater.inflate(R.layout.item_message, parent, false);
-        }
-
-        wrapper = (LinearLayout) row.findViewById(R.id.wrapper);
-
-        SipMessage coment = getItem(position);
-
-        countryName = (TextView) row.findViewById(R.id.comment);
-
-        countryName.setText(coment.comment);
-
-        countryName.setBackgroundResource(coment.left ? R.drawable.bubble_left_selector : R.drawable.bubble_right_selector);
-        wrapper.setGravity(coment.left ? Gravity.LEFT : Gravity.RIGHT);
-
-        return row;
-    }
-
-    @Override
-    public long getItemId(int position) {
-        return 0;
-    }
-
-}
\ No newline at end of file
diff --git a/ring-android/app/src/main/java/cx/ring/adapters/SectionsPagerAdapter.java b/ring-android/app/src/main/java/cx/ring/adapters/SectionsPagerAdapter.java
index b9b2d132f..1f3be0040 100644
--- a/ring-android/app/src/main/java/cx/ring/adapters/SectionsPagerAdapter.java
+++ b/ring-android/app/src/main/java/cx/ring/adapters/SectionsPagerAdapter.java
@@ -50,12 +50,11 @@ public class SectionsPagerAdapter extends FragmentStatePagerAdapter implements P
 
     private static final String TAG = SectionsPagerAdapter.class.getSimpleName();
     Context mContext;
-    ArrayList<Fragment> fragments;
+    private final ArrayList<Fragment> fragments = new ArrayList<>();
 
     public SectionsPagerAdapter(Context c, FragmentManager fm) {
         super(fm);
         mContext = c;
-        fragments = new ArrayList<Fragment>();
         fragments.add(new DialingFragment());
         fragments.add(new CallListFragment());
         fragments.add(new HistoryFragment());
diff --git a/ring-android/app/src/main/java/cx/ring/adapters/StarredContactsAdapter.java b/ring-android/app/src/main/java/cx/ring/adapters/StarredContactsAdapter.java
index 6690341a0..d2a4c1d66 100644
--- a/ring-android/app/src/main/java/cx/ring/adapters/StarredContactsAdapter.java
+++ b/ring-android/app/src/main/java/cx/ring/adapters/StarredContactsAdapter.java
@@ -70,6 +70,11 @@ public class StarredContactsAdapter extends BaseAdapter {
         notifyDataSetChanged();
     }
 
+    public void setData(ArrayList<CallContact> contacts) {
+        dataset = contacts;
+        notifyDataSetChanged();
+    }
+
     @Override
     public int getCount() {
         return dataset.size();
@@ -97,7 +102,7 @@ public class StarredContactsAdapter extends BaseAdapter {
 
         CallContact item = dataset.get(pos);
 
-        ((TextView) v.findViewById(R.id.display_name)).setText(item.getmDisplayName());
+        ((TextView) v.findViewById(R.id.display_name)).setText(item.getDisplayName());
         ImageView photo_view = (ImageView) v.findViewById(R.id.photo);
 
         if(item.hasPhoto()){
diff --git a/ring-android/app/src/main/java/cx/ring/client/AccountEditionActivity.java b/ring-android/app/src/main/java/cx/ring/client/AccountEditionActivity.java
index 8026bb8ae..bd93dd18a 100644
--- a/ring-android/app/src/main/java/cx/ring/client/AccountEditionActivity.java
+++ b/ring-android/app/src/main/java/cx/ring/client/AccountEditionActivity.java
@@ -37,6 +37,7 @@ import android.app.AlertDialog;
 import android.app.Fragment;
 import android.app.FragmentManager;
 import android.content.*;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.os.RemoteException;
@@ -49,26 +50,33 @@ import android.view.MenuItem;
 import cx.ring.R;
 import cx.ring.fragments.AdvancedAccountFragment;
 import cx.ring.fragments.AudioManagementFragment;
+import cx.ring.fragments.HomeFragment;
+import cx.ring.fragments.MenuFragment;
 import cx.ring.fragments.NestedSettingsFragment;
 import cx.ring.fragments.SecurityAccountFragment;
 import cx.ring.model.account.Account;
 import cx.ring.service.ISipService;
+import cx.ring.service.LocalService;
 import cx.ring.service.SipService;
 import com.astuetz.PagerSlidingTabStrip;
 import java.util.ArrayList;
 import java.util.Locale;
+import java.util.Map;
 import java.util.Observable;
 import java.util.Observer;
 
 import cx.ring.fragments.GeneralAccountFragment;
 
-public class AccountEditionActivity extends Activity implements GeneralAccountFragment.Callbacks, AudioManagementFragment.Callbacks,
+public class AccountEditionActivity extends Activity implements LocalService.Callbacks, GeneralAccountFragment.Callbacks, AudioManagementFragment.Callbacks,
         AdvancedAccountFragment.Callbacks, SecurityAccountFragment.Callbacks, NestedSettingsFragment.Callbacks {
     private static final String TAG = AccountEditionActivity.class.getSimpleName();
 
+    public static final Uri CONTENT_URI = Uri.withAppendedPath(LocalService.AUTHORITY_URI, "accounts");
+
     private boolean mBound = false;
-    private ISipService service;
-    private Account acc_selected;
+    private LocalService service;
+
+    private Account acc_selected = null;
 
     private NestedSettingsFragment toDisplay;
 
@@ -81,24 +89,35 @@ public class AccountEditionActivity extends Activity implements GeneralAccountFr
     };
 
     PreferencesPagerAdapter mPreferencesPagerAdapter;
+
     private ServiceConnection mConnection = new ServiceConnection() {
 
         @Override
-        public void onServiceConnected(ComponentName className, IBinder binder) {
-            service = ISipService.Stub.asInterface(binder);
+        public void onServiceConnected(ComponentName className, IBinder s) {
+            LocalService.LocalBinder binder = (LocalService.LocalBinder) s;
+            service = binder.getService();
             mBound = true;
 
-            ArrayList<Fragment> fragments = new ArrayList<Fragment>();
+            setContentView(R.layout.activity_account_settings);
+            getActionBar().setDisplayHomeAsUpEnabled(true);
+            String account_id = getIntent().getData().getLastPathSegment();
+            Log.i(TAG, "Service connected " + className.getClassName() + " " + getIntent().getData().toString());
+
+            acc_selected = service.getAccount(account_id);
+            acc_selected.addObserver(mAccountObserver);
+            getActionBar().setTitle(acc_selected.getAlias());
+
+            ArrayList<Fragment> fragments = new ArrayList<>();
             if (acc_selected.isIP2IP()) {
                 fragments.add(new AudioManagementFragment());
             } else {
                 fragments.add(new GeneralAccountFragment());
                 fragments.add(new AudioManagementFragment());
-				if(acc_selected.isSip())
-				{
-					fragments.add(new AdvancedAccountFragment());
-					fragments.add(new SecurityAccountFragment());
-				}
+                if(acc_selected.isSip())
+                {
+                    fragments.add(new AdvancedAccountFragment());
+                    fragments.add(new SecurityAccountFragment());
+                }
             }
 
             ViewPager mViewPager = (ViewPager) findViewById(R.id.pager);
@@ -110,33 +129,22 @@ public class AccountEditionActivity extends Activity implements GeneralAccountFr
             final PagerSlidingTabStrip strip = PagerSlidingTabStrip.class.cast(findViewById(R.id.pager_sliding_strip));
 
             strip.setViewPager(mViewPager);
-
         }
 
         @Override
         public void onServiceDisconnected(ComponentName arg0) {
-
+            acc_selected.deleteObserver(mAccountObserver);
+            mBound = false;
         }
     };
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-
-        setContentView(R.layout.activity_account_settings);
-
-        getActionBar().setDisplayHomeAsUpEnabled(true);
-
-        acc_selected = getIntent().getExtras().getParcelable("account");
-
-        acc_selected.addObserver(mAccountObserver);
-
         if (!mBound) {
-            Log.i(TAG, "onCreate: Binding service...");
-            Intent intent = new Intent(this, SipService.class);
+            Intent intent = new Intent(this, LocalService.class);
             bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
         }
-
     }
 
     @Override
@@ -206,8 +214,12 @@ public class AccountEditionActivity extends Activity implements GeneralAccountFr
 
     private void processAccount() {
         try {
-            service.setCredentials(acc_selected.getAccountID(), acc_selected.getCredentialsHashMapList());
-            service.setAccountDetails(acc_selected.getAccountID(), acc_selected.getDetails());
+            service.getRemoteService().setCredentials(acc_selected.getAccountID(), acc_selected.getCredentialsHashMapList());
+            Map<String, String> details = acc_selected.getDetails();
+            service.getRemoteService().setAccountDetails(acc_selected.getAccountID(), details);
+            Log.w(TAG, "service.setAccountDetails " + details.get("Account.hostname"));
+            getActionBar().setTitle(acc_selected.getAlias());;
+
         } catch (RemoteException e) {
             e.printStackTrace();
         }
@@ -225,7 +237,7 @@ public class AccountEditionActivity extends Activity implements GeneralAccountFr
                         bundle.putString("AccountID", acc_selected.getAccountID());
 
                         try {
-                            service.removeAccount(acc_selected.getAccountID());
+                            service.getRemoteService().removeAccount(acc_selected.getAccountID());
                         } catch (RemoteException e) {
                             e.printStackTrace();
                         }
@@ -244,6 +256,16 @@ public class AccountEditionActivity extends Activity implements GeneralAccountFr
         return alertDialog;
     }
 
+    @Override
+    public ISipService getRemoteService() {
+        return service.getRemoteService();
+    }
+
+    @Override
+    public LocalService getService() {
+        return service;
+    }
+
     public class PreferencesPagerAdapter extends FragmentStatePagerAdapter {
 
         Context mContext;
@@ -289,11 +311,6 @@ public class AccountEditionActivity extends Activity implements GeneralAccountFr
         }
     }
 
-    @Override
-    public ISipService getService() {
-        return service;
-    }
-
     @Override
     public Account getAccount() {
         return acc_selected;
diff --git a/ring-android/app/src/main/java/cx/ring/client/CallActivity.java b/ring-android/app/src/main/java/cx/ring/client/CallActivity.java
index 32682b735..c481bca87 100644
--- a/ring-android/app/src/main/java/cx/ring/client/CallActivity.java
+++ b/ring-android/app/src/main/java/cx/ring/client/CallActivity.java
@@ -33,28 +33,25 @@
 
 package cx.ring.client;
 
-import java.util.*;
-
 import android.app.Activity;
 import android.util.Log;
 import cx.ring.R;
 import cx.ring.fragments.CallFragment;
-import cx.ring.fragments.IMFragment;
+import cx.ring.model.Conversation;
+import cx.ring.model.TextMessage;
 import cx.ring.model.account.Account;
 import cx.ring.model.CallContact;
 import cx.ring.model.Conference;
 import cx.ring.model.SipCall;
-import cx.ring.model.SipMessage;
+import cx.ring.model.account.AccountDetailBasic;
 import cx.ring.service.ISipService;
-import cx.ring.service.SipService;
+import cx.ring.service.LocalService;
 import cx.ring.utils.CallProximityManager;
-import cx.ring.views.CallPaneLayout;
 
 import android.content.ComponentName;
 import android.content.Context;
 import android.content.Intent;
 import android.content.ServiceConnection;
-import android.graphics.Color;
 import android.graphics.PixelFormat;
 import android.net.Uri;
 import android.os.Bundle;
@@ -62,88 +59,37 @@ import android.os.Handler;
 import android.os.IBinder;
 import android.os.RemoteException;
 import android.os.SystemClock;
-import android.support.v4.widget.SlidingPaneLayout;
 import android.view.KeyEvent;
-import android.view.View;
 import android.view.Window;
 import android.view.WindowManager;
 
-public class CallActivity extends Activity implements IMFragment.Callbacks, CallFragment.Callbacks, CallProximityManager.ProximityDirector {
-
+public class CallActivity extends Activity implements LocalService.Callbacks, CallFragment.Callbacks, CallProximityManager.ProximityDirector {
     @SuppressWarnings("unused")
     static final String TAG = "CallActivity";
-    private ISipService mService;
-    CallPaneLayout mSlidingPaneLayout;
+    private boolean init = false;
+    private LocalService service;
 
-    IMFragment mIMFragment;
     CallFragment mCurrentCallFragment;
     private Conference mDisplayedConference;
 
     /* result code sent in case of call failure */
     public static int RESULT_FAILURE = -10;
-    private CallProximityManager mProximityManager;
+    private CallProximityManager mProximityManager = null;
 
     @Override
     protected void onCreate(Bundle savedInstanceState) {
+        Log.i(TAG, "CallActivity onCreate");
         super.onCreate(savedInstanceState);
-        setContentView(R.layout.activity_call_layout);
 
         Window w = getWindow();
         w.setFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED, WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED);
 
-        setUpSlidingPanel();
-
-        mProximityManager = new CallProximityManager(this, this);
-        mProximityManager.startTracking();
-
-        mCurrentCallFragment = new CallFragment();
-        mIMFragment = new IMFragment();
-
-        if(!checkExternalCall()) {
-            mDisplayedConference = getIntent().getParcelableExtra("conference");
-            Bundle IMBundle = new Bundle();
-            if (getIntent().getBooleanExtra("resuming", false)) {
-                IMBundle.putParcelableArrayList("messages", mDisplayedConference.getMessages());
-                mIMFragment.setArguments(IMBundle);
-            } else {
-                IMBundle.putParcelableArrayList("messages", new ArrayList<SipMessage>());
-                mIMFragment.setArguments(IMBundle);
-            }
-        }
-
-        mSlidingPaneLayout.setCurFragment(mCurrentCallFragment);
-        getFragmentManager().beginTransaction().replace(R.id.ongoingcall_pane, mCurrentCallFragment)
-                .replace(R.id.message_list_frame, mIMFragment).commit();
-    }
-
-    private void setUpSlidingPanel() {
-        mSlidingPaneLayout = (CallPaneLayout) findViewById(R.id.slidingpanelayout);
-        mSlidingPaneLayout.setParallaxDistance(500);
-        mSlidingPaneLayout.setSliderFadeColor(Color.TRANSPARENT);
-
-        mSlidingPaneLayout.setPanelSlideListener(new SlidingPaneLayout.PanelSlideListener() {
-
-            @Override
-            public void onPanelSlide(View view, float offSet) {
-            }
-
-            @Override
-            public void onPanelOpened(View view) {
-                getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_PAN);
-            }
-
-            @Override
-            public void onPanelClosed(View view) {
-                mCurrentCallFragment.getBubbleView().restartDrawing();
-                getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_ADJUST_NOTHING);
-            }
-        });
+        Intent intent = new Intent(this, LocalService.class);
+        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
     }
 
     @Override
     public void onFragmentCreated() {
-        Intent intent = new Intent(this, SipService.class);
-        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
     }
 
     @Override
@@ -182,11 +128,12 @@ public class CallActivity extends Activity implements IMFragment.Callbacks, Call
 
     @Override
     protected void onDestroy() {
-
+        Log.i(TAG, "CallActivity onDestroy");
         unbindService(mConnection);
-
-        mProximityManager.stopTracking();
-        mProximityManager.release(0);
+        if (mProximityManager != null) {
+            mProximityManager.stopTracking();
+            mProximityManager.release(0);
+        }
 
         super.onDestroy();
     }
@@ -198,15 +145,34 @@ public class CallActivity extends Activity implements IMFragment.Callbacks, Call
         @SuppressWarnings("unchecked")
         @Override
         public void onServiceConnected(ComponentName className, IBinder binder) {
-            mService = ISipService.Stub.asInterface(binder);
+            service = ((LocalService.LocalBinder)binder).getService();
+
+            if (!init) {
+                mProximityManager = new CallProximityManager(CallActivity.this, CallActivity.this);
+                mProximityManager.startTracking();
+
+                if(!checkExternalCall()) {
+                    mDisplayedConference = getIntent().getParcelableExtra("conference");
+                }
+                Log.i(TAG, "CallActivity onCreate in:" + mDisplayedConference.isIncoming() + " out:" + mDisplayedConference.isOnGoing() + " contact" + mDisplayedConference.getParticipants().get(0).getContact().getDisplayName());
+                init = true;
+            }
 
             if (mDisplayedConference.getState().contentEquals("NONE")) {
+                SipCall call = mDisplayedConference.getParticipants().get(0);
                 try {
-                    mService.placeCall(mDisplayedConference.getParticipants().get(0));
+                    String callId = service.getRemoteService().placeCall(call);
+                    if (callId == null || callId.isEmpty()) {
+                        CallActivity.this.terminateCall();
+                    }
+                    mDisplayedConference = service.getRemoteService().getConference(callId);
                 } catch (RemoteException e) {
                     e.printStackTrace();
                 }
             }
+
+            setContentView(R.layout.activity_call_layout);
+            mCurrentCallFragment = (CallFragment) getFragmentManager().findFragmentById(R.id.ongoingcall_pane);
         }
 
         @Override
@@ -217,25 +183,30 @@ public class CallActivity extends Activity implements IMFragment.Callbacks, Call
     private boolean checkExternalCall() {
         Uri u = getIntent().getData();
         if (u != null) {
-            CallContact c = CallContact.ContactBuilder.buildUnknownContact(u.getSchemeSpecificPart());
+            String number = u.getSchemeSpecificPart();
+            Log.w(TAG, "number " + number);
+            number = CallContact.canonicalNumber(number);
+            Log.w(TAG, "canonicalNumber " + number);
+            CallContact c = service.findContactByNumber(number);
+            Conversation conv = service.getByContact(c);
+            if (conv == null)
+                conv = new Conversation(c);
+            Account acc = service.getAccounts().get(0);
+            String id = conv.getLastAccountUsed();
+            if (id != null && !id.isEmpty()) {
+                Account alt_acc = service.getAccount(id);
+                Log.w(TAG, "Found suitable account for calling " + u.getSchemeSpecificPart() + " " + id + " " + alt_acc.getBasicDetails().getDetailString(AccountDetailBasic.CONFIG_ACCOUNT_TYPE));
+                if (alt_acc.isEnabled())
+                    acc = alt_acc;
+            } else {
+                acc = service.guessAccount(c, number);
+            }
             try {
-                String accountID = (String) mService.getAccountList().get(1); // We use the first account to place outgoing calls
-                Map<String, String> details = (Map<String, String>) mService.getAccountDetails(accountID);
-                ArrayList<Map<String, String>> credentials = (ArrayList<Map<String, String>>) mService.getCredentials(accountID);
-                Map<String, String> state = (Map<String, String>) mService.getVolatileAccountDetails(accountID);
-                Account acc = new Account(accountID, details, credentials, state);
-
-                Bundle args = new Bundle();
-                args.putString(SipCall.ID, Integer.toString(Math.abs(new Random().nextInt())));
-                args.putParcelable(SipCall.ACCOUNT, acc);
-                args.putInt(SipCall.STATE, SipCall.state.CALL_STATE_NONE);
-                args.putInt(SipCall.TYPE, SipCall.direction.CALL_TYPE_OUTGOING);
-                args.putParcelable(SipCall.CONTACT, c);
-
+                SipCall call = new SipCall(null, acc.getAccountID(), number, SipCall.Direction.OUTGOING);
+                call.setCallState(SipCall.State.NONE);
+                call.setContact(c);
                 mDisplayedConference = new Conference(Conference.DEFAULT_ID);
-                mDisplayedConference.getParticipants().add(new SipCall(args));
-            } catch (RemoteException e) {
-                e.printStackTrace();
+                mDisplayedConference.getParticipants().add(call);
             } catch (Exception e) {
                 e.printStackTrace();
             }
@@ -245,8 +216,13 @@ public class CallActivity extends Activity implements IMFragment.Callbacks, Call
     }
 
     @Override
-    public ISipService getService() {
-        return mService;
+    public ISipService getRemoteService() {
+        return service.getRemoteService();
+    }
+
+    @Override
+    public LocalService getService() {
+        return service;
     }
 
     @Override
@@ -273,30 +249,7 @@ public class CallActivity extends Activity implements IMFragment.Callbacks, Call
     @Override
     public void terminateCall() {
         mHandler.removeCallbacks(mUpdateTimeTask);
-        mCurrentCallFragment.getBubbleView().stopThread();
-        TimerTask quit = new TimerTask() {
-
-            @Override
-            public void run() {
-                finish();
-            }
-        };
-
-        new Timer().schedule(quit, 1000);
-    }
-
-    @Override
-    public boolean sendIM(SipMessage msg) {
-
-        try {
-            Log.i(TAG, "Sending:"+msg.comment+"to"+mDisplayedConference.getId());
-            mService.sendTextMessage(mDisplayedConference.getId(), msg);
-        } catch (RemoteException e) {
-            e.printStackTrace();
-            return false;
-        }
-
-        return true;
+        finish();
     }
 
     @Override
@@ -304,17 +257,6 @@ public class CallActivity extends Activity implements IMFragment.Callbacks, Call
         mHandler.postDelayed(mUpdateTimeTask, 0);
     }
 
-    @Override
-    public void slideChatScreen() {
-
-        if (mSlidingPaneLayout.isOpen()) {
-            mSlidingPaneLayout.closePane();
-        } else {
-            mCurrentCallFragment.getBubbleView().stopThread();
-            mSlidingPaneLayout.openPane();
-        }
-    }
-
     @Override
     public boolean shouldActivateProximity() {
         return true;
@@ -322,7 +264,5 @@ public class CallActivity extends Activity implements IMFragment.Callbacks, Call
 
     @Override
     public void onProximityTrackingChanged(boolean acquired) {
-        // TODO Stub de la méthode généré automatiquement
-
     }
 }
diff --git a/ring-android/app/src/main/java/cx/ring/client/ConversationActivity.java b/ring-android/app/src/main/java/cx/ring/client/ConversationActivity.java
new file mode 100644
index 000000000..a0ce37504
--- /dev/null
+++ b/ring-android/app/src/main/java/cx/ring/client/ConversationActivity.java
@@ -0,0 +1,386 @@
+package cx.ring.client;
+
+import android.app.Activity;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.ServiceConnection;
+import android.net.Uri;
+import android.os.Bundle;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.BaseAdapter;
+import android.widget.EditText;
+import android.widget.ImageView;
+import android.widget.ListView;
+import android.widget.TextView;
+
+import java.text.DateFormat;
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.Set;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+
+import cx.ring.R;
+import cx.ring.adapters.ContactPictureTask;
+import cx.ring.model.CallContact;
+import cx.ring.model.Conference;
+import cx.ring.model.Conversation;
+import cx.ring.model.SipCall;
+import cx.ring.model.TextMessage;
+import cx.ring.model.account.Account;
+import cx.ring.service.LocalService;
+
+public class ConversationActivity extends Activity {
+    private static final String TAG = ConversationActivity.class.getSimpleName();
+
+    public static final Uri CONTENT_URI = Uri.withAppendedPath(LocalService.AUTHORITY_URI, "conversations");
+
+    private boolean mBound = false;
+    private LocalService service = null;
+    private Conversation conversation = null;
+    private String preferredNumber = null;
+
+
+    private ListView histList = null;
+    private View msgSendBtn = null;
+    private EditText msgEditTxt = null;
+    private ViewGroup bottomPane = null;
+
+    private ConversationAdapter adapter = null;
+
+    private ServiceConnection mConnection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName className, IBinder binder) {
+            service = ((LocalService.LocalBinder)binder).getService();
+            IntentFilter intentFilter = new IntentFilter();
+            intentFilter.addAction(LocalService.ACTION_CONF_UPDATE);
+            registerReceiver(receiver, intentFilter);
+
+            mBound = true;
+
+            String conv_id = getIntent().getData().getLastPathSegment();
+            preferredNumber = getIntent().getStringExtra("number");
+            conversation = service.getConversation(conv_id);
+            if (conversation == null) {
+                long contact_id = CallContact.contactIdFromId(conv_id);
+                CallContact contact;
+                if (contact_id >= 0)
+                    contact = service.findContactById(contact_id);
+                else if (preferredNumber != null && !preferredNumber.isEmpty()) {
+                    contact = service.findContactByNumber(preferredNumber);
+                    if (contact == null)
+                        contact = CallContact.ContactBuilder.buildUnknownContact(conv_id);
+                } else {
+                    contact = service.findContactByNumber(conv_id);
+                    if (contact == null)
+                        contact = CallContact.ContactBuilder.buildUnknownContact(conv_id);
+                    preferredNumber = conv_id;
+                }
+                conversation = service.startConversation(contact);
+            }
+
+            Log.w(TAG, "ConversationActivity onServiceConnected " + conv_id);
+
+            if (conversation == null) {
+                finish();
+                return;
+            }
+
+            getActionBar().setTitle(conversation.getContact().getDisplayName());
+
+            Conference conf = conversation.getCurrentCall();
+            bottomPane.setVisibility(conf == null ? View.GONE : View.VISIBLE);
+            if (conf != null) {
+                Log.w(TAG, "ConversationActivity onServiceConnected " + conf.getId() + " " + conversation.getCurrentCall());
+                bottomPane.setOnClickListener(new View.OnClickListener() {
+                    @Override
+                    public void onClick(View v) {
+                        startActivity(new Intent(ConversationActivity.this.getApplicationContext(), CallActivity.class).putExtra("conference", conversation.getCurrentCall()));
+                    }
+                });
+            }
+
+            adapter.updateDataset(conversation.getHistory());
+            scrolltoBottom();
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName arg0) {
+            Log.w(TAG, "ConversationActivity onServiceDisconnected " + arg0.getClassName());
+            mBound = false;
+        }
+    };
+    final BroadcastReceiver receiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            Log.w(TAG, "onReceive " + intent.getAction() + " " + intent.getDataString());
+            //conversation = service.getConversation(conversation.getId());
+            conversation = service.getByContact(conversation.getContact());
+            adapter.updateDataset(conversation.getHistory());
+            scrolltoBottom();
+            Conference conf = conversation.getCurrentCall();
+            bottomPane.setVisibility(conf == null ? View.GONE : View.VISIBLE);
+        }
+    };
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        setContentView(R.layout.frag_conversation);
+        msgEditTxt = (EditText) findViewById(R.id.msg_input_txt);
+        msgSendBtn = findViewById(R.id.msg_send);
+        msgSendBtn.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                onSendTextMessage(msgEditTxt.getText().toString());
+                msgEditTxt.setText("");
+            }
+        });
+        bottomPane = (ViewGroup) findViewById(R.id.ongoingcall_pane);
+        bottomPane.setVisibility(View.GONE);
+        //getActionBar().setDisplayHomeAsUpEnabled(true);
+        conversation = getIntent().getParcelableExtra("conversation");
+
+        adapter = new ConversationAdapter(this);
+        histList = (ListView) findViewById(R.id.hist_list);
+        histList.setAdapter(adapter);
+
+        if (!mBound) {
+            Log.i(TAG, "onCreate: Binding service...");
+            Intent intent = new Intent(this, LocalService.class);
+            bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
+            service = null;
+        }
+    }
+
+    private void scrolltoBottom() {
+        histList.post(new Runnable() {
+            @Override
+            public void run() {
+                // Select the last row so it will scroll into view...
+                histList.setSelection(adapter.getCount() - 1);
+            }
+        });
+    }
+
+    private class ConversationAdapter extends BaseAdapter {
+        final private Context context;
+        final private ArrayList<Conversation.ConversationElement> texts = new ArrayList<>();
+        private ExecutorService infos_fetcher = Executors.newCachedThreadPool();
+
+        public void updateDataset(ArrayList<Conversation.ConversationElement> list) {
+            Log.i(TAG, "updateDataset " + list.size());
+            if (list.size() == 0 && texts.size() == 0)
+                return;
+            texts.clear();
+            texts.addAll(list);
+            notifyDataSetChanged();
+        }
+
+        ConversationAdapter(Context ctx) {
+            context = ctx;
+        }
+
+        @Override
+        public int getCount() {
+            return texts.size();
+        }
+
+        @Override
+        public Conversation.ConversationElement getItem(int position) {
+            return texts.get(position);
+        }
+
+        @Override
+        public long getItemId(int position) {
+            return 0;
+        }
+
+        @Override
+        public View getView(int position, View convertView, ViewGroup parent) {
+            if (convertView == null)
+                convertView = LayoutInflater.from(context).inflate(R.layout.item_textmsg, null);
+
+            ViewGroup txtEntry = (ViewGroup) convertView.findViewById(R.id.txt_entry);
+            TextView msgTxt = (TextView) convertView.findViewById(R.id.msg_txt);
+            TextView msgDetailTxt = (TextView) convertView.findViewById(R.id.msg_details_txt);
+            ImageView photo = (ImageView) convertView.findViewById(R.id.photo);
+
+            ViewGroup txtEntryRight = (ViewGroup) convertView.findViewById(R.id.txt_entry_right);
+            TextView msgTxtRight = (TextView) convertView.findViewById(R.id.msg_txt_right);
+            TextView msgDetailTxtRight = (TextView) convertView.findViewById(R.id.msg_details_txt_right);
+
+            ViewGroup callEntry = (ViewGroup) convertView.findViewById(R.id.call_entry);
+            TextView histTxt = (TextView) convertView.findViewById(R.id.call_hist_txt);
+            TextView histDetailTxt = (TextView) convertView.findViewById(R.id.call_details_txt);
+
+            Conversation.ConversationElement txt = texts.get(position);
+            if (txt.text != null) {
+                callEntry.setVisibility(View.GONE);
+                if (txt.text.isIncoming()) {
+                    txtEntry.setVisibility(View.VISIBLE);
+                    txtEntryRight.setVisibility(View.GONE);
+                    msgTxt.setText(txt.text.getMessage());
+                    msgDetailTxt.setText(DateFormat.getDateTimeInstance().format(new Date(txt.text.getTimestamp())));
+                    infos_fetcher.execute(new ContactPictureTask(context, photo, txt.text.getContact()));
+                } else {
+                    txtEntry.setVisibility(View.GONE);
+                    txtEntryRight.setVisibility(View.VISIBLE);
+                    msgTxtRight.setText(txt.text.getMessage());
+                    msgDetailTxtRight.setText(DateFormat.getDateTimeInstance().format(new Date(txt.text.getTimestamp())));
+                }
+            } else {
+                callEntry.setVisibility(View.VISIBLE);
+                txtEntry.setVisibility(View.GONE);
+                txtEntryRight.setVisibility(View.GONE);
+                msgTxt.setText("");
+                histTxt.setText((txt.call.isIncoming() ? "Incoming" : "Outgoing") + " call with " + txt.call.getNumber());
+                histDetailTxt.setText(DateFormat.getDateTimeInstance().format(txt.call.getStartDate()));
+            }
+
+            return convertView;
+        }
+    }
+
+    @Override
+    protected void onDestroy() {
+        if (mBound) {
+            unregisterReceiver(receiver);
+            unbindService(mConnection);
+            mBound = false;
+        }
+        super.onDestroy();
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        // Inflate the menu items for use in the action bar
+        MenuInflater inflater = getMenuInflater();
+        inflater.inflate(R.menu.conversation_actions, menu);
+        return super.onCreateOptionsMenu(menu);
+    }
+
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        // Handle presses on the action bar items
+        switch (item.getItemId()) {
+            case R.id.conv_action_audiocall:
+                onAudioCall();
+                return true;
+            case R.id.conv_action_videocall:
+                return true;
+            default:
+                return super.onOptionsItemSelected(item);
+        }
+    }
+
+    public void launchCallActivity(SipCall infos) {
+        Conference tmp = conversation.getCurrentCall();
+        if (tmp == null)
+            //tmp = service.startConversation(infos.getContact());
+            tmp = new Conference(Conference.DEFAULT_ID);
+
+        tmp.getParticipants().add(infos);
+        Intent intent = new Intent().setClass(this, CallActivity.class);
+        intent.putExtra("conference", tmp);
+        intent.putExtra("resuming", false);
+        startActivityForResult(intent, HomeActivity.REQUEST_CODE_CALL);
+        // overridePendingTransition(R.anim.slide_down, R.anim.slide_up);
+    }
+
+    private void onSendTextMessage(String txt) {
+
+        Conference conf = conversation.getCurrentCall();
+        if (conf == null || !conf.isOnGoing()) {
+            String account = conversation.getLastAccountUsed();
+            if (account == null || account.isEmpty())
+                account = service.guessAccount(conversation.getContact(), conversation.contact.getPhones().get(0).getNumber()).getAccountID();
+            String number = preferredNumber;
+            if (number == null || number.isEmpty())
+                number = conversation.getLastNumberUsed(account);
+            if (number == null || number.isEmpty())
+                number = conversation.contact.getPhones().get(0).getNumber();
+            try {
+                service.getRemoteService().sendAccountTextMessage(account, number, txt);
+            } catch (RemoteException e) {
+                e.printStackTrace();
+            }
+        } else {
+            try {
+                service.getRemoteService().sendTextMessage(conf.getId(), new TextMessage(false, txt));
+            } catch (RemoteException e) {
+                e.printStackTrace();
+            }
+        }
+    }
+
+    private void onAudioCall() {
+        Conference conf = conversation.getCurrentCall();
+        if (conf != null) {
+            startActivity(new Intent(ConversationActivity.this.getApplicationContext(), CallActivity.class).putExtra("conference", conversation.getCurrentCall()));
+            return;
+        }
+
+        if (service.getAccounts().isEmpty()) {
+            //createNotRegisteredDialog().show();
+            return;
+        }
+
+        Account usedAccount = service.getAccounts().get(0);
+        CallContact contact = null;
+        if (conversation != null) {
+            String last_used = conversation.getLastAccountUsed();
+            Account a = service.getAccount(last_used);
+            if (a != null/* && a.isEnabled()*/)
+                usedAccount = a;
+            else {
+                Set<String> acc_ids = conversation.getAccountsUsed();
+                for (Account acc : service.getAccounts()) {
+                    if (acc_ids.contains(acc.getAccountID())) {
+                        usedAccount = acc;
+                        break;
+                    }
+                }
+            }
+            contact = conversation.getContact();
+        }   
+
+        String number = preferredNumber;
+        if (number == null)
+            number = conversation.getLastNumberUsed(usedAccount.getAccountID());
+        if (number == null && contact != null)
+            number = contact.getPhones().get(0).getNumber();
+
+        //conversation.getHistory().getAccountID()
+        //if (usedAccount.isRegistered() || usedAccount.isIP2IP()) {
+         /*   Bundle args = new Bundle();
+            args.putParcelable(SipCall.ACCOUNT, usedAccount);
+            args.putInt(SipCall.STATE, SipCall.State.NONE);
+            args.putInt(SipCall.TYPE, SipCall.Direction.OUTGOING);
+            args.putParcelable(SipCall.CONTACT, contact);*/
+        SipCall call = new SipCall(null, usedAccount.getAccountID(), number, SipCall.Direction.OUTGOING);
+        call.setContact(contact);
+
+            try {
+                launchCallActivity(call);
+            } catch (Exception e) {
+                e.printStackTrace();
+                Log.e(TAG, e.toString());
+            }
+        /*} else {
+            createNotRegisteredDialog().show();
+        }*/
+
+    }
+}
diff --git a/ring-android/app/src/main/java/cx/ring/client/HomeActivity.java b/ring-android/app/src/main/java/cx/ring/client/HomeActivity.java
index 9358e7ef5..52d9b3707 100644
--- a/ring-android/app/src/main/java/cx/ring/client/HomeActivity.java
+++ b/ring-android/app/src/main/java/cx/ring/client/HomeActivity.java
@@ -36,9 +36,8 @@ import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
-import java.util.Random;
 import java.util.Timer;
-import java.util.TimerTask;
+import java.util.regex.Pattern;
 
 import android.app.Activity;
 import android.app.AlertDialog;
@@ -52,14 +51,13 @@ import cx.ring.fragments.HistoryFragment;
 import cx.ring.fragments.HomeFragment;
 import cx.ring.fragments.MenuFragment;
 import cx.ring.history.HistoryEntry;
+import cx.ring.history.HistoryManager;
+import cx.ring.loaders.LoaderConstants;
 import cx.ring.model.account.Account;
-import cx.ring.model.CallContact;
 import cx.ring.model.Conference;
 import cx.ring.model.SipCall;
 import cx.ring.service.ISipService;
-import cx.ring.service.SipService;
-import cx.ring.views.SlidingUpPanelLayout;
-import cx.ring.views.SlidingUpPanelLayout.PanelSlideListener;
+import cx.ring.service.LocalService;
 
 import android.app.Fragment;
 import android.app.FragmentManager;
@@ -72,18 +70,12 @@ import android.content.Intent;
 import android.content.ServiceConnection;
 import android.content.res.AssetManager;
 import android.content.res.Configuration;
-import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
 import android.os.IBinder;
 import android.preference.PreferenceManager;
-import android.provider.ContactsContract;
-import android.provider.ContactsContract.CommonDataKinds.Phone;
-import android.provider.ContactsContract.CommonDataKinds.SipAddress;
 import android.support.design.widget.FloatingActionButton;
 import android.support.design.widget.NavigationView;
-import android.support.v4.app.FragmentActivity;
-import android.support.v4.view.GravityCompat;
 import android.support.v4.widget.DrawerLayout;
 import android.support.v7.app.ActionBarDrawerToggle;
 import android.support.v7.app.AppCompatActivity;
@@ -91,14 +83,14 @@ import android.support.v7.widget.Toolbar;
 import android.util.Log;
 import android.util.TypedValue;
 import android.view.Gravity;
+import android.view.Menu;
+import android.view.MenuInflater;
 import android.view.MenuItem;
 import android.view.View;
 import android.view.ViewGroup;
-import android.widget.RelativeLayout;
-import android.widget.Toast;
 
-public class HomeActivity extends AppCompatActivity implements DialingFragment.Callbacks, AccountsManagementFragment.Callbacks,
-        ContactListFragment.Callbacks, CallListFragment.Callbacks, HistoryFragment.Callbacks, NavigationView.OnNavigationItemSelectedListener, MenuFragment.Callbacks {
+public class HomeActivity extends AppCompatActivity implements LocalService.Callbacks, DialingFragment.Callbacks,
+        /*ContactListFragment.Callbacks, */HistoryFragment.Callbacks, NavigationView.OnNavigationItemSelectedListener {
 
     static final String TAG = HomeActivity.class.getSimpleName();
 
@@ -107,12 +99,13 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
     private MenuFragment fMenuHead = null;
 
     private boolean mBound = false;
-    private ISipService service;
+    private LocalService service;
 
     public static final int REQUEST_CODE_PREFERENCES = 1;
     public static final int REQUEST_CODE_CALL = 3;
+    public static final int REQUEST_CODE_CONVERSATION = 4;
 
-    SlidingUpPanelLayout mContactDrawer;
+    //SlidingUpPanelLayout mContactDrawer;
     private DrawerLayout mNavigationDrawer;
     private ActionBarDrawerToggle mDrawerToggle;
     private Toolbar toolbar;
@@ -123,6 +116,22 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
 
     protected Fragment fContent;
 
+    public static final Pattern RING_ID_REGEX = Pattern.compile("^\\s+(?:ring(?:[\\s\\:]+))?(\\p{XDigit}{40})\\s+$", Pattern.CASE_INSENSITIVE);
+
+    private static void setDefaultUncaughtExceptionHandler() {
+        try {
+            Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() {
+                @Override
+                public void uncaughtException(Thread t, Throwable e) {
+                    Log.e(TAG, "Uncaught Exception detected in thread ", e);
+                    //e.printStackTrace();
+                }
+            });
+        } catch (SecurityException e) {
+            Log.e(TAG, "Could not set the Default Uncaught Exception Handler");
+        }
+    }
+
     /* called before activity is killed, e.g. rotation */
     @Override
     protected void onSaveInstanceState(Bundle bundle) {
@@ -131,14 +140,18 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
+        setDefaultUncaughtExceptionHandler();
+
         super.onCreate(savedInstanceState);
         setContentView(R.layout.activity_home);
 
         // Bind to LocalService
         if (!mBound) {
             Log.i(TAG, "onStart: Binding service...");
-            Intent intent = new Intent(this, SipService.class);
+            /*Intent intent = new Intent(this, SipService.class);
             startService(intent);
+            bindService(intent, mConnection, Context.BIND_AUTO_CREATE);*/
+            Intent intent = new Intent(this, LocalService.class);
             bindService(intent, mConnection, Context.BIND_AUTO_CREATE);
         }
 
@@ -148,9 +161,13 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
 
         fMenu = (NavigationView) findViewById(R.id.left_drawer);
         fMenu.setNavigationItemSelectedListener(this);
-
-        mContactsFragment = new ContactListFragment();
-        getFragmentManager().beginTransaction().replace(R.id.contacts_frame, mContactsFragment).commit();
+/*
+        FragmentManager fm = getFragmentManager();
+        mContactsFragment = (ContactListFragment) fm.findFragmentByTag(ContactListFragment.TAG);
+        if(mContactsFragment == null) {
+            mContactsFragment = new ContactListFragment();
+            getFragmentManager().beginTransaction().replace(R.id.contacts_frame, mContactsFragment, ContactListFragment.TAG).commit();
+        }
 
         mContactDrawer = (SlidingUpPanelLayout) findViewById(R.id.contact_panel);
         // mContactDrawer.setShadowDrawable(getResources().getDrawable(R.drawable.above_shadow));
@@ -187,7 +204,7 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
 
             }
         });
-
+*/
         mNavigationDrawer = (DrawerLayout) findViewById(R.id.drawer_layout);
 
         getSupportActionBar().setDisplayHomeAsUpEnabled(true);
@@ -217,17 +234,23 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
     @Override
     protected void onPostCreate(Bundle savedInstanceState) {
         super.onPostCreate(savedInstanceState);
-        // Sync the toggle state after onRestoreInstanceState has occurred.
+        // Sync the toggle State after onRestoreInstanceState has occurred.
         mDrawerToggle.syncState();
-        if (mContactDrawer.isExpanded()) {
+        /*if (mContactDrawer.isExpanded()) {
             getSupportActionBar().hide();
-        }
+        }*/
     }
 
     @Override
     public void onConfigurationChanged(Configuration newConfig) {
         super.onConfigurationChanged(newConfig);
-        mDrawerToggle.onConfigurationChanged(newConfig);
+        //mDrawerToggle.onConfigurationChanged(newConfig);
+    }
+
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        getMenuInflater().inflate(R.menu.history, menu);
+        return super.onCreateOptionsMenu(menu);
     }
 
     @Override
@@ -248,7 +271,11 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
         TypedValue tv = new TypedValue();
         if (getTheme().resolveAttribute(android.R.attr.actionBarSize, tv, true)) {
             int abSz = TypedValue.complexToDimensionPixelSize(tv.data,getResources().getDisplayMetrics());
-            ViewGroup.LayoutParams params = toolbar.getLayoutParams();
+            ViewGroup.LayoutParams params = toolbar.getLayoutParams();//toolbar.setContentInsetsRelative();
+
+            //TypedArray a = obtainStyledAttributes(attrs, R.styleable.Toolbar_titleMarginBottom);
+
+            //toolbar.get
             if (double_h) {
                 params.height = abSz*2;
                 actionButton.setVisibility(View.VISIBLE);
@@ -261,6 +288,7 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
             toolbar.setMinimumHeight(abSz);
         }
         toolbar.setTitle(title_res);
+        //toolbar.setTitleTextAppearance(toolbar.getT);
     }
 
     public FloatingActionButton getActionButton() {
@@ -336,10 +364,10 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
             return;
         }
 
-        if (mContactDrawer.isExpanded() || mContactDrawer.isAnchored()) {
+        /*if (mContactDrawer.isExpanded() || mContactDrawer.isAnchored()) {
             mContactDrawer.collapsePane();
             return;
-        }
+        }*/
 
         if (getFragmentManager().getBackStackEntryCount() > 1) {
             popCustomBackStack();
@@ -347,20 +375,7 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
             return;
         }
 
-        if (isClosing) {
-            super.onBackPressed();
-            t.cancel();
-            finish();
-        } else {
-            t.schedule(new TimerTask() {
-                @Override
-                public void run() {
-                    isClosing = false;
-                }
-            }, 3000);
-            Toast.makeText(this, getResources().getString(R.string.close_msg), Toast.LENGTH_SHORT).show();
-            isClosing = true;
-        }
+        super.onBackPressed();
     }
 
     private void popCustomBackStack() {
@@ -376,20 +391,20 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
     @Override
     protected void onPause() {
         super.onPause();
-
-        if (mBound) {
-            unbindService(mConnection);
-            mBound = false;
-        }
+        Log.d(TAG, "onPause");
     }
 
     /* activity finishes itself or is being killed by the system */
     @Override
     protected void onDestroy() {
         super.onDestroy();
-        Log.i(TAG, "onDestroy: destroying service...");
-        Intent sipServiceIntent = new Intent(this, SipService.class);
-        stopService(sipServiceIntent);
+        if (mBound) {
+            unbindService(mConnection);
+            mBound = false;
+        }
+        //Log.i(TAG, "onDestroy: destroying service...");
+        //Intent sipServiceIntent = new Intent(this, SipService.class);
+        //stopService(sipServiceIntent);
     }
 
     public void launchCallActivity(SipCall infos) {
@@ -410,9 +425,13 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
     private ServiceConnection mConnection = new ServiceConnection() {
 
         @Override
-        public void onServiceConnected(ComponentName className, IBinder binder) {
-            service = ISipService.Stub.asInterface(binder);
-            fContent = new HomeFragment();
+        public void onServiceConnected(ComponentName className, IBinder s) {
+            Log.i(TAG, "onServiceConnected " + className.getClassName());
+            LocalService.LocalBinder binder = (LocalService.LocalBinder) s;
+            service = binder.getService();
+
+            //service = ISipService.Stub.asInterface(binder);
+            fContent = new CallListFragment();
             if (fMenuHead != null)
                 fMenu.removeHeaderView(fMenuHead.getView());
             fMenu.inflateHeaderView(R.layout.menuheader);
@@ -420,18 +439,19 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
 
             getFragmentManager().beginTransaction().replace(R.id.main_frame, fContent, "Home").addToBackStack("Home").commit();
             mBound = true;
-            Log.d(TAG, "Service connected service=" + service);
+            Log.i(TAG, "Service connected service=" + service);
         }
 
         @Override
-        public void onServiceDisconnected(ComponentName arg0) {
+        public void onServiceDisconnected(ComponentName className) {
+            Log.i(TAG, "onServiceConnected " + className.getClassName());
             if (fMenuHead != null) {
                 fMenu.removeHeaderView(fMenuHead.getView());
                 fMenuHead = null;
             }
 
             mBound = false;
-            Log.d(TAG, "Service disconnected service=" + service);
+            Log.i(TAG, "Service disconnected service=" + service);
         }
     };
 
@@ -442,8 +462,17 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
         if (mDrawerToggle.onOptionsItemSelected(item)) {
             return true;
         }
-
-        return super.onOptionsItemSelected(item);
+        switch (item.getItemId()) {
+            case R.id.menu_clear_history:
+                // TODO clean Database!
+                //mHistoryManager.clearDB();
+                //getLoaderManager().restartLoader(LoaderConstants.HISTORY_LOADER, null, this);
+                HistoryManager m = new HistoryManager(this);
+                m.clearDB();
+                return true;
+            default:
+                return super.onOptionsItemSelected(item);
+        }
     }
 
     @Override
@@ -466,10 +495,16 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
     }
 
     @Override
-    public ISipService getService() {
+    public ISipService getRemoteService() {
+        return service.getRemoteService();
+    }
+
+    @Override
+    public LocalService getService() {
         return service;
     }
 
+    /*
     @Override
     public void onTextContact(final CallContact c) {
         // TODO
@@ -483,6 +518,7 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
         startActivity(intent);
     }
 
+
     @Override
     public void onCallContact(final CallContact c) {
 
@@ -506,10 +542,10 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
             public void run() {
 
                 Bundle args = new Bundle();
-                args.putString(SipCall.ID, Integer.toString(Math.abs(new Random().nextInt())));
+                //args.putString(SipCall.ID, Integer.toString(Math.abs(new Random().nextInt())));
                 args.putParcelable(SipCall.ACCOUNT, fMenuHead.getSelectedAccount());
-                args.putInt(SipCall.STATE, SipCall.state.CALL_STATE_NONE);
-                args.putInt(SipCall.TYPE, SipCall.direction.CALL_TYPE_OUTGOING);
+                args.putInt(SipCall.STATE, SipCall.State.NONE);
+                args.putInt(SipCall.TYPE, SipCall.Direction.OUTGOING);
 
                 Cursor cPhones = getContentResolver().query(Phone.CONTENT_URI, CONTACTS_PHONES_PROJECTION, Phone.CONTACT_ID + " =" + c.getId(),
                         null, null);
@@ -533,10 +569,10 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
             }
         });
         launcher.start();
-        mContactDrawer.collapsePane();
+        //mContactDrawer.collapsePane();
 
     }
-
+*/
     @Override
     public void onCallHistory(HistoryEntry to) {
 
@@ -549,10 +585,10 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
 
         if (usedAccount.isRegistered()) {
             Bundle args = new Bundle();
-            args.putString(SipCall.ID, Integer.toString(Math.abs(new Random().nextInt())));
+            //args.putString(SipCall.ID, Integer.toString(Math.abs(new Random().nextInt())));
             args.putParcelable(SipCall.ACCOUNT, usedAccount);
-            args.putInt(SipCall.STATE, SipCall.state.CALL_STATE_NONE);
-            args.putInt(SipCall.TYPE, SipCall.direction.CALL_TYPE_OUTGOING);
+            args.putInt(SipCall.STATE, SipCall.State.NONE);
+            args.putInt(SipCall.TYPE, SipCall.Direction.OUTGOING);
             args.putParcelable(SipCall.CONTACT, to.getContact());
 
             try {
@@ -567,7 +603,15 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
 
     @Override
     public void onCallDialed(String to) {
-        Account usedAccount = fMenuHead.getSelectedAccount();
+        Intent intent = new Intent()
+                .setClass(this, CallActivity.class)
+                .setAction(Intent.ACTION_CALL)
+                .setData(Uri.parse(to));
+        /*intent.putExtra("conference", tmp);
+        intent.putExtra("resuming", false);*/
+        startActivityForResult(intent, REQUEST_CODE_CALL);
+
+        /*Account usedAccount = fMenuHead.getSelectedAccount();
 
         if (usedAccount == null) {
             createAccountDialog().show();
@@ -576,10 +620,14 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
 
         if (usedAccount.isRegistered() || usedAccount.isIP2IP()) {
             Bundle args = new Bundle();
-            args.putString(SipCall.ID, Integer.toString(Math.abs(new Random().nextInt())));
+
+            Matcher m = RING_ID_REGEX.matcher(to);
+            if (m.matches() && m.groupCount() > 0) {
+                to = "ring:"+m.group(1);
+            }
             args.putParcelable(SipCall.ACCOUNT, usedAccount);
-            args.putInt(SipCall.STATE, SipCall.state.CALL_STATE_NONE);
-            args.putInt(SipCall.TYPE, SipCall.direction.CALL_TYPE_OUTGOING);
+            args.putInt(SipCall.STATE, SipCall.State.NONE);
+            args.putInt(SipCall.TYPE, SipCall.Direction.OUTGOING);
             args.putParcelable(SipCall.CONTACT, CallContact.ContactBuilder.buildUnknownContact(to));
 
             try {
@@ -589,7 +637,7 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
             }
         } else {
             createNotRegisteredDialog().show();
-        }
+        }*/
     }
 
     private AlertDialog createNotRegisteredDialog() {
@@ -634,6 +682,7 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
         return alertDialog;
     }
 
+    /*
     @Override
     public void onContactDragged() {
         mContactDrawer.collapsePane();
@@ -661,7 +710,7 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
     public void setDragView(RelativeLayout relativeLayout) {
         mContactDrawer.setDragView(relativeLayout);
     }
-
+*/
     @Override
     public boolean onNavigationItemSelected(MenuItem pos) {
         pos.setChecked(true);
@@ -670,7 +719,7 @@ public class HomeActivity extends AppCompatActivity implements DialingFragment.C
         switch (pos.getItemId()) {
             case R.id.menuitem_home:
 
-                if (fContent instanceof HomeFragment)
+                if (fContent instanceof CallListFragment)
                     break;
 
                 if (getFragmentManager().getBackStackEntryCount() == 1)
diff --git a/ring-android/app/src/main/java/cx/ring/client/NewConversationActivity.java b/ring-android/app/src/main/java/cx/ring/client/NewConversationActivity.java
new file mode 100644
index 000000000..9ccde7884
--- /dev/null
+++ b/ring-android/app/src/main/java/cx/ring/client/NewConversationActivity.java
@@ -0,0 +1,141 @@
+package cx.ring.client;
+
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.net.Uri;
+import android.os.Bundle;
+import android.view.Menu;
+import android.view.MenuInflater;
+import android.view.MenuItem;
+import android.widget.RelativeLayout;
+import android.widget.SearchView;
+
+import cx.ring.R;
+import cx.ring.fragments.ContactListFragment;
+import cx.ring.model.CallContact;
+
+public class NewConversationActivity extends Activity implements ContactListFragment.Callbacks {
+
+    //private SearchView searchView = null;
+
+    @Override
+    protected void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        getActionBar().setDisplayHomeAsUpEnabled(true);
+        setContentView(R.layout.activity_new_conversation);
+    }
+/*
+    @Override
+    public boolean onCreateOptionsMenu(Menu menu) {
+        MenuInflater inflater = getMenuInflater();
+        inflater.inflate(R.menu.newconv_option_menu, menu);
+        //searchView = (SearchView) menu.findItem(R.id.contact_search).getActionView();
+        return true;
+    }
+*/
+    @Override
+    public boolean onOptionsItemSelected(MenuItem item) {
+        switch (item.getItemId()) {
+            case android.R.id.home:
+                finish();
+                return true;
+        }
+        return super.onOptionsItemSelected(item);
+    }
+
+    @Override
+    public void onCallContact(final CallContact c) {
+        if (c.getPhones().size() > 1) {
+            final CharSequence colors[] = new CharSequence[c.getPhones().size()];
+            int i = 0;
+            for (CallContact.Phone p : c.getPhones())
+                colors[i++] = p.getNumber();
+
+            AlertDialog.Builder builder = new AlertDialog.Builder(this);
+            builder.setTitle("Choose a number");
+            builder.setItems(colors, new DialogInterface.OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    CharSequence selected = colors[which];
+                    Intent intent = new Intent()
+                            .setClass(NewConversationActivity.this, ConversationActivity.class)
+                            .setAction(Intent.ACTION_VIEW)
+                            .setData(Uri.withAppendedPath(ConversationActivity.CONTENT_URI, c.getIds().get(0)))
+                            .putExtra("number", selected);
+                    startActivityForResult(intent, HomeActivity.REQUEST_CODE_CONVERSATION);
+                }
+            });
+            builder.show();
+        } else {
+            Intent intent = new Intent()
+                    .setClass(this, ConversationActivity.class)
+                    .setAction(Intent.ACTION_VIEW)
+                    .setData(Uri.withAppendedPath(ConversationActivity.CONTENT_URI, c.getIds().get(0)));
+            startActivityForResult(intent, HomeActivity.REQUEST_CODE_CONVERSATION);
+        }
+    }
+
+    @Override
+    public void onTextContact(final CallContact c) {
+        if (c.getPhones().size() > 1) {
+            final CharSequence colors[] = new CharSequence[c.getPhones().size()];// {"red", "green", "blue", "black"};
+            int i = 0;
+            for (CallContact.Phone p : c.getPhones())
+                colors[i++] = p.getNumber();
+
+            AlertDialog.Builder builder = new AlertDialog.Builder(this);
+            builder.setTitle("Choose a number");
+            builder.setItems(colors, new DialogInterface.OnClickListener() {
+                @Override
+                public void onClick(DialogInterface dialog, int which) {
+                    CharSequence selected = colors[which];
+                    Intent intent = new Intent()
+                            .setClass(NewConversationActivity.this, ConversationActivity.class)
+                            .setAction(Intent.ACTION_VIEW)
+                            .setData(Uri.withAppendedPath(ConversationActivity.CONTENT_URI, c.getIds().get(0)))
+                            .putExtra("number", selected);
+                    startActivityForResult(intent, HomeActivity.REQUEST_CODE_CONVERSATION);
+                }
+            });
+            builder.show();
+        } else {
+            Intent intent = new Intent()
+                    .setClass(this, ConversationActivity.class)
+                    .setAction(Intent.ACTION_VIEW)
+                    .setData(Uri.withAppendedPath(ConversationActivity.CONTENT_URI, c.getIds().get(0)));
+            startActivityForResult(intent, HomeActivity.REQUEST_CODE_CONVERSATION);
+        }
+    }
+
+    @Override
+    public void onContactDragged() {
+
+    }
+
+    @Override
+    public void toggleDrawer() {
+
+    }
+
+    @Override
+    public void onEditContact(CallContact item) {
+
+    }
+
+    @Override
+    public void setDragView(RelativeLayout relativeLayout) {
+
+    }
+
+    @Override
+    public void toggleForSearchDrawer() {
+
+    }
+/*
+    @Override
+    public SearchView getSearchView() {
+        return searchView;
+    }*/
+}
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/AccountWrapperFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/AccountWrapperFragment.java
deleted file mode 100644
index e22fb0c68..000000000
--- a/ring-android/app/src/main/java/cx/ring/fragments/AccountWrapperFragment.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- *  Copyright (C) 2004-2014 Savoir-Faire Linux Inc.
- *
- *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  Additional permission under GNU GPL version 3 section 7:
- *
- *  If you modify this program, or any covered work, by linking or
- *  combining it with the OpenSSL project's OpenSSL library (or a
- *  modified version of that library), containing parts covered by the
- *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
- *  grants you additional permission to convey the resulting work.
- *  Corresponding Source for a non-source form of such a combination
- *  shall include the source code for the parts of OpenSSL used as well
- *  as that of the covered work.
- */
-
-package cx.ring.fragments;
-
-import android.content.BroadcastReceiver;
-import android.content.Context;
-import android.content.Intent;
-import android.content.IntentFilter;
-import android.os.Bundle;
-import android.app.Fragment;
-import android.util.Log;
-import cx.ring.interfaces.AccountsInterface;
-import cx.ring.service.ConfigurationManagerCallback;
-
-public abstract class AccountWrapperFragment extends Fragment implements AccountsInterface
-{
-    static final String TAG = "AccountWrapperFragment";
-
-    private AccountsReceiver mReceiver;
-
-
-    @Override
-    public void onCreate(Bundle savedInstanceState) {
-        super.onCreate(savedInstanceState);
-        mReceiver = new AccountsReceiver();
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
-        IntentFilter intentFilter = new IntentFilter();
-        intentFilter.addAction(ConfigurationManagerCallback.ACCOUNT_STATE_CHANGED);
-        intentFilter.addAction(ConfigurationManagerCallback.ACCOUNTS_CHANGED);
-        getActivity().registerReceiver(mReceiver, intentFilter);
-    }
-
-    @Override
-    public void accountsChanged() {
-        Log.i(TAG, "accountsChanged");
-    }
-
-    @Override
-    public void accountStateChanged(String accoundID, String state, int code) {
-        Log.i(TAG, "accountStateChanged" + accoundID + " " + state + " " + code);
-    }
-
-    @Override
-    public void onPause() {
-        super.onPause();
-        getActivity().unregisterReceiver(mReceiver);
-    }
-
-    public class AccountsReceiver extends BroadcastReceiver {
-
-        private final String TAG = AccountsReceiver.class.getSimpleName();
-
-        @Override
-        public void onReceive(Context context, Intent intent) {
-            if (intent.getAction().contentEquals(ConfigurationManagerCallback.ACCOUNT_STATE_CHANGED)) {
-                Log.i(TAG, "Received " + intent.getAction() + " " + intent.getStringExtra("Account") + " " + intent.getStringExtra("state") + " " + intent.getIntExtra("code", 0));
-                accountStateChanged(intent.getStringExtra("Account"), intent.getStringExtra("state"), intent.getIntExtra("code", 0));
-            } else if (intent.getAction().contentEquals(ConfigurationManagerCallback.ACCOUNTS_CHANGED)) {
-                Log.i(TAG, "Received" + intent.getAction());
-                accountsChanged();
-            }
-
-        }
-    }
-
-
-}
\ No newline at end of file
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/AccountsManagementFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/AccountsManagementFragment.java
index d9b2570ca..f8ca5ab5e 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/AccountsManagementFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/AccountsManagementFragment.java
@@ -2,7 +2,8 @@
  *  Copyright (C) 2004-2014 Savoir-Faire Linux Inc.
  *
  *  Author: Alexandre Savard <alexandre.savard@savoirfairelinux.com>
- *      Alexandre Lision <alexandre.lision@savoirfairelinux.com>
+ *          Alexandre Lision <alexandre.lision@savoirfairelinux.com>
+ *          Adrien Béraud <adrien.beraud@savoirfairelinux.com>
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -35,11 +36,12 @@ package cx.ring.fragments;
 import android.animation.Animator;
 import android.animation.AnimatorListenerAdapter;
 import android.app.Activity;
-import android.app.LoaderManager;
-import android.content.AsyncTaskLoader;
+import android.app.Fragment;
+import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
-import android.content.Loader;
+import android.content.IntentFilter;
+import android.net.Uri;
 import android.os.Bundle;
 import android.os.RemoteException;
 import android.support.design.widget.FloatingActionButton;
@@ -53,28 +55,25 @@ import cx.ring.R;
 import cx.ring.client.AccountEditionActivity;
 import cx.ring.client.AccountWizard;
 import cx.ring.client.HomeActivity;
-import cx.ring.loaders.AccountsStateLoader;
-import cx.ring.loaders.AccountsLoader;
-import cx.ring.loaders.LoaderConstants;
 import cx.ring.model.account.Account;
-import cx.ring.model.account.AccountDetailAdvanced;
 import cx.ring.model.account.AccountDetailBasic;
-import cx.ring.service.ISipService;
+import cx.ring.service.LocalService;
 import cx.ring.views.dragsortlv.DragSortListView;
 
 import java.io.File;
 import java.util.ArrayList;
-import java.util.Map;
+import java.util.List;
 
-public class AccountsManagementFragment extends AccountWrapperFragment implements LoaderManager.LoaderCallbacks<Bundle> {
-    static final String TAG = "AccountManagementFrag";
-    static final String DEFAULT_ACCOUNT_ID = "IP2IP";
-    static final int ACCOUNT_CREATE_REQUEST = 1;
+public class AccountsManagementFragment extends Fragment {
+    static final String TAG = AccountsManagementFragment.class.getSimpleName();
+
+    private static final String DEFAULT_ACCOUNT_ID = "IP2IP";
+    public static final int ACCOUNT_CREATE_REQUEST = 1;
     public static final int ACCOUNT_EDIT_REQUEST = 2;
-    AccountsAdapter mAccountsAdapter;
-    AccountsAdapter mIP2IPAdapter;
+    private AccountsAdapter mAccountsAdapter;
+    private AccountsAdapter mIP2IPAdapter;
 
-    DragSortListView mDnDListView;
+    private DragSortListView mDnDListView;
     private View mLoadingView;
     private int mShortAnimationDuration;
 
@@ -86,46 +85,31 @@ public class AccountsManagementFragment extends AccountWrapperFragment implement
                 mAccountsAdapter.remove(item);
                 mAccountsAdapter.insert(item, to);
                 try {
-                    mCallbacks.getService().setAccountOrder(mAccountsAdapter.generateAccountOrder());
+                    mCallbacks.getService().getRemoteService().setAccountOrder(mAccountsAdapter.generateAccountOrder());
                 } catch (RemoteException e) {
                     e.printStackTrace();
                 }
             }
         }
-
-    };
-
-    private Callbacks mCallbacks = sDummyCallbacks;
-    private Account ip2ip;
-    private static Callbacks sDummyCallbacks = new Callbacks() {
-
-        @Override
-        public ISipService getService() {
-            return null;
-        }
     };
-    private AccountsLoader accountsLoader;
 
-    public interface Callbacks {
-
-        public ISipService getService();
-
-    }
+    private LocalService.Callbacks mCallbacks = LocalService.DUMMY_CALLBACKS;
+    //private Account ip2ip;
 
     @Override
     public void onAttach(Activity activity) {
         super.onAttach(activity);
-        if (!(activity instanceof Callbacks)) {
+        if (!(activity instanceof LocalService.Callbacks)) {
             throw new IllegalStateException("Activity must implement fragment's callbacks.");
         }
 
-        mCallbacks = (Callbacks) activity;
+        mCallbacks = (LocalService.Callbacks) activity;
     }
 
     @Override
     public void onDetach() {
         super.onDetach();
-        mCallbacks = sDummyCallbacks;
+        mCallbacks = LocalService.DUMMY_CALLBACKS;
     }
 
     @Override
@@ -133,13 +117,23 @@ public class AccountsManagementFragment extends AccountWrapperFragment implement
         super.onCreate(savedInstanceState);
 
         Log.i(TAG, "Create Account Management Fragment");
-        mAccountsAdapter = new AccountsAdapter(getActivity(), new ArrayList<Account>());
-        mIP2IPAdapter = new AccountsAdapter(getActivity(), new ArrayList<Account>());
+        mAccountsAdapter = new AccountsAdapter(getActivity());
+        mIP2IPAdapter = new AccountsAdapter(getActivity());
         this.setHasOptionsMenu(true);
 
         mShortAnimationDuration = getResources().getInteger(android.R.integer.config_mediumAnimTime);
         Log.i(TAG, "anim time: " + mShortAnimationDuration);
-        getLoaderManager().initLoader(LoaderConstants.ACCOUNTS_LOADER, null, this);
+        //getLoaderManager().initLoader(LoaderConstants.ACCOUNTS_LOADER, null, this);
+
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(LocalService.ACTION_ACCOUNT_UPDATE);
+        getActivity().registerReceiver(mReceiver, intentFilter);
+    }
+
+    @Override
+    public void onDestroy() {
+        super.onDestroy();
+        getActivity().unregisterReceiver(mReceiver);
     }
 
     @Override
@@ -170,8 +164,7 @@ public class AccountsManagementFragment extends AccountWrapperFragment implement
 
             @Override
             public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3) {
-                launchAccountEditActivity(ip2ip);
-
+                launchAccountEditActivity(mIP2IPAdapter.accounts.get(0));
             }
         });
 
@@ -185,7 +178,8 @@ public class AccountsManagementFragment extends AccountWrapperFragment implement
 
     public void onResume() {
         super.onResume();
-        accountsLoader.onContentChanged();
+        //accountsLoader.onContentChanged();
+        refreshAccountList();
         ((HomeActivity) getActivity()).setToolbarState(true, R.string.menu_item_accounts);
         FloatingActionButton btn = ((HomeActivity) getActivity()).getActionButton();
         btn.setImageResource(R.drawable.ic_add_white_24dp);
@@ -196,6 +190,7 @@ public class AccountsManagementFragment extends AccountWrapperFragment implement
                 startActivityForResult(intent, ACCOUNT_CREATE_REQUEST);
             }
         });
+        crossfade();
     }
 
     @Override
@@ -220,29 +215,17 @@ public class AccountsManagementFragment extends AccountWrapperFragment implement
     private void launchAccountEditActivity(Account acc) {
         Log.i(TAG, "Launch account edit activity");
 
-        Intent intent = new Intent().setClass(getActivity(), AccountEditionActivity.class);
-        Bundle bundle = new Bundle();
-        bundle.putParcelable("account", acc);
-
-        intent.putExtras(bundle);
-
+        Intent intent = new Intent()
+                .setClass(getActivity(), AccountEditionActivity.class)
+                .setAction(Intent.ACTION_EDIT)
+                .setData(Uri.withAppendedPath(AccountEditionActivity.CONTENT_URI, acc.getAccountID()));
         startActivityForResult(intent, ACCOUNT_EDIT_REQUEST);
     }
 
-    @Override
-    public void accountsChanged() {
-        accountsLoader.onContentChanged();
-    }
-
-    @Override
-    public void accountStateChanged(String accoundID, String state, int code) {
-        mAccountsAdapter.updateAccount(accoundID, state, code);
-    }
-
     @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
         super.onActivityResult(requestCode, resultCode, data);
-        accountsLoader.onContentChanged();
+        refreshAccountList();
     }
 
     /**
@@ -254,13 +237,12 @@ public class AccountsManagementFragment extends AccountWrapperFragment implement
 
         // private static final String TAG = AccountSelectionAdapter.class.getSimpleName();
 
-        ArrayList<Account> accounts;
-        Context mContext;
+        private final ArrayList<Account> accounts = new ArrayList<>();
+        private final Context mContext;
 
-        public AccountsAdapter(Context cont, ArrayList<Account> newList) {
+        public AccountsAdapter(Context c) {
             super();
-            accounts = newList;
-            mContext = cont;
+            mContext = c;
         }
 
         public void insert(Account item, int to) {
@@ -335,7 +317,7 @@ public class AccountsManagementFragment extends AccountWrapperFragment implement
                     public void onClick(View v) {
                         item.setEnabled(!item.isEnabled());
                         try {
-                            mCallbacks.getService().setAccountDetails(item.getAccountID(), item.getDetails());
+                            mCallbacks.getService().getRemoteService().setAccountDetails(item.getAccountID(), item.getDetails());
                         } catch (RemoteException e) {
                             e.printStackTrace();
                         }
@@ -381,39 +363,27 @@ public class AccountsManagementFragment extends AccountWrapperFragment implement
 
         }
 
-        public void addAll(ArrayList<Account> results) {
+        public void addAll(List<Account> results) {
             Log.i(TAG, "AccountsAdapter addAll " + results.size());
             accounts.addAll(results);
-            /*for (final Account a : results) {
-                final String acc_id = a.getAccountID();
-                getLoaderManager().initLoader((int)(Long.parseLong(acc_id.substring(0, 8), 16) & 0x00000000FFFFFFFFL), null, new LoaderManager.LoaderCallbacks<Map<String, String>>() {
-                    @Override
-                    public Loader<Map<String, String>> onCreateLoader(int id, Bundle args) {
-                        Log.i(TAG, "AccountsAdapter addAll onCreateLoader " + id + " " + acc_id);
-                        return new AccountsStateLoader(getActivity(), mCallbacks.getService(), acc_id);
-                    }
-                    @Override
-                    public void onLoadFinished(Loader<Map<String, String>> loader, Map<String, String> data) {
-                        Log.w(TAG, "onLoadFinished");
-                        a.setRegistered_state(data.get(AccountDetailAdvanced.CONFIG_ACCOUNT_REGISTRATION_STATUS), Integer.getInteger(data.get(AccountDetailAdvanced.CONFIG_ACCOUNT_REGISTRATION_STATE_CODE)));
-                        notifyDataSetChanged();
-                    }
-                    @Override
-                    public void onLoaderReset(Loader<Map<String, String>> loader) {
-                    }
-                });
-            }*/
+            notifyDataSetChanged();
+        }
+
+        public void replaceAll(List<Account> results) {
+            Log.i(TAG, "AccountsAdapter replaceAll " + results.size());
+            accounts.clear();
+            accounts.addAll(results);
             notifyDataSetChanged();
         }
 
         /**
-         * Modify state of specific account
+         * Modify State of specific account
          */
         public void updateAccount(String accoundID, String state, int code) {
             Log.i(TAG, "updateAccount:" + state);
             for (Account a : accounts) {
                 if (a.getAccountID().contentEquals(accoundID)) {
-                    a.setRegistered_state(state, code);
+                    a.setRegistrationState(state, code);
                     notifyDataSetChanged();
                     return;
                 }
@@ -453,33 +423,24 @@ public class AccountsManagementFragment extends AccountWrapperFragment implement
         });
     }
 
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().contentEquals(LocalService.ACTION_ACCOUNT_UPDATE)) {
+                refreshAccountList();
+            }
+        }
+    };
 
-    @Override
-    public AsyncTaskLoader<Bundle> onCreateLoader(int arg0, Bundle arg1) {
-        accountsLoader = new AccountsLoader(getActivity(), mCallbacks.getService());
-        return accountsLoader;
-    }
-
-    @Override
-    public void onLoadFinished(Loader<Bundle> bundleLoader, Bundle results) {
-        mAccountsAdapter.removeAll();
-        ArrayList<Account> tmp = results.getParcelableArrayList(AccountsStateLoader.ACCOUNTS);
-        ip2ip = results.getParcelable(AccountsStateLoader.ACCOUNT_IP2IP);
-        mAccountsAdapter.addAll(tmp);
-        mIP2IPAdapter.removeAll();
-        mIP2IPAdapter.insert(ip2ip, 0);
+    private void refreshAccountList() {
+        Log.i(TAG, "refreshAccountList");
+        mAccountsAdapter.replaceAll(mCallbacks.getService().getAccounts());
         if (mAccountsAdapter.isEmpty()) {
             mDnDListView.setEmptyView(getView().findViewById(R.id.empty_account_list));
         }
-        for (Account acc : tmp) {
-
-        }
-        crossfade();
-    }
-
-    @Override
-    public void onLoaderReset(Loader<Bundle> bundleLoader) {
-
+        mIP2IPAdapter.replaceAll(mCallbacks.getService().getIP2IPAccount());
+        Log.i(TAG, "refreshAccountList DONE");
+        mAccountsAdapter.notifyDataSetChanged();
+        mIP2IPAdapter.notifyDataSetChanged();
     }
-
 }
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/AudioManagementFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/AudioManagementFragment.java
index ec688e08a..4f90c0055 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/AudioManagementFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/AudioManagementFragment.java
@@ -42,6 +42,7 @@ import cx.ring.model.account.AccountDetailAdvanced;
 import cx.ring.model.account.Account;
 import cx.ring.model.Codec;
 import cx.ring.service.ISipService;
+import cx.ring.service.LocalService;
 import cx.ring.views.dragsortlv.DragSortListView;
 
 import android.app.Activity;
@@ -73,26 +74,23 @@ public class AudioManagementFragment extends PreferenceFragment {
     ArrayList<Codec> codecs;
     private DragSortListView mCodecList;
     CodecAdapter listAdapter;
-    private static Callbacks sDummyCallbacks = new Callbacks() {
-
+    private static final Callbacks sDummyCallbacks = new Callbacks() {
         @Override
-        public ISipService getService() {
+        public ISipService getRemoteService() {
+            return null;
+        }
+        @Override
+        public LocalService getService() {
             return null;
         }
-
         @Override
         public Account getAccount() {
             return null;
         }
-
     };
 
-    public interface Callbacks {
-
-        public ISipService getService();
-
-        public Account getAccount();
-
+    public interface Callbacks extends LocalService.Callbacks {
+        Account getAccount();
     }
 
     @Override
@@ -104,7 +102,7 @@ public class AudioManagementFragment extends PreferenceFragment {
 
         mCallbacks = (Callbacks) activity;
         try {
-            codecs = (ArrayList<Codec>) mCallbacks.getService().getAudioCodecList(mCallbacks.getAccount().getAccountID());
+            codecs = (ArrayList<Codec>) mCallbacks.getRemoteService().getAudioCodecList(mCallbacks.getAccount().getAccountID());
             //mCallbacks.getService().getRingtoneList();
         } catch (RemoteException e) {
             e.printStackTrace();
@@ -125,7 +123,7 @@ public class AudioManagementFragment extends PreferenceFragment {
                 listAdapter.remove(item);
                 listAdapter.insert(item, to);
                 try {
-                    mCallbacks.getService().setActiveCodecList(getActiveCodecList(), mCallbacks.getAccount().getAccountID());
+                    mCallbacks.getRemoteService().setActiveCodecList(getActiveCodecList(), mCallbacks.getAccount().getAccountID());
                 } catch (RemoteException e) {
                     e.printStackTrace();
                 }
@@ -193,7 +191,7 @@ public class AudioManagementFragment extends PreferenceFragment {
                 listAdapter.getItem(pos).toggleState();
                 listAdapter.notifyDataSetChanged();
                 try {
-                    mCallbacks.getService().setActiveCodecList(getActiveCodecList(), mCallbacks.getAccount().getAccountID());
+                    mCallbacks.getRemoteService().setActiveCodecList(getActiveCodecList(), mCallbacks.getAccount().getAccountID());
                 } catch (RemoteException e) {
                     e.printStackTrace();
                 }
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.java
index 24bd94f8d..1abbce9ef 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/CallFragment.java
@@ -33,59 +33,68 @@ package cx.ring.fragments;
 
 import android.app.Activity;
 import android.app.FragmentManager;
+import android.net.Uri;
+import android.support.design.widget.FloatingActionButton;
+import android.support.v4.app.NotificationCompat;
+import android.support.v4.app.NotificationManagerCompat;
+import android.app.PendingIntent;
 import android.content.BroadcastReceiver;
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.res.Resources;
 import android.graphics.Bitmap;
-import android.graphics.BitmapFactory;
-import android.graphics.PointF;
 import android.net.wifi.WifiInfo;
 import android.net.wifi.WifiManager;
 import android.os.Bundle;
 import android.os.PowerManager;
 import android.os.PowerManager.WakeLock;
 import android.os.RemoteException;
-import android.util.FloatMath;
 import android.util.Log;
 import android.view.*;
-import android.view.SurfaceHolder.Callback;
 import android.view.View.OnClickListener;
 import android.view.inputmethod.InputMethodManager;
 import android.widget.*;
 import android.widget.CompoundButton.OnCheckedChangeListener;
 import cx.ring.R;
+import cx.ring.adapters.ContactPictureTask;
+import cx.ring.client.CallActivity;
+import cx.ring.client.ConversationActivity;
+import cx.ring.client.HomeActivity;
 import cx.ring.interfaces.CallInterface;
-import cx.ring.service.ISipService;
 
 import java.util.ArrayList;
 import java.util.Locale;
+import java.util.Random;
 
-import cx.ring.model.Attractor;
-import cx.ring.model.Bubble;
 import cx.ring.model.BubbleContact;
-import cx.ring.model.BubbleModel;
-import cx.ring.model.BubbleUser;
-import cx.ring.model.BubblesView;
 import cx.ring.model.CallContact;
 import cx.ring.model.Conference;
 import cx.ring.model.SecureSipCall;
 import cx.ring.model.SipCall;
+import cx.ring.model.account.Account;
+import cx.ring.service.LocalService;
+import cx.ring.service.SipService;
 
-public class CallFragment extends CallableWrapperFragment implements CallInterface, Callback {
+public class CallFragment extends CallableWrapperFragment implements CallInterface {
 
     static final String TAG = "CallFragment";
 
-
-
     private float bubbleSize = 75; // dip
     private float attractorSize = 40;
     public static final int REQUEST_TRANSFER = 10;
 
     // Screen wake lock for incoming call
     private WakeLock mScreenWakeLock;
+    private ImageView contactBubbleView;
+    private TextView contactBubbleTxt;
+    private View acceptButton;
+    private View refuseButton;
+    private View hangupButton;
+
+    private View securityIndicator;
 
+    /*
     private BubblesView mBubbleView;
     private BubbleModel mBubbleModel;
 
@@ -95,15 +104,15 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
     private Bitmap buttonUnhold;
     private Bitmap buttonTransfer;
     private Bitmap buttonHangUp;
-
+*/
     private final int BTN_MSG_IDX = 0;
     private final int BTN_HOLD_IDX = 1;
     private final int BTN_TRANSFER_IDX = 2;
     private final int BTN_HUNGUP_IDX = 3;
-
+/*
     private BubbleModel.ActionGroup userActions;
     private BubbleModel.ActionGroup callActions;
-
+*/
     ViewSwitcher mSecuritySwitch;
     private TextView mCallStatusTxt;
     private ToggleButton mToggleSpeakers;
@@ -124,10 +133,11 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
 
     @Override
     public void onCreate(Bundle savedBundle) {
+        Log.i(TAG, "onCreate");
         super.onCreate(savedBundle);
 
         Resources r = getResources();
-
+/*
         bubbleSize = r.getDimension(R.dimen.bubble_size);
         attractorSize = r.getDimension(R.dimen.bubble_action_size);
         float attractorMargin = r.getDimension(R.dimen.bubble_action_margin);
@@ -203,7 +213,6 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
 
             @Override
             public boolean bubbleEjected(Bubble b) {
-                //if (b.isUser) {
                 try {
                     if (b.isConference())
                         mCallbacks.getService().hangUpConference(b.getCallID());
@@ -214,15 +223,13 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
                     e.printStackTrace();
                 }
                 return true;
-                /*}
-                return false;*/
             }
-        });
+        });*/
 
         setHasOptionsMenu(true);
         PowerManager powerManager = (PowerManager) getActivity().getSystemService(Context.POWER_SERVICE);
         mScreenWakeLock = powerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP | PowerManager.ON_AFTER_RELEASE,
-                "org.sflphone.onIncomingCall");
+                "cx.ring.onIncomingCall");
         mScreenWakeLock.setReferenceCounted(false);
 
         Log.d(TAG, "Acquire wake up lock");
@@ -240,65 +247,38 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
     }
 
     /**
-     * A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity.
+     * The Activity calling this fragment has to implement this interface
      */
-    private static Callbacks sDummyCallbacks = new Callbacks() {
-
-        @Override
-        public void onFragmentCreated() {
-
-        }
+    public interface Callbacks extends LocalService.Callbacks {
+        void onFragmentCreated();
+        void startTimer();
+        void terminateCall();
+        Conference getDisplayedConference();
+        void updateDisplayedConference(Conference c);
+    }
 
+    /**
+     * A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity.
+     */
+    private static class DummyCallbacks extends LocalService.DummyCallbacks implements Callbacks {
         @Override
-        public ISipService getService() {
-            return null;
-        }
-
+        public void onFragmentCreated() {}
         @Override
-        public void terminateCall() {
-        }
-
+        public void terminateCall() {}
         @Override
         public Conference getDisplayedConference() {
             return null;
         }
-
         @Override
-        public void updateDisplayedConference(Conference c) {
-        }
-
-        @Override
-        public void startTimer() {
-        }
-
+        public void updateDisplayedConference(Conference c) { }
         @Override
-        public void slideChatScreen() {
-        }
-
-    };
-
-    /**
-     * The Activity calling this fragment has to implement this interface
-     */
-    public interface Callbacks {
-
-        public void onFragmentCreated();
-
-        public ISipService getService();
-
-        public void startTimer();
-
-        public void slideChatScreen();
-
-        public void terminateCall();
-
-        public Conference getDisplayedConference();
-
-        public void updateDisplayedConference(Conference c);
+        public void startTimer() { }
     }
+    private static final Callbacks sDummyCallbacks = new DummyCallbacks();
 
     @Override
     public void onAttach(Activity activity) {
+        Log.i(TAG, "onAttach");
         super.onAttach(activity);
 
         if (!(activity instanceof Callbacks)) {
@@ -312,6 +292,30 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
 
     }
 
+    public void refreshState() {
+        Conference conf = getConference();
+        if (conf == null)  {
+            contactBubbleView.setImageBitmap(null);
+            contactBubbleTxt.setText("");
+            acceptButton.setVisibility(View.GONE);
+            refuseButton.setVisibility(View.GONE);
+            hangupButton.setVisibility(View.GONE);
+        } else if (conf.getParticipants().size() == 1) {
+            SipCall call = conf.getParticipants().get(0);
+            if (call.isIncoming() && call.isRinging()) {
+                Log.w(TAG, "CallFragment refreshState INCOMING " + call.getCallId());
+                initIncomingCallDisplay();
+            } else if (conf.getParticipants().get(0).isRinging()) {
+                Log.w(TAG, "CallFragment refreshState RINGING " + call.getCallId());
+                initOutGoingCallDisplay();
+            } else if (call.isOngoing()) {
+                initNormalStateDisplay();
+            }
+        } else if (conf.getParticipants().size() > 1) {
+            initNormalStateDisplay();
+        }
+    }
+
     @Override
     public void onCreateOptionsMenu(Menu m, MenuInflater inf) {
         super.onCreateOptionsMenu(m, inf);
@@ -323,7 +327,15 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
         super.onOptionsItemSelected(item);
         switch (item.getItemId()) {
             case R.id.menuitem_chat:
-                mCallbacks.slideChatScreen();
+                //mCallbacks.slideChatScreen();
+                Intent intent = new Intent()
+                        .setClass(getActivity(), ConversationActivity.class)
+                        .setAction(Intent.ACTION_VIEW)
+                        .setData(Uri.withAppendedPath(ConversationActivity.CONTENT_URI, getConference().getParticipants().get(0).getContact().getIds().get(0)));
+                intent.putExtra("resuming", true);
+                //intent.putExtra("contact", ((Conversation) v.getTag()).getContact());
+                //intent.putExtra("conversation", (Conversation) v.getTag());
+                startActivityForResult(intent, HomeActivity.REQUEST_CODE_CONVERSATION);
                 break;
         }
 
@@ -345,6 +357,7 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
     public void onResume() {
         super.onResume();
         initializeWiFiListener();
+        refreshState();
     }
 
     @Override
@@ -358,7 +371,13 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
 
     @Override
     public void callStateChanged(Conference updated, String callID, String newState) {
-        mCallbacks.updateDisplayedConference(updated);
+        Conference cur = getConference();
+        if (cur.getId().equals(callID) || cur.getCallById(callID) != null) {
+            mCallbacks.updateDisplayedConference(updated);
+        } else {
+            return;
+        }
+
         Log.i(TAG, "Call :" + callID + " " + newState);
 
         if (getConference().isOnGoing()) {
@@ -371,6 +390,8 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
             } else
                 initOutGoingCallDisplay();
         } else {
+            NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getActivity());
+            notificationManager.cancel(getConference().notificationId);
             mCallStatusTxt.setText(newState);
             mCallbacks.terminateCall();
         }
@@ -420,7 +441,7 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
                     transfer = data.getParcelableExtra("transfer");
                     try {
 
-                        mCallbacks.getService().attendedTransfer(transfer.getCallId(), c.getParticipants().get(0).getCallId());
+                        mCallbacks.getRemoteService().attendedTransfer(transfer.getCallId(), c.getParticipants().get(0).getCallId());
 
                     } catch (RemoteException e) {
                         e.printStackTrace();
@@ -431,17 +452,17 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
                     String to = data.getStringExtra("to_number");
                     transfer = data.getParcelableExtra("transfer");
                     try {
-                        mCallbacks.getService().transfer(transfer.getCallId(), to);
-                        mCallbacks.getService().hangUp(transfer.getCallId());
+                        mCallbacks.getRemoteService().transfer(transfer.getCallId(), to);
+                        mCallbacks.getRemoteService().hangUp(transfer.getCallId());
                     } catch (RemoteException e) {
                         e.printStackTrace();
                     }
                     break;
                 case Activity.RESULT_CANCELED:
                 default:
-                    synchronized (mBubbleModel) {
+                    /*synchronized (mBubbleModel) {
                         mBubbleModel.clear();
-                    }
+                    }*/
                     initNormalStateDisplay();
                     break;
             }
@@ -453,10 +474,17 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
         Log.i(TAG, "onCreateView");
         final ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.frag_call, container, false);
 
+/*
         mBubbleView = (BubblesView) rootView.findViewById(R.id.main_view);
         //mBubbleView.setFragment(this);
         mBubbleView.setModel(mBubbleModel);
         mBubbleView.getHolder().addCallback(this);
+*/
+        contactBubbleView = (ImageView) rootView.findViewById(R.id.contact_bubble);
+        contactBubbleTxt = (TextView) rootView.findViewById(R.id.contact_bubble_txt);
+        acceptButton  = rootView.findViewById(R.id.call_accept_btn);
+        refuseButton  = rootView.findViewById(R.id.call_refuse_btn);
+        hangupButton  = rootView.findViewById(R.id.call_hangup_btn);
 
         mCallStatusTxt = (TextView) rootView.findViewById(R.id.call_status_txt);
 
@@ -468,18 +496,18 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
             @Override
             public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                 try {
-                    mCallbacks.getService().toggleSpeakerPhone(isChecked);
+                    mCallbacks.getRemoteService().toggleSpeakerPhone(isChecked);
                 } catch (RemoteException e) {
                     e.printStackTrace();
                 }
 
             }
         });
-
+/*
         synchronized (mBubbleModel) {
             mBubbleModel.setSize(mBubbleView.getWidth(), mBubbleView.getHeight() - mToggleSpeakers.getHeight(), bubbleSize);
-        }
-
+        }*/
+/*
         rootView.findViewById(R.id.dialpad_btn).setOnClickListener(new OnClickListener() {
 
             @Override
@@ -487,7 +515,9 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
                 InputMethodManager lManager = (InputMethodManager) getActivity().getSystemService(Context.INPUT_METHOD_SERVICE);
                 lManager.toggleSoftInput(InputMethodManager.SHOW_IMPLICIT, InputMethodManager.HIDE_IMPLICIT_ONLY);
             }
-        });
+        });*/
+
+        securityIndicator = rootView.findViewById(R.id.security_indicator);
 
         return rootView;
     }
@@ -498,7 +528,49 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
 
     private void initNormalStateDisplay() {
         Log.i(TAG, "Start normal display");
-        synchronized (mBubbleModel) {
+        mCallbacks.startTimer();
+        acceptButton.setVisibility(View.GONE);
+        refuseButton.setVisibility(View.GONE);
+
+        final SipCall call = getConference().getParticipants().get(0);
+        CallContact contact = call.getContact();
+        //contactBubbleView.setImageBitmap(getContactPhoto(contact, contactBubbleView.getWidth()));
+        new ContactPictureTask(getActivity(), contactBubbleView, contact).run();
+        contactBubbleTxt.setText(contact.getDisplayName());
+
+        hangupButton.setVisibility(View.VISIBLE);
+        hangupButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                try {
+                    mCallbacks.getRemoteService().hangUp(call.getCallId());
+                    mCallbacks.terminateCall();
+                } catch (RemoteException e) {
+                    e.printStackTrace();
+                }
+            }
+        });
+
+        NotificationCompat.Builder noti = new NotificationCompat.Builder(getActivity())
+                .setContentTitle("Current call with " + contact.getDisplayName())
+                .setOngoing(true)
+                .setSmallIcon(R.drawable.ic_launcher)
+                .setContentText("call")
+                .setContentIntent(PendingIntent.getActivity(getActivity(), new Random().nextInt(),
+                        new Intent(getActivity(), CallActivity.class).putExtra("conference", getConference()), PendingIntent.FLAG_ONE_SHOT))
+                .addAction(R.drawable.ic_call_end_white_24dp, "Hangup",
+                        PendingIntent.getService(getActivity(), new Random().nextInt(),
+                                new Intent(getActivity(), SipService.class)
+                                        .setAction(SipService.ACTION_CALL_END)
+                                        .putExtra("conf", call.getCallId()),
+                                PendingIntent.FLAG_ONE_SHOT));
+        Log.w("CallNotification ", "Updating " + getConference().notificationId + " for " + contact.getDisplayName());
+        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getActivity());
+        notificationManager.notify(getConference().notificationId, noti.build());
+
+        getActivity().getActionBar().setTitle(contact.getDisplayName());
+
+        /*synchronized (mBubbleModel) {
             mCallbacks.startTimer();
             mBubbleModel.clearAttractors();
             PointF c = mBubbleModel.getCircleCenter();
@@ -513,19 +585,28 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
                 if (partee == null) {
                     continue;
                 }
-                float dX = FloatMath.cos(angle_part * i + angle_shift) * radiusCalls;
-                float dY = FloatMath.sin(angle_part * i + angle_shift) * radiusCalls;
+                double dX = Math.cos(angle_part * i + angle_shift) * radiusCalls;
+                double dY = Math.sin(angle_part * i + angle_shift) * radiusCalls;
                 getBubbleFor(partee, (int) (c.x + dX), (int) (c.y + dY));
             }
         }
-        mBubbleModel.curState = BubbleModel.State.Incall;
+        mBubbleModel.curState = BubbleModel.State.Incall;*/
         updateSecurityDisplay();
     }
 
     private void updateSecurityDisplay() {
-
         //First we check if at least one participant use a security layer.
-        if (!getConference().useSecureLayer())
+        boolean secure_call = false;
+        for (SipCall c : getConference().getParticipants()) {
+            Account acc = mCallbacks.getService().getAccount(c.getAccount());
+            if (acc != null && (acc.isRing() || acc.useSecureLayer())) {
+                secure_call = true;
+                break;
+            }
+        }
+
+        securityIndicator.setVisibility(secure_call ? View.VISIBLE : View.GONE);
+        if (!secure_call)
             return;
 
         Log.i(TAG, "Enable security display");
@@ -550,7 +631,7 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
                         @Override
                         public void onClick(View v) {
                             try {
-                                mCallbacks.getService().confirmSAS(secured.getCallId());
+                                mCallbacks.getRemoteService().confirmSAS(secured.getCallId());
                                 showLock(R.drawable.green_lock);
                             } catch (RemoteException e) {
                                 e.printStackTrace();
@@ -573,18 +654,86 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
         mSecuritySwitch.setVisibility(View.VISIBLE);
     }
 
+    protected Bitmap getContactPhoto(CallContact contact, int size) {
+        if (contact.getPhotoId() > 0) {
+            return ContactPictureTask.loadContactPhoto(getActivity().getContentResolver(), contact.getId());
+        } else {
+            return ContactPictureTask.decodeSampledBitmapFromResource(getResources(), R.drawable.ic_contact_picture, size, size);
+        }
+    }
+
     private void initIncomingCallDisplay() {
         Log.i(TAG, "Start incoming display");
-        if (getConference().getParticipants().get(0).getAccount().isAutoanswerEnabled()) {
+        if (mCallbacks.getService().getAccount(getConference().getParticipants().get(0).getAccount()).isAutoanswerEnabled()) {
             try {
-                mCallbacks.getService().accept(getConference().getParticipants().get(0).getCallId());
+                mCallbacks.getRemoteService().accept(getConference().getParticipants().get(0).getCallId());
             } catch (RemoteException e) {
                 e.printStackTrace();
             } catch (NullPointerException e) {
                 e.printStackTrace();
             }
         } else {
-            getBubbleFor(getConference().getParticipants().get(0), mBubbleModel.getWidth() / 2, 2 * mBubbleModel.getHeight() / 3);
+            final SipCall call = getConference().getParticipants().get(0);
+            CallContact contact = call.getContact();
+            //contactBubbleView.setImageBitmap(getContactPhoto(contact, contactBubbleView.getWidth()));
+            new ContactPictureTask(getActivity(), contactBubbleView, contact).run();
+            contactBubbleTxt.setText(contact.getDisplayName());
+            acceptButton.setVisibility(View.VISIBLE);
+            acceptButton.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    acceptButton.setOnClickListener(null);
+                    refuseButton.setOnClickListener(null);
+                    try {
+                        mCallbacks.getRemoteService().accept(call.getCallId());
+                    } catch (RemoteException e) {
+                        e.printStackTrace();
+                    }
+                }
+            });
+            refuseButton.setVisibility(View.VISIBLE);
+            refuseButton.setOnClickListener(new OnClickListener() {
+                @Override
+                public void onClick(View v) {
+                    acceptButton.setOnClickListener(null);
+                    refuseButton.setOnClickListener(null);
+                    try {
+                        mCallbacks.getRemoteService().refuse(call.getCallId());
+                        mCallbacks.terminateCall();
+                    } catch (RemoteException e) {
+                        e.printStackTrace();
+                    }
+                }
+            });
+            hangupButton.setVisibility(View.GONE);
+
+            NotificationCompat.Builder noti = new NotificationCompat.Builder(getActivity())
+                    .setContentTitle("Incoming call with " + contact.getDisplayName())
+                    .setContentText("incoming call")
+                    .setOngoing(true)
+                    .setSmallIcon(R.drawable.ic_launcher)
+                    .setContentIntent(PendingIntent.getActivity(getActivity(), new Random().nextInt(),
+                            new Intent(getActivity(), CallActivity.class).putExtra("conference", getConference()), PendingIntent.FLAG_ONE_SHOT))
+                    .addAction(R.drawable.ic_action_accept, "Accept",
+                            PendingIntent.getService(getActivity(), new Random().nextInt(),
+                                    new Intent(getActivity(), SipService.class)
+                                            .setAction(SipService.ACTION_CALL_ACCEPT)
+                                            .putExtra("conf", call.getCallId()),
+                                    PendingIntent.FLAG_ONE_SHOT))
+                    .addAction(R.drawable.ic_call_end_white_24dp, "Refuse",
+                            PendingIntent.getService(getActivity(), new Random().nextInt(),
+                                    new Intent(getActivity(), SipService.class)
+                                            .setAction(SipService.ACTION_CALL_REFUSE)
+                                            .putExtra("conf", call.getCallId()),
+                                    PendingIntent.FLAG_ONE_SHOT));
+            Log.w("CallNotification ", "Updating for incoming " + getConference().notificationId);
+            NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getActivity());
+            notificationManager.notify(getConference().notificationId, noti.build());
+
+            getActivity().getActionBar().setTitle(contact.getDisplayName());
+
+
+            /*getBubbleFor(getConference().getParticipants().get(0), mBubbleModel.getWidth() / 2, 2 * mBubbleModel.getHeight() / 3);
             synchronized (mBubbleModel) {
                 mBubbleModel.clearAttractors();
                 mBubbleModel.addAttractor(new Attractor(new PointF(3 * mBubbleModel.getWidth() / 4, 2 * mBubbleModel.getHeight() / 3), attractorSize, new Attractor.Callback() {
@@ -616,13 +765,56 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
                     }
                 }, buttonHangUp));
             }
-            mBubbleModel.curState = BubbleModel.State.Incoming;
+            mBubbleModel.curState = BubbleModel.State.Incoming;*/
         }
     }
 
     private void initOutGoingCallDisplay() {
         Log.i(TAG, "Start outgoing display");
-        synchronized (mBubbleModel) {
+
+        final SipCall call = getConference().getParticipants().get(0);
+        CallContact contact = call.getContact();
+        //contactBubbleView.setImageBitmap(getContactPhoto(contact, contactBubbleView.getWidth()));
+        new ContactPictureTask(getActivity(), contactBubbleView, contact).run();
+        contactBubbleTxt.setText(contact.getDisplayName());
+
+        acceptButton.setVisibility(View.GONE);
+        refuseButton.setVisibility(View.GONE);
+
+        hangupButton.setVisibility(View.VISIBLE);
+        hangupButton.setOnClickListener(new OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                try {
+                    mCallbacks.getRemoteService().hangUp(call.getCallId());
+                    mCallbacks.terminateCall();
+                } catch (RemoteException e) {
+                    e.printStackTrace();
+                }
+            }
+        });
+
+        NotificationCompat.Builder noti = new NotificationCompat.Builder(getActivity())
+                .setContentTitle("Outgoing call with " + contact.getDisplayName())
+                .setOngoing(true)
+                .setSmallIcon(R.drawable.ic_launcher)
+                .setContentText("Outgoing call")
+                .setContentIntent(PendingIntent.getActivity(getActivity(), new Random().nextInt(),
+                        new Intent(getActivity(), CallActivity.class).putExtra("conference", getConference()), PendingIntent.FLAG_ONE_SHOT))
+                .addAction(R.drawable.ic_call_end_white_24dp, "Cancel",
+                        PendingIntent.getService(getActivity(), new Random().nextInt(),
+                                new Intent(getActivity(), SipService.class)
+                                        .setAction(SipService.ACTION_CALL_END)
+                                        .putExtra("conf", call.getCallId()),
+                                PendingIntent.FLAG_ONE_SHOT));
+
+        Log.w("CallNotification ", "Updating for outgoing " + getConference().notificationId);
+        NotificationManagerCompat notificationManager = NotificationManagerCompat.from(getActivity());
+        notificationManager.notify(getConference().notificationId, noti.build());
+
+        getActivity().getActionBar().setTitle(contact.getDisplayName());
+
+        /*synchronized (mBubbleModel) {
             PointF c = mBubbleModel.getCircleCenter();
             float radiusCalls = mBubbleModel.getCircleSize();
             getBubbleForUser(getConference(), c.x, c.y);
@@ -634,18 +826,18 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
             }
             mBubbleModel.clearAttractors();
         }
-        mBubbleModel.curState = BubbleModel.State.Outgoing;
-    }
-
-    /**
-     * Retrieves or create a bubble for a given contact. If the bubble exists, it is moved to the new location.
-     *
-     * @param call The call associated to a contact
-     * @param x    Initial or new x position.
-     * @param y    Initial or new y position.
-     * @return Bubble corresponding to the contact.
-     */
-    private Bubble getBubbleFor(SipCall call, float x, float y) {
+        mBubbleModel.curState = BubbleModel.State.Outgoing;*/
+    }
+    /*
+        /**
+         * Retrieves or create a bubble for a given contact. If the bubble exists, it is moved to the new location.
+         *
+         * @param call The call associated to a contact
+         * @param x    Initial or new x position.
+         * @param y    Initial or new y position.
+         * @return Bubble corresponding to the contact.
+         */
+   /*  private Bubble getBubbleFor(SipCall call, float x, float y) {
         Bubble contact_bubble = mBubbleModel.getBubble(call.getCallId());
         if (contact_bubble != null) {
             ((BubbleContact) contact_bubble).setCall(call);
@@ -670,31 +862,41 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
 
         contact_bubble = new BubbleUser(getActivity(), CallContact.ContactBuilder.buildUserContact(getActivity().getContentResolver()), conf, x, y,
                 bubbleSize * 1.3f);
-/*
-        try {
-            ((BubbleUser) contact_bubble).setMute(mCallbacks.getService().isCaptureMuted());
-        } catch (RemoteException e) {
-            e.printStackTrace();
-        } catch (NullPointerException e1) {
-            e1.printStackTrace();
-        }*/
         mBubbleModel.addBubble(contact_bubble);
         return contact_bubble;
     }
 
+
     public boolean canOpenIMPanel() {
         return mBubbleModel.curState == BubbleModel.State.Incall && (mBubbleView == null || !mBubbleView.isDraggingBubble());
     }
 
+
     @Override
     public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
         synchronized (mBubbleModel) {
             mBubbleModel.setSize(width, height, bubbleSize);
         }
+        Log.w(TAG, "CallFragment surfaceChanged " + getConference().getParticipants().size());
         if (getConference().getParticipants().size() == 1) {
             if (getConference().getParticipants().get(0).isIncoming() && getConference().getParticipants().get(0).isRinging()) {
+                Log.w(TAG, "CallFragment surfaceChanged INCOMING" + getConference().getParticipants().get(0).getCallId());
                 initIncomingCallDisplay();
             } else if (getConference().getParticipants().get(0).isRinging()) {
+                Log.w(TAG, "CallFragment surfaceChanged RINGING" + getConference().getParticipants().get(0).getCallId());
+                initOutGoingCallDisplay();
+            } else if (getConference().getParticipants().get(0).isOngoing()) {
+                initNormalStateDisplay();
+            }
+        } else if (getConference().getParticipants().size() > 1) {
+            initNormalStateDisplay();
+        }
+        if (getConference().getParticipants().size() == 1) {
+            if (getConference().getParticipants().get(0).isIncoming() && getConference().getParticipants().get(0).isRinging()) {
+                Log.w(TAG, "CallFragment surfaceChanged INCOMING" + getConference().getParticipants().get(0).getCallId());
+                initIncomingCallDisplay();
+            } else if (getConference().getParticipants().get(0).isRinging()) {
+                Log.w(TAG, "CallFragment surfaceChanged RINGING" + getConference().getParticipants().get(0).getCallId());
                 initOutGoingCallDisplay();
             } else if (getConference().getParticipants().get(0).isOngoing()) {
                 initNormalStateDisplay();
@@ -703,13 +905,13 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
             initNormalStateDisplay();
         }
     }
-
+*/
     public void makeTransfer(BubbleContact contact) {
         FragmentManager fm = getFragmentManager();
         editName = TransferDFragment.newInstance();
         Bundle b = new Bundle();
         try {
-            b.putParcelableArrayList("calls", (ArrayList<Conference>) mCallbacks.getService().getConcurrentCalls());
+            b.putParcelableArrayList("calls", (ArrayList<Conference>) mCallbacks.getRemoteService().getConcurrentCalls());
             b.putParcelable("call_selected", contact.associated_call);
             editName.setArguments(b);
             editName.setTargetFragment(this, REQUEST_TRANSFER);
@@ -719,7 +921,7 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
         }
 
     }
-
+/*
     @Override
     public void surfaceCreated(SurfaceHolder holder) {
 
@@ -738,10 +940,10 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
     public BubblesView getBubbleView() {
         return mBubbleView;
     }
-
+*/
     public void updateTime() {
         if (getConference() != null) {
-            long duration = System.currentTimeMillis() - getConference().getParticipants().get(0).getTimestampStart_();
+            long duration = System.currentTimeMillis() - getConference().getParticipants().get(0).getTimestampStart();
             duration = duration / 1000;
             if (getConference().isOnGoing())
                 mCallStatusTxt.setText(String.format("%d:%02d:%02d", duration / 3600, duration % 3600 / 60, duration % 60));
@@ -760,7 +962,7 @@ public class CallFragment extends CallableWrapperFragment implements CallInterfa
                     String toSend = Character.toString(event.getDisplayLabel());
                     toSend = toSend.toUpperCase(Locale.getDefault());
                     Log.d(TAG, "toSend " + toSend);
-                    mCallbacks.getService().playDtmf(toSend);
+                    mCallbacks.getRemoteService().playDtmf(toSend);
                     break;
             }
         } catch (RemoteException e) {
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/CallListFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/CallListFragment.java
index 997085ea4..36a19db0a 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/CallListFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/CallListFragment.java
@@ -31,60 +31,124 @@
 package cx.ring.fragments;
 
 import android.app.Activity;
+import android.app.Fragment;
+import android.content.BroadcastReceiver;
 import android.content.ClipData;
 import android.content.ClipData.Item;
 import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
+import android.graphics.Bitmap;
 import android.graphics.Color;
+import android.net.Uri;
 import android.os.*;
+import android.support.design.widget.FloatingActionButton;
 import android.util.Log;
+import android.util.LruCache;
 import android.view.DragEvent;
 import android.view.LayoutInflater;
 import android.view.View;
 import android.view.View.DragShadowBuilder;
 import android.view.View.OnDragListener;
 import android.view.ViewGroup;
+import android.view.animation.AnimationUtils;
 import android.widget.*;
 import android.widget.AdapterView.OnItemClickListener;
 import android.widget.AdapterView.OnItemLongClickListener;
 
-import cx.ring.client.CallActivity;
+import cx.ring.R;
+import cx.ring.adapters.ContactPictureTask;
+import cx.ring.client.ConversationActivity;
 import cx.ring.client.HomeActivity;
+import cx.ring.client.NewConversationActivity;
 import cx.ring.model.Conference;
-import cx.ring.service.ISipService;
+import cx.ring.model.Conversation;
+import cx.ring.service.LocalService;
 
+import java.lang.ref.WeakReference;
+import java.text.DateFormat;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.HashMap;
-import java.util.Observable;
-import java.util.Observer;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
 
-public class CallListFragment extends CallableWrapperFragment {
+public class CallListFragment extends Fragment {
 
     private static final String TAG = CallListFragment.class.getSimpleName();
 
-    private Callbacks mCallbacks = sDummyCallbacks;
-    private TextView mConversationsTitleTextView;
-    CallListAdapter mConferenceAdapter;
+    private LocalService.Callbacks mCallbacks = LocalService.DUMMY_CALLBACKS;
+    //private TextView mConversationsTitleTextView;
+    private CallListAdapter mConferenceAdapter;
+    private FloatingActionButton newconv_btn = null;
 
-    public static final int REQUEST_TRANSFER = 10;
-    public static final int REQUEST_CONF = 20;
+    @Override
+    public void onStart() {
+        Log.i(TAG, "onStart");
+        super.onStart();
+        // Bind to LocalService
+        /*Intent intent = new Intent(getActivity(), LocalService.class);
+        getActivity().bindService(intent, mConnection, Context.BIND_AUTO_CREATE);*/
+
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(LocalService.ACTION_CONF_UPDATE);
+        getActivity().registerReceiver(receiver, intentFilter);
+        updateLists();
+    }
 
-    /**
-     * A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity.
-     */
-    private static Callbacks sDummyCallbacks = new Callbacks() {
+    @Override
+    public void onStop() {
+        Log.i(TAG, "onStop");
+        super.onStop();
+        // Unbind from the service
+        /*if (mBound) {
+            getActivity().unbindService(mConnection);
+            mBound = false;
+        }*/
+        getActivity().unregisterReceiver(receiver);
+    }
 
+    final BroadcastReceiver receiver = new BroadcastReceiver() {
         @Override
-        public ISipService getService() {
-            Log.i(TAG, "I'm a dummy");
-            return null;
+        public void onReceive(Context context, Intent intent) {
+            Log.w(TAG, "onReceive " + intent.getAction() + " " + intent.getDataString());
+            updateLists();
         }
+    };
+/*
+    private ServiceConnection mConnection = new ServiceConnection() {
+
+        @Override
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            Log.w(TAG, "onServiceConnected " + className.getClassName());
+            // We've bound to LocalService, cast the IBinder and get LocalService instance
+            LocalService.LocalBinder binder = (LocalService.LocalBinder) service;
+            mService = binder.getService();
+            IntentFilter intentFilter = new IntentFilter();
+            intentFilter.addAction(LocalService.ACTION_CONF_UPDATE);
 
+            getActivity().registerReceiver(receiver, intentFilter);
+            mBound = true;
+
+            updateLists();
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName arg0) {
+            Log.w(TAG, "onServiceDisconnected " + arg0.getClassName());
+            getActivity().unregisterReceiver(receiver);
+            mBound = false;
+        }
     };
+*/
 
+    public static final int REQUEST_TRANSFER = 10;
+    public static final int REQUEST_CONF = 20;
+
+    /*
     @Override
-    public void callStateChanged(Conference c, String callID, String state) {
-        Log.i(TAG, "callStateChanged" + callID + "    " + state);
+    public void callStateChanged(Conference c, String callID, String State) {
+        Log.i(TAG, "callStateChanged " + callID + "    " + State);
         updateLists();
     }
 
@@ -101,7 +165,7 @@ public class CallListFragment extends CallableWrapperFragment {
     }
 
     @Override
-    public void confChanged(Conference c, String id, String state) {
+    public void confChanged(Conference c, String id, String State) {
         Log.i(TAG, "confChanged");
         updateLists();
     }
@@ -111,26 +175,29 @@ public class CallListFragment extends CallableWrapperFragment {
         Log.i(TAG, "confChanged");
         updateLists();
     }
-
-    /**
-     * The Activity calling this fragment has to implement this interface
-     */
-    public interface Callbacks {
-        public ISipService getService();
-    }
+*/
 
     @Override
     public void onAttach(Activity activity) {
+        Log.i(TAG, "onAttach");
         super.onAttach(activity);
 
-        if (!(activity instanceof Callbacks)) {
+        if (!(activity instanceof LocalService.Callbacks)) {
             throw new IllegalStateException("Activity must implement fragment's callbacks.");
         }
 
-        mCallbacks = (Callbacks) activity;
-
+        mCallbacks = (LocalService.Callbacks) activity;
+        if (mCallbacks.getService() != null) {
+            /*mConvList = new ConversationList(getActivity(), mCallbacks.getService());
+            if (mConferenceAdapter != null) {
+                Log.i(TAG, "mConvList.addObserver");
+                mConferenceAdapter.updateDataset(mConvList.getConversations());
+                mConvList.addObserver(mConferenceAdapter);
+            }*/
+        }
     }
 
+    /*
     private Runnable mUpdateTimeTask = new Runnable() {
         public void run() {
             final long start = SystemClock.uptimeMillis();
@@ -142,52 +209,51 @@ public class CallListFragment extends CallableWrapperFragment {
             mConferenceAdapter.notifyDataSetChanged();
             mHandler.postAtTime(this, start + (((minutes * 60) + seconds + 1) * 1000));
         }
-    };
+    };*/
 
-    private Handler mHandler = new Handler();
+    //private Handler mHandler = new Handler();
 
+    /*9
     @Override
     public void onResume() {
         super.onResume();
         if (mCallbacks.getService() != null) {
+            if (mConvList != null)
+                mConvList.startListener();
 
             updateLists();
-            if (!mConferenceAdapter.isEmpty()) {
-                mHandler.postDelayed(mUpdateTimeTask, 0);
-            }
         }
 
     }
-
-    @SuppressWarnings("unchecked")
-    // No proper solution with HashMap runtime cast
+*/
     public void updateLists() {
-        try {
-            HashMap<String, Conference> confs = (HashMap<String, Conference>) mCallbacks.getService().getConferenceList();
-            String newTitle = getResources().getQuantityString(cx.ring.R.plurals.home_conferences_title, confs.size(), confs.size());
-            mConversationsTitleTextView.setText(newTitle);
-            mConferenceAdapter.updateDataset(new ArrayList<Conference>(confs.values()));
-        } catch (RemoteException e) {
-            e.printStackTrace();
-        }
+        if (mCallbacks.getService() != null)
+            mConferenceAdapter.updateDataset(mCallbacks.getService().getConversations());
     }
 
     @Override
     public void onDetach() {
+        Log.i(TAG, "onDetach");
         super.onDetach();
-        mCallbacks = sDummyCallbacks;
-
+        mCallbacks = LocalService.DUMMY_CALLBACKS;
     }
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
+        Log.i(TAG, "onCreate");
         super.onCreate(savedInstanceState);
     }
 
     @Override
     public void onPause() {
         super.onPause();
-        mHandler.removeCallbacks(mUpdateTimeTask);
+        //mHandler.removeCallbacks(mUpdateTimeTask);
+    }
+
+    @Override
+    public void onResume() {
+        super.onResume();
+        ((HomeActivity)getActivity()).setToolbarState(false, R.string.app_name);
     }
 
     @Override
@@ -200,24 +266,51 @@ public class CallListFragment extends CallableWrapperFragment {
         Log.i(TAG, "onCreateView");
         View inflatedView = inflater.inflate(cx.ring.R.layout.frag_call_list, container, false);
 
-        mConversationsTitleTextView = (TextView) inflatedView.findViewById(cx.ring.R.id.confs_counter);
+        newconv_btn = (FloatingActionButton) inflatedView.findViewById(R.id.newconv_fab);
+        newconv_btn.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                startActivity(new Intent().setClass(getActivity(), NewConversationActivity.class));
+            }
+        });
 
+        //mConversationsTitleTextView = (TextView) inflatedView.findViewById(cx.ring.R.id.confs_counter);
+/*
+        if (mConferenceAdapter != null && mConvList != null)
+            mConvList.deleteObserver(mConferenceAdapter);*/
         mConferenceAdapter = new CallListAdapter(getActivity());
-        ((ListView) inflatedView.findViewById(cx.ring.R.id.confs_list)).setAdapter(mConferenceAdapter);
-        ((ListView) inflatedView.findViewById(cx.ring.R.id.confs_list)).setOnItemClickListener(callClickListener);
-        ((ListView) inflatedView.findViewById(cx.ring.R.id.confs_list)).setOnItemLongClickListener(mItemLongClickListener);
+        /*if (mConvList != null) {
+            Log.i(TAG, "mConvList.addObserver");
+            mConferenceAdapter.updateDataset(mConvList.getConversations());
+            mConvList.addObserver(mConferenceAdapter);
+        }*/
+        /*if (mBound) {
+            mConferenceAdapter.updateDataset(mService.getConversations());
+        }*/
+        LocalService service = mCallbacks.getService();
+        if (service != null)
+            mConferenceAdapter.updateDataset(mCallbacks.getService().getConversations());
+
+        ListView list = (ListView) inflatedView.findViewById(cx.ring.R.id.confs_list);
+        list.setAdapter(mConferenceAdapter);
+        list.setOnItemClickListener(callClickListener);
+        list.setOnItemLongClickListener(mItemLongClickListener);
 
         return inflatedView;
     }
 
-    OnItemClickListener callClickListener = new OnItemClickListener() {
+    private final OnItemClickListener callClickListener = new OnItemClickListener() {
 
         @Override
         public void onItemClick(AdapterView<?> arg0, View v, int arg2, long arg3) {
-            Intent intent = new Intent().setClass(getActivity(), CallActivity.class);
+            Intent intent = new Intent()
+                    .setClass(getActivity(), ConversationActivity.class)
+                    .setAction(Intent.ACTION_VIEW)
+                    .setData(Uri.withAppendedPath(ConversationActivity.CONTENT_URI, ((CallListAdapter.ViewHolder) v.getTag()).conv.getContact().getIds().get(0)));
             intent.putExtra("resuming", true);
-            intent.putExtra("conference", (Conference) v.getTag());
-            startActivityForResult(intent, HomeActivity.REQUEST_CODE_CALL);
+            //intent.putExtra("contact", ((Conversation) v.getTag()).getContact());
+            //intent.putExtra("conversation", (Conversation) v.getTag());
+            startActivityForResult(intent, HomeActivity.REQUEST_CODE_CONVERSATION);
         }
     };
 
@@ -229,7 +322,8 @@ public class CallListFragment extends CallableWrapperFragment {
             vibe.vibrate(80);
             Intent i = new Intent();
             Bundle b = new Bundle();
-            b.putParcelable("conference", (Conference) adptv.getAdapter().getItem(pos));
+            //b.putParcelable("conference", (Conference) adptv.getAdapter().getItem(pos));
+            b.putParcelable("contact", ((Conversation) adptv.getAdapter().getItem(pos)).getContact());
             i.putExtra("bconference", b);
 
             DragShadowBuilder shadowBuilder = new View.DragShadowBuilder(view);
@@ -240,20 +334,32 @@ public class CallListFragment extends CallableWrapperFragment {
 
     };
 
-    public class CallListAdapter extends BaseAdapter implements Observer {
-
-        private ArrayList<Conference> calls;
+    public class CallListAdapter extends BaseAdapter /*implements Observer*/ {
+        final private ArrayList<Conversation> calls = new ArrayList<>();
+        final private ExecutorService infos_fetcher = Executors.newCachedThreadPool();
+        final private LruCache<Long, Bitmap> mMemoryCache;
+        final private HashMap<Long, WeakReference<ContactPictureTask>> running_tasks = new HashMap<>();
 
         private Context mContext;
 
         public CallListAdapter(Context act) {
             super();
             mContext = act;
-            calls = new ArrayList<Conference>();
-
+            final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
+            final int cacheSize = maxMemory / 8;
+            Log.i(TAG, "CallListAdapter created " + cacheSize);
+            mMemoryCache = new LruCache<Long, Bitmap>(cacheSize){
+                @Override
+                protected int sizeOf(Long key, Bitmap bitmap) {
+                    return bitmap.getByteCount() / 1024;
+                }
+            };
         }
 
-        public void updateDataset(ArrayList<Conference> list) {
+        public void updateDataset(Collection<Conversation> list) {
+            Log.i(TAG, "updateDataset " + list.size());
+            if (list.size() == 0 && calls.size() == 0)
+                return;
             calls.clear();
             calls.addAll(list);
             notifyDataSetChanged();
@@ -265,7 +371,7 @@ public class CallListFragment extends CallableWrapperFragment {
         }
 
         @Override
-        public Conference getItem(int position) {
+        public Conversation getItem(int position) {
             return calls.get(position);
         }
 
@@ -274,38 +380,82 @@ public class CallListFragment extends CallableWrapperFragment {
             return 0;
         }
 
+        private class ViewHolder {
+            TextView conv_title;
+            TextView conv_status;
+            ImageView photo;
+            int position;
+            Conversation conv;
+        }
+
         @Override
-        public View getView(int position, View convertView, ViewGroup parent) {
+        public View getView(final int position, View convertView, ViewGroup parent) {
             if (convertView == null)
                 convertView = LayoutInflater.from(mContext).inflate(cx.ring.R.layout.item_calllist, null);
 
-            Conference call = calls.get(position);
-            if (call.getParticipants().size() == 1) {
-                ((TextView) convertView.findViewById(cx.ring.R.id.call_title)).setText(call.getParticipants().get(0).getmContact().getmDisplayName());
-
-                long duration = (System.currentTimeMillis() - (call.getParticipants().get(0).getTimestampStart_())) / 1000;
-
-                ((TextView) convertView.findViewById(cx.ring.R.id.call_time)).setText(String.format("%d:%02d:%02d", duration / 3600, (duration % 3600) / 60,
-                        (duration % 60)));
+            ViewHolder holder = (ViewHolder) convertView.getTag();
+            if (holder == null) {
+                holder = new ViewHolder();
+                holder.photo = (ImageView) convertView.findViewById(R.id.photo);
+                holder.conv_title = (TextView) convertView.findViewById(cx.ring.R.id.msg_txt);
+                holder.conv_status = (TextView) convertView.findViewById(cx.ring.R.id.call_status);
+                holder.position = -1;
+                convertView.setTag(holder);
+            }
+            final ViewHolder h = holder;
+            if (h.position == position && h.conv != null && h.conv == calls.get(position)) {
+                return convertView;
+            }
+            h.conv = calls.get(position);
+            h.position = position;
+            h.conv_title.setText(h.conv.getContact().getDisplayName());
+            h.conv_status.setText(DateFormat.getDateTimeInstance().format(h.conv.getLastInteraction()));
+
+            final Long cid = h.conv.getContact().getId();
+            Bitmap bmp = mMemoryCache.get(cid);
+            if (bmp != null) {
+                h.photo.setImageBitmap(bmp);
             } else {
-//                String tmp = "Conference with " + call.getParticipants().size() + " participants";
-                ((TextView) convertView.findViewById(cx.ring.R.id.call_title)).setText(getString(cx.ring.R.string.home_conf_item, call.getParticipants().size()));
+                holder.photo.setImageBitmap(mMemoryCache.get(-1l));
+                final WeakReference<ViewHolder> wh = new WeakReference<>(holder);
+                final ContactPictureTask.PictureLoadedCallback cb = new ContactPictureTask.PictureLoadedCallback() {
+                    @Override
+                    public void onPictureLoaded(final Bitmap bmp) {
+                        final ViewHolder fh = wh.get();
+                        if (fh == null || fh.photo.getParent() == null)
+                            return;
+                        //if (fh.position == position) {
+                        if (fh.conv.getContact().getId() == cid) {
+                            fh.photo.post(new Runnable() {
+                                @Override
+                                public void run() {
+                                    fh.photo.setImageBitmap(bmp);
+                                    fh.photo.startAnimation(AnimationUtils.loadAnimation(fh.photo.getContext(), R.anim.contact_fadein));
+                                }
+                            });
+                        }
+                    }
+                };
+                WeakReference<ContactPictureTask> wtask = running_tasks.get(cid);
+                ContactPictureTask task = wtask == null ? null : wtask.get();
+                if (task != null) {
+                    task.addCallback(cb);
+                } else {
+                    task = new ContactPictureTask(mContext, h.photo, h.conv.getContact(), new ContactPictureTask.PictureLoadedCallback() {
+                        @Override
+                        public void onPictureLoaded(Bitmap bmp) {
+                            mMemoryCache.put(cid, bmp);
+                            running_tasks.remove(cid);
+                        }
+                    });
+                    task.addCallback(cb);
+                    running_tasks.put(cid, new WeakReference<>(task));
+                    infos_fetcher.execute(task);
+                }
             }
-            // ((TextView) convertView.findViewById(R.id.num_participants)).setText("" + call.getParticipants().size());
-            ((TextView) convertView.findViewById(cx.ring.R.id.call_status)).setText(call.getState());
-
             convertView.setOnDragListener(dragListener);
-            convertView.setTag(call);
-
             return convertView;
         }
-
-        @Override
-        public void update(Observable observable, Object data) {
-            Log.i(TAG, "Updating views...");
-            notifyDataSetChanged();
-        }
-
     }
 
     OnDragListener dragListener = new OnDragListener() {
@@ -335,8 +485,8 @@ public class CallListFragment extends CallableWrapperFragment {
                     Intent intent = i.getIntent();
                     intent.setExtrasClassLoader(Conference.class.getClassLoader());
 
-                    Conference initial = (Conference) view.getTag();
-                    Conference target = (Conference) v.getTag();
+                    Conversation initial = ((CallListAdapter.ViewHolder) view.getTag()).conv;
+                    Conversation target = ((CallListAdapter.ViewHolder) v.getTag()).conv;
 
                     if (initial == target) {
                         return true;
@@ -344,8 +494,8 @@ public class CallListFragment extends CallableWrapperFragment {
 
                     DropActionsChoice dialog = DropActionsChoice.newInstance();
                     Bundle b = new Bundle();
-                    b.putParcelable("call_initial", initial);
-                    b.putParcelable("call_targeted", target);
+                    b.putParcelable("call_initial", initial.getCurrentCall());
+                    b.putParcelable("call_targeted", target.getCurrentCall());
                     dialog.setArguments(b);
                     dialog.setTargetFragment(CallListFragment.this, 0);
                     dialog.show(getFragmentManager(), "dialog");
@@ -376,7 +526,7 @@ public class CallListFragment extends CallableWrapperFragment {
                     Conference c = data.getParcelableExtra("target");
                     transfer = data.getParcelableExtra("transfer");
                     try {
-                        mCallbacks.getService().attendedTransfer(transfer.getParticipants().get(0).getCallId(), c.getParticipants().get(0).getCallId());
+                        mCallbacks.getService().getRemoteService().attendedTransfer(transfer.getParticipants().get(0).getCallId(), c.getParticipants().get(0).getCallId());
                         mConferenceAdapter.notifyDataSetChanged();
                     } catch (RemoteException e) {
                         // TODO Auto-generated catch block
@@ -389,10 +539,10 @@ public class CallListFragment extends CallableWrapperFragment {
                     String to = data.getStringExtra("to_number");
                     transfer = data.getParcelableExtra("transfer");
                     try {
-                        Toast.makeText(getActivity(), getString(cx.ring.R.string.home_transfering, transfer.getParticipants().get(0).getmContact().getmDisplayName(), to),
+                        Toast.makeText(getActivity(), getString(cx.ring.R.string.home_transfering, transfer.getParticipants().get(0).getContact().getDisplayName(), to),
                                 Toast.LENGTH_SHORT).show();
-                        mCallbacks.getService().transfer(transfer.getParticipants().get(0).getCallId(), to);
-                        mCallbacks.getService().hangUp(transfer.getParticipants().get(0).getCallId());
+                        mCallbacks.getService().getRemoteService().transfer(transfer.getParticipants().get(0).getCallId(), to);
+                        mCallbacks.getService().getRemoteService().hangUp(transfer.getParticipants().get(0).getCallId());
                     } catch (RemoteException e) {
                         // TODO Auto-generated catch block
                         e.printStackTrace();
@@ -424,20 +574,20 @@ public class CallListFragment extends CallableWrapperFragment {
 
             if (call_target.hasMultipleParticipants() && !call_to_add.hasMultipleParticipants()) {
 
-                mCallbacks.getService().addParticipant(call_to_add.getParticipants().get(0), call_target.getId());
+                mCallbacks.getService().getRemoteService().addParticipant(call_to_add.getParticipants().get(0), call_target.getId());
 
             } else if (call_target.hasMultipleParticipants() && call_to_add.hasMultipleParticipants()) {
 
                 // We join two conferences
-                mCallbacks.getService().joinConference(call_to_add.getId(), call_target.getId());
+                mCallbacks.getService().getRemoteService().joinConference(call_to_add.getId(), call_target.getId());
 
             } else if (!call_target.hasMultipleParticipants() && call_to_add.hasMultipleParticipants()) {
 
-                mCallbacks.getService().addParticipant(call_target.getParticipants().get(0), call_to_add.getId());
+                mCallbacks.getService().getRemoteService().addParticipant(call_target.getParticipants().get(0), call_to_add.getId());
 
             } else {
                 // We join two single calls to create a conf
-                mCallbacks.getService().joinParticipant(call_to_add.getParticipants().get(0).getCallId(),
+                mCallbacks.getService().getRemoteService().joinParticipant(call_to_add.getParticipants().get(0).getCallId(),
                         call_target.getParticipants().get(0).getCallId());
             }
 
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/CallableWrapperFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/CallableWrapperFragment.java
index eb0a6328b..3ea8dcab1 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/CallableWrapperFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/CallableWrapperFragment.java
@@ -46,19 +46,11 @@ import java.util.HashMap;
 
 public abstract class CallableWrapperFragment extends Fragment implements CallInterface {
 
-
-    private CallReceiver mReceiver;
-
+    private final CallReceiver mReceiver = new CallReceiver();
 
     @Override
     public void onCreate(Bundle savedInstanceState) {
         super.onCreate(savedInstanceState);
-        mReceiver = new CallReceiver();
-    }
-
-    @Override
-    public void onResume() {
-        super.onResume();
         IntentFilter intentFilter = new IntentFilter();
         intentFilter.addAction(CallManagerCallBack.INCOMING_CALL);
         intentFilter.addAction(CallManagerCallBack.INCOMING_TEXT);
@@ -76,10 +68,9 @@ public abstract class CallableWrapperFragment extends Fragment implements CallIn
         getActivity().registerReceiver(mReceiver, intentFilter);
     }
 
-
     @Override
-    public void onPause() {
-        super.onPause();
+    public void onDestroy() {
+        super.onDestroy();
         getActivity().unregisterReceiver(mReceiver);
     }
 
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/ConferenceDFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/ConferenceDFragment.java
index 7bfbafae8..1e7075128 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/ConferenceDFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/ConferenceDFragment.java
@@ -26,7 +26,7 @@ import android.widget.BaseAdapter;
 import android.widget.ListView;
 import android.widget.TextView;
 
-public class ConferenceDFragment extends DialogFragment implements LoaderManager.LoaderCallbacks<Bundle> {
+public class ConferenceDFragment extends DialogFragment implements LoaderManager.LoaderCallbacks<ContactsLoader.Result> {
 
 
     SimpleCallListAdapter mAdapter;
@@ -75,7 +75,7 @@ public class ConferenceDFragment extends DialogFragment implements LoaderManager
 
         
 
-        final AlertDialog a = new AlertDialog.Builder(getActivity()).setView(rootView).setTitle("Transfer " + call_selected.getParticipants().get(0).getmContact())
+        final AlertDialog a = new AlertDialog.Builder(getActivity()).setView(rootView).setTitle("Transfer " + call_selected.getParticipants().get(0).getContact())
                 .setNegativeButton(android.R.string.no, new DialogInterface.OnClickListener() {
                     public void onClick(DialogInterface dialog, int whichButton) {
 
@@ -87,7 +87,7 @@ public class ConferenceDFragment extends DialogFragment implements LoaderManager
     }
 
     @Override
-    public Loader<Bundle> onCreateLoader(int id, Bundle args) {
+    public Loader<ContactsLoader.Result> onCreateLoader(int id, Bundle args) {
         Uri baseUri;
 
         if (args != null) {
@@ -101,14 +101,14 @@ public class ConferenceDFragment extends DialogFragment implements LoaderManager
     }
 
     @Override
-    public void onLoadFinished(Loader<Bundle> loader, Bundle data) {
+    public void onLoadFinished(Loader<ContactsLoader.Result> loader, ContactsLoader.Result data) {
 
 //        ArrayList<CallContact> tmp = data.getParcelableArrayList("Contacts");
 
     }
 
     @Override
-    public void onLoaderReset(Loader<Bundle> loader) {
+    public void onLoaderReset(Loader<ContactsLoader.Result> loader) {
         // Thi is called when the last Cursor provided to onLoadFinished
         // mListAdapter.swapCursor(null);
     }
@@ -136,7 +136,7 @@ public class ConferenceDFragment extends DialogFragment implements LoaderManager
             }
 
             if(calls.get(position).getParticipants().size() == 1){
-                tv.setText(calls.get(position).getParticipants().get(0).getmContact().getmDisplayName());
+                tv.setText(calls.get(position).getParticipants().get(0).getContact().getDisplayName());
             } else {
                 tv.setText("Conference with "+ calls.get(position).getParticipants().size() + " participants");
             }
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/ContactListFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/ContactListFragment.java
index 9640452f0..d3ff53a21 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/ContactListFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/ContactListFragment.java
@@ -39,9 +39,7 @@ import cx.ring.adapters.StarredContactsAdapter;
 import cx.ring.loaders.ContactsLoader;
 import cx.ring.loaders.LoaderConstants;
 import cx.ring.model.CallContact;
-import cx.ring.service.ISipService;
-import cx.ring.views.SwipeListViewTouchListener;
-import cx.ring.views.stickylistheaders.StickyListHeadersListView;
+import se.emilsjolander.stickylistheaders.StickyListHeadersListView;
 
 import android.app.Activity;
 import android.app.Fragment;
@@ -51,14 +49,13 @@ import android.net.Uri;
 import android.os.Bundle;
 import android.provider.ContactsContract.Contacts;
 import android.util.Log;
-import android.view.DragEvent;
 import android.view.LayoutInflater;
+import android.view.Menu;
+import android.view.MenuInflater;
 import android.view.MotionEvent;
 import android.view.View;
 import android.view.View.DragShadowBuilder;
 import android.view.View.MeasureSpec;
-import android.view.View.OnClickListener;
-import android.view.View.OnDragListener;
 import android.view.View.OnTouchListener;
 import android.view.ViewGroup;
 import android.widget.AdapterView;
@@ -67,66 +64,58 @@ import android.widget.AdapterView.OnItemLongClickListener;
 import android.widget.GridView;
 import android.widget.LinearLayout;
 import android.widget.ListAdapter;
-import android.widget.ListView;
 import android.widget.RelativeLayout;
 import android.widget.SearchView;
 import android.widget.SearchView.OnQueryTextListener;
+import android.widget.TextView;
 
-public class ContactListFragment extends Fragment implements OnQueryTextListener, LoaderManager.LoaderCallbacks<Bundle> {
-    private static final String TAG = "ContactListFragment";
+public class ContactListFragment extends Fragment implements OnQueryTextListener, LoaderManager.LoaderCallbacks<ContactsLoader.Result> {
+    public static final String TAG = "ContactListFragment";
     ContactsAdapter mListAdapter;
     StarredContactsAdapter mGridAdapter;
-    SearchView mQuickReturnSearchView;
+    //SearchView mQuickReturnSearchView;
     String mCurFilter;
     StickyListHeadersListView mContactList;
+
+    // favorite contacts
+    private LinearLayout llMain;
     private GridView mStarredGrid;
-    private SwipeListViewTouchListener mSwipeLvTouchListener;
+    private TextView favHeadLabel;
+    //private SwipeListViewTouchListener mSwipeLvTouchListener;
     private LinearLayout mHeader;
+    private ViewGroup newcontact;
 
     @Override
     public void onCreate(Bundle savedInBundle) {
         super.onCreate(savedInBundle);
         mGridAdapter = new StarredContactsAdapter(getActivity());
         mListAdapter = new ContactsAdapter(this);
+        setHasOptionsMenu(true);
     }
 
     public Callbacks mCallbacks = sDummyCallbacks;
-    private LinearLayout llMain;
     /**
      * A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity.
      */
-    private static Callbacks sDummyCallbacks = new Callbacks() {
+    private static final Callbacks sDummyCallbacks = new Callbacks() {
         @Override
         public void onCallContact(CallContact c) {
         }
-
         @Override
         public void onTextContact(CallContact c) {
         }
-
         @Override
         public void onEditContact(CallContact c) {
         }
-
-        @Override
-        public ISipService getService() {
-            Log.i(TAG, "Dummy");
-            return null;
-        }
-
         @Override
         public void onContactDragged() {
         }
-
         @Override
         public void toggleDrawer() {
         }
-
         @Override
         public void setDragView(RelativeLayout relativeLayout) {
-            
         }
-
         @Override
         public void toggleForSearchDrawer() {
         }
@@ -134,21 +123,12 @@ public class ContactListFragment extends Fragment implements OnQueryTextListener
 
     public interface Callbacks {
         void onCallContact(CallContact c);
-
         void onTextContact(CallContact c);
-
-        public ISipService getService();
-
         void onContactDragged();
-
         void toggleDrawer();
-
         void onEditContact(CallContact item);
-
         void setDragView(RelativeLayout relativeLayout);
-
         void toggleForSearchDrawer();
-
     }
 
     @Override
@@ -157,9 +137,7 @@ public class ContactListFragment extends Fragment implements OnQueryTextListener
         if (!(activity instanceof Callbacks)) {
             throw new IllegalStateException("Activity must implement fragment's callbacks.");
         }
-
         mCallbacks = (Callbacks) activity;
-        
     }
 
     @Override
@@ -168,11 +146,20 @@ public class ContactListFragment extends Fragment implements OnQueryTextListener
         mCallbacks = sDummyCallbacks;
     }
 
+    @Override
+    public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
+        inflater.inflate(R.menu.newconv_option_menu, menu);
+        SearchView searchView = (SearchView) menu.findItem(R.id.contact_search).getActionView();
+        searchView.setOnQueryTextListener(ContactListFragment.this);
+    }
+
     @Override
     public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
         View inflatedView = inflater.inflate(R.layout.frag_contact_list, container, false);
         mHeader = (LinearLayout) inflater.inflate(R.layout.frag_contact_list_header, null);
         mContactList = (StickyListHeadersListView) inflatedView.findViewById(R.id.contacts_stickylv);
+        //mContactList.setDividerHeight(0);
+        mContactList.setDivider(null);
 
         inflatedView.findViewById(R.id.drag_view).setOnTouchListener(new OnTouchListener() {
 
@@ -182,7 +169,7 @@ public class ContactListFragment extends Fragment implements OnQueryTextListener
             }
         });
 
-        inflatedView.findViewById(R.id.contact_search_button).setOnClickListener(new OnClickListener() {
+        /*inflatedView.findViewById(R.id.contact_search_button).setOnClickListener(new OnClickListener() {
 
             @Override
             public void onClick(View v) {
@@ -203,10 +190,23 @@ public class ContactListFragment extends Fragment implements OnQueryTextListener
         });
         
         mCallbacks.setDragView(((RelativeLayout) inflatedView.findViewById(R.id.slider_button)));
-
-        mQuickReturnSearchView = (SearchView) mHeader.findViewById(R.id.contact_search);
+*/
+        //mQuickReturnSearchView = (SearchView) mHeader.findViewById(R.id.contact_search);
         mStarredGrid = (GridView) mHeader.findViewById(R.id.favorites_grid);
         llMain = (LinearLayout) mHeader.findViewById(R.id.llMain);
+        favHeadLabel = (TextView) mHeader.findViewById(R.id.fav_head_label);
+        newcontact = (ViewGroup) mHeader.findViewById(R.id.newcontact_element);
+        newcontact.setVisibility(View.GONE);
+        newcontact.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                CallContact c = (CallContact) v.getTag();
+                if (c == null)
+                    return;
+                mCallbacks.onCallContact(c);
+            }
+        });
+
         return inflatedView;
     }
 
@@ -218,7 +218,7 @@ public class ContactListFragment extends Fragment implements OnQueryTextListener
         mContactList.setAdapter(mListAdapter);
 
         mStarredGrid.setAdapter(mGridAdapter);
-        mQuickReturnSearchView.setIconifiedByDefault(false);
+        /*mQuickReturnSearchView.setIconifiedByDefault(false);
 
         mQuickReturnSearchView.setOnClickListener(new OnClickListener() {
 
@@ -228,7 +228,7 @@ public class ContactListFragment extends Fragment implements OnQueryTextListener
                 mQuickReturnSearchView.setFocusable(true);
             }
         });
-        mQuickReturnSearchView.setOnQueryTextListener(ContactListFragment.this);
+        mQuickReturnSearchView.setOnQueryTextListener(ContactListFragment.this);*/
 
         getLoaderManager().initLoader(LoaderConstants.CONTACT_LOADER, null, this);
 
@@ -246,7 +246,7 @@ public class ContactListFragment extends Fragment implements OnQueryTextListener
     };
 
     private void setGridViewListeners() {
-        mStarredGrid.setOnDragListener(dragListener);
+        //mStarredGrid.setOnDragListener(dragListener);
         mStarredGrid.setOnItemClickListener(new OnItemClickListener() {
 
             @Override
@@ -258,7 +258,7 @@ public class ContactListFragment extends Fragment implements OnQueryTextListener
     }
 
     private void setListViewListeners() {
-        mSwipeLvTouchListener = new SwipeListViewTouchListener(mContactList.getWrappedList(), new SwipeListViewTouchListener.OnSwipeCallback() {
+        /*mSwipeLvTouchListener = new SwipeListViewTouchListener(mContactList.getWrappedList(), new SwipeListViewTouchListener.OnSwipeCallback() {
             @Override
             public void onSwipeLeft(ListView listView, int[] reverseSortedPositions) {
             }
@@ -270,21 +270,21 @@ public class ContactListFragment extends Fragment implements OnQueryTextListener
                 down.findViewById(R.id.quick_starred).setClickable(true);
 
             }
-        }, true, false);
+        }, true, false);*/
 
-        mContactList.getWrappedList().setOnDragListener(dragListener);
-        mContactList.getWrappedList().setOnTouchListener(mSwipeLvTouchListener);
+        /*mContactList.getWrappedList().setOnDragListener(dragListener);
+        mContactList.getWrappedList().setOnTouchListener(mSwipeLvTouchListener);*/
         mContactList.getWrappedList().setOnItemLongClickListener(mItemLongClickListener);
-        mContactList.getWrappedList().setOnItemClickListener(new OnItemClickListener() {
+        /*mContactList.getWrappedList().setOnItemClickListener(new OnItemClickListener() {
 
             @Override
             public void onItemClick(AdapterView<?> arg0, View view, int pos, long id) {
                 Log.i(TAG, "Opening Item");
                 mSwipeLvTouchListener.openItem(view, pos, id);
             }
-        });
+        });*/
     }
-
+/*
     OnDragListener dragListener = new OnDragListener() {
 
         @Override
@@ -309,29 +309,36 @@ public class ContactListFragment extends Fragment implements OnQueryTextListener
             return true;
         }
 
-    };
+    };*/
 
     @Override
     public boolean onQueryTextChange(String newText) {
+        mCurFilter = newText;
         if (newText.isEmpty()) {
             getLoaderManager().restartLoader(LoaderConstants.CONTACT_LOADER, null, this);
+            newcontact.setVisibility(View.GONE);
             return true;
         }
-        mCurFilter = newText;
         Bundle b = new Bundle();
         b.putString("filter", mCurFilter);
         getLoaderManager().restartLoader(LoaderConstants.CONTACT_LOADER, b, this);
+        newcontact.setVisibility(View.VISIBLE);
+        ((TextView)newcontact.findViewById(R.id.display_name)).setText("Call \"" + newText + "\"");
+        CallContact contact = CallContact.ContactBuilder.buildUnknownContact(newText);
+        newcontact.setTag(contact);
         return true;
     }
 
     @Override
     public boolean onQueryTextSubmit(String query) {
         // Return false to let the SearchView perform the default action
-        return false;
+        //return false;
+
+        return true;
     }
 
     @Override
-    public Loader<Bundle> onCreateLoader(int id, Bundle args) {
+    public Loader<ContactsLoader.Result> onCreateLoader(int id, Bundle args) {
         Uri baseUri;
 
         Log.i(TAG, "createLoader");
@@ -347,26 +354,27 @@ public class ContactListFragment extends Fragment implements OnQueryTextListener
     }
 
     @Override
-    public void onLoadFinished(Loader<Bundle> loader, Bundle data) {
-
-        mGridAdapter.removeAll();
-        mListAdapter.clear();
-        ArrayList<CallContact> tmp = data.getParcelableArrayList("Contacts");
-        ArrayList<CallContact> tmp2 = data.getParcelableArrayList("Starred");
-        mListAdapter.addAll(tmp);
-        mGridAdapter.addAll(tmp2);
-
+    public void onLoadFinished(Loader<ContactsLoader.Result> loader, ContactsLoader.Result data) {
+        mListAdapter.setData(data.contacts);
         setListViewListeners();
-        setGridViewListeners();
-
-        mStarredGrid.post(new Runnable() {
-
-            @Override
-            public void run() {
-                setGridViewHeight(mStarredGrid, llMain);
-            }
-        });
 
+        if (data.starred.isEmpty()) {
+            llMain.setVisibility(View.GONE);
+            favHeadLabel.setVisibility(View.GONE);
+            mGridAdapter.removeAll();
+        } else {
+            llMain.setVisibility(View.VISIBLE);
+            favHeadLabel.setVisibility(View.VISIBLE);
+            mGridAdapter.setData(data.starred);
+            setGridViewListeners();
+            mStarredGrid.post(new Runnable() {
+
+                @Override
+                public void run() {
+                    setGridViewHeight(mStarredGrid, llMain);
+                }
+            });
+        }
     }
 
     // Sets the GridView holder's height to fully expand it
@@ -399,6 +407,6 @@ public class ContactListFragment extends Fragment implements OnQueryTextListener
     }
 
     @Override
-    public void onLoaderReset(Loader<Bundle> loader) {
+    public void onLoaderReset(Loader<ContactsLoader.Result> loader) {
     }
 }
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/DetailsHistoryEntryFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/DetailsHistoryEntryFragment.java
index 608115bbe..5af66ebef 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/DetailsHistoryEntryFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/DetailsHistoryEntryFragment.java
@@ -51,7 +51,6 @@ import cx.ring.model.SipCall;
 import cx.ring.service.ISipService;
 
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.Map;
 import java.util.NavigableMap;
 import java.util.Random;
@@ -126,7 +125,7 @@ public class DetailsHistoryEntryFragment extends Fragment {
         lvMain.setAdapter(mAdapter);
         iv = (RelativeLayout) inflatedView.findViewById(R.id.iv);
 
-        ((TextView) iv.findViewById(R.id.history_call_name)).setText(toDisplay.getContact().getmDisplayName());
+        ((TextView) iv.findViewById(R.id.history_call_name)).setText(toDisplay.getContact().getDisplayName());
 
         tasker = new ContactPictureTask(getActivity(), (ImageView) inflatedView.findViewById(R.id.contact_photo), toDisplay.getContact());
         tasker.run();
@@ -142,8 +141,8 @@ public class DetailsHistoryEntryFragment extends Fragment {
                     Bundle args = new Bundle();
                     args.putString(SipCall.ID, Integer.toString(Math.abs(new Random().nextInt())));
                     args.putParcelable(SipCall.ACCOUNT, new Account(toDisplay.getAccountID(), details, creds, state));
-                    args.putInt(SipCall.STATE, SipCall.state.CALL_STATE_RINGING);
-                    args.putInt(SipCall.TYPE, SipCall.direction.CALL_TYPE_OUTGOING);
+                    args.putInt(SipCall.STATE, SipCall.State.RINGING);
+                    args.putInt(SipCall.TYPE, SipCall.Direction.OUTGOING);
                     args.putParcelable(SipCall.CONTACT, toDisplay.getContact());
 
                     mCallbacks.onCall(new SipCall(args));
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/DialingFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/DialingFragment.java
index 71425d431..7d434fc29 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/DialingFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/DialingFragment.java
@@ -36,6 +36,7 @@ import java.util.Locale;
 import android.app.Fragment;
 import cx.ring.R;
 import cx.ring.service.ISipService;
+import cx.ring.service.LocalService;
 import cx.ring.views.ClearableEditText;
 
 import android.app.Activity;
@@ -64,31 +65,22 @@ public class DialingFragment extends Fragment implements OnTouchListener {
     ClearableEditText textField;
     private Callbacks mCallbacks = sDummyCallbacks;
 
-    /**
-     * A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity.
-     */
-    private static Callbacks sDummyCallbacks = new Callbacks() {
-        @Override
-        public void onCallDialed(String to) {
-        }
-
-        @Override
-        public ISipService getService() {
-            // TODO Auto-generated method stub
-            return null;
-        }
-    };
-
     /**
      * The Activity calling this fragment has to implement this interface
-     * 
+     *
      */
-    public interface Callbacks {
+    public interface Callbacks extends LocalService.Callbacks {
         void onCallDialed(String account);
+    }
 
-        public ISipService getService();
-
+    /**
+     * A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity.
+     */
+    private static class DummyCallbacks extends LocalService.DummyCallbacks implements Callbacks {
+        @Override
+        public void onCallDialed(String to) {}
     }
+    private static final Callbacks sDummyCallbacks = new DummyCallbacks();
 
     @Override
     public void setUserVisibleHint(boolean isVisibleToUser) {
@@ -211,7 +203,7 @@ public class DialingFragment extends Fragment implements OnTouchListener {
             try {
                 String toSend = Character.toString(s.charAt(start));
                 toSend.toUpperCase(Locale.getDefault());
-                mCallbacks.getService().playDtmf(toSend);
+                mCallbacks.getRemoteService().playDtmf(toSend);
             } catch (RemoteException e) {
                 e.printStackTrace();
             }
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/GeneralAccountFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/GeneralAccountFragment.java
index 6e9a5f23b..7e1774c72 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/GeneralAccountFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/GeneralAccountFragment.java
@@ -60,7 +60,7 @@ public class GeneralAccountFragment extends PreferenceFragment {
 
     public interface Callbacks {
 
-        public Account getAccount();
+        Account getAccount();
 
     }
 
@@ -133,30 +133,31 @@ public class GeneralAccountFragment extends PreferenceFragment {
         @Override
         public boolean onPreferenceChange(Preference preference, Object newValue) {
 
-            Log.i(TAG, "Changing preference value:" + newValue);
+            Log.i(TAG, "Changing preference " + preference.getKey() + " to value:" + newValue);
+            final Account acc = mCallbacks.getAccount();
             if (preference instanceof CheckBoxPreference) {
-                mCallbacks.getAccount().getBasicDetails().setDetailString(preference.getKey(), newValue.toString());
+                acc.getBasicDetails().setDetailString(preference.getKey(), newValue.toString());
             } else {
                 if (preference instanceof PasswordPreference) {
                     String tmp = "";
                     for (int i = 0; i < ((String) newValue).length(); ++i) {
                         tmp += "*";
                     }
-                    if(mCallbacks.getAccount().isSip())
-                        mCallbacks.getAccount().getCredentials().get(0).setDetailString(preference.getKey(), newValue.toString());
+                    if(acc.isSip())
+                        acc.getCredentials().get(0).setDetailString(preference.getKey(), newValue.toString());
                     preference.setSummary(tmp);
                 } else if(preference.getKey().contentEquals(AccountDetailBasic.CONFIG_ACCOUNT_USERNAME)) {
-					if(mCallbacks.getAccount().isSip()){
-						mCallbacks.getAccount().getCredentials().get(0).setDetailString(preference.getKey(), newValue.toString());
+					if(acc.isSip()){
+                        acc.getCredentials().get(0).setDetailString(preference.getKey(), newValue.toString());
 					}
                     preference.setSummary((CharSequence) newValue);
                 } else {
                     preference.setSummary((CharSequence) newValue);
                 }
-                
-                mCallbacks.getAccount().getBasicDetails().setDetailString(preference.getKey(), newValue.toString());
+
+                acc.getBasicDetails().setDetailString(preference.getKey(), newValue.toString());
             }
-            mCallbacks.getAccount().notifyObservers();
+            acc.notifyObservers();
             return true;
         }
     };
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/HistoryFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/HistoryFragment.java
index c7221b3c7..6b050550c 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/HistoryFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/HistoryFragment.java
@@ -46,7 +46,6 @@ import cx.ring.history.HistoryManager;
 import cx.ring.loaders.HistoryLoader;
 import cx.ring.loaders.LoaderConstants;
 import cx.ring.history.HistoryEntry;
-import cx.ring.service.ISipService;
 
 import android.app.Activity;
 import android.content.Context;
@@ -71,27 +70,16 @@ public class HistoryFragment extends ListFragment implements LoaderManager.Loade
     private Callbacks mCallbacks = sDummyCallbacks;
     HistoryManager mHistoryManager;
 
-    private static Callbacks sDummyCallbacks = new Callbacks() {
-        @Override
-        public void onCallHistory(HistoryEntry to) {
-        }
-
+    public interface Callbacks {
+        void onCallHistory(HistoryEntry to);
+    }
+    private static final Callbacks sDummyCallbacks = new Callbacks() {
         @Override
-        public ISipService getService() {
-            Log.i(TAG, "Dummy");
-            return null;
-        }
-
+        public void onCallHistory(HistoryEntry to) {}
     };
 
     public static String ARGS = "Bundle.args";
 
-    public interface Callbacks {
-        public void onCallHistory(HistoryEntry to);
-
-        public ISipService getService();
-
-    }
 
     @Override
     public void onAttach(Activity activity) {
@@ -216,11 +204,11 @@ public class HistoryFragment extends ListFragment implements LoaderManager.Loade
             // to the view objects
 
             // SipCall call = (SipCall) mCallList.values().toArray()[position];
-            entryView.displayName.setText(dataset.get(pos).getContact().getmDisplayName());
+            entryView.displayName.setText(dataset.get(pos).getContact().getDisplayName());
             infos_fetcher.execute(new ContactPictureTask(mContext, entryView.photo, dataset.get(pos).getContact()));
 
-            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()));
+            entryView.incoming.setText(getString(R.string.hist_in_calls, dataset.get(pos).getIncomingSum()));
+            entryView.outgoing.setText(getString(R.string.hist_out_calls, dataset.get(pos).getOutgoingSum()));
 
             /*if (dataset.get(pos).getCalls().lastEntry().getValue().getRecordPath().length() > 0) {
                 entryView.replay.setVisibility(View.VISIBLE);
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/IMFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/IMFragment.java
deleted file mode 100644
index 0769d6348..000000000
--- a/ring-android/app/src/main/java/cx/ring/fragments/IMFragment.java
+++ /dev/null
@@ -1,193 +0,0 @@
-/*
- *  Copyright (C) 2004-2014 Savoir-Faire Linux Inc.
- *
- *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  Additional permission under GNU GPL version 3 section 7:
- *
- *  If you modify this program, or any covered work, by linking or
- *  combining it with the OpenSSL project's OpenSSL library (or a
- *  modified version of that library), containing parts covered by the
- *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
- *  grants you additional permission to convey the resulting work.
- *  Corresponding Source for a non-source form of such a combination
- *  shall include the source code for the parts of OpenSSL used as well
- *  as that of the covered work.
- */
-package cx.ring.fragments;
-
-import android.widget.*;
-import cx.ring.R;
-import cx.ring.adapters.DiscussArrayAdapter;
-import cx.ring.model.Conference;
-import cx.ring.model.SipMessage;
-import cx.ring.service.ISipService;
-
-import android.app.Activity;
-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.TextView.OnEditorActionListener;
-
-public class IMFragment extends CallableWrapperFragment {
-    static final String TAG = IMFragment.class.getSimpleName();
-
-    private Callbacks mCallbacks = sDummyCallbacks;
-
-    DiscussArrayAdapter mAdapter;
-    ListView list;
-
-    private EditText sendTextField;
-
-    @Override
-    public void onCreate(Bundle savedBundle) {
-        super.onCreate(savedBundle);
-
-        mAdapter = new DiscussArrayAdapter(getActivity(), getArguments());
-
-    }
-
-    @Override
-    public void incomingText(Conference updated, String ID, String from, String msg) {
-        mCallbacks.updateDisplayedConference(updated);
-        if(updated.equals(mCallbacks.getDisplayedConference())){
-            SipMessage sipMsg = new SipMessage(true, msg);
-            putMessage(sipMsg);
-        }
-
-    }
-
-
-    /**
-     * A dummy implementation of the {@link Callbacks} interface that does nothing. Used only when this fragment is not attached to an activity.
-     */
-    private static Callbacks sDummyCallbacks = new Callbacks() {
-
-        @Override
-        public ISipService getService() {
-            return null;
-        }
-
-        @Override
-        public Conference getDisplayedConference() {
-            return null;
-        }
-
-        @Override
-        public boolean sendIM(SipMessage msg) {
-            return false;
-        }
-
-        @Override
-        public void updateDisplayedConference(Conference c) {
-
-        }
-
-    };
-
-    /**
-     * The Activity calling this fragment has to implement this interface
-     */
-    public interface Callbacks {
-        public ISipService getService();
-
-        public Conference getDisplayedConference();
-
-        public boolean sendIM(SipMessage msg);
-
-        public void updateDisplayedConference(Conference c);
-    }
-
-    @Override
-    public void onAttach(Activity activity) {
-        super.onAttach(activity);
-
-        if (!(activity instanceof Callbacks)) {
-            throw new IllegalStateException("Activity must implement fragment's callbacks.");
-        }
-
-        mCallbacks = (Callbacks) activity;
-    }
-
-    @Override
-    public void onDetach() {
-        super.onDetach();
-        mCallbacks = sDummyCallbacks;
-    }
-
-    @Override
-    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
-        ViewGroup rootView = (ViewGroup) inflater.inflate(R.layout.frag_imessaging, container, false);
-
-        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) {
-                    sendMessage();
-                }
-                return true;
-            }
-        });
-
-        rootView.findViewById(R.id.send_im_button).setOnClickListener(new OnClickListener() {
-
-            @Override
-            public void onClick(View v) {
-                sendMessage();
-            }
-        });
-
-
-        return rootView;
-    }
-
-    private void sendMessage() {
-        if (sendTextField.getText().toString().length() > 0) {
-            SipMessage toSend = new SipMessage(false, sendTextField.getText().toString());
-            if (mCallbacks.sendIM(toSend)) {
-                putMessage(toSend);
-                sendTextField.setText("");
-            } else {
-                Toast.makeText(getActivity(), "Error sending message", Toast.LENGTH_SHORT).show();
-            }
-        }
-    }
-
-
-    @Override
-    public void onActivityResult(int requestCode, int resultCode, Intent data) {
-        super.onActivityResult(requestCode, resultCode, data);
-    }
-
-    public void putMessage(SipMessage msg) {
-        mAdapter.add(msg);
-        Log.i(TAG, "Messages" + mAdapter.getCount());
-    }
-}
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/MenuFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/MenuFragment.java
index 42bc78648..ad0ed2376 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/MenuFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/MenuFragment.java
@@ -31,9 +31,13 @@
 package cx.ring.fragments;
 
 import android.app.Activity;
+import android.app.Fragment;
 import android.app.LoaderManager;
 import android.content.AsyncTaskLoader;
+import android.content.BroadcastReceiver;
+import android.content.Context;
 import android.content.Intent;
+import android.content.IntentFilter;
 import android.content.Loader;
 import android.os.Bundle;
 import android.os.RemoteException;
@@ -46,28 +50,25 @@ import android.widget.AdapterView.OnItemSelectedListener;
 import cx.ring.R;
 import cx.ring.adapters.AccountSelectionAdapter;
 import cx.ring.adapters.ContactPictureTask;
+import cx.ring.client.HomeActivity;
 import cx.ring.loaders.AccountsLoader;
 import cx.ring.loaders.LoaderConstants;
 import cx.ring.model.account.Account;
 import cx.ring.model.CallContact;
+import cx.ring.service.ConfigurationManagerCallback;
 import cx.ring.service.ISipService;
+import cx.ring.service.LocalService;
 
 import java.util.ArrayList;
 
-public class MenuFragment extends AccountWrapperFragment implements LoaderManager.LoaderCallbacks<Bundle> {
+public class MenuFragment extends Fragment /*extends AccountWrapperFragment implements LoaderManager.LoaderCallbacks<Bundle>*/ {
 
     @SuppressWarnings("unused")
     private static final String TAG = MenuFragment.class.getSimpleName();
 
     AccountSelectionAdapter mAccountAdapter;
     private Spinner spinnerAccounts;
-    private Callbacks mCallbacks = sDummyCallbacks;
-    private static Callbacks sDummyCallbacks = new Callbacks() {
-        @Override
-        public ISipService getService() {
-            return null;
-        }
-    };
+    private LocalService.Callbacks mCallbacks = LocalService.DUMMY_CALLBACKS;
 
     public Account retrieveAccountById(String accountID) {
         Account toReturn;
@@ -79,23 +80,20 @@ public class MenuFragment extends AccountWrapperFragment implements LoaderManage
         return toReturn;
     }
 
-    public interface Callbacks {
-        ISipService getService();
-    }
-
     @Override
     public void onAttach(Activity activity) {
         super.onAttach(activity);
-        if (!(activity instanceof Callbacks)) {
+        if (!(activity instanceof LocalService.Callbacks)) {
             throw new IllegalStateException("Activity must implement fragment's callbacks.");
         }
-        mCallbacks = (Callbacks) activity;
+        mCallbacks = (LocalService.Callbacks) activity;
+        updateAllAccounts();
     }
 
     @Override
     public void onDetach() {
         super.onDetach();
-        mCallbacks = sDummyCallbacks;
+        mCallbacks = LocalService.DUMMY_CALLBACKS;
     }
 
     @Override
@@ -103,25 +101,34 @@ public class MenuFragment extends AccountWrapperFragment implements LoaderManage
         super.onCreate(savedInstanceState);
     }
 
-    public void onResume() {
-        super.onResume();
-
-        Log.i(TAG, "Resuming");
-        getLoaderManager().restartLoader(LoaderConstants.ACCOUNTS_LOADER, null, this);
-
-    }
-
     @Override
     public void onActivityResult(int requestCode, int resultCode, Intent data) {
         super.onActivityResult(requestCode, resultCode, data);
-        getLoaderManager().restartLoader(LoaderConstants.ACCOUNTS_LOADER, null, this);
+        //getLoaderManager().restartLoader(LoaderConstants.ACCOUNTS_LOADER, null, this);
     }
 
+    private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            if (intent.getAction().contentEquals(LocalService.ACTION_ACCOUNT_UPDATE)) {
+                updateAllAccounts();
+            }
+        }
+    };
 
+    @Override
+    public void onResume() {
+        Log.i(TAG, "Resuming");
+        super.onResume();
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(LocalService.ACTION_ACCOUNT_UPDATE);
+        getActivity().registerReceiver(mReceiver, intentFilter);
+    }
 
     @Override
     public void onPause() {
         super.onPause();
+        getActivity().unregisterReceiver(mReceiver);
     }
 
     @Override
@@ -139,7 +146,7 @@ public class MenuFragment extends AccountWrapperFragment implements LoaderManage
                 mAccountAdapter.setSelectedAccount(pos);
                 //view.findViewById(R.id.account_selected).setVisibility(View.GONE);
                 try {
-                    mCallbacks.getService().setAccountOrder(mAccountAdapter.getAccountOrder());
+                    mCallbacks.getRemoteService().setAccountOrder(mAccountAdapter.getAccountOrder());
                 } catch (RemoteException e) {
                     e.printStackTrace();
                 }
@@ -155,7 +162,9 @@ public class MenuFragment extends AccountWrapperFragment implements LoaderManage
         CallContact user = CallContact.ContactBuilder.buildUserContact(getActivity().getContentResolver());
         new ContactPictureTask(getActivity(), (ImageView) inflatedView.findViewById(R.id.user_photo), user).run();
 
-        ((TextView) inflatedView.findViewById(R.id.user_name)).setText(user.getmDisplayName());
+        ((TextView) inflatedView.findViewById(R.id.user_name)).setText(user.getDisplayName());
+
+        updateAllAccounts();
 
         return inflatedView;
     }
@@ -172,10 +181,15 @@ public class MenuFragment extends AccountWrapperFragment implements LoaderManage
     }
 
     public void updateAllAccounts() {
-        if (getActivity() != null)
-            getLoaderManager().restartLoader(LoaderConstants.ACCOUNTS_LOADER, null, this);
+        /*if (getActivity() != null)
+            getLoaderManager().restartLoader(LoaderConstants.ACCOUNTS_LOADER, null, this);*/
+        if (mAccountAdapter != null && mCallbacks.getService() != null) {
+            mAccountAdapter.removeAll();
+            mAccountAdapter.addAll(mCallbacks.getService().getAccounts());
+        }
     }
 
+    /*
     @Override
     public void accountsChanged() {
         updateAllAccounts();
@@ -183,16 +197,16 @@ public class MenuFragment extends AccountWrapperFragment implements LoaderManage
     }
 
     @Override
-    public void accountStateChanged(String accoundID, String state, int code) {
-        Log.w(TAG, "accountStateChanged " + accoundID + " " + state);
+    public void accountStateChanged(String accoundID, String State, int code) {
+        Log.w(TAG, "accountStateChanged " + accoundID + " " + State);
 
         if (mAccountAdapter != null)
-            mAccountAdapter.updateAccount(accoundID, state, code);
+            mAccountAdapter.updateAccount(accoundID, State, code);
     }
 
     @Override
     public AsyncTaskLoader<Bundle> onCreateLoader(int arg0, Bundle arg1) {
-        AccountsLoader l = new AccountsLoader(getActivity(), mCallbacks.getService());
+        AccountsLoader l = new AccountsLoader(getActivity(), mCallbacks.getRemoteService());
         l.forceLoad();
         return l;
     }
@@ -208,6 +222,6 @@ public class MenuFragment extends AccountWrapperFragment implements LoaderManage
     @Override
     public void onLoaderReset(Loader<Bundle> loader) {
 
-    }
+    }*/
 
 }
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/NestedSettingsFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/NestedSettingsFragment.java
index 87e358183..6d192f12b 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/NestedSettingsFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/NestedSettingsFragment.java
@@ -47,6 +47,7 @@ import cx.ring.model.account.SRTPManager;
 import cx.ring.model.account.TLSManager;
 import cx.ring.model.account.Account;
 import cx.ring.service.ISipService;
+import cx.ring.service.LocalService;
 
 import java.util.ArrayList;
 
@@ -62,23 +63,24 @@ public class NestedSettingsFragment extends PreferenceFragment {
     TLSManager mTlsManager;
 
     private static Callbacks sDummyCallbacks = new Callbacks() {
-
         @Override
-        public Account getAccount() {
+        public ISipService getRemoteService() {
             return null;
         }
-
         @Override
-        public ISipService getService() {
+        public LocalService getService() {
+            return null;
+        }
+        @Override
+        public Account getAccount() {
             return null;
         }
-
     };
 
     public String[] getTlsMethods() {
         ArrayList<String> methods = null;
         try {
-            methods = (ArrayList<String>) mCallbacks.getService().getTlsSupportedMethods();
+            methods = (ArrayList<String>) mCallbacks.getRemoteService().getTlsSupportedMethods();
         } catch (RemoteException e) {
             e.printStackTrace();
         }
@@ -105,12 +107,8 @@ public class NestedSettingsFragment extends PreferenceFragment {
         return false;
     }
 
-    public interface Callbacks {
-
-        public Account getAccount();
-
-        public ISipService getService();
-
+    public interface Callbacks extends LocalService.Callbacks {
+        Account getAccount();
     }
 
     @Override
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/SecurityAccountFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/SecurityAccountFragment.java
index 01042e6ef..f03999540 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/SecurityAccountFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/SecurityAccountFragment.java
@@ -50,8 +50,7 @@ public class SecurityAccountFragment extends PreferenceFragment {
     private static final String TAG = SecurityAccountFragment.class.getSimpleName();
 
     private Callbacks mCallbacks = sDummyCallbacks;
-    private static Callbacks sDummyCallbacks = new Callbacks() {
-
+    private static final Callbacks sDummyCallbacks = new Callbacks() {
         @Override
         public Account getAccount() {
             return null;
@@ -68,19 +67,13 @@ public class SecurityAccountFragment extends PreferenceFragment {
         @Override
         public void displayTLSScreen() {
         }
-
     };
 
     public interface Callbacks {
-
-        public Account getAccount();
-
-        public void displayCredentialsScreen();
-
-        public void displaySRTPScreen();
-
-        public void displayTLSScreen();
-
+        Account getAccount();
+        void displayCredentialsScreen();
+        void displaySRTPScreen();
+        void displayTLSScreen();
     }
 
     @Override
diff --git a/ring-android/app/src/main/java/cx/ring/fragments/TransferDFragment.java b/ring-android/app/src/main/java/cx/ring/fragments/TransferDFragment.java
index cb331defb..a2d8a57a4 100644
--- a/ring-android/app/src/main/java/cx/ring/fragments/TransferDFragment.java
+++ b/ring-android/app/src/main/java/cx/ring/fragments/TransferDFragment.java
@@ -70,7 +70,7 @@ import android.widget.ListView;
 import android.widget.TextView;
 import android.widget.Toast;
 
-public class TransferDFragment extends DialogFragment implements LoaderManager.LoaderCallbacks<Bundle> {
+public class TransferDFragment extends DialogFragment implements LoaderManager.LoaderCallbacks<ContactsLoader.Result> {
     public static final int RESULT_TRANSFER_CONF = Activity.RESULT_FIRST_USER + 1;
     public static final int RESULT_TRANSFER_NUMBER = Activity.RESULT_FIRST_USER + 2;
 
@@ -124,7 +124,7 @@ public class TransferDFragment extends DialogFragment implements LoaderManager.L
         mEditText.setAdapter(autoCompleteAdapter);
 
         final AlertDialog a = new AlertDialog.Builder(getActivity()).setView(rootView)
-                .setTitle("Transfer " + call_selected.getmContact().getmDisplayName())
+                .setTitle("Transfer " + call_selected.getContact().getDisplayName())
                 .setPositiveButton(android.R.string.ok, new DialogInterface.OnClickListener() {
                     @Override
                     public void onClick(DialogInterface dialog, int whichButton) {
@@ -165,7 +165,7 @@ public class TransferDFragment extends DialogFragment implements LoaderManager.L
     }
 
     @Override
-    public Loader<Bundle> onCreateLoader(int id, Bundle args) {
+    public Loader<ContactsLoader.Result> onCreateLoader(int id, Bundle args) {
         Uri baseUri;
 
         if (args != null) {
@@ -179,14 +179,14 @@ public class TransferDFragment extends DialogFragment implements LoaderManager.L
     }
 
     @Override
-    public void onLoadFinished(Loader<Bundle> loader, Bundle data) {
+    public void onLoadFinished(Loader<ContactsLoader.Result> loader, ContactsLoader.Result data) {
 
 //        ArrayList<CallContact> tmp = data.getParcelableArrayList("Contacts");
 
     }
 
     @Override
-    public void onLoaderReset(Loader<Bundle> loader) {
+    public void onLoaderReset(Loader<ContactsLoader.Result> loader) {
         // Thi is called when the last Cursor provided to onLoadFinished
         // mListAdapter.swapCursor(null);
     }
@@ -281,7 +281,7 @@ public class TransferDFragment extends DialogFragment implements LoaderManager.L
                 tv = (TextView) mInflater.inflate(android.R.layout.simple_dropdown_item_1line, parent, false);
             }
 
-            tv.setText(calls.get(position).getParticipants().get(0).getmContact().getmDisplayName());
+            tv.setText(calls.get(position).getParticipants().get(0).getContact().getDisplayName());
             return tv;
         }
 
diff --git a/ring-android/app/src/main/java/cx/ring/history/DatabaseHelper.java b/ring-android/app/src/main/java/cx/ring/history/DatabaseHelper.java
index a623e989d..43c116f95 100644
--- a/ring-android/app/src/main/java/cx/ring/history/DatabaseHelper.java
+++ b/ring-android/app/src/main/java/cx/ring/history/DatabaseHelper.java
@@ -48,13 +48,12 @@ import java.sql.SQLException;
  */
 public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
 
-    // name of the database file for your application -- change to something appropriate for your app
     private static final String DATABASE_NAME = "history.db";
     // any time you make changes to your database objects, you may have to increase the database version
-    private static final int DATABASE_VERSION = 2;
+    private static final int DATABASE_VERSION = 4;
 
-    // the DAO object we use to access the SimpleData table
     private Dao<HistoryCall, Integer> historyDao = null;
+    private Dao<HistoryText, Integer> historyTextDao = null;
 
     public DatabaseHelper(Context context) {
         super(context, DATABASE_NAME, null, DATABASE_VERSION);
@@ -67,8 +66,10 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
     @Override
     public void onCreate(SQLiteDatabase db, ConnectionSource connectionSource) {
         try {
+            //TableUtils.dropTable(connectionSource, HistoryCall.class, true);
             Log.i(DatabaseHelper.class.getName(), "onCreate");
             TableUtils.createTable(connectionSource, HistoryCall.class);
+            TableUtils.createTable(connectionSource, HistoryText.class);
         } catch (SQLException e) {
             Log.e(DatabaseHelper.class.getName(), "Can't create database", e);
             throw new RuntimeException(e);
@@ -84,6 +85,7 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
         try {
             Log.i(DatabaseHelper.class.getName(), "onUpgrade");
             TableUtils.dropTable(connectionSource, HistoryCall.class, true);
+            TableUtils.dropTable(connectionSource, HistoryText.class, true);
             // after we drop the old databases, we create the new ones
             onCreate(db, connectionSource);
         } catch (SQLException e) {
@@ -102,6 +104,12 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
         }
         return historyDao;
     }
+    public Dao<HistoryText, Integer> getTextHistoryDao() throws SQLException {
+        if (historyTextDao == null) {
+            historyTextDao = getDao(HistoryText.class);
+        }
+        return historyTextDao;
+    }
 
     /**
      * Close the database connections and clear any cached DAOs.
@@ -110,5 +118,6 @@ public class DatabaseHelper extends OrmLiteSqliteOpenHelper {
     public void close() {
         super.close();
         historyDao = null;
+        historyTextDao = null;
     }
 }
diff --git a/ring-android/app/src/main/java/cx/ring/history/HistoryCall.java b/ring-android/app/src/main/java/cx/ring/history/HistoryCall.java
index 2e7672919..0e818d0ae 100644
--- a/ring-android/app/src/main/java/cx/ring/history/HistoryCall.java
+++ b/ring-android/app/src/main/java/cx/ring/history/HistoryCall.java
@@ -46,11 +46,11 @@ import java.util.TimeZone;
 public class HistoryCall implements Parcelable {
 
     @DatabaseField(index = true, columnName="TIMESTAMP_START")
-    long call_start;
+    public long call_start;
     @DatabaseField
-    long call_end;
+    public long call_end;
     @DatabaseField
-    String number;
+    public String number;
     @DatabaseField
     boolean missed;
     @DatabaseField
@@ -62,6 +62,8 @@ public class HistoryCall implements Parcelable {
     @DatabaseField
     long contactID;
     @DatabaseField
+    String contactKey;
+    @DatabaseField
     String callID;
 
     public String getAccountID() {
@@ -73,14 +75,15 @@ public class HistoryCall implements Parcelable {
     }
 
     public HistoryCall(SipCall call) {
-        call_start = call.getTimestampStart_();
-        call_end = call.getTimestampEnd_();
-        accountID = call.getAccount().getAccountID();
-        number = call.getmContact().getPhones().get(0).getNumber();
+        call_start = call.getTimestampStart();
+        call_end = call.getTimestampEnd();
+        accountID = call.getAccount();
+        number = call.getNumber();
         missed = call.isRinging() && call.isIncoming();
         direction = call.getCallType();
         recordPath = call.getRecordPath();
-        contactID = call.getmContact().getId();
+        contactID = call.getContact().getId();
+        contactKey = call.getContact().getKey();
         callID = call.getCallId();
     }
 
@@ -90,10 +93,10 @@ public class HistoryCall implements Parcelable {
 
     public String getDirection() {
         switch (direction) {
-            case SipCall.direction.CALL_TYPE_INCOMING:
-                return "CALL_TYPE_INCOMING";
-            case SipCall.direction.CALL_TYPE_OUTGOING:
-                return "CALL_TYPE_OUTGOING";
+            case SipCall.Direction.INCOMING:
+                return "INCOMING";
+            case SipCall.Direction.OUTGOING:
+                return "OUTGOING";
             default:
                 return "CALL_TYPE_UNDETERMINED";
         }
@@ -102,9 +105,15 @@ public class HistoryCall implements Parcelable {
     public String getDate() {
         return HistoryTimeModel.timeToHistoryConst(call_start);
     }
+    public Date getStartDate() {
+        return new Date(call_start);
+    }
+    public Date getEndDate() {
+        return new Date(call_end);
+    }
 
     public String getStartString(String format) {
-        Timestamp stamp = new Timestamp(call_start * 1000); // in milliseconds
+        Timestamp stamp = new Timestamp(call_start); // in milliseconds
         Date date = new Date(stamp.getTime());
         SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.getDefault());
         sdf.setTimeZone(TimeZone.getDefault());
@@ -114,7 +123,7 @@ public class HistoryCall implements Parcelable {
 
     public String getDurationString() {
 
-        long duration = call_end - call_start;
+        long duration = (call_end - call_start)/1000;
         if (duration < 60)
             return String.format(Locale.getDefault(), "%02d secs", duration);
 
@@ -122,7 +131,6 @@ public class HistoryCall implements Parcelable {
             return String.format(Locale.getDefault(), "%02d mins %02d secs", (duration % 3600) / 60, (duration % 60));
 
         return String.format(Locale.getDefault(), "%d h %02d mins %02d secs", duration / 3600, (duration % 3600) / 60, (duration % 60));
-
     }
 
     public long getDuration() {
@@ -152,6 +160,7 @@ public class HistoryCall implements Parcelable {
         dest.writeInt(direction);
         dest.writeString(recordPath);
         dest.writeLong(contactID);
+        dest.writeString(contactKey);
         dest.writeString(callID);
     }
 
@@ -174,6 +183,7 @@ public class HistoryCall implements Parcelable {
         direction = in.readInt();
         recordPath = in.readString();
         contactID = in.readLong();
+        contactKey = in.readString();
         callID = in.readString();
     }
 
@@ -182,11 +192,14 @@ public class HistoryCall implements Parcelable {
     }
 
     public boolean isIncoming() {
-        return direction == SipCall.direction.CALL_TYPE_INCOMING;
+        return direction == SipCall.Direction.INCOMING;
     }
 
     public boolean isMissed() {
         return missed;
     }
 
+    public CharSequence getCallId() {
+        return callID;
+    }
 }
diff --git a/ring-android/app/src/main/java/cx/ring/history/HistoryEntry.java b/ring-android/app/src/main/java/cx/ring/history/HistoryEntry.java
index 385355c75..433db3c56 100644
--- a/ring-android/app/src/main/java/cx/ring/history/HistoryEntry.java
+++ b/ring-android/app/src/main/java/cx/ring/history/HistoryEntry.java
@@ -34,15 +34,18 @@ package cx.ring.history;
 import android.os.Parcel;
 import android.os.Parcelable;
 import cx.ring.model.CallContact;
+import cx.ring.model.TextMessage;
 
 import java.util.ArrayList;
+import java.util.Date;
 import java.util.NavigableMap;
 import java.util.TreeMap;
 
 public class HistoryEntry implements Parcelable {
 
     private CallContact contact;
-    private NavigableMap<Long, HistoryCall> calls;
+    private final NavigableMap<Long, HistoryCall> calls = new TreeMap<>();
+    private final NavigableMap<Long, TextMessage> text_messages = new TreeMap<>();
     private String accountID;
     int missed_sum;
     int outgoing_sum;
@@ -50,7 +53,6 @@ public class HistoryEntry implements Parcelable {
 
     public HistoryEntry(String account, CallContact c) {
         contact = c;
-        calls = new TreeMap<Long, HistoryCall>();
         accountID = account;
         missed_sum = outgoing_sum = incoming_sum = 0;
     }
@@ -66,6 +68,9 @@ public class HistoryEntry implements Parcelable {
     public NavigableMap<Long, HistoryCall> getCalls() {
         return calls;
     }
+    public NavigableMap<Long, TextMessage> getTextMessages() {
+        return text_messages;
+    }
 
     public CallContact getContact() {
         return contact;
@@ -97,13 +102,24 @@ public class HistoryEntry implements Parcelable {
             setContact(linkedTo);
     }
 
+    public void addTextMessage(TextMessage text) {
+        text_messages.put(text.getTimestamp(), text);
+        if (contact.isUnknown() && !text.getContact().isUnknown())
+            setContact(text.getContact());
+    }
+    /*public void addTextMessage(HistoryText text) {
+        TextMessage txt = new TextMessage(text);
+        txt.setContact(contact);
+        text_messages.put(txt.getTimestamp(), txt);
+    }*/
+
     public String getNumber() {
         return calls.lastEntry().getValue().number;
     }
 
     public String getTotalDuration() {
         int duration = 0;
-        ArrayList<HistoryCall> all_calls = new ArrayList<HistoryCall>(calls.values());
+        ArrayList<HistoryCall> all_calls = new ArrayList<>(calls.values());
         for (HistoryCall all_call : all_calls) {
             duration += all_call.getDuration();
         }
@@ -114,15 +130,60 @@ public class HistoryEntry implements Parcelable {
         return duration / 60 + "min";
     }
 
-    public int getMissed_sum() {
+    public Date getLastCallDate() {
+        /*Date d = new Date(0);
+        for (Map.Entry<Long, HistoryCall> c : getCalls().entrySet()) {
+            Date nd = c.getValue().getStartDate();
+            if (d.compareTo(nd) < 0)
+                d = nd;
+        }
+        return d;*/
+        return new Date(calls.isEmpty() ? 0 : calls.lastEntry().getKey());
+    }
+    public Date getLastTextDate() {
+        return new Date(text_messages.isEmpty() ? 0 : text_messages.lastEntry().getKey());
+    }
+    public Date getLastInteraction() {
+        return new Date(Math.max(calls.isEmpty() ? 0 : calls.lastEntry().getKey(), text_messages.isEmpty() ? 0 : text_messages.lastEntry().getKey()));
+    }
+
+    public HistoryCall getLastOutgoingCall() {
+        for (HistoryCall c : calls.descendingMap().values())
+            if (!c.isIncoming())
+                return c;
+        return null;
+    }
+    public TextMessage getLastOutgoingText() {
+        for (TextMessage c : text_messages.descendingMap().values())
+            if (c.isOutgoing())
+                return c;
+        return null;
+    }
+
+    public String getLastNumberUsed() {
+        HistoryCall call = getLastOutgoingCall();
+        TextMessage text = getLastOutgoingText();
+        if (call == null && text == null)
+            return null;
+        if (call == null)
+            return text.getNumber();
+        if (text == null)
+            return call.getNumber();
+        if (call.call_start < text.getTimestamp())
+            return text.getNumber();
+        else
+            return call.getNumber();
+    }
+
+    public int getMissedSum() {
         return missed_sum;
     }
 
-    public int getOutgoing_sum() {
+    public int getOutgoingSum() {
         return outgoing_sum;
     }
 
-    public int getIncoming_sum() {
+    public int getIncomingSum() {
         return incoming_sum;
     }
 
@@ -136,8 +197,10 @@ public class HistoryEntry implements Parcelable {
 
         dest.writeParcelable(contact, 0);
 
-        dest.writeList(new ArrayList<HistoryCall>(calls.values()));
-        dest.writeList(new ArrayList<Long>(calls.keySet()));
+        dest.writeList(new ArrayList<>(calls.values()));
+        dest.writeList(new ArrayList<>(calls.keySet()));
+        dest.writeList(new ArrayList<>(text_messages.values()));
+        dest.writeList(new ArrayList<>(text_messages.keySet()));
 
         dest.writeString(accountID);
         dest.writeInt(missed_sum);
@@ -159,21 +222,24 @@ public class HistoryEntry implements Parcelable {
     private HistoryEntry(Parcel in) {
         contact = in.readParcelable(CallContact.class.getClassLoader());
 
-        ArrayList<HistoryCall> values = new ArrayList<HistoryCall>();
+        ArrayList<HistoryCall> values = new ArrayList<>();
         in.readList(values, HistoryCall.class.getClassLoader());
-
-        ArrayList<Long> keys = new ArrayList<Long>();
+        ArrayList<Long> keys = new ArrayList<>();
         in.readList(keys, Long.class.getClassLoader());
-
-        calls = new TreeMap<Long, HistoryCall>();
         for (int i = 0; i < keys.size(); ++i) {
             calls.put(keys.get(i), values.get(i));
         }
+        ArrayList<TextMessage> tvalues = new ArrayList<>();
+        in.readList(tvalues, TextMessage.class.getClassLoader());
+        ArrayList<Long> tkeys = new ArrayList<>();
+        in.readList(tkeys, Long.class.getClassLoader());
+        for (int i = 0; i < keys.size(); ++i) {
+            text_messages.put(tkeys.get(i), tvalues.get(i));
+        }
 
         accountID = in.readString();
         missed_sum = in.readInt();
         outgoing_sum = in.readInt();
         incoming_sum = in.readInt();
     }
-
 }
diff --git a/ring-android/app/src/main/java/cx/ring/history/HistoryManager.java b/ring-android/app/src/main/java/cx/ring/history/HistoryManager.java
index 591cbf06b..07355c29b 100644
--- a/ring-android/app/src/main/java/cx/ring/history/HistoryManager.java
+++ b/ring-android/app/src/main/java/cx/ring/history/HistoryManager.java
@@ -32,6 +32,8 @@
 package cx.ring.history;
 
 import android.content.Context;
+import android.util.Log;
+
 import com.j256.ormlite.android.apptools.OpenHelperManager;
 import com.j256.ormlite.stmt.QueryBuilder;
 import com.j256.ormlite.table.TableUtils;
@@ -53,9 +55,10 @@ public class HistoryManager {
 
     public boolean insertNewEntry(Conference toInsert){
         for (SipCall call : toInsert.getParticipants()) {
-            call.setTimestampEnd_(System.currentTimeMillis());
+            call.setTimestampEnd(System.currentTimeMillis());
             HistoryCall persistent = new HistoryCall(call);
             try {
+                Log.w("HistoryManager", "HistoryDao().create() " + persistent.getNumber() + " " + persistent.getStartDate().toString() + " " + persistent.getEndDate());
                 getHelper().getHistoryDao().create(persistent);
             } catch (SQLException e) {
                 e.printStackTrace();
@@ -65,6 +68,17 @@ public class HistoryManager {
         return true;
     }
 
+    public boolean insertNewTextMessage(HistoryText txt) {
+        try {
+            Log.w("HistoryManager", "HistoryDao().create() acc:" + txt.getAccountID() + " num:" + txt.getNumber() + " date:" + txt.getDate().toString() + " msg:" + txt.getMessage());
+            getHelper().getTextHistoryDao().create(txt);
+        } catch (SQLException e) {
+            e.printStackTrace();
+            return false;
+        }
+        return true;
+    }
+
     /*
     * Necessary when user hang up a call in a Conference
     * The call creates an HistoryCall, but the conference still goes on
@@ -84,16 +98,21 @@ public class HistoryManager {
     }
 
     public List<HistoryCall> getAll() throws SQLException {
-
         QueryBuilder<HistoryCall, Integer> qb = getHelper().getHistoryDao().queryBuilder();
         qb.orderBy("TIMESTAMP_START", true);
-
         return getHelper().getHistoryDao().query(qb.prepare());
     }
 
+    public List<HistoryText> getAllTextMessages() throws SQLException {
+        QueryBuilder<HistoryText, Integer> qb = getHelper().getTextHistoryDao().queryBuilder();
+        qb.orderBy("TIMESTAMP", true);
+        return getHelper().getTextHistoryDao().query(qb.prepare());
+    }
+
     public boolean clearDB() {
         try {
             TableUtils.clearTable(getHelper().getConnectionSource(), HistoryCall.class);
+            TableUtils.clearTable(getHelper().getConnectionSource(), HistoryText.class);
         } catch (SQLException e) {
             e.printStackTrace();
             return false;
diff --git a/ring-android/app/src/main/java/cx/ring/history/HistoryText.java b/ring-android/app/src/main/java/cx/ring/history/HistoryText.java
new file mode 100644
index 000000000..372c2038a
--- /dev/null
+++ b/ring-android/app/src/main/java/cx/ring/history/HistoryText.java
@@ -0,0 +1,187 @@
+/*
+ *  Copyright (C) 2004-2014 Savoir-Faire Linux Inc.
+ *
+ *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Additional permission under GNU GPL version 3 section 7:
+ *
+ *  If you modify this program, or any covered work, by linking or
+ *  combining it with the OpenSSL project's OpenSSL library (or a
+ *  modified version of that library), containing parts covered by the
+ *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+ *  grants you additional permission to convey the resulting work.
+ *  Corresponding Source for a non-source form of such a combination
+ *  shall include the source code for the parts of OpenSSL used as well
+ *  as that of the covered work.
+ */
+
+
+package cx.ring.history;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import com.j256.ormlite.field.DatabaseField;
+
+import java.sql.Timestamp;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+import cx.ring.model.CallContact;
+import cx.ring.model.TextMessage;
+
+public class HistoryText implements Parcelable {
+
+    @DatabaseField(index = true, columnName="id")
+    public String id;
+    @DatabaseField(index = true, columnName="TIMESTAMP")
+    public long time;
+    @DatabaseField
+    public String number;
+    @DatabaseField
+    int direction;
+    @DatabaseField
+    String accountID;
+    @DatabaseField
+    long contactID;
+    @DatabaseField
+    String contactKey;
+    @DatabaseField
+    String callID;
+    @DatabaseField
+    String message;
+
+    public HistoryText(TextMessage txt) {
+        id = txt.getId();
+        time = txt.getTimestamp();
+        accountID = txt.getAccount();
+        number = txt.getNumber();
+        direction = txt.getCallType();
+        message = txt.getMessage();
+        callID = txt.getCallId();
+        if (txt.getContact() != null) {
+            contactID = txt.getContact().getId();
+            contactKey = txt.getContact().getKey();
+        }
+    }
+
+    public String getAccountID() {
+        return accountID;
+    }
+
+    public long getContactID() {
+        return contactID;
+    }
+
+    /*
+    public HistoryText(String account, String from, String msg, CallContact contact, boolean incoming) {
+        time = System.currentTimeMillis();
+        accountID = account;
+        number = from;
+        direction = incoming ? TextMessage.direction.INCOMING : TextMessage.direction.OUTGOING;
+        if (contact != null) {
+            contactID = contact.getId();
+            contactKey = contact.getKey();
+        }
+        //callID = call.getCallId();
+        message = msg;
+    }*/
+
+    /* Needed by ORMLite */
+    public HistoryText() {
+    }
+
+    public String getDirection() {
+        switch (direction) {
+            case TextMessage.direction.INCOMING:
+                return "INCOMING";
+            case TextMessage.direction.OUTGOING:
+                return "OUTGOING";
+            default:
+                return "CALL_TYPE_UNDETERMINED";
+        }
+    }
+
+    public Date getDate() {
+        return new Date(time);
+    }
+
+    public String getTimeString(String format) {
+        Timestamp stamp = new Timestamp(time); // in milliseconds
+        Date date = new Date(stamp.getTime());
+        SimpleDateFormat sdf = new SimpleDateFormat(format, Locale.getDefault());
+        sdf.setTimeZone(TimeZone.getDefault());
+        return sdf.format(date);
+
+    }
+
+    public String getNumber() {
+        return number;
+    }
+
+    public String getMessage() {
+        return message;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeString(id);
+        dest.writeLong(time);
+        dest.writeString(accountID);
+        dest.writeString(number);
+        dest.writeInt(direction);
+        dest.writeLong(contactID);
+        dest.writeString(callID);
+        dest.writeString(message);
+    }
+
+    public static final Creator<HistoryText> CREATOR = new Creator<HistoryText>() {
+        public HistoryText createFromParcel(Parcel in) {
+            return new HistoryText(in);
+        }
+
+        public HistoryText[] newArray(int size) {
+            return new HistoryText[size];
+        }
+    };
+
+    public HistoryText(Parcel in) {
+        id = in.readString();
+        time = in.readLong();
+        accountID = in.readString();
+        number = in.readString();
+        direction = in.readInt();
+        contactID = in.readLong();
+        callID = in.readString();
+        message = in.readString();
+    }
+
+    public boolean isIncoming() {
+        return direction == TextMessage.direction.INCOMING;
+    }
+
+    public String getCallId() {
+        return callID;
+    }
+}
diff --git a/ring-android/app/src/main/java/cx/ring/loaders/AccountsLoader.java b/ring-android/app/src/main/java/cx/ring/loaders/AccountsLoader.java
index 32c2cc7f0..b96b6662c 100644
--- a/ring-android/app/src/main/java/cx/ring/loaders/AccountsLoader.java
+++ b/ring-android/app/src/main/java/cx/ring/loaders/AccountsLoader.java
@@ -76,24 +76,23 @@ public class AccountsLoader extends AsyncTaskLoader<Bundle> {
             Map<String, String> state;
             for (String id : accountIDs) {
 
+                details = (Map<String, String>) service.getAccountDetails(id);
+                state = (Map<String, String>) service.getVolatileAccountDetails(id);
                 if (id.contentEquals(ACCOUNT_IP2IP)) {
-                    details = (HashMap<String, String>) service.getAccountDetails(id);
-                    state = (Map<String, String>) service.getVolatileAccountDetails(id);
                     IP2IP = new Account(ACCOUNT_IP2IP, details, new ArrayList<Map<String, String>>(), state); // Empty credentials
                     //accounts.add(IP2IP);
                     continue;
                 }
-                details = (Map<String, String>) service.getAccountDetails(id);
+
                 credentials = (ArrayList<Map<String, String>>) service.getCredentials(id);
-                state = (Map<String, String>) service.getVolatileAccountDetails(id);
-                for (Map.Entry<String, String> entry : state.entrySet()) {
+                /*for (Map.Entry<String, String> entry : state.entrySet()) {
                     Log.i(TAG, "state:" + entry.getKey() + " -> " + entry.getValue());
-                }
+                }*/
                 Account tmp = new Account(id, details, credentials, state);
 
                 accounts.add(tmp);
 
-                Log.i(TAG, "account:" + tmp.getAlias() + " " + tmp.isEnabled());
+               // Log.i(TAG, "account:" + tmp.getAlias() + " " + tmp.isEnabled());
 
             }
         } catch (RemoteException | NullPointerException e) {
diff --git a/ring-android/app/src/main/java/cx/ring/loaders/ContactsLoader.java b/ring-android/app/src/main/java/cx/ring/loaders/ContactsLoader.java
index 3482d3479..fd71e80af 100644
--- a/ring-android/app/src/main/java/cx/ring/loaders/ContactsLoader.java
+++ b/ring-android/app/src/main/java/cx/ring/loaders/ContactsLoader.java
@@ -36,24 +36,32 @@ import java.util.ArrayList;
 import cx.ring.model.CallContact;
 
 import android.content.AsyncTaskLoader;
+import android.content.ContentResolver;
 import android.content.Context;
 import android.database.Cursor;
 import android.net.Uri;
 import android.os.Bundle;
+import android.provider.ContactsContract;
 import android.provider.ContactsContract.CommonDataKinds.Phone;
 import android.provider.ContactsContract.CommonDataKinds.SipAddress;
 import android.provider.ContactsContract.Contacts;
+import android.util.Log;
 
-public class ContactsLoader extends AsyncTaskLoader<Bundle> {
-    
-//    private static final String TAG = ContactsLoader.class.getSimpleName();
+public class ContactsLoader extends AsyncTaskLoader<ContactsLoader.Result>
+{
+    private static final String TAG = ContactsLoader.class.getSimpleName();
+
+    public class Result {
+        public final ArrayList<CallContact> contacts = new ArrayList<>();
+        public final ArrayList<CallContact> starred = new ArrayList<>();
+    }
 
     // These are the Contacts rows that we will retrieve.
-    static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { Contacts._ID, Contacts.DISPLAY_NAME, Contacts.PHOTO_ID, Contacts.LOOKUP_KEY, Contacts.STARRED };
+    static final String[] CONTACTS_SUMMARY_PROJECTION = new String[] { Contacts._ID, Contacts.LOOKUP_KEY, Contacts.DISPLAY_NAME, Contacts.PHOTO_ID, Contacts.STARRED };
     static final String[] CONTACTS_PHONES_PROJECTION = new String[] { Phone.NUMBER, Phone.TYPE };
     static final String[] CONTACTS_SIP_PROJECTION = new String[] { SipAddress.SIP_ADDRESS, SipAddress.TYPE };
 
-    String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND (" + Contacts.HAS_PHONE_NUMBER + "=1) AND (" + Contacts.DISPLAY_NAME + " != '' ))";
+    static private final String select = "((" + Contacts.DISPLAY_NAME + " NOTNULL) AND (" + Contacts.HAS_PHONE_NUMBER + "=1) AND (" + Contacts.DISPLAY_NAME + " != '' ))";
     Uri baseUri;
 
     public ContactsLoader(Context context, Uri u) {
@@ -62,52 +70,55 @@ public class ContactsLoader extends AsyncTaskLoader<Bundle> {
     }
 
     @Override
-    public Bundle loadInBackground() {
-        ArrayList<CallContact> contacts = new ArrayList<CallContact>();
-        ArrayList<CallContact> starred = new ArrayList<CallContact>();
+    public Result loadInBackground() {
+        Result res = new Result();
+
+        ContentResolver cr = getContext().getContentResolver();
+        Cursor result = cr.query(baseUri, CONTACTS_SUMMARY_PROJECTION, select, null, Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
+        if (result == null)
+            return res;
 
-        Cursor result = getContext().getContentResolver().query(baseUri, CONTACTS_SUMMARY_PROJECTION, select, null,
-                Contacts.DISPLAY_NAME + " COLLATE LOCALIZED ASC");
         int iID = result.getColumnIndex(Contacts._ID);
+        int iKey = result.getColumnIndex(ContactsContract.Data.LOOKUP_KEY);
         int iName = result.getColumnIndex(Contacts.DISPLAY_NAME);
         int iPhoto = result.getColumnIndex(Contacts.PHOTO_ID);
         int iStarred = result.getColumnIndex(Contacts.STARRED);
         CallContact.ContactBuilder builder = CallContact.ContactBuilder.getInstance();
-        
+
         while (result.moveToNext()) {
-            builder.startNewContact(result.getLong(iID), result.getString(iName), result.getLong(iPhoto));
+            long cid = result.getLong(iID);
+            builder.startNewContact(cid, result.getString(iKey), result.getString(iName), result.getLong(iPhoto));
             
-//            Cursor cPhones = getContext().getContentResolver().query(Phone.CONTENT_URI, CONTACTS_PHONES_PROJECTION,
-//                    Phone.CONTACT_ID + " =" + result.getLong(iID), null, null);
-
-//            while (cPhones.moveToNext()) {
-//                builder.addPhoneNumber(cPhones.getString(cPhones.getColumnIndex(Phone.NUMBER)), cPhones.getInt(cPhones.getColumnIndex(Phone.TYPE)));
-////                Log.i(TAG,"Phone:"+cPhones.getString(cPhones.getColumnIndex(Phone.NUMBER)));
-//            }
-//            cPhones.close();
-//
-//            Cursor cSip = getContext().getContentResolver().query(Phone.CONTENT_URI, CONTACTS_SIP_PROJECTION,
-//                    Phone.CONTACT_ID + "=" + result.getLong(iID), null, null);
-//
-//            while (cSip.moveToNext()) {
-//                builder.addSipNumber(cSip.getString(cSip.getColumnIndex(SipAddress.SIP_ADDRESS)), cSip.getInt(cSip.getColumnIndex(SipAddress.TYPE)));
-////                Log.i(TAG,"Phone:"+cSip.getString(cSip.getColumnIndex(SipAddress.SIP_ADDRESS)));
-//            }
-//            cSip.close();
-
-            contacts.add(builder.build());
+            Cursor cPhones = cr.query(Phone.CONTENT_URI, CONTACTS_PHONES_PROJECTION, Phone.CONTACT_ID + " =" + cid, null, null);
+            if (cPhones != null) {
+                while (cPhones.moveToNext()) {
+                    builder.addPhoneNumber(cPhones.getString(cPhones.getColumnIndex(Phone.NUMBER)), cPhones.getInt(cPhones.getColumnIndex(Phone.TYPE)));
+                    Log.w(TAG,"Phone:"+cPhones.getString(cPhones.getColumnIndex(Phone.NUMBER)));
+                }
+                cPhones.close();
+            }
+
+            //Cursor cSip = cr.query(Phone.CONTENT_URI, CONTACTS_SIP_PROJECTION, Phone.CONTACT_ID + "=" + cid, null, null);
+            Cursor cSip = cr.query(ContactsContract.Data.CONTENT_URI,
+                    CONTACTS_SIP_PROJECTION,
+                    ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=? AND " + ContactsContract.Data.MIMETYPE + "=?",
+                    new String[]{String.valueOf(cid), ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE}, null);
+            if (cSip != null) {
+                while (cSip.moveToNext()) {
+                    builder.addSipNumber(cSip.getString(cSip.getColumnIndex(SipAddress.SIP_ADDRESS)), cSip.getInt(cSip.getColumnIndex(SipAddress.TYPE)));
+                    Log.w(TAG, "SIP Phone for " + cid + " :" + cSip.getString(cSip.getColumnIndex(SipAddress.SIP_ADDRESS)));
+                }
+                cSip.close();
+            }
+
+            res.contacts.add(builder.build());
             if (result.getInt(iStarred) == 1) {
-                starred.add(builder.build());
+                res.starred.add(builder.build());
             }
            
-        }        
-        
+        }
         result.close();
-        Bundle toReturn = new Bundle();
-        
-       toReturn.putParcelableArrayList("Contacts", contacts);
-       toReturn.putParcelableArrayList("Starred", starred);
 
-        return toReturn;
+        return res;
     }
 }
diff --git a/ring-android/app/src/main/java/cx/ring/loaders/HistoryLoader.java b/ring-android/app/src/main/java/cx/ring/loaders/HistoryLoader.java
index b6712ea9f..7606f2f85 100644
--- a/ring-android/app/src/main/java/cx/ring/loaders/HistoryLoader.java
+++ b/ring-android/app/src/main/java/cx/ring/loaders/HistoryLoader.java
@@ -63,7 +63,7 @@ public class HistoryLoader extends AsyncTaskLoader<ArrayList<HistoryEntry>> {
     @Override
     public ArrayList<HistoryEntry> loadInBackground() {
 
-        HashMap<String,HistoryEntry> historyEntries = new HashMap<String, HistoryEntry>();
+        HashMap<String,HistoryEntry> historyEntries = new HashMap<>();
 
         try {
             List<HistoryCall> list = historyManager.getAll();
@@ -77,11 +77,12 @@ public class HistoryLoader extends AsyncTaskLoader<ArrayList<HistoryEntry>> {
                             ContactsContract.Contacts._ID + " = ?",
                             new String[]{String.valueOf(call.getContactID())}, null);
                     int iID = result.getColumnIndex(ContactsContract.Contacts._ID);
+                    int iKey = result.getColumnIndex(ContactsContract.Contacts.LOOKUP_KEY);
                     int iName = result.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
                     int iPhoto = result.getColumnIndex(ContactsContract.Contacts.PHOTO_ID);
 
                     if (result.moveToFirst()) {
-                        builder.startNewContact(result.getLong(iID), result.getString(iName), result.getLong(iPhoto));
+                        builder.startNewContact(result.getLong(iID), result.getString(iKey), result.getString(iName), result.getLong(iPhoto));
                         builder.addPhoneNumber(call.getNumber(), 0);
                         contact = builder.build();
                     } else {
diff --git a/ring-android/app/src/main/java/cx/ring/model/Bubble.java b/ring-android/app/src/main/java/cx/ring/model/Bubble.java
index 3cf6e8a05..3387427eb 100644
--- a/ring-android/app/src/main/java/cx/ring/model/Bubble.java
+++ b/ring-android/app/src/main/java/cx/ring/model/Bubble.java
@@ -143,7 +143,7 @@ public abstract class Bubble {
     }
 
     protected Bitmap getContactPhoto(Context context, CallContact contact, int size) {
-        if (contact.getPhoto_id() > 0) {
+        if (contact.getPhotoId() > 0) {
             return ContactPictureTask.loadContactPhoto(context.getContentResolver(), contact.getId());
         } else {
             return ContactPictureTask.decodeSampledBitmapFromResource(context.getResources(), R.drawable.ic_contact_picture, size, size);
diff --git a/ring-android/app/src/main/java/cx/ring/model/BubbleContact.java b/ring-android/app/src/main/java/cx/ring/model/BubbleContact.java
index e21f98a7c..7c0ce6ed6 100644
--- a/ring-android/app/src/main/java/cx/ring/model/BubbleContact.java
+++ b/ring-android/app/src/main/java/cx/ring/model/BubbleContact.java
@@ -38,7 +38,7 @@ public class BubbleContact extends Bubble {
     public SipCall associated_call;
 
     public BubbleContact(Context context, SipCall call, float x, float y, float size) {
-        super(context, call.getmContact(), x, y, size);
+        super(context, call.getContact(), x, y, size);
         associated_call = call;
     }
 
@@ -62,7 +62,7 @@ public class BubbleContact extends Bubble {
 
     @Override
     public String getName() {
-        return associated_call.getmContact().getmDisplayName();
+        return associated_call.getContact().getDisplayName();
     }
 
     @Override
diff --git a/ring-android/app/src/main/java/cx/ring/model/BubblesView.java b/ring-android/app/src/main/java/cx/ring/model/BubblesView.java
index 8b465dde2..890a2bec6 100644
--- a/ring-android/app/src/main/java/cx/ring/model/BubblesView.java
+++ b/ring-android/app/src/main/java/cx/ring/model/BubblesView.java
@@ -97,7 +97,7 @@ public class BubblesView extends GLSurfaceView implements SurfaceHolder.Callback
         SurfaceHolder holder = getHolder();
         holder.addCallback(this);
 
-        this.setZOrderOnTop(true); // necessary
+        //this.setZOrderOnTop(true); // necessary
         holder.setFormat(PixelFormat.TRANSLUCENT);
         // create thread only; it's started in surfaceCreated()
         createThread();
@@ -313,9 +313,9 @@ public class BubblesView extends GLSurfaceView implements SurfaceHolder.Callback
                     } else
                         canvas.drawBitmap(ic_bg, null, a.getBounds(showed * 2.f, b.getPos(), showed), action_paint);
                     canvas.drawBitmap(a.getBitmap(), null, a.getBounds(showed, b.getPos(), showed), null);
-                    float dist_raw = FloatMath.sqrt((b.pos.x - a.pos.x) * (b.pos.x - a.pos.x) + (b.pos.y - a.pos.y) * (b.pos.y - a.pos.y));
-                    float dist_min = a.radius + b.radius + bubbleActionTextDistMin;
-                    float dist = Math.max(0, dist_raw - dist_min);
+                    double dist_raw = Math.sqrt((b.pos.x - a.pos.x) * (b.pos.x - a.pos.x) + (b.pos.y - a.pos.y) * (b.pos.y - a.pos.y));
+                    double dist_min = a.radius + b.radius + bubbleActionTextDistMin;
+                    double dist = Math.max(0, dist_raw - dist_min);
                     if (actions.enabled && dist < dist_range) {
                         white_name_paint.setAlpha(255 - (int) (255 * dist / dist_range));
                         canvas.drawText(a.name, a.getBounds().centerX(), a.getBounds().centerY() - a.radius * 2.2f, white_name_paint);
@@ -343,7 +343,7 @@ public class BubblesView extends GLSurfaceView implements SurfaceHolder.Callback
             return true;
 
         if (action == MotionEvent.ACTION_UP) {
-            if (thread.suspendFlag) {
+            if (thread != null && thread.suspendFlag) {
                 Log.i(TAG, "Relaunch drawing thread");
                 thread.setPaused(false);
             }
@@ -354,7 +354,7 @@ public class BubblesView extends GLSurfaceView implements SurfaceHolder.Callback
                 }
             }
             dragging_bubble = false;
-        } else if (action != MotionEvent.ACTION_DOWN && !isDraggingBubble() && !thread.suspendFlag) {
+        } else if (action != MotionEvent.ACTION_DOWN && !isDraggingBubble() && thread != null && !thread.suspendFlag) {
             Log.i(TAG, "Not dragging thread should be stopped");
             thread.setPaused(true);
         }
diff --git a/ring-android/app/src/main/java/cx/ring/model/CallContact.java b/ring-android/app/src/main/java/cx/ring/model/CallContact.java
index c067a750f..e11861c07 100644
--- a/ring-android/app/src/main/java/cx/ring/model/CallContact.java
+++ b/ring-android/app/src/main/java/cx/ring/model/CallContact.java
@@ -32,6 +32,9 @@ package cx.ring.model;
 
 import java.lang.ref.WeakReference;
 import java.util.ArrayList;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
 
 import android.content.ContentResolver;
 import android.database.Cursor;
@@ -39,29 +42,70 @@ import android.graphics.Bitmap;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.provider.ContactsContract.Profile;
+import android.support.annotation.NonNull;
+
+import cx.ring.client.ConversationActivity;
+import cx.ring.service.LocalService;
 
 public class CallContact implements Parcelable {
+    static public final Pattern ANGLE_BRACKETS_PATTERN = Pattern.compile("(?:[^<>]+<)?([^<>]+)>?\\s*");
+    public static final Pattern RING_ID_PATTERN = Pattern.compile("^\\s*(?:ring(?:[\\s\\:]+))?(\\p{XDigit}{40})(?:@ring\\.dht)?\\s*$", Pattern.CASE_INSENSITIVE);
 
     public static int DEFAULT_ID = 0;
 
     private long id;
+    private String key;
     private String mDisplayName;
     private long photo_id;
-    private ArrayList<Phone> phones, sip_phones;
+    private ArrayList<Phone> phones/*, sip_phones*/;
     private String mEmail;
     private boolean isUser;
-    private WeakReference<Bitmap> contact_photo = new WeakReference<Bitmap>(null);
+    private WeakReference<Bitmap> contact_photo = new WeakReference<>(null);
 
-    private CallContact(long cID, String displayName, long photoID, ArrayList<Phone> p, ArrayList<Phone> sip, String mail, boolean user) {
+    private CallContact(long cID, String k, String displayName, long photoID, ArrayList<Phone> p, String mail, boolean user) {
         id = cID;
+        key = k;
         mDisplayName = displayName;
         phones = p;
-        sip_phones = sip;
         mEmail = mail;
         photo_id = photoID;
         isUser = user;
     }
 
+    private static String nobracketsNumber(@NonNull String number) {
+        Matcher m = ANGLE_BRACKETS_PATTERN.matcher(number);
+        if (m.find())
+            return m.group(1);
+        return number;
+    }
+
+    public static String canonicalNumber(@NonNull String number) {
+        number = nobracketsNumber(number);
+        Matcher m = RING_ID_PATTERN.matcher(number);
+        if (m.find())
+            return "ring:"+m.group(1);
+        return number;
+    }
+
+    public ArrayList<String> getIds() {
+        ArrayList<String> ret = new ArrayList<>(1+phones.size());
+        if (id != -1)
+            ret.add("c:" + Long.toHexString(id));
+        for (Phone p : phones)
+            ret.add(canonicalNumber(p.getNumber()));
+        return ret;
+    }
+
+    public static long contactIdFromId(String id) {
+        if (!id.startsWith("c:"))
+            return -1;
+        try {
+            return Long.parseLong(id.substring(2), 16);
+        } catch (Exception e) {
+            return -1;
+        }
+    }
+
     public CallContact(Parcel in) {
         readFromParcel(in);
     }
@@ -70,15 +114,21 @@ public class CallContact implements Parcelable {
         return id;
     }
 
-    public String getmDisplayName() {
-        return mDisplayName;
+    public String getDisplayName() {
+        if (!mDisplayName.isEmpty())
+            return mDisplayName;
+        if (!phones.isEmpty())
+            return phones.get(0).getNumber();
+        /*if (!sip_phones.isEmpty())
+            return sip_phones.get(0).getNumber();*/
+        return "";
     }
 
-    public long getPhoto_id() {
+    public long getPhotoId() {
         return photo_id;
     }
 
-    public void setPhoto_id(long photo_id) {
+    public void setPhotoId(long photo_id) {
         this.photo_id = photo_id;
     }
 
@@ -90,53 +140,56 @@ public class CallContact implements Parcelable {
         this.phones = phones;
     }
 
-    public ArrayList<Phone> getSip_phones() {
-        return sip_phones;
+    public String getEmail() {
+        return mEmail;
     }
 
-    public void setSip_phones(ArrayList<Phone> sip_phones) {
-        this.sip_phones = sip_phones;
+    public void setEmail(String mEmail) {
+        this.mEmail = mEmail;
     }
 
-    public Phone getSipPhone() {
-        if (sip_phones.size() > 0) {
-            return sip_phones.get(0);
-        }
-        if (phones.size() > 0) {
-            return phones.get(0);
-        }
-        return null;
+    public boolean hasNumber(String number) {
+        if (number == null || number.isEmpty())
+            return false;
+        number = canonicalNumber(number);
+        for (Phone p : phones)
+            if (canonicalNumber(p.getNumber()).equals(number))
+                return true;
+        return false;
     }
 
-    public String getmEmail() {
-        return mEmail;
+    @Override
+    public String toString() {
+        return mDisplayName;
     }
 
-    public void setmEmail(String mEmail) {
-        this.mEmail = mEmail;
+    public void setId(long id) {
+        this.id = id;
     }
 
-    @Override
-    public String toString() {
-        return mDisplayName;
+    public void setDisplayName(String displayName) {
+        this.mDisplayName = displayName;
+    }
+
+    public String getKey() {
+        return key;
     }
 
     public static class ContactBuilder {
 
         long contactID;
+        String key;
         String contactName;
         long contactPhoto;
         ArrayList<Phone> phones;
-        ArrayList<Phone> sip;
         String contactMail;
 
-        public ContactBuilder startNewContact(long id, String displayName, long photo_id) {
+        public ContactBuilder startNewContact(long id, String k, String displayName, long photo_id) {
             contactID = id;
-
+            key = k;
             contactName = displayName;
             contactPhoto = photo_id;
-            phones = new ArrayList<Phone>();
-            sip = new ArrayList<Phone>();
+            phones = new ArrayList<>();
             return this;
         }
 
@@ -146,12 +199,12 @@ public class CallContact implements Parcelable {
         }
 
         public ContactBuilder addSipNumber(String num, int type) {
-            sip.add(new Phone(num, type));
+            phones.add(new Phone(num, type, NumberType.SIP));
             return this;
         }
 
         public CallContact build() {
-            return new CallContact(contactID, contactName, contactPhoto, phones, sip, contactMail, false);
+            return new CallContact(contactID, key, contactName, contactPhoto, phones, contactMail, false);
         }
 
         public static ContactBuilder getInstance() {
@@ -159,25 +212,30 @@ public class CallContact implements Parcelable {
         }
 
         public static CallContact buildUnknownContact(String to) {
-            ArrayList<Phone> phones = new ArrayList<Phone>();
+            ArrayList<Phone> phones = new ArrayList<>();
             phones.add(new Phone(to, 0));
 
-            return new CallContact(-1, to, 0, phones, new ArrayList<CallContact.Phone>(), "", false);
+            return new CallContact(-1, null, to, 0, phones, "", false);
+        }
+        public static CallContact buildUnknownContact(String to, int type) {
+            ArrayList<Phone> phones = new ArrayList<>();
+            phones.add(new Phone(to, type));
+            return new CallContact(-1, null, to, 0, phones, "", false);
         }
 
         public static CallContact buildUserContact(ContentResolver cr) {
-            String[] mProjection = new String[] { Profile._ID, Profile.DISPLAY_NAME_PRIMARY, Profile.PHOTO_ID };
+            String[] mProjection = new String[] { Profile._ID, Profile.LOOKUP_KEY, Profile.DISPLAY_NAME_PRIMARY, Profile.PHOTO_ID };
             Cursor mProfileCursor = cr.query(Profile.CONTENT_URI, mProjection, null, null, null);
             CallContact result;
             if (mProfileCursor.getCount() > 0) {
                 mProfileCursor.moveToFirst();
+                String key = mProfileCursor.getString(mProfileCursor.getColumnIndex(Profile.LOOKUP_KEY));
                 String displayName = mProfileCursor.getString(mProfileCursor.getColumnIndex(Profile.DISPLAY_NAME_PRIMARY));
 
-                result = new CallContact(mProfileCursor.getLong(mProfileCursor.getColumnIndex(Profile._ID)), displayName,
-                        mProfileCursor.getLong(mProfileCursor.getColumnIndex(Profile.PHOTO_ID)), new ArrayList<Phone>(),
-                        new ArrayList<CallContact.Phone>(), "", true);
+                result = new CallContact(mProfileCursor.getLong(mProfileCursor.getColumnIndex(Profile._ID)), key, displayName,
+                        mProfileCursor.getLong(mProfileCursor.getColumnIndex(Profile.PHOTO_ID)), new ArrayList<Phone>(), "", true);
             } else {
-                result = new CallContact(-1, "Me", 0, new ArrayList<Phone>(), new ArrayList<CallContact.Phone>(), "", true);
+                result = new CallContact(-1, null, "Me", 0, new ArrayList<Phone>(), "", true);
             }
             mProfileCursor.close();
             return result;
@@ -193,26 +251,22 @@ public class CallContact implements Parcelable {
     @Override
     public void writeToParcel(Parcel dest, int flags) {
         dest.writeLong(id);
+        dest.writeString(key);
         dest.writeString(mDisplayName);
         dest.writeLong(photo_id);
         dest.writeTypedList(phones);
-
-        dest.writeTypedList(sip_phones);
-
         dest.writeString(mEmail);
         dest.writeByte((byte) (isUser ? 1 : 0));
 
     }
 
     private void readFromParcel(Parcel in) {
-
         id = in.readLong();
+        key = in.readString();
         mDisplayName = in.readString();
         photo_id = in.readLong();
-        phones = new ArrayList<CallContact.Phone>();
-        sip_phones = new ArrayList<CallContact.Phone>();
+        phones = new ArrayList<>();
         in.readTypedList(phones, Phone.CREATOR);
-        in.readTypedList(sip_phones, Phone.CREATOR);
         mEmail = in.readString();
         isUser = in.readByte() == 1;
     }
@@ -229,15 +283,48 @@ public class CallContact implements Parcelable {
         }
     };
 
-    public static class Phone implements Parcelable {
+    public enum NumberType {
+        UNKNOWN(0),
+        TEL(1),
+        SIP(2),
+        IP(2),
+        RING(3);
+
+        private final int type;
+        NumberType(int t) {
+            type = t;
+        }
+        private static final NumberType[] VALS = NumberType.values();
+        public static NumberType fromInteger(int _id)
+        {
+            for (NumberType v : VALS)
+                if (v.type == _id)
+                    return v;
+            return UNKNOWN;
+        }
+        /*public static NumberType guess(String num) {
+            String canon = canonicalNumber(num);
+            Matcher m = URI_NUMBER_REGEX.matcher(canon);
+
+            return UNKNOWN;
+        }*/
+    }
 
-        int type;
+    public static class Phone implements Parcelable {
+        NumberType ntype;
         String number;
+        int category; // Home, work, custom etc.
 
-        public Phone(String num, int ty) {
-            type = ty;
+        public Phone(String num, int cat) {
+            ntype = NumberType.UNKNOWN;
+            category = cat;
             number = num;
         }
+        public Phone(String num, int cat, NumberType nty) {
+            ntype = nty;
+            number = num;
+            category = cat;
+        }
 
         public Phone(Parcel in) {
             readFromParcel(in);
@@ -250,13 +337,15 @@ public class CallContact implements Parcelable {
 
         @Override
         public void writeToParcel(Parcel dest, int arg1) {
-            dest.writeInt(type);
+            dest.writeInt(ntype.type);
             dest.writeString(number);
+            dest.writeInt(category);
         }
 
         private void readFromParcel(Parcel in) {
-            type = in.readInt();
+            ntype = NumberType.fromInteger(in.readInt());
             number = in.readString();
+            category = in.readInt();
         }
 
         public static final Parcelable.Creator<Phone> CREATOR = new Parcelable.Creator<Phone>() {
@@ -271,12 +360,12 @@ public class CallContact implements Parcelable {
             }
         };
 
-        public int getType() {
-            return type;
+        public NumberType getType() {
+            return ntype;
         }
 
         public void setType(int type) {
-            this.type = type;
+            this.ntype = NumberType.fromInteger(type);
         }
 
         public String getNumber() {
@@ -289,13 +378,12 @@ public class CallContact implements Parcelable {
 
     }
 
-    public void addPhoneNumber(String tel, int type) {
-        phones.add(new Phone(tel, type));
+    public void addPhoneNumber(String tel, int car) {
+        phones.add(new Phone(tel, car));
 
     }
-
-    public void addSipNumber(String tel, int type) {
-        sip_phones.add(new Phone(tel, type));
+    public void addNumber(String tel, int cat, NumberType type) {
+        phones.add(new Phone(tel, cat, type));
 
     }
 
@@ -314,7 +402,7 @@ public class CallContact implements Parcelable {
     }
 
     public void setPhoto(Bitmap externalBMP) {
-        contact_photo = new WeakReference<Bitmap>(externalBMP);
+        contact_photo = new WeakReference<>(externalBMP);
     }
 
     /**
diff --git a/ring-android/app/src/main/java/cx/ring/model/Conference.java b/ring-android/app/src/main/java/cx/ring/model/Conference.java
index db027f6a9..a604bb1bb 100644
--- a/ring-android/app/src/main/java/cx/ring/model/Conference.java
+++ b/ring-android/app/src/main/java/cx/ring/model/Conference.java
@@ -36,13 +36,20 @@ import java.util.ArrayList;
 import android.os.Parcel;
 import android.os.Parcelable;
 
+import java.util.Random;
+import java.util.concurrent.ThreadLocalRandom;
+
 public class Conference implements Parcelable {
 
     private String id;
     private int mConfState;
     private ArrayList<SipCall> participants;
     private boolean recording;
-    private ArrayList<SipMessage> messages;
+    private ArrayList<TextMessage> messages;
+
+    public int notificationId;
+
+    private final static Random rand = new Random();
 
     public static String DEFAULT_ID = "-1";
 
@@ -54,13 +61,13 @@ public class Conference implements Parcelable {
         participants.remove(toRemove);
     }
 
-    public boolean useSecureLayer() {
+    /*public boolean useSecureLayer() {
         for(SipCall call : participants){
             if(call.getAccount().useSecureLayer())
                 return true;
         }
         return false;
-    }
+    }*/
 
     public interface state {
         int ACTIVE_ATTACHED = 0;
@@ -104,8 +111,8 @@ public class Conference implements Parcelable {
     public void writeToParcel(Parcel out, int flags) {
         out.writeString(id);
         out.writeInt(mConfState);
-        ArrayList<SipCall> normal_calls = new ArrayList<SipCall>();
-        ArrayList<SecureSipCall> secure_calls = new ArrayList<SecureSipCall>();
+        ArrayList<SipCall> normal_calls = new ArrayList<>();
+        ArrayList<SecureSipCall> secure_calls = new ArrayList<>();
 
         for(SipCall part : participants){
             if(part instanceof SecureSipCall)
@@ -117,6 +124,7 @@ public class Conference implements Parcelable {
         out.writeTypedList(normal_calls);
         out.writeByte((byte) (recording ? 1 : 0));
         out.writeTypedList(messages);
+        out.writeInt(notificationId);
     }
 
     public static final Parcelable.Creator<Conference> CREATOR = new Parcelable.Creator<Conference>() {
@@ -131,36 +139,38 @@ public class Conference implements Parcelable {
 
 
     private Conference(Parcel in) {
-        participants = new ArrayList<SipCall>();
+        participants = new ArrayList<>();
         id = in.readString();
         mConfState = in.readInt();
-        ArrayList<SecureSipCall> tmp = new ArrayList<SecureSipCall>();
+        ArrayList<SecureSipCall> tmp = new ArrayList<>();
         in.readTypedList(tmp, SecureSipCall.CREATOR);
         in.readTypedList(participants, SipCall.CREATOR);
         participants.addAll(tmp);
         recording = in.readByte() == 1;
-        messages = new ArrayList<SipMessage>();
-        in.readTypedList(messages, SipMessage.CREATOR);
+        messages = new ArrayList<>();
+        in.readTypedList(messages, TextMessage.CREATOR);
+        notificationId = in.readInt();
     }
 
     public Conference(SipCall call) {
         this(DEFAULT_ID);
         participants.add(call);
+        notificationId = rand.nextInt();
     }
 
     public Conference(String cID) {
         id = cID;
-        participants = new ArrayList<SipCall>();
+        participants = new ArrayList<>();
         recording = false;
-        messages = new ArrayList<SipMessage>();
+        messages = new ArrayList<>();
     }
 
     public Conference(Conference c) {
         id = c.id;
         mConfState = c.mConfState;
-        participants = new ArrayList<SipCall>(c.participants);
+        participants = new ArrayList<>(c.participants);
         recording = c.recording;
-        messages = new ArrayList<SipMessage>();
+        messages = new ArrayList<>();
     }
 
     public String getId() {
@@ -275,11 +285,11 @@ public class Conference implements Parcelable {
         return participants.size() == 1 && participants.get(0).isOngoing() || participants.size() > 1;
     }
 
-    public ArrayList<SipMessage> getMessages() {
+    public ArrayList<TextMessage> getMessages() {
         return messages;
     }
 
-    public void addSipMessage(SipMessage sipMessage) {
+    public void addSipMessage(TextMessage sipMessage) {
         messages.add(sipMessage);
     }
 
diff --git a/ring-android/app/src/main/java/cx/ring/model/Conversation.java b/ring-android/app/src/main/java/cx/ring/model/Conversation.java
new file mode 100644
index 000000000..db311cd51
--- /dev/null
+++ b/ring-android/app/src/main/java/cx/ring/model/Conversation.java
@@ -0,0 +1,232 @@
+package cx.ring.model;
+
+import android.database.ContentObservable;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.util.Log;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+import cx.ring.history.HistoryCall;
+import cx.ring.history.HistoryEntry;
+import cx.ring.history.HistoryText;
+import cx.ring.model.account.Account;
+
+public class Conversation extends ContentObservable implements Parcelable
+{
+    static final String TAG = Conversation.class.getSimpleName();
+
+    public CallContact contact;
+    //private HistoryEntry history;
+    /** accountId -> histroy entries */
+    final private Map<String, HistoryEntry> history = new HashMap<>();
+
+    //private Conference current_call = null;
+    public final ArrayList<Conference> current_calls;
+
+    public String getLastNumberUsed(String accountID) {
+        HistoryEntry he = history.get(accountID);
+        if (he == null)
+            return null;
+        return he.getLastNumberUsed();
+    }
+
+    public Conference getConference(String id) {
+        for (Conference c : current_calls)
+            if (c.getId().contentEquals(id) || c.getCallById(id) != null)
+                return c;
+        return null;
+    }
+
+    public Pair<HistoryEntry, HistoryCall> findHistoryByCallId(String id) {
+        for (HistoryEntry e : history.values()) {
+            for (HistoryCall c : e.getCalls().values()) {
+                if (c.getCallId().equals(id))
+                    return new Pair<>(e, c);
+            }
+        }
+        return null;
+    }
+
+    public class ConversationElement {
+        public HistoryCall call = null;
+        public TextMessage text = null;
+        public ConversationElement(HistoryCall c) {
+            call = c;
+        }
+        public ConversationElement(TextMessage t) {
+            text = t;
+        }
+        public long getDate() {
+            if (text != null)
+                return text.getTimestamp();
+            else if (call != null)
+                return call.call_start;
+            return 0;
+        }
+    }
+
+    public Conversation(CallContact c) {
+        contact = c;
+        current_calls = new ArrayList<>();
+    }
+
+    public static final Creator<Conversation> CREATOR = new Creator<Conversation>() {
+        @Override
+        public Conversation createFromParcel(Parcel in) {
+            return new Conversation(in);
+        }
+
+        @Override
+        public Conversation[] newArray(int size) {
+            return new Conversation[size];
+        }
+    };
+
+    public CallContact getContact() {
+        return contact;
+    }
+
+    public Date getLastInteraction() {
+        if (!current_calls.isEmpty()) {
+            return new Date();
+        }
+        Date d = new Date(0);
+
+        //for (Map.Entry<String, HistoryEntry> e : history.entrySet()) {
+        for (HistoryEntry e : history.values()) {
+            Date nd = e.getLastInteraction();
+            if (d.compareTo(nd) < 0)
+                d = nd;
+        }
+        return d;
+    }
+
+    public void addHistoryCall(HistoryCall c) {
+        String accountId = c.getAccountID();
+        if (history.containsKey(accountId))
+            history.get(accountId).addHistoryCall(c, contact);
+        else {
+            HistoryEntry e = new HistoryEntry(accountId, contact);
+            e.addHistoryCall(c, contact);
+            history.put(accountId, e);
+        }
+    }
+    public void addTextMessage(TextMessage txt) {
+        if (txt.getCallId() != null && !txt.getCallId().isEmpty()) {
+            Conference conf = getConference(txt.getCallId());
+            if (conf == null)
+                return;
+            conf.addSipMessage(txt);
+        }// else {
+        if (txt.getContact() == null)
+            txt.setContact(contact);
+        String accountId = txt.getAccount();
+        if (history.containsKey(accountId))
+            history.get(accountId).addTextMessage(txt);
+        else {
+            HistoryEntry e = new HistoryEntry(accountId, contact);
+            e.addTextMessage(txt);
+            history.put(accountId, e);
+        }
+        //}
+    }
+
+    /*public HistoryEntry getHistory(String account_id) {
+        return history.get(account_id);
+    }*/
+
+    public ArrayList<ConversationElement> getHistory() {
+        ArrayList<ConversationElement> all = new ArrayList<>();
+        for (HistoryEntry e : history.values()) {
+            for (HistoryCall c : e.getCalls().values())
+                all.add(new ConversationElement(c));
+            for (TextMessage t : e.getTextMessages().values())
+                all.add(new ConversationElement(t));
+        }
+        Collections.sort(all, new Comparator<ConversationElement>() {
+            @Override
+            public int compare(ConversationElement lhs, ConversationElement rhs) {
+                return (int)((lhs.getDate() - rhs.getDate())/1000l);
+            }
+        });
+        return all;
+    }
+
+    public Set<String> getAccountsUsed() {
+        return history.keySet();
+    }
+
+    public String getLastAccountUsed() {
+        String last = null;
+        Date d = new Date(0);
+        for (Map.Entry<String, HistoryEntry> e : history.entrySet()) {
+            Date nd = e.getValue().getLastInteraction();
+            if (d.compareTo(nd) < 0) {
+                d = nd;
+                last = e.getKey();
+            }
+        }
+        return last;
+    }
+
+    public Conference getCurrentCall() {
+        if (current_calls.isEmpty())
+            return null;
+        return current_calls.get(0);
+    }
+    public void setCurrentCall(Conference c) {
+        current_calls.add(c);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel dest, int flags) {
+        dest.writeParcelable(contact, flags);
+        //dest.writeParcelable(current_call, flags);
+        dest.writeList(current_calls);
+        dest.writeList(new ArrayList<>(history.values()));
+        dest.writeList(new ArrayList<>(history.keySet()));
+    }
+
+    protected Conversation(Parcel in) {
+        contact = in.readParcelable(CallContact.class.getClassLoader());
+        //current_call = in.readParcelable(Conference.class.getClassLoader());
+        current_calls = in.readArrayList(Conference.class.getClassLoader());
+
+        ArrayList<HistoryEntry> values = new ArrayList<>();
+        in.readList(values, HistoryEntry.class.getClassLoader());
+        ArrayList<String> keys = new ArrayList<>();
+        in.readList(keys, String.class.getClassLoader());
+        for (int i = 0; i < keys.size(); ++i)
+            history.put(keys.get(i), values.get(i));
+    }
+
+    public ArrayList<TextMessage> getTextMessages() {
+        ArrayList<TextMessage> texts = new ArrayList<>();
+        for (HistoryEntry h : history.values()) {
+            texts.addAll(h.getTextMessages().values());
+        }
+        Collections.sort(texts, new Comparator<TextMessage>() {
+            @Override
+            public int compare(TextMessage lhs, TextMessage rhs) {
+                return (int)((lhs.getTimestamp() - rhs.getTimestamp())/1000l);
+            }
+        });
+        return texts;
+    }
+
+}
diff --git a/ring-android/app/src/main/java/cx/ring/model/SecureSipCall.java b/ring-android/app/src/main/java/cx/ring/model/SecureSipCall.java
index c606cc130..8ca7ef131 100644
--- a/ring-android/app/src/main/java/cx/ring/model/SecureSipCall.java
+++ b/ring-android/app/src/main/java/cx/ring/model/SecureSipCall.java
@@ -55,10 +55,10 @@ public class SecureSipCall extends SipCall {
 
     private boolean isInitialized;
 
-    public SecureSipCall(SipCall call) {
+    public SecureSipCall(SipCall call, String keyExchange) {
         super(call);
         isInitialized = false;
-        String keyExchange = getAccount().getSrtpDetails().getDetailString(AccountDetailSrtp.CONFIG_SRTP_KEY_EXCHANGE);
+        //String keyExchange = getAccount().getSrtpDetails().getDetailString(AccountDetailSrtp.CONFIG_SRTP_KEY_EXCHANGE);
         /*if (keyExchange.contentEquals("zrtp")) {
             mSecureLayerUsed = SecureLayer.ZRTP_LAYER;
         } else */if (keyExchange.contentEquals("sdes")) {
@@ -124,7 +124,7 @@ public class SecureSipCall extends SipCall {
     }
 
     /*
-    * returns what state should be visible during call
+    * returns what State should be visible during call
     */
     public int displayModule() {
         /*if (isInitialized) {
diff --git a/ring-android/app/src/main/java/cx/ring/model/SipCall.java b/ring-android/app/src/main/java/cx/ring/model/SipCall.java
index 5524f2027..0aa9c511e 100644
--- a/ring-android/app/src/main/java/cx/ring/model/SipCall.java
+++ b/ring-android/app/src/main/java/cx/ring/model/SipCall.java
@@ -35,7 +35,6 @@ import android.os.Bundle;
 import android.os.Parcel;
 import android.os.Parcelable;
 import android.util.Log;
-import cx.ring.model.account.Account;
 
 public class SipCall implements Parcelable {
 
@@ -43,24 +42,34 @@ public class SipCall implements Parcelable {
     public static String ACCOUNT = "account";
     public static String CONTACT = "contact";
     public static String TYPE = "type";
-    public static String STATE = "state";
+    public static String STATE = "State";
+    public static String NUMBER = "number";
 
     private static final String TAG = SipCall.class.getSimpleName();
 
     private String mCallID = "";
-    private Account mAccount = null;
+    private String mAccount = "";
     private CallContact mContact = null;
+    private String mNumber = "";
     private boolean isRecording = false;
     private long timestampStart_ = 0;
     private long timestampEnd_ = 0;
 
     private int mCallType;
-    private int mCallState = state.CALL_STATE_NONE;
+    private int mCallState = State.NONE;
+
+    public SipCall(String id, String account, String number, int direction) {
+        mCallID = id;
+        mAccount = account;
+        mNumber = number;
+        mCallType = direction;
+    }
 
     public SipCall(SipCall call) {
         mCallID = call.mCallID;
         mAccount = call.mAccount;
         mContact = call.mContact;
+        mNumber = call.mNumber;
         isRecording = call.isRecording;
         timestampStart_ = call.timestampStart_;
         timestampEnd_ = call.timestampEnd_;
@@ -75,10 +84,10 @@ public class SipCall implements Parcelable {
      */
 
     protected SipCall(Parcel in) {
-
         mCallID = in.readString();
-        mAccount = in.readParcelable(Account.class.getClassLoader());
+        mAccount = in.readString();
         mContact = in.readParcelable(CallContact.class.getClassLoader());
+        mNumber = in.readString();
         isRecording = in.readByte() == 1;
         mCallType = in.readInt();
         mCallState = in.readInt();
@@ -88,14 +97,11 @@ public class SipCall implements Parcelable {
 
     public SipCall(Bundle args) {
         mCallID = args.getString(ID);
-        mAccount = args.getParcelable(ACCOUNT);
+        mAccount = args.getString(ACCOUNT);
         mCallType = args.getInt(TYPE);
         mCallState = args.getInt(STATE);
         mContact = args.getParcelable(CONTACT);
-    }
-
-    public long getTimestampEnd_() {
-        return timestampEnd_;
+        mNumber = args.getString(NUMBER);
     }
 
     public String getRecordPath() {
@@ -109,29 +115,29 @@ public class SipCall implements Parcelable {
     public Bundle getBundle() {
         Bundle args = new Bundle();
         args.putString(SipCall.ID, mCallID);
-        args.putParcelable(SipCall.ACCOUNT, mAccount);
+        args.putString(SipCall.ACCOUNT, mAccount);
         args.putInt(SipCall.STATE, mCallState);
         args.putInt(SipCall.TYPE, mCallType);
         args.putParcelable(SipCall.CONTACT, mContact);
+        args.putString(SipCall.NUMBER, mNumber);
         return args;
     }
 
-
-    public interface direction {
-        int CALL_TYPE_INCOMING = 1;
-        int CALL_TYPE_OUTGOING = 2;
+    public interface Direction {
+        int INCOMING = 1;
+        int OUTGOING = 2;
     }
 
-    public interface state {
-        int CALL_STATE_NONE = 0;
-        int CALL_STATE_CONNECTING = 1;
-        int CALL_STATE_RINGING = 2;
-        int CALL_STATE_CURRENT = 3;
-        int CALL_STATE_HUNGUP = 4;
-        int CALL_STATE_BUSY = 5;
-        int CALL_STATE_FAILURE = 6;
-        int CALL_STATE_HOLD = 7;
-        int CALL_STATE_UNHOLD = 8;
+    public interface State {
+        int NONE = 0;
+        int CONNECTING = 1;
+        int RINGING = 2;
+        int CURRENT = 3;
+        int HUNGUP = 4;
+        int BUSY = 5;
+        int FAILURE = 6;
+        int HOLD = 7;
+        int UNHOLD = 8;
     }
 
     @Override
@@ -141,11 +147,10 @@ public class SipCall implements Parcelable {
 
     @Override
     public void writeToParcel(Parcel out, int flags) {
-
         out.writeString(mCallID);
-        out.writeParcelable(mAccount, 0);
-
+        out.writeString(mAccount);
         out.writeParcelable(mContact, 0);
+        out.writeString(mNumber);
         out.writeByte((byte) (isRecording ? 1 : 0));
         out.writeInt(mCallType);
         out.writeInt(mCallState);
@@ -171,32 +176,36 @@ public class SipCall implements Parcelable {
         return mCallID;
     }
 
-    public long getTimestampStart_() {
+    public long getTimestampStart() {
         return timestampStart_;
     }
 
-    public void setTimestampStart_(long timestampStart_) {
-        this.timestampStart_ = timestampStart_;
+    public void setTimestampStart(long timestampStart) {
+        this.timestampStart_ = timestampStart;
     }
 
-    public void setTimestampEnd_(long timestampEnd_) {
-        this.timestampEnd_ = timestampEnd_;
+    public long getTimestampEnd() {
+        return timestampEnd_;
+    }
+
+    public void setTimestampEnd(long timestampEnd) {
+        this.timestampEnd_ = timestampEnd;
     }
 
-    public void setAccount(Account account) {
+    public void setAccount(String account) {
         mAccount = account;
     }
 
-    public Account getAccount() {
+    public String getAccount() {
         return mAccount;
     }
 
     public String getCallTypeString() {
         switch (mCallType) {
-            case direction.CALL_TYPE_INCOMING:
-                return "CALL_TYPE_INCOMING";
-            case direction.CALL_TYPE_OUTGOING:
-                return "CALL_TYPE_OUTGOING";
+            case Direction.INCOMING:
+                return "INCOMING";
+            case Direction.OUTGOING:
+                return "OUTGOING";
             default:
                 return "CALL_TYPE_UNDETERMINED";
         }
@@ -206,37 +215,49 @@ public class SipCall implements Parcelable {
         mCallState = callState;
     }
 
-    public CallContact getmContact() {
+    public void setContact(CallContact c) {
+        mContact = c;
+    }
+
+    public CallContact getContact() {
         return mContact;
     }
 
+    public void setNumber(String n) {
+        mNumber = n;
+    }
+
+    public String getNumber() {
+        return mNumber;
+    }
+
     public String getCallStateString() {
 
         String text_state;
 
         switch (mCallState) {
-            case state.CALL_STATE_NONE:
+            case State.NONE:
                 text_state = "NONE";
                 break;
-            case state.CALL_STATE_RINGING:
+            case State.RINGING:
                 text_state = "RINGING";
                 break;
-            case state.CALL_STATE_CURRENT:
+            case State.CURRENT:
                 text_state = "CURRENT";
                 break;
-            case state.CALL_STATE_HUNGUP:
+            case State.HUNGUP:
                 text_state = "HUNGUP";
                 break;
-            case state.CALL_STATE_BUSY:
+            case State.BUSY:
                 text_state = "BUSY";
                 break;
-            case state.CALL_STATE_FAILURE:
+            case State.FAILURE:
                 text_state = "FAILURE";
                 break;
-            case state.CALL_STATE_HOLD:
+            case State.HOLD:
                 text_state = "HOLD";
                 break;
-            case state.CALL_STATE_UNHOLD:
+            case State.UNHOLD:
                 text_state = "UNHOLD";
                 break;
             default:
@@ -256,7 +277,7 @@ public class SipCall implements Parcelable {
 
     public void printCallInfo() {
         Log.i(TAG, "CallInfo: CallID: " + mCallID);
-        Log.i(TAG, "          AccountID: " + mAccount.getAccountID());
+        Log.i(TAG, "          AccountID: " + mAccount);
         Log.i(TAG, "          CallState: " + mCallState);
         Log.i(TAG, "          CallType: " + mCallType);
     }
@@ -270,29 +291,29 @@ public class SipCall implements Parcelable {
     }
 
     public boolean isOutGoing() {
-        return mCallType == direction.CALL_TYPE_OUTGOING;
+        return mCallType == Direction.OUTGOING;
     }
 
     public boolean isRinging() {
-        return mCallState == state.CALL_STATE_RINGING || mCallState == state.CALL_STATE_NONE;
+        return mCallState == State.RINGING || mCallState == State.NONE;
     }
 
     public boolean isIncoming() {
-        return mCallType == direction.CALL_TYPE_INCOMING;
+        return mCallType == Direction.INCOMING;
     }
 
     public boolean isOngoing() {
-        return !(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);
+        return !(mCallState == State.RINGING || mCallState == State.NONE || mCallState == State.FAILURE
+                || mCallState == State.BUSY || mCallState == State.HUNGUP);
 
     }
 
     public boolean isOnHold() {
-        return mCallState == state.CALL_STATE_HOLD;
+        return mCallState == State.HOLD;
     }
 
     public boolean isCurrent() {
-        return mCallState == state.CALL_STATE_CURRENT;
+        return mCallState == State.CURRENT;
     }
 
 
diff --git a/ring-android/app/src/main/java/cx/ring/model/SipMessage.java b/ring-android/app/src/main/java/cx/ring/model/SipMessage.java
deleted file mode 100644
index f8a43cc15..000000000
--- a/ring-android/app/src/main/java/cx/ring/model/SipMessage.java
+++ /dev/null
@@ -1,72 +0,0 @@
-/*
- *  Copyright (C) 2004-2014 Savoir-Faire Linux Inc.
- *
- *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  Additional permission under GNU GPL version 3 section 7:
- *
- *  If you modify this program, or any covered work, by linking or
- *  combining it with the OpenSSL project's OpenSSL library (or a
- *  modified version of that library), containing parts covered by the
- *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
- *  grants you additional permission to convey the resulting work.
- *  Corresponding Source for a non-source form of such a combination
- *  shall include the source code for the parts of OpenSSL used as well
- *  as that of the covered work.
- */
-package cx.ring.model;
-
-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);
-        comment = in.readString();
-    }
-
-}
\ No newline at end of file
diff --git a/ring-android/app/src/main/java/cx/ring/model/SipMessage.aidl b/ring-android/app/src/main/java/cx/ring/model/TextMessage.aidl
similarity index 52%
rename from ring-android/app/src/main/java/cx/ring/model/SipMessage.aidl
rename to ring-android/app/src/main/java/cx/ring/model/TextMessage.aidl
index 072914601..1af4f254e 100644
--- a/ring-android/app/src/main/java/cx/ring/model/SipMessage.aidl
+++ b/ring-android/app/src/main/java/cx/ring/model/TextMessage.aidl
@@ -1,4 +1,4 @@
 package cx.ring.model;
 
 
-parcelable SipMessage;
\ No newline at end of file
+parcelable TextMessage;
\ No newline at end of file
diff --git a/ring-android/app/src/main/java/cx/ring/model/TextMessage.java b/ring-android/app/src/main/java/cx/ring/model/TextMessage.java
new file mode 100644
index 000000000..e7d44df9f
--- /dev/null
+++ b/ring-android/app/src/main/java/cx/ring/model/TextMessage.java
@@ -0,0 +1,294 @@
+/*
+ *  Copyright (C) 2004-2014 Savoir-Faire Linux Inc.
+ *
+ *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux>
+ *          Alexandre Savard <alexandre.savard@gmail.com>
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 3 of the License, or
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ *  Additional permission under GNU GPL version 3 section 7:
+ *
+ *  If you modify this program, or any covered work, by linking or
+ *  combining it with the OpenSSL project's OpenSSL library (or a
+ *  modified version of that library), containing parts covered by the
+ *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
+ *  grants you additional permission to convey the resulting work.
+ *  Corresponding Source for a non-source form of such a combination
+ *  shall include the source code for the parts of OpenSSL used as well
+ *  as that of the covered work.
+ */
+package cx.ring.model;
+
+import android.os.Bundle;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import cx.ring.history.HistoryText;
+
+public class TextMessage implements Parcelable {
+
+    public static String ID = "id";
+    public static String ACCOUNT = "account";
+    public static String CONTACT = "contact";
+    public static String NUMBER = "number";
+    public static String CALL = "call";
+    public static String TYPE = "type";
+    public static String STATE = "State";
+    public static String MESSAGE = "message";
+    public static String TIME = "time";
+
+    private static final String TAG = TextMessage.class.getSimpleName();
+
+    private String mID = "";
+    private String mAccount = null;
+    private CallContact mContact = null;
+    private String mNumber = null;
+    private long mTimestamp = 0;
+
+    private int mType;
+    private int mState = state.NONE;
+    private String mMessage;
+    private String mCallID = "";
+
+    public TextMessage(TextMessage msg) {
+        mID = msg.mID;
+        mAccount = msg.mAccount;
+        mContact = msg.mContact;
+        mNumber = msg.mNumber;
+        mTimestamp = msg.mTimestamp;
+        mType = msg.mType;
+        mState = msg.mState;
+        mMessage = msg.mMessage;
+        mCallID = msg.mCallID;
+    }
+
+    /**
+     * *********************
+     * Construtors
+     * *********************
+     */
+
+    /*public TextMessage(String account, String number, String message, boolean in) {
+        mAccount = account;
+        mNumber = number;
+        mMessage = message;
+        mTimestamp = System.currentTimeMillis();
+        mType = in ? direction.INCOMING : direction.OUTGOING;
+    }*/
+
+    public TextMessage(boolean in, String message) {
+        mMessage = message;
+        mType = in ? direction.INCOMING : direction.OUTGOING;
+        mTimestamp = System.currentTimeMillis();
+    }
+
+    public TextMessage(boolean in, String message, String number, String callid, String account) {
+        mAccount = account;
+        mNumber = number;
+        mMessage = message;
+        mTimestamp = System.currentTimeMillis();
+        mCallID = callid;
+        mType = in ? direction.INCOMING : direction.OUTGOING;
+    }
+
+    public TextMessage(HistoryText h) {
+        mID = h.id;
+        mAccount = h.getAccountID();
+        mNumber = h.getNumber();
+        mMessage = h.getMessage();
+        mTimestamp = h.getDate().getTime();
+        mType = h.isIncoming() ? direction.INCOMING : direction.OUTGOING;
+        mCallID = h.getCallId();
+    }
+
+    protected TextMessage(Parcel in) {
+        mID = in.readString();
+        mAccount = in.readString();
+        mContact = in.readParcelable(CallContact.class.getClassLoader());
+        mNumber = in.readString();
+        mCallID = in.readString();
+        mType = in.readInt();
+        mState = in.readInt();
+        mTimestamp = in.readLong();
+        mMessage = in.readString();
+    }
+
+    public TextMessage(Bundle args) {
+        mID = args.getString(ID);
+        mAccount = args.getParcelable(ACCOUNT);
+        mNumber = args.getString(NUMBER);
+        mCallID = args.getString(CALL);
+        mType = args.getInt(TYPE);
+        mState = args.getInt(STATE);
+        mContact = args.getParcelable(CONTACT);
+        mMessage = args.getString(MESSAGE);
+        mTimestamp = args.getLong(TIME);
+    }
+
+    public String getRecordPath() {
+        return "";
+    }
+
+    public int getCallType() {
+        return mType;
+    }
+
+    public Bundle getBundle() {
+        Bundle args = new Bundle();
+        args.putString(ID, mID);
+        args.putString(ACCOUNT, mAccount);
+        args.putString(NUMBER, mNumber);
+        args.putString(CALL, mCallID);
+        args.putInt(STATE, mState);
+        args.putInt(TYPE, mType);
+        args.putParcelable(CONTACT, mContact);
+        args.putString(MESSAGE, mMessage);
+        args.putLong(TIME, mTimestamp);
+        return args;
+    }
+
+    public String getMessage() {
+        return mMessage;
+    }
+
+    public void setContact(CallContact contact) {
+        mContact = contact;
+    }
+
+    public void setCallId(String callId) {
+        this.mCallID = callId;
+    }
+
+    public String getCallId() {
+        return mCallID;
+    }
+
+    public void setNumber(String number) {
+        this.mNumber = number;
+    }
+
+    public interface direction {
+        int INCOMING = 1;
+        int OUTGOING = 2;
+    }
+
+    public interface state {
+        int NONE = 0;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeString(mID);
+        out.writeString(mAccount);
+        out.writeParcelable(mContact, 0);
+        out.writeString(mNumber);
+        out.writeString(mCallID);
+        out.writeInt(mType);
+        out.writeInt(mState);
+        out.writeLong(mTimestamp);
+        out.writeString(mMessage);
+    }
+
+    public static final Creator<TextMessage> CREATOR = new Creator<TextMessage>() {
+        public TextMessage createFromParcel(Parcel in) {
+            return new TextMessage(in);
+        }
+
+        public TextMessage[] newArray(int size) {
+            return new TextMessage[size];
+        }
+    };
+
+    public void setID(String id) {
+        mID = id;
+    }
+
+    public String getId() {
+        return mID;
+    }
+
+    public long getTimestamp() {
+        return mTimestamp;
+    }
+
+    public void setTimestamp(long timestamp) {
+        this.mTimestamp = timestamp;
+    }
+
+    public void setAccount(String account) {
+        mAccount = account;
+    }
+
+    public String getAccount() {
+        return mAccount;
+    }
+
+    public String getTypeString() {
+        switch (mType) {
+            case direction.INCOMING:
+                return "INCOMING";
+            case direction.OUTGOING:
+                return "OUTGOING";
+            default:
+                return "UNDETERMINED";
+        }
+    }
+
+    public void setState(int callState) {
+        mState = callState;
+    }
+
+    public CallContact getContact() {
+        return mContact;
+    }
+
+    public String getNumber() {
+        return mNumber;
+    }
+
+    public String getStateString() {
+        String text_state;
+        switch (mState) {
+            case state.NONE:
+                text_state = "NONE";
+                break;
+            default:
+                text_state = "NULL";
+        }
+        return text_state;
+    }
+
+    /**
+     * Compare sip calls based on call ID
+     */
+    @Override
+    public boolean equals(Object c) {
+        return c instanceof TextMessage && ((TextMessage) c).mID.contentEquals((mID));
+    }
+
+    public boolean isOutgoing() {
+        return mType == direction.OUTGOING;
+    }
+
+    public boolean isIncoming() {
+        return mType == direction.INCOMING;
+    }
+
+}
diff --git a/ring-android/app/src/main/java/cx/ring/model/account/Account.java b/ring-android/app/src/main/java/cx/ring/model/account/Account.java
index 0f938c125..4c0529943 100644
--- a/ring-android/app/src/main/java/cx/ring/model/account/Account.java
+++ b/ring-android/app/src/main/java/cx/ring/model/account/Account.java
@@ -57,10 +57,13 @@ public class Account extends java.util.Observable implements Parcelable {
         advancedDetails = new AccountDetailAdvanced(details);
         srtpDetails = new AccountDetailSrtp(details);
         tlsDetails = new AccountDetailTls(details);
-        volatileDetails = new AccountDetailVolatile(volatile_details);
-        credentialsDetails = new ArrayList<>();
-        for (int i = 0; i < credentials.size(); ++i) {
-            credentialsDetails.add(new AccountCredentials(credentials.get(i)));
+        if (volatile_details != null)
+            volatileDetails = new AccountDetailVolatile(volatile_details);
+        if (credentials != null) {
+            credentialsDetails = new ArrayList<>();
+            for (int i = 0; i < credentials.size(); ++i) {
+                credentialsDetails.add(new AccountCredentials(credentials.get(i)));
+            }
         }
     }
 
@@ -84,8 +87,8 @@ public class Account extends java.util.Observable implements Parcelable {
         return volatileDetails.getDetailString(AccountDetailVolatile.CONFIG_ACCOUNT_REGISTRATION_STATUS);
     }
 
-    public void setRegistered_state(String registered_state, int code) {
-        Log.i(TAG, "setRegistered_state " + registered_state + " " + code);
+    public void setRegistrationState(String registered_state, int code) {
+        Log.i(TAG, "setRegistrationState " + registered_state + " " + code);
         volatileDetails.setDetailString(AccountDetailVolatile.CONFIG_ACCOUNT_REGISTRATION_STATUS, registered_state);
         volatileDetails.setDetailString(AccountDetailVolatile.CONFIG_ACCOUNT_REGISTRATION_STATE_CODE, Integer.toString(code));
     }
@@ -141,7 +144,7 @@ public class Account extends java.util.Observable implements Parcelable {
         advancedDetails = new AccountDetailAdvanced((HashMap<String, String>) in.readSerializable());
         srtpDetails = new AccountDetailSrtp((HashMap<String, String>) in.readSerializable());
         tlsDetails = new AccountDetailTls((HashMap<String, String>) in.readSerializable());
-        credentialsDetails = new ArrayList<AccountCredentials>();
+        credentialsDetails = new ArrayList<>();
         int cred_count = in.readInt();
         for (int i = 0; i < cred_count; ++i) {
             credentialsDetails.add(new AccountCredentials((HashMap<String, String>) in.readSerializable()));
@@ -202,7 +205,7 @@ public class Account extends java.util.Observable implements Parcelable {
     }
 
     public HashMap<String, String> getDetails() {
-        HashMap<String, String> results = new HashMap<String, String>();
+        HashMap<String, String> results = new HashMap<>();
 
         results.putAll(basicDetails.getDetailsHashMap());
         results.putAll(advancedDetails.getDetailsHashMap());
diff --git a/ring-android/app/src/main/java/cx/ring/model/account/AccountDetail.java b/ring-android/app/src/main/java/cx/ring/model/account/AccountDetail.java
index 54fce72ae..9ec2ef288 100644
--- a/ring-android/app/src/main/java/cx/ring/model/account/AccountDetail.java
+++ b/ring-android/app/src/main/java/cx/ring/model/account/AccountDetail.java
@@ -26,10 +26,12 @@ import java.util.HashMap;
 
 public interface AccountDetail {
 
-    public static final String TRUE_STR = "true";
-    public static final String FALSE_STR = "false";
+    String TAG = AccountDetail.class.getSimpleName();
 
-    public static class PreferenceEntry {
+    String TRUE_STR = "true";
+    String FALSE_STR = "false";
+
+    class PreferenceEntry {
         public String mKey;
         public boolean isTwoState;
         public String mValue;
@@ -47,20 +49,19 @@ public interface AccountDetail {
         }
 
         public boolean isChecked() {
-            return mValue.contentEquals("true");
+            return mValue.contentEquals(TRUE_STR);
         }
     }
 
-    public static final String TAG = "PreferenceHashMap";
 
-    public ArrayList<PreferenceEntry> getDetailValues();
+    ArrayList<PreferenceEntry> getDetailValues();
 
-    public ArrayList<String> getValuesOnly();
+    ArrayList<String> getValuesOnly();
 
-    public HashMap<String, String> getDetailsHashMap();
+    HashMap<String, String> getDetailsHashMap();
 
-    public String getDetailString(String key);
+    String getDetailString(String key);
 
-    public void setDetailString(String key, String newValue);
+    void setDetailString(String key, String newValue);
 
 }
diff --git a/ring-android/app/src/main/java/cx/ring/model/account/AccountDetailAdvanced.java b/ring-android/app/src/main/java/cx/ring/model/account/AccountDetailAdvanced.java
index 587550503..0691d1624 100644
--- a/ring-android/app/src/main/java/cx/ring/model/account/AccountDetailAdvanced.java
+++ b/ring-android/app/src/main/java/cx/ring/model/account/AccountDetailAdvanced.java
@@ -22,8 +22,11 @@
 package cx.ring.model.account;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.Map;
+import java.util.Set;
 
 import android.util.Log;
 
@@ -51,12 +54,26 @@ public class AccountDetailAdvanced implements AccountDetail {
     public static final String CONFIG_AUDIO_PORT_MIN = "Account.audioPortMin";
     public static final String CONFIG_AUDIO_PORT_MAX = "Account.audioPortMax";
 
+    private static final Set<String> CONFIG_KEYS = new HashSet<>(Arrays.asList(
+            CONFIG_ACCOUNT_MAILBOX,
+            CONFIG_ACCOUNT_REGISTRATION_EXPIRE,
+            CONFIG_CREDENTIAL_NUMBER,
+            CONFIG_ACCOUNT_DTMF_TYPE,
+            CONFIG_RINGTONE_PATH, CONFIG_RINGTONE_ENABLED,
+            CONFIG_KEEP_ALIVE_ENABLED,
+            CONFIG_LOCAL_INTERFACE, CONFIG_PUBLISHED_SAMEAS_LOCAL, CONFIG_LOCAL_PORT,
+            CONFIG_PUBLISHED_PORT, CONFIG_PUBLISHED_ADDRESS,
+            CONFIG_STUN_SERVER, CONFIG_STUN_ENABLE,
+            CONFIG_AUDIO_PORT_MIN, CONFIG_AUDIO_PORT_MAX));
+
     private ArrayList<AccountDetail.PreferenceEntry> privateArray;
 
     public AccountDetailAdvanced(Map<String, String> pref) {
-        privateArray = new ArrayList<AccountDetail.PreferenceEntry>();
+        privateArray = new ArrayList<>();
 
         for (String key : pref.keySet()) {
+            if (!CONFIG_KEYS.contains(key))
+                continue;
             PreferenceEntry p = new PreferenceEntry(key);
             p.mValue = pref.get(key);
 
@@ -75,7 +92,7 @@ public class AccountDetailAdvanced implements AccountDetail {
     }
 
     public ArrayList<String> getValuesOnly() {
-        ArrayList<String> valueList = new ArrayList<String>();
+        ArrayList<String> valueList = new ArrayList<>();
 
         for (AccountDetail.PreferenceEntry p : privateArray) {
             Log.i(TAG, "" + p.mValue);
diff --git a/ring-android/app/src/main/java/cx/ring/model/account/AccountDetailBasic.java b/ring-android/app/src/main/java/cx/ring/model/account/AccountDetailBasic.java
index 6e95f122c..9170ed4fd 100644
--- a/ring-android/app/src/main/java/cx/ring/model/account/AccountDetailBasic.java
+++ b/ring-android/app/src/main/java/cx/ring/model/account/AccountDetailBasic.java
@@ -45,10 +45,25 @@ public class AccountDetailBasic implements AccountDetail {
     public static final String CONFIG_ACCOUNT_ENABLE = "Account.enable";
     public static final String CONFIG_PRESENCE_ENABLE = "Account.presenceEnabled";
 
+    public static final String ACCOUNT_TYPE_RING = "RING";
+    public static final String ACCOUNT_TYPE_SIP = "SIP";
+    public static final String ACCOUNT_TYPE_IAX = "IAX";
+
     private ArrayList<AccountDetail.PreferenceEntry> privateArray;
 
+    public String getAlias() {
+        return getDetailString(CONFIG_ACCOUNT_ALIAS);
+    }
+    public String getUsername() {
+        return getDetailString(CONFIG_ACCOUNT_USERNAME);
+    }
+    public String getHostname() {
+        return getDetailString(CONFIG_ACCOUNT_HOSTNAME);
+    }
+
+
     public AccountDetailBasic(Map<String, String> pref) {
-        privateArray = new ArrayList<AccountDetail.PreferenceEntry>();
+        privateArray = new ArrayList<>();
 
         for (String key : pref.keySet()) {
             PreferenceEntry p = new PreferenceEntry(key);
@@ -66,7 +81,7 @@ public class AccountDetailBasic implements AccountDetail {
     }
 
     public ArrayList<String> getValuesOnly() {
-        ArrayList<String> valueList = new ArrayList<String>();
+        ArrayList<String> valueList = new ArrayList<>();
 
         for (AccountDetail.PreferenceEntry p : privateArray) {
             Log.i(TAG, "" + p.mValue);
@@ -77,7 +92,7 @@ public class AccountDetailBasic implements AccountDetail {
     }
 
     public HashMap<String, String> getDetailsHashMap() {
-        HashMap<String, String> map = new HashMap<String, String>();
+        HashMap<String, String> map = new HashMap<>();
 
         for (AccountDetail.PreferenceEntry p : privateArray) {
             map.put(p.mKey, p.mValue);
@@ -100,13 +115,14 @@ public class AccountDetailBasic implements AccountDetail {
     }
 
     public void setDetailString(String key, String newValue) {
-        for (int i = 0; i < privateArray.size(); ++i) {
-            PreferenceEntry p = privateArray.get(i);
+        for (PreferenceEntry p : privateArray) {
             if (p.mKey.equals(key)) {
-                privateArray.get(i).mValue = newValue;
+                p.mValue = newValue;
+                Log.w(TAG, "setDetailString " + key + " -> " + newValue);
+                //return;
             }
         }
-
+        Log.w(TAG, "setDetailString FAIL" + key + " -> " + newValue);
     }
 
 }
diff --git a/ring-android/app/src/main/java/cx/ring/model/account/AccountDetailSrtp.java b/ring-android/app/src/main/java/cx/ring/model/account/AccountDetailSrtp.java
index a70942338..81d1bc7c9 100644
--- a/ring-android/app/src/main/java/cx/ring/model/account/AccountDetailSrtp.java
+++ b/ring-android/app/src/main/java/cx/ring/model/account/AccountDetailSrtp.java
@@ -41,7 +41,7 @@ public class AccountDetailSrtp implements AccountDetail {
     private ArrayList<AccountDetail.PreferenceEntry> privateArray;
 
     public static ArrayList<AccountDetail.PreferenceEntry> getPreferenceEntries() {
-        ArrayList<AccountDetail.PreferenceEntry> preference = new ArrayList<AccountDetail.PreferenceEntry>();
+        ArrayList<AccountDetail.PreferenceEntry> preference = new ArrayList<>();
 
         preference.add(new PreferenceEntry(CONFIG_SRTP_ENABLE, true));
         preference.add(new PreferenceEntry(CONFIG_SRTP_KEY_EXCHANGE, false));
diff --git a/ring-android/app/src/main/java/cx/ring/model/account/AccountDetailTls.java b/ring-android/app/src/main/java/cx/ring/model/account/AccountDetailTls.java
index 595f9d820..9ebfa2415 100644
--- a/ring-android/app/src/main/java/cx/ring/model/account/AccountDetailTls.java
+++ b/ring-android/app/src/main/java/cx/ring/model/account/AccountDetailTls.java
@@ -46,7 +46,7 @@ public class AccountDetailTls implements AccountDetail {
     private ArrayList<AccountDetail.PreferenceEntry> privateArray;
 
     public static ArrayList<AccountDetail.PreferenceEntry> getPreferenceEntries() {
-        ArrayList<AccountDetail.PreferenceEntry> preference = new ArrayList<AccountDetail.PreferenceEntry>();
+        ArrayList<AccountDetail.PreferenceEntry> preference = new ArrayList<>();
 
         preference.add(new PreferenceEntry(CONFIG_TLS_LISTENER_PORT));
         preference.add(new PreferenceEntry(CONFIG_TLS_ENABLE, true));
diff --git a/ring-android/app/src/main/java/cx/ring/service/CallManagerCallBack.java b/ring-android/app/src/main/java/cx/ring/service/CallManagerCallBack.java
index 66bc4aeac..aaf74804e 100644
--- a/ring-android/app/src/main/java/cx/ring/service/CallManagerCallBack.java
+++ b/ring-android/app/src/main/java/cx/ring/service/CallManagerCallBack.java
@@ -1,28 +1,33 @@
 package cx.ring.service;
 
+import android.support.v4.app.NotificationCompat;
+import android.app.PendingIntent;
 import android.content.Intent;
 import android.os.Bundle;
 import android.util.Log;
+
+import cx.ring.R;
 import cx.ring.client.CallActivity;
+import cx.ring.history.HistoryText;
+import cx.ring.model.CallContact;
+import cx.ring.model.TextMessage;
 import cx.ring.model.account.Account;
+import cx.ring.model.account.AccountDetailSrtp;
 import cx.ring.utils.SwigNativeConverter;
 
 import java.util.ArrayList;
-import java.util.HashMap;
 import java.util.Map;
 
-import cx.ring.model.CallContact;
 import cx.ring.model.Conference;
 import cx.ring.model.SecureSipCall;
 import cx.ring.model.SipCall;
-import cx.ring.model.SipMessage;
 
 public class CallManagerCallBack extends Callback {
 
     private static final String TAG = "CallManagerCallBack";
     private SipService mService;
 
-    static public final String CALL_STATE_CHANGED = "call-state-changed";
+    static public final String CALL_STATE_CHANGED = "call-State-changed";
     static public final String INCOMING_CALL = "incoming-call";
     static public final String INCOMING_TEXT = "incoming-text";
     static public final String CONF_CREATED = "conf_created";
@@ -46,11 +51,12 @@ public class CallManagerCallBack extends Callback {
 
     @Override
     public void callStateChanged(String callID, String newState, int detail_code) {
-        Log.d(TAG, "on_call_state_changed : (" + callID + ", " + newState + ")");
+        Log.w(TAG, "on_call_state_changed : (" + callID + ", " + newState + ")");
 
         Conference toUpdate = mService.findConference(callID);
 
         if (toUpdate == null) {
+            Log.w(TAG, "callStateChanged: can't find call " + callID);
             return;
         }
 
@@ -59,38 +65,52 @@ public class CallManagerCallBack extends Callback {
         intent.putExtra("State", newState);
         intent.putExtra("DetailCode", detail_code);
 
-        if (newState.equals("RINGING")) {
-            toUpdate.setCallState(callID, SipCall.state.CALL_STATE_RINGING);
-        } else if (newState.equals("CURRENT")) {
-            if (toUpdate.isRinging()) {
-                toUpdate.getCallById(callID).setTimestampStart_(System.currentTimeMillis());
-            }
-            toUpdate.setCallState(callID, SipCall.state.CALL_STATE_CURRENT);
-        } else if (newState.equals("HUNGUP")) {
-            Log.d(TAG, "Hanging up " + callID);
-            SipCall call = toUpdate.getCallById(callID);
-            if (!toUpdate.hasMultipleParticipants()) {
-                if (toUpdate.isRinging() && toUpdate.isIncoming()) {
-                    mService.mNotificationManager.publishMissedCallNotification(mService.getConferences().get(callID));
+        if (toUpdate.isRinging() && !newState.equals("RINGING")) {
+            Log.w(TAG, "Setting call start date " + callID);
+            toUpdate.getCallById(callID).setTimestampStart(System.currentTimeMillis());
+        }
+
+        switch (newState) {
+            case "CONNECTING":
+                toUpdate.setCallState(callID, SipCall.State.CONNECTING); break;
+            case "RINGING":
+                toUpdate.setCallState(callID, SipCall.State.RINGING); break;
+            case "CURRENT":
+                toUpdate.setCallState(callID, SipCall.State.CURRENT); break;
+            case "HOLD":
+                toUpdate.setCallState(callID, SipCall.State.HOLD); break;
+            case "UNHOLD":
+                toUpdate.setCallState(callID, SipCall.State.CURRENT); break;
+            case "HUNGUP":
+            case "INACTIVE":
+                Log.d(TAG, "Hanging up " + callID);
+                Log.w("CallNotification ", "Canceling " + toUpdate.notificationId);
+                mService.mNotificationManager.notificationManager.cancel(toUpdate.notificationId);
+                SipCall call = toUpdate.getCallById(callID);
+                if (!toUpdate.hasMultipleParticipants()) {
+                    if (toUpdate.isRinging() && toUpdate.isIncoming()) {
+                        mService.mNotificationManager.publishMissedCallNotification(mService.getConferences().get(callID));
+                    }
+                    toUpdate.setCallState(callID, SipCall.State.HUNGUP);
+                    mService.mHistoryManager.insertNewEntry(toUpdate);
+                    mService.getConferences().remove(toUpdate.getId());
+                } else {
+                    toUpdate.setCallState(callID, SipCall.State.HUNGUP);
+                    mService.mHistoryManager.insertNewEntry(call);
                 }
-                toUpdate.setCallState(callID, SipCall.state.CALL_STATE_HUNGUP);
-                mService.mHistoryManager.insertNewEntry(toUpdate);
+                break;
+            case "BUSY":
+                mService.mNotificationManager.notificationManager.cancel(toUpdate.notificationId);
+                toUpdate.setCallState(callID, SipCall.State.BUSY);
                 mService.getConferences().remove(toUpdate.getId());
-            } else {
-                toUpdate.setCallState(callID, SipCall.state.CALL_STATE_HUNGUP);
-                mService.mHistoryManager.insertNewEntry(call);
-            }
-        } else if (newState.equals("BUSY")) {
-            toUpdate.setCallState(callID, SipCall.state.CALL_STATE_BUSY);
-            mService.getConferences().remove(toUpdate.getId());
-        } else if (newState.equals("FAILURE")) {
-            toUpdate.setCallState(callID, SipCall.state.CALL_STATE_FAILURE);
-            mService.getConferences().remove(toUpdate.getId());
-            Ringservice.hangUp(callID);
-        } else if (newState.equals("HOLD")) {
-            toUpdate.setCallState(callID, SipCall.state.CALL_STATE_HOLD);
-        } else if (newState.equals("UNHOLD")) {
-            toUpdate.setCallState(callID, SipCall.state.CALL_STATE_CURRENT);
+                break;
+            case "FAILURE":
+                Log.w("CallNotification ", "Canceling " + toUpdate.notificationId);
+                mService.mNotificationManager.notificationManager.cancel(toUpdate.notificationId);
+                toUpdate.setCallState(callID, SipCall.State.FAILURE);
+                mService.getConferences().remove(toUpdate.getId());
+                Ringservice.hangUp(callID);
+                break;
         }
         intent.putExtra("conference", toUpdate);
         mService.sendBroadcast(intent);
@@ -99,32 +119,28 @@ public class CallManagerCallBack extends Callback {
 
     @Override
     public void incomingCall(String accountID, String callID, String from) {
-        Log.d(TAG, "on_incoming_call(" + accountID + ", " + callID + ", " + from + ")");
+        Log.w(TAG, "on_incoming_call(" + accountID + ", " + callID + ", " + from + ")");
 
         try {
             StringMap details = Ringservice.getAccountDetails(accountID);
-            VectMap credentials = Ringservice.getCredentials(accountID);
-            StringMap state = Ringservice.getVolatileAccountDetails(accountID);
-            Account acc = new Account(accountID, details.toNative(), credentials.toNative(), state.toNative());
-
-            Bundle args = new Bundle();
-            args.putString(SipCall.ID, callID);
-            args.putParcelable(SipCall.ACCOUNT, acc);
-            args.putInt(SipCall.STATE, SipCall.state.CALL_STATE_RINGING);
-            args.putInt(SipCall.TYPE, SipCall.direction.CALL_TYPE_INCOMING);
-
-            CallContact unknow = CallContact.ContactBuilder.buildUnknownContact(from);
-            args.putParcelable(SipCall.CONTACT, unknow);
+            //VectMap credentials = Ringservice.getCredentials(accountID);
+            //StringMap state = Ringservice.getVolatileAccountDetails(accountID);
+            Account acc = new Account(accountID, details.toNative(), null, null);
 
             Intent toSend = new Intent(CallManagerCallBack.INCOMING_CALL);
             toSend.setClass(mService, CallActivity.class);
             toSend.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
-            SipCall newCall = new SipCall(args);
-            newCall.setTimestampStart_(System.currentTimeMillis());
+
+            CallContact unknown = CallContact.ContactBuilder.buildUnknownContact(from);
+
+            SipCall newCall = new SipCall(callID, accountID, from, SipCall.Direction.INCOMING);
+            newCall.setContact(unknown);
+            newCall.setCallState(SipCall.State.RINGING);
+            newCall.setTimestampStart(System.currentTimeMillis());
 
             Conference toAdd;
             if (acc.useSecureLayer()) {
-               SecureSipCall secureCall = new SecureSipCall(newCall);
+               SecureSipCall secureCall = new SecureSipCall(newCall, acc.getSrtpDetails().getDetailString(AccountDetailSrtp.CONFIG_SRTP_KEY_EXCHANGE));
                 toAdd = new Conference(secureCall);
             } else {
                 toAdd = new Conference(newCall);
@@ -132,6 +148,22 @@ public class CallManagerCallBack extends Callback {
 
             mService.getConferences().put(toAdd.getId(), toAdd);
 
+            NotificationCompat.Builder noti = new NotificationCompat.Builder(mService)
+                    .setContentTitle("Incoming call with " + from)
+                    .setContentText("incoming call")
+                    .setOngoing(true)
+                    .setSmallIcon(R.drawable.ic_launcher)
+                    .addAction(R.drawable.ic_call_end_white_24dp, "End call",
+                            PendingIntent.getService(mService, 4278,
+                                new Intent(mService, SipService.class)
+                                        .setAction(SipService.ACTION_CALL_END)
+                                        .putExtra("conf", toAdd.getId()),
+                                    PendingIntent.FLAG_ONE_SHOT));
+
+            //mService.startForeground(toAdd.notificationId, noti);
+            Log.w("CallNotification ", "Adding for incoming " + toAdd.notificationId);
+            mService.mNotificationManager.notificationManager.notify(toAdd.notificationId, noti.build());
+
             Bundle bundle = new Bundle();
             bundle.putParcelable("conference", toAdd);
             toSend.putExtra("resuming", false);
@@ -175,33 +207,37 @@ public class CallManagerCallBack extends Callback {
     }
 
     @Override
-    public void incomingMessage(String ID, String from, StringMap messages) {
+    public void incomingMessage(String id, String from, StringMap messages) {
         Log.w(TAG, "on_incoming_message:" + messages);
 
         String msg = messages.get("text/plain");
         if (msg == null)
             return;
 
-        Intent intent = new Intent(INCOMING_TEXT);
-        intent.putExtra("CallID", ID);
-        intent.putExtra("From", from);
-        intent.putExtra("Msg", msg);
-
-        if (mService.getConferences().get(ID) != null) {
-            mService.getConferences().get(ID).addSipMessage(new SipMessage(true, msg));
-            intent.putExtra("conference", mService.getConferences().get(ID));
-        } else {
-            for (Map.Entry<String, Conference> stringConferenceEntry : mService.getConferences().entrySet()) {
-                Conference tmp = stringConferenceEntry.getValue();
-                for (SipCall c : tmp.getParticipants()) {
-                    if (c.getCallId().contentEquals(ID)) {
-                        mService.getConferences().get(tmp.getId()).addSipMessage(new SipMessage(true, msg));
-                        intent.putExtra("conference", tmp);
-                    }
+        Conference conf = mService.getConferences().get(id);
+        if (conf == null) {
+            for (Conference tmp : mService.getConferences().values())
+                if (tmp.getCallById(id) != null) {
+                    conf = tmp;
+                    break;
                 }
+            if (conf == null) {
+                Log.w(TAG, "Discarding message for unknown call " + id);
+                return;
             }
-
         }
+
+        TextMessage message = new TextMessage(true, msg, from, id, conf.hasMultipleParticipants() ? null : conf.getParticipants().get(0).getAccount());
+        if (!conf.hasMultipleParticipants())
+            message.setContact(conf.getParticipants().get(0).getContact());
+
+        conf.addSipMessage(message);
+
+        mService.mHistoryManager.insertNewTextMessage(new HistoryText(message));
+
+        Intent intent = new Intent(INCOMING_TEXT);
+        intent.putExtra("txt", message);
+        intent.putExtra("conference", conf.getId());
         mService.sendBroadcast(intent);
     }
 
@@ -215,10 +251,21 @@ public class CallManagerCallBack extends Callback {
         for (SipCall call : toReInsert.getParticipants()) {
             mService.getConferences().put(call.getCallId(), new Conference(call));
         }
-        intent.putExtra("conference", mService.getConferences().get(confID));
+
+        Conference conf = mService.getConferences().get(confID);
+
+        Log.w("CallNotification ", "Canceling " + conf.notificationId);
+        //NotificationManager mNotifyMgr = (NotificationManager) mService.getSystemService(Context.NOTIFICATION_SERVICE);
+        mService.mNotificationManager.notificationManager.cancel(conf.notificationId);
+
+        intent.putExtra("conference", conf);
         mService.getConferences().remove(confID);
         mService.sendBroadcast(intent);
 
+        if (mService.getConferences().size() == 0) {
+            mService.stopForeground(true);
+        }
+
     }
 
     @Override
diff --git a/ring-android/app/src/main/java/cx/ring/service/ConfigurationManagerCallback.java b/ring-android/app/src/main/java/cx/ring/service/ConfigurationManagerCallback.java
index ceb49699c..e852a0d94 100644
--- a/ring-android/app/src/main/java/cx/ring/service/ConfigurationManagerCallback.java
+++ b/ring-android/app/src/main/java/cx/ring/service/ConfigurationManagerCallback.java
@@ -26,13 +26,17 @@ import android.content.Context;
 import android.content.Intent;
 import android.util.Log;
 
+import cx.ring.history.HistoryText;
+import cx.ring.model.TextMessage;
+
 public class ConfigurationManagerCallback extends ConfigurationCallback {
 
     private  SipService mService;
     private static final String TAG = "ConfigurationManagerCb";
 
     static public final String ACCOUNTS_CHANGED = "accounts-changed";
-    static public final String ACCOUNT_STATE_CHANGED = "account-state-changed";
+    static public final String ACCOUNT_STATE_CHANGED = "account-State-changed";
+    static public final String INCOMING_TEXT = "incoming--txt-msg";
 
     public ConfigurationManagerCallback(SipService context) {
         super();
@@ -58,7 +62,19 @@ public class ConfigurationManagerCallback extends ConfigurationCallback {
 
     @Override
     public void registrationStateChanged(String account_id, String state, int code, String detail_str) {
-        sendAccountStateChangedMessage(account_id, state, 0);
+        Log.w(getClass().getName(), "registrationStateChanged: " + account_id + " " + state + " " + code + " " + detail_str);
+        sendAccountStateChangedMessage(account_id, state, code);
+    }
+
+    @Override
+    public void incomingAccountMessage(String accountID, String from, String msg) {
+        Log.w(TAG, "incomingAccountMessage : " + accountID + " " + from + " " + msg);
+
+        TextMessage message = new TextMessage(true, msg, from, null, accountID);
+        mService.mHistoryManager.insertNewTextMessage(new HistoryText(message));
+        Intent intent = new Intent(INCOMING_TEXT);
+        intent.putExtra("txt", message);
+        mService.sendBroadcast(intent);
     }
 
     @Override
@@ -69,7 +85,7 @@ public class ConfigurationManagerCallback extends ConfigurationCallback {
     private void sendAccountStateChangedMessage(String accoundID, String state, int code) {
         Intent intent = new Intent(ACCOUNT_STATE_CHANGED);
         intent.putExtra("Account", accoundID);
-        intent.putExtra("state", state);
+        intent.putExtra("State", state);
         intent.putExtra("code", code);
         mService.sendBroadcast(intent);
     }
@@ -79,6 +95,7 @@ public class ConfigurationManagerCallback extends ConfigurationCallback {
         OpenSlParams audioParams = OpenSlParams.createInstance(mService);
         ret.add(audioParams.getSampleRate());
         ret.add(audioParams.getBufferSize());
+        Log.w(getClass().getName(), "getHardwareAudioFormat: " + audioParams.getSampleRate() + " " + audioParams.getBufferSize());
     }
 
     @Override
diff --git a/ring-android/app/src/main/java/cx/ring/service/ISipService.aidl b/ring-android/app/src/main/java/cx/ring/service/ISipService.aidl
index 4708062d2..5281c5e7f 100644
--- a/ring-android/app/src/main/java/cx/ring/service/ISipService.aidl
+++ b/ring-android/app/src/main/java/cx/ring/service/ISipService.aidl
@@ -1,8 +1,8 @@
 package cx.ring.service;
 
 import cx.ring.model.SipCall;
+import cx.ring.model.TextMessage;
 import cx.ring.model.Conference;
-import cx.ring.model.SipMessage;
 
 interface ISipService {
     
@@ -57,7 +57,7 @@ interface ISipService {
 	void playDtmf(in String key);
     
     /* IM */
-    void sendTextMessage(in String callID, in SipMessage message);
+    void sendTextMessage(in String callID, in TextMessage message);
     void sendAccountTextMessage(in String accountid, in String to, in String msg);
 
 
diff --git a/ring-android/app/src/main/java/cx/ring/service/LocalService.java b/ring-android/app/src/main/java/cx/ring/service/LocalService.java
new file mode 100644
index 000000000..02c22f2a6
--- /dev/null
+++ b/ring-android/app/src/main/java/cx/ring/service/LocalService.java
@@ -0,0 +1,813 @@
+package cx.ring.service;
+
+import android.app.Service;
+import android.content.AsyncTaskLoader;
+import android.content.BroadcastReceiver;
+import android.content.ComponentName;
+import android.content.ContentResolver;
+import android.content.ContentUris;
+import android.content.Context;
+import android.content.Intent;
+import android.content.IntentFilter;
+import android.content.Loader;
+import android.content.ServiceConnection;
+import android.database.Cursor;
+import android.net.ConnectivityManager;
+import android.net.NetworkInfo;
+import android.net.Uri;
+import android.os.AsyncTask;
+import android.os.Binder;
+import android.os.IBinder;
+import android.os.RemoteException;
+import android.provider.ContactsContract;
+import android.support.annotation.NonNull;
+import android.util.Log;
+import android.util.LongSparseArray;
+import android.util.Pair;
+
+import java.lang.ref.WeakReference;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import cx.ring.BuildConfig;
+import cx.ring.history.HistoryCall;
+import cx.ring.history.HistoryEntry;
+import cx.ring.history.HistoryManager;
+import cx.ring.history.HistoryText;
+import cx.ring.model.CallContact;
+import cx.ring.model.Conference;
+import cx.ring.model.Conversation;
+import cx.ring.model.SipCall;
+import cx.ring.model.TextMessage;
+import cx.ring.model.account.Account;
+import cx.ring.utils.Utilities;
+
+
+public class LocalService extends Service {
+    static final String TAG = LocalService.class.getSimpleName();
+    static public final String ACTION_CONF_UPDATE = BuildConfig.APPLICATION_ID + ".action.CONF_UPDATE";
+    static public final String ACTION_ACCOUNT_UPDATE = BuildConfig.APPLICATION_ID + ".action.ACCOUNT_UPDATE";
+
+    public static final String AUTHORITY = "cx.ring";
+    public static final Uri AUTHORITY_URI = Uri.parse("content://" + AUTHORITY);
+
+    private ISipService mService = null;
+
+    // Binder given to clients
+    private final IBinder mBinder = new LocalBinder();
+
+    private Map<String, Conversation> conversations = new HashMap<>();
+    private ArrayList<Account> all_accounts = new ArrayList<>();
+    private List<Account> accounts = all_accounts;
+    private List<Account> ip2ip_account = all_accounts;
+
+    private HistoryManager historyManager;
+
+    AccountsLoader mAccountLoader = null;
+
+    public interface Callbacks {
+        ISipService getRemoteService();
+        LocalService getService();
+    }
+    public static class DummyCallbacks implements Callbacks {
+        @Override
+        public ISipService getRemoteService() {
+            return null;
+        }
+        @Override
+        public LocalService getService() {
+            return null;
+        }
+    }
+    public static final Callbacks DUMMY_CALLBACKS = new DummyCallbacks();
+
+    @Override
+    public void onCreate() {
+        Log.e(TAG, "onCreate");
+        super.onCreate();
+        historyManager = new HistoryManager(this);
+        Intent intent = new Intent(this, SipService.class);
+        startService(intent);
+        bindService(intent, mConnection, BIND_AUTO_CREATE | BIND_IMPORTANT | BIND_ABOVE_CLIENT );
+    }
+
+    @Override
+    public void onDestroy() {
+        Log.e(TAG, "onDestroy");
+        super.onDestroy();
+        stopListener();
+    }
+
+    private final Loader.OnLoadCompleteListener<ArrayList<Account>> onAccountsLoaded = new Loader.OnLoadCompleteListener<ArrayList<Account>>() {
+        @Override
+        public void onLoadComplete(Loader<ArrayList<Account>> loader, ArrayList<Account> data) {
+            Log.w(TAG, "AccountsLoader Loader.OnLoadCompleteListener");
+            all_accounts = data;
+            accounts = all_accounts.subList(0,data.size()-1);
+            ip2ip_account = all_accounts.subList(data.size()-1,data.size());
+            sendBroadcast(new Intent(ACTION_ACCOUNT_UPDATE));
+        }
+    };
+
+    private ServiceConnection mConnection = new ServiceConnection() {
+        @Override
+        public void onServiceConnected(ComponentName className, IBinder service) {
+            Log.w(TAG, "onServiceConnected " + className.getClassName());
+            mService = ISipService.Stub.asInterface(service);
+            //mBound = true;
+            mAccountLoader = new AccountsLoader(LocalService.this);
+            mAccountLoader.registerListener(1, onAccountsLoaded);
+            mAccountLoader.startLoading();
+            mAccountLoader.forceLoad();
+            startListener();
+        }
+
+        @Override
+        public void onServiceDisconnected(ComponentName arg0) {
+            Log.w(TAG, "onServiceDisconnected " + arg0.getClassName());
+            if (mAccountLoader != null) {
+                mAccountLoader.unregisterListener(onAccountsLoaded);
+                mAccountLoader.cancelLoad();
+                mAccountLoader.stopLoading();
+            }
+            //mBound = false;
+            mService = null;
+        }
+    };
+
+    /**
+     * Class used for the client Binder.  Because we know this service always
+     * runs in the same process as its clients, we don't need to deal with IPC.
+     */
+    public class LocalBinder extends Binder {
+        public LocalService getService() {
+            // Return this instance of LocalService so clients can call public methods
+            return LocalService.this;
+        }
+    }
+
+    @Override
+    public IBinder onBind(Intent intent) {
+        return mBinder;
+    }
+
+    @Override
+    public boolean onUnbind(Intent intent) {
+        Log.e(TAG, "onUnbind");
+        if (mConnection != null) {
+            unbindService(mConnection);
+            mConnection = null;
+        }
+        return super.onUnbind(intent);
+    }
+
+    public ISipService getRemoteService() {
+        return mService;
+    }
+
+    public List<Account> getAccounts() { return accounts; }
+    public List<Account> getIP2IPAccount() { return ip2ip_account; }
+    public Account getAccount(String account_id) {
+        for (Account acc : all_accounts)
+            if (acc.getAccountID().equals(account_id))
+                return acc;
+        return null;
+    }
+
+    public ArrayList<Conversation> getConversations() {
+        ArrayList<Conversation> convs = new ArrayList<>(conversations.values());
+        Collections.sort(convs, new Comparator<Conversation>() {
+            @Override
+            public int compare(Conversation lhs, Conversation rhs) {
+                return (int) ((rhs.getLastInteraction().getTime() - lhs.getLastInteraction().getTime())/1000l);
+            }
+        });
+        return convs;
+    }
+
+    public Conversation getConversation(String id) {
+        return conversations.get(id);
+    }
+
+    public Conference getConference(String id) {
+        for (Conversation conv : conversations.values()) {
+            Conference conf = conv.getConference(id);
+            if (conf != null)
+                return conf;
+        }
+        return null;
+    }
+
+    public Conversation getByContact(CallContact contact) {
+        ArrayList<String> keys = contact.getIds();
+        for (String k : keys) {
+            Conversation c = conversations.get(k);
+            if (c != null)
+                return c;
+        }
+        Log.w(TAG, "getByContact failed");
+        return null;
+    }
+    public Conversation getByCallId(String callId) {
+        for (Conversation conv : conversations.values()) {
+            Conference conf = conv.getConference(callId);
+            if (conf != null)
+                return conv;
+        }
+        return null;
+    }
+
+    public Conversation startConversation(CallContact contact) {
+        Conversation c = getByContact(contact);
+        if (c == null) {
+            c = new Conversation(contact);
+            conversations.put(contact.getIds().get(0), c);
+        }
+        return c;
+    }
+
+    public CallContact findContactByNumber(String number) {
+        for (Conversation conv : conversations.values()) {
+            if (conv.contact.hasNumber(number))
+                return conv.contact;
+        }
+        return findContactByNumber(getContentResolver(), number);
+    }
+
+    public CallContact findContactById(long id) {
+        return findById(getContentResolver(), id);
+    }
+
+    public Account guessAccount(CallContact c, String number) {
+        number = CallContact.canonicalNumber(number);
+        if (Utilities.isIpAddress(number))
+            return ip2ip_account.get(0);
+        /*Conversation conv = getByContact(c);
+        if (conv != null) {
+            return
+        }*/
+        return accounts.get(0);
+    }
+
+    public static final String[] DATA_PROJECTION = {
+            ContactsContract.Data._ID,
+            ContactsContract.RawContacts.CONTACT_ID,
+            ContactsContract.Data.LOOKUP_KEY,
+            ContactsContract.Data.DISPLAY_NAME_PRIMARY,
+            ContactsContract.Data.PHOTO_ID,
+            ContactsContract.Data.PHOTO_THUMBNAIL_URI
+    };
+    public static final String[] CONTACT_PROJECTION = {
+            ContactsContract.Data._ID,
+            ContactsContract.Data.LOOKUP_KEY,
+            ContactsContract.Data.DISPLAY_NAME_PRIMARY,
+            ContactsContract.Data.PHOTO_ID,
+    };
+
+    public static final String[] PHONELOOKUP_PROJECTION = {
+            ContactsContract.PhoneLookup._ID,
+            ContactsContract.PhoneLookup.LOOKUP_KEY,
+            ContactsContract.PhoneLookup.PHOTO_ID,
+            ContactsContract.Contacts.DISPLAY_NAME_PRIMARY
+    };
+
+    private static final String[] CONTACTS_PHONES_PROJECTION = {
+            ContactsContract.CommonDataKinds.Phone.NUMBER,
+            ContactsContract.CommonDataKinds.Phone.TYPE
+    };
+    private static final String[] CONTACTS_SIP_PROJECTION = {
+            ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS,
+            ContactsContract.CommonDataKinds.SipAddress.TYPE
+    };
+   /* private static final String[] CONTACTS_PHOTO_PROJECTION = {
+            ContactsContract.CommonDataKinds.Photo.,
+            ContactsContract.CommonDataKinds.SipAddress.TYPE
+    };
+*/
+    private static final String ID_SELECTION = ContactsContract.CommonDataKinds.Phone.CONTACT_ID + "=?";
+    private static final String KEY_SELECTION = ContactsContract.Contacts.LOOKUP_KEY + "=?";
+
+    private static void lookupDetails(@NonNull ContentResolver res, @NonNull CallContact c) {
+        Log.w(TAG, "lookupDetails " + c.getKey());
+
+        Cursor cPhones = res.query(
+                ContactsContract.CommonDataKinds.Phone.CONTENT_URI,
+                CONTACTS_PHONES_PROJECTION,
+                ID_SELECTION,
+                new String[]{String.valueOf(c.getId())}, null);
+        if (cPhones != null) {
+            final int iNum =  cPhones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER);
+            final int iType =  cPhones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.TYPE);
+            while (cPhones.moveToNext()) {
+                c.addNumber(cPhones.getString(iNum), cPhones.getInt(iType), CallContact.NumberType.TEL);
+                Log.w(TAG,"Phone:"+cPhones.getString(cPhones.getColumnIndex(ContactsContract.CommonDataKinds.Phone.NUMBER)));
+            }
+            cPhones.close();
+        }
+
+        Uri baseUri = ContentUris.withAppendedId(ContactsContract.Contacts.CONTENT_URI, c.getId());
+        Uri targetUri = Uri.withAppendedPath(baseUri, ContactsContract.Contacts.Data.CONTENT_DIRECTORY);
+        Cursor cSip = res.query(targetUri,
+                CONTACTS_SIP_PROJECTION,
+                ContactsContract.Data.MIMETYPE + "=?",
+                new String[]{ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE}, null);
+        if (cSip != null) {
+            final int iSip =  cSip.getColumnIndex(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS);
+            final int iType =  cSip.getColumnIndex(ContactsContract.CommonDataKinds.SipAddress.TYPE);
+            while (cSip.moveToNext()) {
+                c.addNumber(cSip.getString(iSip), cSip.getInt(iType), CallContact.NumberType.SIP);
+                Log.w(TAG, "SIP phone:" + cSip.getString(iSip));
+            }
+            cSip.close();
+        }
+
+        /*Cursor cPhoto = res.query(targetUri,
+                CONTACTS_SIP_PROJECTION,
+                ContactsContract.Data.MIMETYPE + "=?",
+                new String[]{ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE}, null);
+        if (cSip != null) {
+            final int iSip =  cSip.getColumnIndex(ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS);
+            final int iType =  cSip.getColumnIndex(ContactsContract.CommonDataKinds.SipAddress.TYPE);
+            while (cSip.moveToNext()) {
+                c.addNumber(cSip.getString(iSip), cSip.getInt(iType), CallContact.NumberType.SIP);
+                Log.w(TAG, "SIP phone:" + cSip.getString(iSip));
+            }
+            cSip.close();
+        }*/
+    }
+
+    public static CallContact findByKey(@NonNull ContentResolver res, String key) {
+        Log.e(TAG, "findByKey " + key);
+
+        final CallContact.ContactBuilder builder = CallContact.ContactBuilder.getInstance();
+        Cursor result = res.query( Uri.withAppendedPath(ContactsContract.Contacts.CONTENT_LOOKUP_URI, key), CONTACT_PROJECTION,
+                null, null, null);
+
+        CallContact contact = null;
+        if (result != null && result.moveToFirst()) {
+            int iID = result.getColumnIndex(ContactsContract.Data._ID);
+            int iKey = result.getColumnIndex(ContactsContract.Data.LOOKUP_KEY);
+            int iName = result.getColumnIndex(ContactsContract.Data.DISPLAY_NAME);
+            int iPhoto = result.getColumnIndex(ContactsContract.Data.PHOTO_ID);
+            long cid = result.getLong(iID);
+
+            Log.w(TAG, "Contact id:" + cid + " key:" + result.getString(iKey));
+
+            builder.startNewContact(cid, result.getString(iKey), result.getString(iName), result.getLong(iPhoto));
+            result.close();
+
+            contact = builder.build();
+            lookupDetails(res, contact);
+        }
+        return contact;
+    }
+
+     public static CallContact findById(@NonNull ContentResolver res, long id) {
+         Log.e(TAG, "findById " + id);
+
+         final CallContact.ContactBuilder builder = CallContact.ContactBuilder.getInstance();
+         Cursor result = res.query(ContactsContract.Contacts.CONTENT_URI, CONTACT_PROJECTION,
+                 ContactsContract.Contacts._ID + " = ?",
+                 new String[]{String.valueOf(id)}, null);
+         if (result == null)
+             return null;
+
+         CallContact contact = null;
+         if (result.moveToFirst()) {
+             int iID = result.getColumnIndex(ContactsContract.Data._ID);
+             int iKey = result.getColumnIndex(ContactsContract.Data.LOOKUP_KEY);
+             int iName = result.getColumnIndex(ContactsContract.Data.DISPLAY_NAME);
+             int iPhoto = result.getColumnIndex(ContactsContract.Data.PHOTO_ID);
+             long cid = result.getLong(iID);
+
+             Log.w(TAG, "Contact id:" + cid + " key:" + result.getString(iKey));
+
+             builder.startNewContact(cid, result.getString(iKey), result.getString(iName), result.getLong(iPhoto));
+             contact = builder.build();
+             lookupDetails(res, contact);
+         }
+         result.close();
+         return contact;
+    }
+    /*
+    public static int getRawContactId(@NonNull ContentResolver res, long contactId)
+    {
+        Cursor c= res.query(
+                ContactsContract.RawContacts.CONTENT_URI,
+                new String[]{ContactsContract.RawContacts._ID},
+                ContactsContract.RawContacts.CONTACT_ID+"=?",
+                new String[]{String.valueOf(contactId)},
+                null);
+        if (c == null)
+            return -1;
+        if (c.moveToFirst()) {
+            int rawContactId = c.getInt(c.getColumnIndex(ContactsContract.RawContacts._ID));
+            Log.d(TAG, "Contact Id: " + contactId + " Raw Contact Id: " + rawContactId);
+            return rawContactId;
+        }
+        c.close();
+        return -1;
+    }
+*/
+    @NonNull
+    public static CallContact findContactBySipNumber(@NonNull ContentResolver res, String number) {
+        final CallContact.ContactBuilder builder = CallContact.ContactBuilder.getInstance();
+        Cursor result = res.query(ContactsContract.Data.CONTENT_URI,
+                DATA_PROJECTION,
+                ContactsContract.CommonDataKinds.SipAddress.SIP_ADDRESS + "=?" + " AND " + ContactsContract.Data.MIMETYPE + "=?",
+                new String[]{number, ContactsContract.CommonDataKinds.SipAddress.CONTENT_ITEM_TYPE}, null);
+        if (result == null)  {
+            Log.w(TAG, "findContactBySipNumber " + number + " can't find contact.");
+            return CallContact.ContactBuilder.buildUnknownContact(number);
+        }
+        int iID = result.getColumnIndex(ContactsContract.Data._ID);
+        int icID = result.getColumnIndex(ContactsContract.RawContacts.CONTACT_ID);
+        int iKey = result.getColumnIndex(ContactsContract.Data.LOOKUP_KEY);
+        int iName = result.getColumnIndex(ContactsContract.Data.DISPLAY_NAME);
+        int iPhoto = result.getColumnIndex(ContactsContract.Data.PHOTO_ID);
+        int iPhotoThumb = result.getColumnIndex(ContactsContract.Data.PHOTO_THUMBNAIL_URI);
+
+        ArrayList<CallContact> contacts = new ArrayList<>(1);
+        while (result.moveToNext()) {
+            long cid = result.getLong(icID);
+            long id = result.getLong(iID);
+            builder.startNewContact(cid, result.getString(iKey), result.getString(iName), result.getLong(iPhoto));
+            CallContact contact = builder.build();
+            //Log.w(TAG, "findContactBySipNumber " + number + " found name:" + contact.getDisplayName() + " id:" + contact.getId() + " key:" + contact.getKey() + " rawid:"+getRawContactId(res, contact.getId()) + " rid:"+id + " photo:"+result.getLong(iPhoto) + " thumb:" + result.getString(iPhotoThumb));
+            lookupDetails(res, contact);
+            contacts.add(contact);
+        }
+        result.close();
+
+        //lookupDetails(res, contact);
+        /*if (contact == null) {
+            Log.w(TAG, "Can't find contact with number " + number);
+            contact = CallContact.ContactBuilder.buildUnknownContact(number);
+        }*/
+        if (contacts.isEmpty()) {
+            Log.w(TAG, "findContactBySipNumber " + number + " can't find contact.");
+            return CallContact.ContactBuilder.buildUnknownContact(number);
+        }
+        return contacts.get(0);
+    }
+
+    @NonNull
+    public static CallContact findContactByNumber(@NonNull ContentResolver res, String number) {
+        //Log.w(TAG, "findContactByNumber " + number);
+
+        final CallContact.ContactBuilder builder = CallContact.ContactBuilder.getInstance();
+        Uri uri = Uri.withAppendedPath(ContactsContract.PhoneLookup.CONTENT_FILTER_URI, Uri.encode(number));
+        Cursor result = res.query(uri, PHONELOOKUP_PROJECTION, null, null, null);
+        if (result == null)  {
+            Log.w(TAG, "findContactByNumber " + number + " can't find contact.");
+            return findContactBySipNumber(res, number);
+        }
+        if (!result.moveToFirst())  {
+            result.close();
+            Log.w(TAG, "findContactByNumber " + number + " can't find contact.");
+            return findContactBySipNumber(res, number);
+        }
+        int iID = result.getColumnIndex(ContactsContract.Contacts._ID);
+        int iKey = result.getColumnIndex(ContactsContract.Data.LOOKUP_KEY);
+        int iName = result.getColumnIndex(ContactsContract.Contacts.DISPLAY_NAME);
+        int iPhoto = result.getColumnIndex(ContactsContract.Contacts.PHOTO_ID);
+        builder.startNewContact(result.getLong(iID), result.getString(iKey), result.getString(iName), result.getLong(iPhoto));
+        result.close();
+        CallContact contact = builder.build();
+        lookupDetails(res, contact);
+        /*if (contact == null) {
+            Log.w(TAG, "Can't find contact with number " + number);
+            contact = CallContact.ContactBuilder.buildUnknownContact(number);
+        }*/
+        Log.w(TAG, "findContactByNumber " + number + " found " + contact.getDisplayName());
+
+        return contact;
+    }
+
+    private class ConversationLoader extends AsyncTask<Void, Void, Map<String, Conversation>> {
+        private final ContentResolver cr;
+
+        public ConversationLoader(Context c) {
+            cr = c.getContentResolver();
+        }
+
+        private CallContact getByNumber(HashMap<String, CallContact> cache, String number) {
+            if (number == null || number.isEmpty())
+                return null;
+            number = CallContact.canonicalNumber(number);
+            CallContact c = cache.get(number);
+            if (c == null) {
+                c = findContactByNumber(cr, number);
+                //if (c != null)
+                cache.put(number, c);
+            }
+            return c;
+        }
+
+        Pair<HistoryEntry, HistoryCall> findHistoryByCallId(final Map<String, Conversation> confs, String id) {
+            for (Conversation c : confs.values()) {
+                Pair<HistoryEntry, HistoryCall> h = c.findHistoryByCallId(id);
+                if (h != null)
+                    return h;
+            }
+            return null;
+        }
+
+        @Override
+        protected Map<String, Conversation> doInBackground(Void... params) {
+            List<HistoryCall> history = null;
+            List<HistoryText> historyTexts = null;
+            Map<String, Conference> confs = null;
+            final Map<String, Conversation> ret = new HashMap<>();
+            final LongSparseArray<CallContact> localContactCache = new LongSparseArray<>(64);
+            final HashMap<String, CallContact> localNumberCache = new HashMap<>(64);
+
+
+            try {
+                history = historyManager.getAll();
+                historyTexts = historyManager.getAllTextMessages();
+                confs = mService.getConferenceList();
+            } catch (RemoteException | SQLException e) {
+                e.printStackTrace();
+            }
+
+            for (HistoryCall call : history) {
+                //Log.w(TAG, "History call : " + call.getNumber() + " " + call.call_start + " " + call.call_end + " " + call.getEndDate().toString());
+                CallContact contact;
+                if (call.getContactID() <= CallContact.DEFAULT_ID) {
+                    contact = getByNumber(localNumberCache, call.getNumber());
+                } else {
+                    contact = localContactCache.get(call.getContactID());
+                    if (contact == null) {
+                        contact = findById(cr, call.getContactID());
+                        if (contact != null)
+                            contact.addPhoneNumber(call.getNumber(), 0);
+                        else {
+                            Log.w(TAG, "Can't find contact with id " + call.getContactID());
+                            contact = getByNumber(localNumberCache, call.getNumber());
+                        }
+                        localContactCache.put(contact.getId(), contact);
+                    }
+                }
+
+                Map.Entry<String, Conversation> merge = null;
+                for (Map.Entry<String, Conversation> ce : ret.entrySet()) {
+                    Conversation c = ce.getValue();
+                    if ((contact.getId() > 0 && contact.getId() == c.contact.getId()) || c.contact.hasNumber(call.getNumber())) {
+                        merge = ce;
+                        break;
+                    }
+                }
+                if (merge != null) {
+                    Conversation c = merge.getValue();
+                    //Log.w(TAG, "        Join to " + merge.getKey() + " " + c.getContact().getDisplayName() + " " + call.getNumber());
+                    if (c.getContact().getId() <= 0 && contact.getId() > 0) {
+                        c.contact = contact;
+                        ret.remove(merge.getKey());
+                        ret.put(contact.getIds().get(0), c);
+                    }
+                    c.addHistoryCall(call);
+                    continue;
+                }
+                String key = contact.getIds().get(0);
+                if (ret.containsKey(key)) {
+                    ret.get(key).addHistoryCall(call);
+                } else {
+                    Conversation c = new Conversation(contact);
+                    c.addHistoryCall(call);
+                    ret.put(key, c);
+                }
+            }
+
+            for (HistoryText htext : historyTexts) {
+                CallContact contact;
+
+                if (htext.getContactID() <= CallContact.DEFAULT_ID) {
+                    contact = getByNumber(localNumberCache, htext.getNumber());
+                } else {
+                    contact = localContactCache.get(htext.getContactID());
+                    if (contact == null) {
+                        contact = findById(cr, htext.getContactID());
+                        if (contact != null)
+                            contact.addPhoneNumber(htext.getNumber(), 0);
+                        else {
+                            Log.w(TAG, "Can't find contact with id " + htext.getContactID());
+                            contact = getByNumber(localNumberCache, htext.getNumber());
+                        }
+                        localContactCache.put(contact.getId(), contact);
+                    }
+                }
+
+                Pair<HistoryEntry, HistoryCall> p = findHistoryByCallId(ret, htext.getCallId());
+
+                if (contact == null && p != null)
+                    contact = p.first.getContact();
+                if (contact == null)
+                    continue;
+
+                TextMessage msg = new TextMessage(htext);
+                msg.setContact(contact);
+
+                if (p  != null) {
+                    if (msg.getNumber() == null || msg.getNumber().isEmpty())
+                        msg.setNumber(p.second.getNumber());
+                    p.first.addTextMessage(msg);
+                }
+
+                String key = contact.getIds().get(0);
+                if (ret.containsKey(key)) {
+                    ret.get(key).addTextMessage(msg);
+                } else {
+                    Conversation c = new Conversation(contact);
+                    c.addTextMessage(msg);
+                    ret.put(key, c);
+                }
+            }
+
+            /*context.clear();
+            ctx = null;*/
+            for (Map.Entry<String, Conference> c : confs.entrySet()) {
+                //Log.w(TAG, "ConversationLoader handling " + c.getKey() + " " + c.getValue().getId());
+                Conference conf = c.getValue();
+                ArrayList<SipCall> calls = conf.getParticipants();
+                if (calls.size() >= 1) {
+                    CallContact contact = calls.get(0).getContact();
+                    //Log.w(TAG, "Contact : " + contact.getId() + " " + contact.getDisplayName());
+                    Conversation conv = null;
+                    ArrayList<String> ids = contact.getIds();
+                    for (String id : ids) {
+                        //Log.w(TAG, "    uri attempt : " + id);
+                        conv = ret.get(id);
+                        if (conv != null) break;
+                    }
+                    if (conv != null) {
+                        //Log.w(TAG, "Adding conference to existing conversation ");
+                        conv.current_calls.add(conf);
+                    } else {
+                        conv = new Conversation(contact);
+                        conv.current_calls.add(conf);
+                        ret.put(ids.get(0), conv);
+                    }
+                }
+            }
+            for (Conversation c : ret.values())
+                Log.w(TAG, "Conversation : " + c.getContact().getId() + " " + c.getContact().getDisplayName() + " " + c.getContact().getPhones().get(0).getNumber() + " " + c.getLastInteraction().toString());
+            return ret;
+        }
+    }
+
+    private void updated(Map<String, Conversation> res) {
+        Log.w(TAG, "Conversation list updated");
+        conversations = res;
+        sendBroadcast(new Intent(ACTION_CONF_UPDATE));
+    }
+
+    public class AccountsLoader extends AsyncTaskLoader<ArrayList<Account>> {
+        public static final String ACCOUNTS = "accounts";
+        public static final String ACCOUNT_IP2IP = "IP2IP";
+        public AccountsLoader(Context context) {
+            super(context);
+            Log.w(TAG, "AccountsLoader constructor");
+        }
+        @SuppressWarnings("unchecked")
+        @Override
+        public ArrayList<Account> loadInBackground() {
+            Log.w(TAG, "AccountsLoader loadInBackground");
+            ArrayList<Account> accounts = new ArrayList<>();
+            Account IP2IP = null;
+            try {
+                ArrayList<String> accountIDs = (ArrayList<String>) mService.getAccountList();
+                Map<String, String> details;
+                ArrayList<Map<String, String>> credentials;
+                Map<String, String> state;
+                for (String id : accountIDs) {
+                    details = (Map<String, String>) mService.getAccountDetails(id);
+                    state = (Map<String, String>) mService.getVolatileAccountDetails(id);
+                    if (id.contentEquals(ACCOUNT_IP2IP)) {
+                        IP2IP = new Account(ACCOUNT_IP2IP, details, new ArrayList<Map<String, String>>(), state); // Empty credentials
+                        //accounts.add(IP2IP);
+                        continue;
+                    }
+                    credentials = (ArrayList<Map<String, String>>) mService.getCredentials(id);
+                /*for (Map.Entry<String, String> entry : State.entrySet()) {
+                    Log.i(TAG, "State:" + entry.getKey() + " -> " + entry.getValue());
+                }*/
+                    Account tmp = new Account(id, details, credentials, state);
+                    accounts.add(tmp);
+                    // Log.i(TAG, "account:" + tmp.getAlias() + " " + tmp.isEnabled());
+
+                }
+            } catch (RemoteException | NullPointerException e) {
+                Log.e(TAG, e.toString());
+            }
+            accounts.add(IP2IP);
+            return accounts;
+        }
+    }
+
+    final BroadcastReceiver receiver = new BroadcastReceiver() {
+        @Override
+        public void onReceive(Context context, Intent intent) {
+            switch(intent.getAction()) {
+                case ConnectivityManager.CONNECTIVITY_ACTION:
+                    Log.w(TAG, "ConnectivityManager.CONNECTIVITY_ACTION " + " " + intent.getStringExtra(ConnectivityManager.EXTRA_EXTRA_INFO) + " " + intent.getStringExtra(ConnectivityManager.EXTRA_EXTRA_INFO));
+                    ConnectivityManager cm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
+                    NetworkInfo ni = cm.getActiveNetworkInfo();
+                    Log.w(TAG, "ActiveNetworkInfo: " + (ni == null ? "null" : ni.toString()));
+                    break;
+                case ConfigurationManagerCallback.ACCOUNT_STATE_CHANGED:
+                    Log.w(TAG, "Received " + intent.getAction() + " " + intent.getStringExtra("Account") + " " + intent.getStringExtra("State") + " " + intent.getIntExtra("code", 0));
+                    //accountStateChanged(intent.getStringExtra("Account"), intent.getStringExtra("State"), intent.getIntExtra("code", 0));
+                    for (Account a : accounts) {
+                        if (a.getAccountID().contentEquals(intent.getStringExtra("Account"))) {
+                            a.setRegistrationState(intent.getStringExtra("State"), intent.getIntExtra("code", 0));
+                            //notifyDataSetChanged();
+                            sendBroadcast(new Intent(ACTION_ACCOUNT_UPDATE));
+                            break;
+                        }
+                    }
+                    break;
+                case ConfigurationManagerCallback.ACCOUNTS_CHANGED:
+                    Log.w(TAG, "Received" + intent.getAction());
+                    //accountsChanged();
+                    mAccountLoader.onContentChanged();
+                    mAccountLoader.startLoading();
+                    break;
+                case CallManagerCallBack.INCOMING_TEXT:
+                case ConfigurationManagerCallback.INCOMING_TEXT:
+                    TextMessage txt = intent.getParcelableExtra("txt");
+                    String call = txt.getCallId();
+                    if (call != null && !call.isEmpty()) {
+                        Conversation conv = getByCallId(call);
+                        conv.addTextMessage(txt);
+                        /*Conference conf = conv.getConference(call);
+                        conf.addSipMessage(txt);
+                        Conversation conv = getByContact(conf.)*/
+                    } else {
+                        CallContact contact = findContactByNumber(txt.getNumber());
+                        Conversation conv = startConversation(contact);
+                        txt.setContact(conv.getContact());
+                        Log.w(TAG, "New text messsage " + txt.getAccount() + " " + txt.getContact().getId() + " " + txt.getMessage());
+                        conv.addTextMessage(txt);
+                    }
+                    sendBroadcast(new Intent(ACTION_CONF_UPDATE));
+                    break;
+                default:
+                    Log.w(TAG, "onReceive " + intent.getAction() + " " + intent.getDataString());
+                    new ConversationLoader(context){
+                        @Override
+                        protected void onPostExecute(Map<String, Conversation> res) {
+                            updated(res);
+                        }
+                    }.execute();
+            }
+        }
+    };
+
+    public void startListener() {
+        final WeakReference<LocalService> self = new WeakReference<>(this);
+        new ConversationLoader(this){
+            @Override
+            protected void onPreExecute() {
+                super.onPreExecute();
+                Log.w(TAG, "onPreExecute");
+            }
+
+            @Override
+            protected void onPostExecute(Map<String, Conversation> res) {
+                Log.w(TAG, "onPostExecute");
+                LocalService this_ = self.get();
+                if (this_ != null)
+                    this_.updated(res);
+                else
+                    Log.e(TAG, "AsyncTask finished but parent is destroyed..");
+            }
+        }.execute();
+
+        IntentFilter intentFilter = new IntentFilter();
+        intentFilter.addAction(ConfigurationManagerCallback.ACCOUNT_STATE_CHANGED);
+        intentFilter.addAction(ConfigurationManagerCallback.ACCOUNTS_CHANGED);
+        intentFilter.addAction(ConfigurationManagerCallback.INCOMING_TEXT);
+
+        intentFilter.addAction(CallManagerCallBack.INCOMING_CALL);
+        intentFilter.addAction(CallManagerCallBack.INCOMING_TEXT);
+        intentFilter.addAction(CallManagerCallBack.CALL_STATE_CHANGED);
+        intentFilter.addAction(CallManagerCallBack.CONF_CREATED);
+        intentFilter.addAction(CallManagerCallBack.CONF_CHANGED);
+        intentFilter.addAction(CallManagerCallBack.CONF_REMOVED);
+
+        intentFilter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
+
+        registerReceiver(receiver, intentFilter);
+    }
+
+    public void stopListener() {
+        unregisterReceiver(receiver);
+    }
+
+}
diff --git a/ring-android/app/src/main/java/cx/ring/service/SipService.java b/ring-android/app/src/main/java/cx/ring/service/SipService.java
index 8f9caae9d..1e3ea96f5 100644
--- a/ring-android/app/src/main/java/cx/ring/service/SipService.java
+++ b/ring-android/app/src/main/java/cx/ring/service/SipService.java
@@ -24,6 +24,7 @@
  */
 package cx.ring.service;
 
+import android.app.Notification;
 import android.os.Handler;
 
 import java.util.ArrayList;
@@ -36,12 +37,21 @@ import java.util.Map.Entry;
 import android.app.Service;
 import android.content.Intent;
 import android.os.*;
+import android.telecom.Call;
 import android.util.Log;
+
+import cx.ring.BuildConfig;
+import cx.ring.R;
 import cx.ring.history.HistoryManager;
+import cx.ring.history.HistoryText;
 import cx.ring.model.Codec;
 import cx.ring.model.Conference;
 import cx.ring.model.SecureSipCall;
-import cx.ring.model.SipMessage;
+import cx.ring.model.TextMessage;
+import cx.ring.model.account.AccountDetail;
+import cx.ring.model.account.AccountDetailBasic;
+import cx.ring.model.account.AccountDetailSrtp;
+import cx.ring.model.account.AccountDetailTls;
 import cx.ring.utils.MediaManager;
 import cx.ring.utils.SipNotifications;
 import cx.ring.utils.SwigNativeConverter;
@@ -54,8 +64,14 @@ public class SipService extends Service {
     private SipServiceExecutor mExecutor;
     private static HandlerThread executorThread;
 
+    static public final String ACTION_CALL_ACCEPT = BuildConfig.APPLICATION_ID + ".action.CALL_ACCEPT";
+    static public final String ACTION_CALL_REFUSE = BuildConfig.APPLICATION_ID + ".action.CALL_REFUSE";
+    //static public final String ACTION_CALL_REFUSE = BuildConfig.APPLICATION_ID + ".action.CALL_REFUSE";
+
+    static public final String ACTION_CALL_END = BuildConfig.APPLICATION_ID + ".action.CALL_END";
+
     private Handler handler = new Handler();
-    private static int POLLING_TIMEOUT = 500;
+    private static int POLLING_TIMEOUT = 50;
     private Runnable pollEvents = new Runnable() {
         @Override
         public void run() {
@@ -74,7 +90,7 @@ public class SipService extends Service {
     protected HistoryManager mHistoryManager;
     protected MediaManager mMediaManager;
 
-    private HashMap<String, Conference> mConferences = new HashMap<>();
+    private final HashMap<String, Conference> mConferences = new HashMap<>();
     private ConfigurationManagerCallback configurationCallback;
     private CallManagerCallBack callManagerCallBack;
 
@@ -141,8 +157,36 @@ public class SipService extends Service {
     /* called for each startService() */
     @Override
     public int onStartCommand(Intent intent, int flags, int startId) {
-        Log.i(TAG, "onStarted " + (intent == null ? "null" : intent.getAction()) + " " + flags);
-        super.onStartCommand(intent, flags, startId);
+        Log.i(TAG, "onStartCommand " + (intent == null ? "null" : intent.getAction()) + " " + flags + " " + startId);
+        String action = intent == null ? null : intent.getAction();
+        try {
+            if (action != null) {
+                if (action.equals(ACTION_CALL_END)) {
+                    Conference c = findConference(intent.getStringExtra("conf"));
+                    if (c != null) {
+                        for (SipCall call : c.getParticipants()) {
+                            mBinder.hangUp(call.getCallId());
+                        }
+                        mBinder.hangUpConference(c.getId());
+                        Log.w("CallNotification ", "Canceling " + c.notificationId);
+                        mNotificationManager.notificationManager.cancel(c.notificationId);
+                    }
+                } else if (action.equals(ACTION_CALL_ACCEPT)) {
+                    Conference c = findConference(intent.getStringExtra("conf"));
+                    if (c != null) {
+                        mBinder.accept(c.getParticipants().get(0).getCallId());
+                    }
+                } else if (action.equals(ACTION_CALL_REFUSE)) {
+                    Conference c = findConference(intent.getStringExtra("conf"));
+                    if (c != null) {
+                        mBinder.refuse(c.getParticipants().get(0).getCallId());
+                    }
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
         return START_STICKY; /* started and stopped explicitly */
     }
 
@@ -265,6 +309,8 @@ public class SipService extends Service {
             public void run() {
                 try {
                     mTask.run();
+                } catch(Exception e){
+                    e.printStackTrace();
                 } finally {
                     synchronized (this) {
                         mDone = true;
@@ -419,27 +465,59 @@ public class SipService extends Service {
                 protected String doRun() throws SameThreadException {
                     Log.i(TAG, "SipService.placeCall() thread running...");
                     Conference toAdd;
-                    if(call.getAccount().useSecureLayer()){
-                        SecureSipCall secureCall = new SecureSipCall(call);
-                        toAdd = new Conference(secureCall);
-                    } else {
-                        toAdd = new Conference(call);
-                    }
-                    mConferences.put(toAdd.getId(), toAdd);
+                    //mConferences.put(toAdd.getId(), toAdd);
                     mMediaManager.obtainAudioFocus(false);
-                    return Ringservice.placeCall(call.getAccount().getAccountID(), call.getmContact().getPhones().get(0).getNumber());
+
+                    String number = call.getNumber();
+                    if ((number == null || number.isEmpty()) && call.getContact() != null) {
+                        number = call.getContact().getPhones().get(0).getNumber();
+                    }
+
+                    Log.i(TAG, "SipService.placeCall() calling... " + number);
+                    String call_id = Ringservice.placeCall(call.getAccount(), number);
+                    call.setCallID(call_id);
+                    if (!call_id.isEmpty()) {
+                        final Map<String, String> details = getAccountDetails(call.getAccount());
+                        if(details.get(AccountDetailBasic.CONFIG_ACCOUNT_TYPE).contentEquals(AccountDetailBasic.ACCOUNT_TYPE_RING)
+                                || details.get(AccountDetailSrtp.CONFIG_SRTP_ENABLE).contentEquals(AccountDetail.TRUE_STR)
+                                || details.get(AccountDetailTls.CONFIG_TLS_ENABLE).contentEquals(AccountDetail.TRUE_STR)) {
+                            Log.i(TAG, "SipService.placeCall() call is secure");
+                            SecureSipCall secureCall = new SecureSipCall(call, details.get(AccountDetailSrtp.CONFIG_SRTP_KEY_EXCHANGE));
+                            toAdd = new Conference(secureCall);
+                        } else {
+                            toAdd = new Conference(call);
+                        }
+                        Log.i(TAG, "SipService.placeCall() returned with call id " + call_id);
+                        mConferences.put(call_id, toAdd);
+                        Notification noti = new Notification.Builder(SipService.this)
+                                .setContentTitle("Ongoing call with " + call.getContact().getDisplayName())
+                                .setContentText("outgoing call")
+                                .setOngoing(true)
+                                .setSmallIcon(R.drawable.ic_launcher)
+                                //.setContentIntent()
+                                /*.setContentText(subject)
+                                .setSmallIcon(R.drawable.new_mail)
+                                .setLargeIcon(aBitmap)*/
+                                .build();
+                        //startForeground(toAdd.notificationId, noti);
+                        Log.w("CallNotification ", "Adding for outgoing " + toAdd.notificationId);
+                        mNotificationManager.notificationManager.notify(toAdd.notificationId, noti);
+                    }
+                    return call_id;
                 }
             });
         }
 
         @Override
         public void refuse(final String callID) {
-
+            mMediaManager.stopRing();
+            Log.e(TAG, "REFUSE");
             getExecutor().execute(new SipRunnable() {
                 @Override
                 protected void doRun() throws SameThreadException {
                     Log.i(TAG, "SipService.refuse() thread running...");
                     Ringservice.refuse(callID);
+                    Ringservice.hangUp(callID);
                 }
             });
         }
@@ -447,6 +525,7 @@ public class SipService extends Service {
         @Override
         public void accept(final String callID) {
             mMediaManager.stopRing();
+            Log.e(TAG, "ACCEPT");
             getExecutor().execute(new SipRunnable() {
                 @Override
                 protected void doRun() throws SameThreadException {
@@ -925,28 +1004,38 @@ public class SipService extends Service {
         }
 
         @Override
-        public void sendTextMessage(final String callID, final SipMessage message) throws RemoteException {
+        public void sendTextMessage(final String callID, final TextMessage message) throws RemoteException {
             getExecutor().execute(new SipRunnable() {
                 @Override
                 protected void doRun() throws SameThreadException, RemoteException {
                     Log.i(TAG, "SipService.sendTextMessage() thread running...");
+                    message.setCallId(callID);
+                    //Conference conf = findConference(callID);
+                    mHistoryManager.insertNewTextMessage(new HistoryText(message));
                     StringMap messages  = new StringMap();
-                    messages.set("text/plain", message.comment);
+                    messages.set("text/plain", message.getMessage());
                     Ringservice.sendTextMessage(callID, messages, "", false);
                     if (getConferences().get(callID) != null)
                         getConferences().get(callID).addSipMessage(message);
+                    Intent intent = new Intent(CallManagerCallBack.INCOMING_TEXT);
+                    intent.putExtra("txt", message);
+                    sendBroadcast(intent);
                 }
             });
-
         }
 
         @Override
-        public void sendAccountTextMessage(final String accountid, final String to, final String msg) {
+        public void sendAccountTextMessage(final String accountID, final String to, final String msg) {
             getExecutor().execute(new SipRunnable() {
                 @Override
                 protected void doRun() throws SameThreadException, RemoteException {
-                    Log.i(TAG, "SipService.sendAccountTextMessage() thread running... " + accountid + " " + to + " " + msg);
-                    Ringservice.sendAccountTextMessage(accountid, to, msg);
+                    Log.i(TAG, "SipService.sendAccountTextMessage() thread running... " + accountID + " " + to + " " + msg);
+                    TextMessage message = new TextMessage(false, msg, to, null, accountID);
+                    mHistoryManager.insertNewTextMessage(new HistoryText(message));
+                    Ringservice.sendAccountTextMessage(accountID, to, msg);
+                    Intent intent = new Intent(ConfigurationManagerCallback.INCOMING_TEXT);
+                    intent.putExtra("txt", message);
+                    sendBroadcast(intent);
                 }
             });
         }
@@ -1271,22 +1360,22 @@ public class SipService extends Service {
             getConferences().remove(conf.getId());
         else
             conf.removeParticipant(conf.getCallById(callID));
+        Log.w("CallNotification ", "Canceling " + conf.notificationId);
+        mNotificationManager.notificationManager.cancel(conf.notificationId);
     }
 
     protected Conference findConference(String callID) {
-        Conference result = null;
-        if (getConferences().get(callID) != null) {
-            result = getConferences().get(callID);
-        } else {
-            for (Entry<String, Conference> stringConferenceEntry : getConferences().entrySet()) {
-                Conference tmp = stringConferenceEntry.getValue();
-                for (SipCall c : tmp.getParticipants()) {
-                    if (c.getCallId().contentEquals(callID)) {
-                        result = tmp;
-                    }
+        Conference result = getConferences().get(callID);
+        if (result != null)
+            return result;
+        for (Entry<String, Conference> stringConferenceEntry : getConferences().entrySet()) {
+            Conference tmp = stringConferenceEntry.getValue();
+            for (SipCall c : tmp.getParticipants()) {
+                if (c.getCallId() != null && callID.contentEquals(c.getCallId())) {
+                    return tmp;
                 }
             }
         }
-        return result;
+        return null;
     }
 }
diff --git a/ring-android/app/src/main/java/cx/ring/utils/MediaManager.java b/ring-android/app/src/main/java/cx/ring/utils/MediaManager.java
index e1abe4e45..c9b59cb16 100644
--- a/ring-android/app/src/main/java/cx/ring/utils/MediaManager.java
+++ b/ring-android/app/src/main/java/cx/ring/utils/MediaManager.java
@@ -115,7 +115,7 @@ public class MediaManager implements OnAudioFocusChangeListener, BluetoothWrappe
     }
     
     
-    /**
+    /**5
      * Start ringing announce for a given contact.
      * It will also focus audio for us.
      * @param remoteContact the contact to ring for. May resolve the contact ringtone if any.
diff --git a/ring-android/app/src/main/java/cx/ring/utils/SipNotifications.java b/ring-android/app/src/main/java/cx/ring/utils/SipNotifications.java
index 356552ba7..76fd929da 100644
--- a/ring-android/app/src/main/java/cx/ring/utils/SipNotifications.java
+++ b/ring-android/app/src/main/java/cx/ring/utils/SipNotifications.java
@@ -41,8 +41,6 @@ import cx.ring.client.HomeActivity;
 import cx.ring.model.Conference;
 import cx.ring.model.SipCall;
 
-import android.app.Notification;
-import android.app.NotificationManager;
 import android.app.PendingIntent;
 import android.content.Context;
 import android.content.Intent;
@@ -51,6 +49,7 @@ import android.graphics.Typeface;
 import android.net.sip.SipProfile;
 import android.support.v4.app.NotificationCompat;
 import android.support.v4.app.NotificationCompat.Builder;
+import android.support.v4.app.NotificationManagerCompat;
 import android.text.Spannable;
 import android.text.SpannableString;
 import android.text.TextUtils;
@@ -58,7 +57,7 @@ import android.text.style.StyleSpan;
 
 public class SipNotifications {
 
-    private final NotificationManager notificationManager;
+    public final NotificationManagerCompat notificationManager;
     private final Context context;
 
     public static final String NOTIF_CREATION = "notif_creation";
@@ -76,7 +75,8 @@ public class SipNotifications {
 
     public SipNotifications(Context aContext) {
         context = aContext;
-        notificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+        notificationManager = NotificationManagerCompat.from(aContext);
+        ;//(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
 
         if (!isInit) {
             cancelAll();
@@ -158,7 +158,7 @@ public class SipNotifications {
         nb.setTicker(tickerText);
         nb.setWhen(when);
         nb.setContentTitle(context.getString(R.string.notif_missed_call_title));
-        nb.setContentText(context.getString(R.string.notif_missed_call_content, missedConf.getParticipants().get(0).getmContact().getmDisplayName()));
+        nb.setContentText(context.getString(R.string.notif_missed_call_content, missedConf.getParticipants().get(0).getContact().getDisplayName()));
         Intent notificationIntent = new Intent(context, HomeActivity.class);
         notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);
         PendingIntent contentIntent = PendingIntent.getActivity(context, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
@@ -168,12 +168,11 @@ public class SipNotifications {
         nb.setOnlyAlertOnce(true);
         nb.setContentIntent(contentIntent);
 
-        Notification notification = nb.build();
         // We have to re-write content view because getNotification setLatestEventInfo implicitly
         // notification.contentView = contentView;
 
         // startForegroundCompat(CALL_NOTIF_ID, notification);
-        notificationManager.notify(CALL_NOTIF_ID, notification);
+        notificationManager.notify(CALL_NOTIF_ID, nb.build());
     }
 
     public void makeNotification(HashMap<String, SipCall> calls) {
@@ -183,21 +182,20 @@ public class SipNotifications {
         Intent notificationIntent = new Intent(context, HomeActivity.class);
         PendingIntent contentIntent = PendingIntent.getActivity(context, 007, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
 
-        NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
-        nm.cancel(NOTIFICATION_ID); // clear previous notifications.
+        //NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+        notificationManager.cancel(NOTIFICATION_ID); // clear previous notifications.
 
         NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
 
         builder.setContentIntent(contentIntent).setOngoing(true).setSmallIcon(R.drawable.ic_launcher)
                 .setContentTitle(calls.size() + " ongoing calls").setTicker("Pending calls").setWhen(System.currentTimeMillis()).setAutoCancel(false);
         builder.setPriority(NotificationCompat.PRIORITY_MAX);
-        Notification n = builder.build();
 
-        nm.notify(NOTIFICATION_ID, n);
+        notificationManager.notify(NOTIFICATION_ID, builder.build());
     }
 
     public void removeNotification() {
-        NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
-        nm.cancel(NOTIFICATION_ID);
+        //NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
+        notificationManager.cancel(NOTIFICATION_ID);
     }
 }
\ No newline at end of file
diff --git a/ring-android/app/src/main/java/cx/ring/utils/Utilities.java b/ring-android/app/src/main/java/cx/ring/utils/Utilities.java
new file mode 100644
index 000000000..1ac13374d
--- /dev/null
+++ b/ring-android/app/src/main/java/cx/ring/utils/Utilities.java
@@ -0,0 +1,35 @@
+package cx.ring.utils;
+
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.regex.PatternSyntaxException;
+
+/**
+ * This class provides a variety of basic utility methods that are not
+ * dependent on any other classes within the org.jamwiki package structure.
+ */
+public class Utilities {
+    private static final String ipv4Pattern = "(([01]?\\d\\d?|2[0-4]\\d|25[0-5])\\.){3}([01]?\\d\\d?|2[0-4]\\d|25[0-5])";
+    private static final String ipv6Pattern = "([0-9a-f]{1,4}:){7}([0-9a-f]){1,4}";
+    private static final Pattern VALID_IPV4_PATTERN = Pattern.compile(ipv4Pattern, Pattern.CASE_INSENSITIVE);
+    private static final Pattern VALID_IPV6_PATTERN = Pattern.compile(ipv6Pattern, Pattern.CASE_INSENSITIVE);
+
+    /**
+     * Determine if the given string is a valid IPv4 or IPv6 address.  This method
+     * uses pattern matching to see if the given string could be a valid IP address.
+     *
+     * @param ipAddress A string that is to be examined to verify whether or not
+     *                  it could be a valid IP address.
+     * @return <code>true</code> if the string is a value that is a valid IP address,
+     * <code>false</code> otherwise.
+     */
+    public static boolean isIpAddress(String ipAddress) {
+
+        Matcher m1 = VALID_IPV4_PATTERN.matcher(ipAddress);
+        if (m1.matches()) {
+            return true;
+        }
+        Matcher m2 = VALID_IPV6_PATTERN.matcher(ipAddress);
+        return m2.matches();
+    }
+}
diff --git a/ring-android/app/src/main/java/cx/ring/views/CallPaneLayout.java b/ring-android/app/src/main/java/cx/ring/views/CallPaneLayout.java
index c9bd68664..cd2afcfbc 100644
--- a/ring-android/app/src/main/java/cx/ring/views/CallPaneLayout.java
+++ b/ring-android/app/src/main/java/cx/ring/views/CallPaneLayout.java
@@ -60,6 +60,7 @@ public class CallPaneLayout extends SlidingPaneLayout
 		super(context, attrs, defStyle);
 	}
 
+	/*
 	@Override
 	public boolean onInterceptTouchEvent(MotionEvent event)
 	{
@@ -68,6 +69,6 @@ public class CallPaneLayout extends SlidingPaneLayout
 		}
 
 		return super.onInterceptTouchEvent(event);
-	}
+	}*/
 
 }
diff --git a/ring-android/app/src/main/java/cx/ring/views/HalfCircleImageView.java b/ring-android/app/src/main/java/cx/ring/views/HalfCircleImageView.java
index e9b0d6acc..46ed0d674 100644
--- a/ring-android/app/src/main/java/cx/ring/views/HalfCircleImageView.java
+++ b/ring-android/app/src/main/java/cx/ring/views/HalfCircleImageView.java
@@ -76,7 +76,7 @@ public class HalfCircleImageView extends ImageView
     private void setup()
     {
         backgroundPaint = new Paint();
-        backgroundPaint.setColor(getResources().getColor(R.color.sfl_dark_blue));
+        backgroundPaint.setColor(getResources().getColor(R.color.color_primary_dark));
         backgroundPaint.setAntiAlias(true);
         // init paint
         paint = new Paint();
diff --git a/ring-android/app/src/main/java/cx/ring/views/NumberPickerPreference.java b/ring-android/app/src/main/java/cx/ring/views/NumberPickerPreference.java
index bbf73429c..cc6b156fb 100644
--- a/ring-android/app/src/main/java/cx/ring/views/NumberPickerPreference.java
+++ b/ring-android/app/src/main/java/cx/ring/views/NumberPickerPreference.java
@@ -92,7 +92,7 @@ public class NumberPickerPreference extends DialogPreference {
             throw new RuntimeException("mNumberPicker is null!");
         }
 
-        // Initialize state
+        // Initialize State
         mNumberPicker.setWrapSelectorWheel(false);
         mNumberPicker.setMaxValue(max);
         mNumberPicker.setMinValue(min);
diff --git a/ring-android/app/src/main/java/cx/ring/views/QuadNumberPickerPreference.java b/ring-android/app/src/main/java/cx/ring/views/QuadNumberPickerPreference.java
index 49bf9d3c1..3604fd29a 100644
--- a/ring-android/app/src/main/java/cx/ring/views/QuadNumberPickerPreference.java
+++ b/ring-android/app/src/main/java/cx/ring/views/QuadNumberPickerPreference.java
@@ -127,7 +127,7 @@ public class QuadNumberPickerPreference extends DialogPreference {
             throw new RuntimeException("mNumberPicker1 or mNumberPicker2 is null!");
         }
 
-        // Initialize state
+        // Initialize State
         mNumberPicker1.setWrapSelectorWheel(false);
         mNumberPicker1.setMaxValue(mMax1);
         mNumberPicker1.setMinValue(mMin1);
diff --git a/ring-android/app/src/main/java/cx/ring/views/SwipeListViewTouchListener.java b/ring-android/app/src/main/java/cx/ring/views/SwipeListViewTouchListener.java
deleted file mode 100644
index 8e054662b..000000000
--- a/ring-android/app/src/main/java/cx/ring/views/SwipeListViewTouchListener.java
+++ /dev/null
@@ -1,409 +0,0 @@
-/*
- *  Copyright (C) 2004-2014 Savoir-Faire Linux Inc.
- *
- *  Author: Alexandre Lision <alexandre.lision@savoirfairelinux.com>
- *
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 3 of the License, or
- *  (at your option) any later version.
- *
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- *
- *  Additional permission under GNU GPL version 3 section 7:
- *
- *  If you modify this program, or any covered work, by linking or
- *  combining it with the OpenSSL project's OpenSSL library (or a
- *  modified version of that library), containing parts covered by the
- *  terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
- *  grants you additional permission to convey the resulting work.
- *  Corresponding Source for a non-source form of such a combination
- *  shall include the source code for the parts of OpenSSL used as well
- *  as that of the covered work.
- */
-
-package cx.ring.views;
-
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-
-import cx.ring.R;
-
-import android.animation.Animator;
-import android.animation.AnimatorListenerAdapter;
-import android.animation.ValueAnimator;
-import android.graphics.Rect;
-import android.view.MotionEvent;
-import android.view.VelocityTracker;
-import android.view.View;
-import android.view.ViewConfiguration;
-import android.view.ViewGroup;
-import android.widget.AbsListView;
-import android.widget.ListView;
-
-public class SwipeListViewTouchListener implements View.OnTouchListener {
-    // Cached ViewConfiguration and system-wide constant values
-    private int mSlop;
-    private int mMinFlingVelocity;
-    private int mMaxFlingVelocity;
-    private long mAnimationTime;
-
-    private static final String TAG = SwipeListViewTouchListener.class.getSimpleName();
-
-    // Fixed properties
-    private ListView mListView;
-    private OnSwipeCallback mCallback;
-    private int mViewWidth = 1; // 1 and not 0 to prevent dividing by zero
-    private boolean dismissLeft = true;
-    private boolean dismissRight = true;
-
-    // Transient properties
-    private List<PendingSwipeData> mPendingSwipes = new ArrayList<PendingSwipeData>();
-    private int mDismissAnimationRefCount = 0;
-    private float mDownX;
-    private float mDownY;
-    private boolean mSwiping;
-    private VelocityTracker mVelocityTracker;
-    private int mDownPosition;
-    private View mDownView, mUnderDownView;
-    private boolean mPaused;
-
-    /**
-     * The callback interface used by {@link SwipeListViewTouchListener} to inform its client about a successful swipe of one or more list item
-     * positions.
-     */
-    public interface OnSwipeCallback {
-        /**
-         * Called when the user has swiped the list item to the left.
-         * 
-         * @param listView
-         *            The originating {@link ListView}.
-         * @param reverseSortedPositions
-         *            An array of positions to dismiss, sorted in descending order for convenience.
-         */
-        void onSwipeLeft(ListView listView, int[] reverseSortedPositions);
-
-        void onSwipeRight(ListView listView, View downView);
-    }
-
-    /**
-     * Constructs a new swipe-to-action touch listener for the given list view.
-     * 
-     * @param listView
-     *            The list view whose items should be dismissable.
-     * @param callback
-     *            The callback to trigger when the user has indicated that she would like to dismiss one or more list items.
-     */
-    public SwipeListViewTouchListener(ListView listView, OnSwipeCallback callback) {
-        ViewConfiguration vc = ViewConfiguration.get(listView.getContext());
-        mSlop = vc.getScaledTouchSlop();
-        mMinFlingVelocity = vc.getScaledMinimumFlingVelocity();
-        mMaxFlingVelocity = vc.getScaledMaximumFlingVelocity();
-        mAnimationTime = listView.getContext().getResources().getInteger(android.R.integer.config_shortAnimTime);
-        mListView = listView;
-        mCallback = callback;
-    }
-
-    /**
-     * Constructs a new swipe-to-action touch listener for the given list view.
-     * 
-     * @param listView
-     *            The list view whose items should be dismissable.
-     * @param callback
-     *            The callback to trigger when the user has indicated that she would like to dismiss one or more list items.
-     * @param dismissLeft
-     *            set if the dismiss animation is up when the user swipe to the left
-     * @param dismissRight
-     *            set if the dismiss animation is up when the user swipe to the right
-     * @see #SwipeListViewTouchListener(ListView, OnSwipeCallback, boolean, boolean)
-     */
-    public SwipeListViewTouchListener(ListView listView, OnSwipeCallback callback, boolean dismissLeft, boolean dismissRight) {
-        this(listView, callback);
-        this.dismissLeft = dismissLeft;
-        this.dismissRight = dismissRight;
-    }
-
-    /**
-     * Enables or disables (pauses or resumes) watching for swipe-to-dismiss gestures.
-     * 
-     * @param enabled
-     *            Whether or not to watch for gestures.
-     */
-    public void setEnabled(boolean enabled) {
-        mPaused = !enabled;
-    }
-
-    /**
-     * Returns an {@link android.widget.AbsListView.OnScrollListener} to be added to the {@link ListView} using
-     * {@link ListView#setOnScrollListener(android.widget.AbsListView.OnScrollListener)}. If a scroll listener is already assigned, the caller should
-     * still pass scroll changes through to this listener. This will ensure that this {@link SwipeListViewTouchListener} is paused during list view
-     * scrolling.</p>
-     * 
-     * @see {@link SwipeListViewTouchListener}
-     */
-    public AbsListView.OnScrollListener makeScrollListener() {
-        return new AbsListView.OnScrollListener() {
-            @Override
-            public void onScrollStateChanged(AbsListView absListView, int scrollState) {
-                setEnabled(scrollState != AbsListView.OnScrollListener.SCROLL_STATE_TOUCH_SCROLL);
-            }
-
-            @Override
-            public void onScroll(AbsListView absListView, int i, int i1, int i2) {
-            }
-        };
-    }
-
-    @Override
-    public boolean onTouch(View item, MotionEvent motionEvent) {
-        if (mViewWidth < 2) {
-            mViewWidth = mListView.getWidth();
-        }
-
-        switch (motionEvent.getActionMasked()) {
-        case MotionEvent.ACTION_DOWN: {
-            if (mPaused) {
-                return false;
-            }
-
-            // TODO: ensure this is a finger, and set a flag
-
-            // Find the child view that was touched (perform a hit test)
-            Rect rect = new Rect();
-            int childCount = mListView.getChildCount();
-            int[] listViewCoords = new int[2];
-            mListView.getLocationOnScreen(listViewCoords);
-            int x = (int) motionEvent.getRawX() - listViewCoords[0];
-            int y = (int) motionEvent.getRawY() - listViewCoords[1];
-            View child;
-            for (int i = 0; i < childCount; i++) {
-                child = mListView.getChildAt(i);
-                child.getHitRect(rect);
-                if (rect.contains(x, y)) {
-                    mDownView = child.findViewById(R.id.contactview);
-                    mUnderDownView = child.findViewById(R.id.contact_underview);
-                    break;
-                }
-            }
-
-            if (mDownView != null) {
-
-                mDownX = motionEvent.getRawX() - mDownView.getTranslationX();
-                mDownY = motionEvent.getRawY();
-                mDownPosition = mListView.getPositionForView(mDownView);
-
-                mVelocityTracker = VelocityTracker.obtain();
-                mVelocityTracker.addMovement(motionEvent);
-            }
-            item.onTouchEvent(motionEvent);
-            return true;
-        }
-
-        case MotionEvent.ACTION_UP: {
-            if (mVelocityTracker == null) {
-                break;
-            }
-
-            float deltaX = motionEvent.getRawX() - mDownX;
-
-            mVelocityTracker.addMovement(motionEvent);
-            mVelocityTracker.computeCurrentVelocity(500); // 1000 by defaut but it was too much
-            float velocityX = Math.abs(mVelocityTracker.getXVelocity());
-            float velocityY = Math.abs(mVelocityTracker.getYVelocity());
-            boolean swipe = false;
-            boolean swipeRight = false;
-
-            if (mDownView.getTranslationX() > mViewWidth / 2) {
-                swipe = true;
-                swipeRight = deltaX > 0;
-            } else if (mMinFlingVelocity <= velocityX && velocityX <= mMaxFlingVelocity && velocityY < velocityX) {
-                swipe = true;
-                swipeRight = mVelocityTracker.getXVelocity() > 0;
-            }
-            if (swipe) {
-                // sufficent swipe value
-                final View downView = mDownView; // mDownView gets null'd before animation ends
-                final int downPosition = mDownPosition;
-                final boolean toTheRight = swipeRight;
-                ++mDismissAnimationRefCount;
-
-                if (toTheRight) {
-                    mDownView.animate().translationX(mViewWidth / 2).alpha(1).setDuration(mAnimationTime).setListener(new AnimatorListenerAdapter() {
-                        @Override
-                        public void onAnimationEnd(Animator animation) {
-                            mListView.requestDisallowInterceptTouchEvent(false);
-                            // mCallback.onSwipeRight(mListView, mUnderDownView);
-                            toggleUnderLayerState(true);
-                            // performSwipeAction(downView, downPosition, toTheRight,dismissRight);
-                        }
-                    });
-                } else {
-                    mDownView.animate().translationX(0).alpha(1).setDuration(mAnimationTime);
-                }
-
-            } else {
-                // cancel
-                mDownView.animate().translationX(0).alpha(1).setDuration(mAnimationTime).setListener(new AnimatorListenerAdapter() {
-                    @Override
-                    public void onAnimationEnd(Animator animation) {
-                        toggleUnderLayerState(false);
-                        mUnderDownView = null;
-                    }
-                });
-            }
-            mVelocityTracker.recycle();
-            mVelocityTracker = null;
-            mDownX = 0;
-            mDownView = null;
-            mDownPosition = ListView.INVALID_POSITION;
-            mSwiping = false;
-            break;
-        }
-
-        case MotionEvent.ACTION_MOVE: {
-            if (mVelocityTracker == null || mPaused) {
-                break;
-            }
-
-            mVelocityTracker.addMovement(motionEvent);
-            mVelocityTracker.computeCurrentVelocity(500);
-            float deltaX = motionEvent.getRawX() - mDownX;
-            float deltaY = motionEvent.getRawY() - mDownY;
-
-            if (Math.abs(deltaX) < Math.abs(deltaY)) {
-                mListView.requestDisallowInterceptTouchEvent(false);
-                return false;
-            }
-
-            if (Math.abs(deltaX) > mSlop) {
-                mSwiping = true;
-                mListView.requestDisallowInterceptTouchEvent(true);
-
-                // Cancel ListView's touch (un-highlighting the item)
-                MotionEvent cancelEvent = MotionEvent.obtain(motionEvent);
-                cancelEvent.setAction(MotionEvent.ACTION_CANCEL | (motionEvent.getActionIndex() << MotionEvent.ACTION_POINTER_INDEX_SHIFT));
-                mListView.onTouchEvent(cancelEvent);
-                cancelEvent.recycle();
-            }
-            if (deltaX < 0)
-                return true;
-
-            if (mSwiping) {
-                mDownView.setTranslationX(deltaX);
-                // mDownView.setAlpha(Math.max(0f, Math.min(1f, 1f - 2f * Math.abs(deltaX) / mViewWidth)));
-                return true;
-            }
-            break;
-        }
-        }
-        return false;
-    }
-
-    private void toggleUnderLayerState(boolean b) {
-        if (mUnderDownView == null)
-            return;
-        mUnderDownView.findViewById(R.id.quick_edit).setClickable(b);
-        mUnderDownView.findViewById(R.id.quick_discard).setClickable(b);
-        mUnderDownView.findViewById(R.id.quick_starred).setClickable(b);
-    }
-
-    class PendingSwipeData implements Comparable<PendingSwipeData> {
-        public int position;
-        public View view;
-
-        public PendingSwipeData(int position, View view) {
-            this.position = position;
-            this.view = view;
-        }
-
-        @Override
-        public int compareTo(PendingSwipeData other) {
-            // Sort by descending position
-            return other.position - position;
-        }
-    }
-
-    private void performSwipeAction(final View swipeView, final int swipePosition, boolean toTheRight, boolean dismiss) {
-        // Animate the dismissed list item to zero-height and fire the dismiss callback when
-        // all dismissed list item animations have completed. This triggers layout on each animation
-        // frame; in the future we may want to do something smarter and more performant.
-
-        final ViewGroup.LayoutParams lp = swipeView.getLayoutParams();
-        final int originalHeight = swipeView.getHeight();
-        final boolean swipeRight = toTheRight;
-
-        ValueAnimator animator;
-        if (dismiss)
-            animator = ValueAnimator.ofInt(originalHeight, 1).setDuration(mAnimationTime);
-        else
-            animator = ValueAnimator.ofInt(originalHeight, originalHeight - 1).setDuration(mAnimationTime);
-
-        animator.addListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                --mDismissAnimationRefCount;
-                if (mDismissAnimationRefCount == 0) {
-                    // No active animations, process all pending dismisses.
-                    // Sort by descending position
-                    Collections.sort(mPendingSwipes);
-
-                    int[] swipePositions = new int[mPendingSwipes.size()];
-                    for (int i = mPendingSwipes.size() - 1; i >= 0; i--) {
-                        swipePositions[i] = mPendingSwipes.get(i).position;
-                    }
-                    // if (swipeRight)
-                    // mCallback.onSwipeRight(mListView, swipePositions);
-                    // else
-                    // mCallback.onSwipeLeft(mListView, swipePositions);
-
-                    ViewGroup.LayoutParams lp;
-                    for (PendingSwipeData pendingDismiss : mPendingSwipes) {
-                        // Reset view presentation
-                        pendingDismiss.view.setAlpha(1f);
-                        pendingDismiss.view.setTranslationX(0);
-                        lp = pendingDismiss.view.getLayoutParams();
-                        lp.height = originalHeight;
-                        pendingDismiss.view.setLayoutParams(lp);
-                    }
-
-                    mPendingSwipes.clear();
-                }
-            }
-        });
-
-        animator.addUpdateListener(new ValueAnimator.AnimatorUpdateListener() {
-            @Override
-            public void onAnimationUpdate(ValueAnimator valueAnimator) {
-                lp.height = (Integer) valueAnimator.getAnimatedValue();
-                swipeView.setLayoutParams(lp);
-            }
-        });
-
-        mPendingSwipes.add(new PendingSwipeData(swipePosition, swipeView));
-        animator.start();
-    }
-
-    public void openItem(View child, int pos, long id) {
-
-        mDownView = child.findViewById(R.id.contactview);
-        mUnderDownView = child.findViewById(R.id.contact_underview);
-        if (mDownView.getTranslationX() > 0)
-            return;
-        mDownView.animate().translationX(mViewWidth / 2).setDuration(mAnimationTime).setListener(new AnimatorListenerAdapter() {
-            @Override
-            public void onAnimationEnd(Animator animation) {
-                mListView.requestDisallowInterceptTouchEvent(false);
-                toggleUnderLayerState(true);
-                // performSwipeAction(downView, downPosition, toTheRight,dismissRight);
-            }
-        });
-    }
-}
diff --git a/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/AdapterWrapper.java b/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/AdapterWrapper.java
deleted file mode 100644
index 22b02a8a9..000000000
--- a/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/AdapterWrapper.java
+++ /dev/null
@@ -1,225 +0,0 @@
-package cx.ring.views.stickylistheaders;
-
-import java.util.LinkedList;
-import java.util.List;
-
-import android.content.Context;
-import android.database.DataSetObserver;
-import android.graphics.drawable.Drawable;
-import android.view.View;
-import android.view.View.OnClickListener;
-import android.view.ViewGroup;
-import android.widget.BaseAdapter;
-import android.widget.Checkable;
-import android.widget.ListAdapter;
-
-/**
- * A {@link ListAdapter} which wraps a {@link StickyListHeadersAdapter} and
- * automatically handles wrapping the result of
- * {@link StickyListHeadersAdapter#getView(int, android.view.View, android.view.ViewGroup)}
- * and
- * {@link StickyListHeadersAdapter#getHeaderView(int, android.view.View, android.view.ViewGroup)}
- * appropriately.
- *
- * @author Jake Wharton (jakewharton@gmail.com)
- */
-class AdapterWrapper extends BaseAdapter implements StickyListHeadersAdapter {
-
-	interface OnHeaderClickListener {
-		public void onHeaderClick(View header, int itemPosition, long headerId);
-	}
-
-	final StickyListHeadersAdapter mDelegate;
-	private final List<View> mHeaderCache = new LinkedList<View>();
-	private final Context mContext;
-	private Drawable mDivider;
-	private int mDividerHeight;
-	private OnHeaderClickListener mOnHeaderClickListener;
-	private DataSetObserver mDataSetObserver = new DataSetObserver() {
-
-		@Override
-		public void onInvalidated() {
-			mHeaderCache.clear();
-			AdapterWrapper.super.notifyDataSetInvalidated();
-		}
-		
-		@Override
-		public void onChanged() {
-			AdapterWrapper.super.notifyDataSetChanged();
-		}
-	};
-
-	AdapterWrapper(Context context,
-			StickyListHeadersAdapter delegate) {
-		this.mContext = context;
-		this.mDelegate = delegate;
-		delegate.registerDataSetObserver(mDataSetObserver);
-	}
-
-	void setDivider(Drawable divider, int dividerHeight) {
-		this.mDivider = divider;
-		this.mDividerHeight = dividerHeight;
-		notifyDataSetChanged();
-	}
-
-	@Override
-	public boolean areAllItemsEnabled() {
-		return mDelegate.areAllItemsEnabled();
-	}
-
-	@Override
-	public boolean isEnabled(int position) {
-		return mDelegate.isEnabled(position);
-	}
-
-	@Override
-	public int getCount() {
-		return mDelegate.getCount();
-	}
-
-	@Override
-	public Object getItem(int position) {
-		return mDelegate.getItem(position);
-	}
-
-	@Override
-	public long getItemId(int position) {
-		return mDelegate.getItemId(position);
-	}
-
-	@Override
-	public boolean hasStableIds() {
-		return mDelegate.hasStableIds();
-	}
-
-	@Override
-	public int getItemViewType(int position) {
-		return mDelegate.getItemViewType(position);
-	}
-
-	@Override
-	public int getViewTypeCount() {
-		return mDelegate.getViewTypeCount();
-	}
-
-	@Override
-	public boolean isEmpty() {
-		return mDelegate.isEmpty();
-	}
-
-	/**
-	 * Will recycle header from {@link WrapperView} if it exists
-	 */
-	private void recycleHeaderIfExists(WrapperView wv) {
-		View header = wv.mHeader;
-		if (header != null) {
-			// reset the headers visibility when adding it to the cache
-			header.setVisibility(View.VISIBLE);
-			mHeaderCache.add(header);
-		}
-	}
-
-	/**
-	 * Get a header view. This optionally pulls a header from the supplied
-	 * {@link WrapperView} and will also recycle the divider if it exists.
-	 */
-	private View configureHeader(WrapperView wv, final int position) {
-		View header = wv.mHeader == null ? popHeader() : wv.mHeader;
-		header = mDelegate.getHeaderView(position, header, wv);
-		if (header == null) {
-			throw new NullPointerException("Header view must not be null.");
-		}
-		//if the header isn't clickable, the listselector will be drawn on top of the header
-		header.setClickable(true);
-		header.setOnClickListener(new OnClickListener() {
-
-			@Override
-			public void onClick(View v) {
-				if(mOnHeaderClickListener != null){
-					long headerId = mDelegate.getHeaderId(position);
-					mOnHeaderClickListener.onHeaderClick(v, position, headerId);
-				}
-			}
-		});
-		return header;
-	}
-
-	private View popHeader() {
-		if(mHeaderCache.size() > 0) {
-			return mHeaderCache.remove(0);
-		}
-		return null;
-	}
-
-	/** Returns {@code true} if the previous position has the same header ID. */
-	private boolean previousPositionHasSameHeader(int position) {
-		return position != 0
-				&& mDelegate.getHeaderId(position) == mDelegate
-						.getHeaderId(position - 1);
-	}
-
-	@Override
-	public WrapperView getView(int position, View convertView, ViewGroup parent) {
-		WrapperView wv = (convertView == null) ? new WrapperView(mContext) : (WrapperView) convertView;
-		View item = mDelegate.getView(position, wv.mItem, parent);
-		View header = null;
-		if (previousPositionHasSameHeader(position)) {
-			recycleHeaderIfExists(wv);
-		} else {
-			header = configureHeader(wv, position);
-		}
-		if((item instanceof Checkable) && !(wv instanceof CheckableWrapperView)) {
-			// Need to create Checkable subclass of WrapperView for ListView to work correctly
-			wv = new CheckableWrapperView(mContext);
-		} else if(!(item instanceof Checkable) && (wv instanceof CheckableWrapperView)) {
-			wv = new WrapperView(mContext);
-		}
-		wv.update(item, header, mDivider, mDividerHeight);
-		return wv;
-	}
-
-	public void setOnHeaderClickListener(OnHeaderClickListener onHeaderClickListener){
-		this.mOnHeaderClickListener = onHeaderClickListener;
-	}
-
-	@Override
-	public boolean equals(Object o) {
-		return mDelegate.equals(o); 
-	}
-
-	@Override
-	public View getDropDownView(int position, View convertView, ViewGroup parent) {
-		return ((BaseAdapter) mDelegate).getDropDownView(position, convertView, parent);
-	}
-
-	@Override
-	public int hashCode() {
-		return mDelegate.hashCode();
-	}
-
-	@Override
-	public void notifyDataSetChanged() {
-		((BaseAdapter) mDelegate).notifyDataSetChanged();
-	}
-
-	@Override
-	public void notifyDataSetInvalidated() {
-		((BaseAdapter) mDelegate).notifyDataSetInvalidated();
-	}
-
-	@Override
-	public String toString() {
-		return mDelegate.toString();
-	}
-
-	@Override
-	public View getHeaderView(int position, View convertView, ViewGroup parent) {
-		return mDelegate.getHeaderView(position, convertView, parent);
-	}
-
-	@Override
-	public long getHeaderId(int position) {
-		return mDelegate.getHeaderId(position);
-	}
-
-}
diff --git a/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/ApiLevelTooLowException.java b/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/ApiLevelTooLowException.java
deleted file mode 100644
index 075dfb4d6..000000000
--- a/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/ApiLevelTooLowException.java
+++ /dev/null
@@ -1,11 +0,0 @@
-package cx.ring.views.stickylistheaders;
-
-public class ApiLevelTooLowException extends RuntimeException {
-
-    private static final long serialVersionUID = -5480068364264456757L;
-
-    public ApiLevelTooLowException(int versionCode) {
-        super("Requires API level " + versionCode);
-    }
-
-}
diff --git a/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/CheckableWrapperView.java b/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/CheckableWrapperView.java
deleted file mode 100644
index e22204f44..000000000
--- a/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/CheckableWrapperView.java
+++ /dev/null
@@ -1,31 +0,0 @@
-package cx.ring.views.stickylistheaders;
-
-import android.content.Context;
-import android.widget.Checkable;
-
-/**
- * A WrapperView that implements the checkable interface
- * 
- * @author Emil Sjölander
- */
-class CheckableWrapperView extends WrapperView implements Checkable {
-
-	public CheckableWrapperView(final Context context) {
-		super(context);
-	}
-
-	@Override
-	public boolean isChecked() {
-		return ((Checkable) mItem).isChecked();
-	}
-
-	@Override
-	public void setChecked(final boolean checked) {
-		((Checkable) mItem).setChecked(checked);
-	}
-
-	@Override
-	public void toggle() {
-		setChecked(!isChecked());
-	}
-}
diff --git a/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/SectionIndexerAdapterWrapper.java b/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/SectionIndexerAdapterWrapper.java
deleted file mode 100644
index dd823ff82..000000000
--- a/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/SectionIndexerAdapterWrapper.java
+++ /dev/null
@@ -1,32 +0,0 @@
-package cx.ring.views.stickylistheaders;
-
-import android.content.Context;
-import android.widget.SectionIndexer;
-
-class SectionIndexerAdapterWrapper extends
-		AdapterWrapper implements SectionIndexer {
-	
-	final SectionIndexer mSectionIndexerDelegate;
-
-	SectionIndexerAdapterWrapper(Context context,
-			StickyListHeadersAdapter delegate) {
-		super(context, delegate);
-		mSectionIndexerDelegate = (SectionIndexer) delegate;
-	}
-
-	@Override
-	public int getPositionForSection(int section) {
-		return mSectionIndexerDelegate.getPositionForSection(section);
-	}
-
-	@Override
-	public int getSectionForPosition(int position) {
-		return mSectionIndexerDelegate.getSectionForPosition(position);
-	}
-
-	@Override
-	public Object[] getSections() {
-		return mSectionIndexerDelegate.getSections();
-	}
-
-}
diff --git a/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/StickyListHeadersAdapter.java b/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/StickyListHeadersAdapter.java
deleted file mode 100644
index 236338d3d..000000000
--- a/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/StickyListHeadersAdapter.java
+++ /dev/null
@@ -1,38 +0,0 @@
-package cx.ring.views.stickylistheaders;
-
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.ListAdapter;
-
-public interface StickyListHeadersAdapter extends ListAdapter {
-	/**
-	 * Get a View that displays the header data at the specified position in the
-	 * set. You can either create a View manually or inflate it from an XML layout
-	 * file.
-	 *
-	 * @param position
-	 * The position of the item within the adapter's data set of the item whose
-	 * header view we want.
-	 * @param convertView
-	 * The old view to reuse, if possible. Note: You should check that this view is
-	 * non-null and of an appropriate type before using. If it is not possible to
-	 * convert this view to display the correct data, this method can create a new
-	 * view.
-	 * @param parent
-	 * The parent that this view will eventually be attached to.
-	 * @return
-	 * A View corresponding to the data at the specified position.
-	 */
-	View getHeaderView(int position, View convertView, ViewGroup parent);
-
-	/**
-	 * Get the header id associated with the specified position in the list.
-	 *
-	 * @param position
-	 * The position of the item within the adapter's data set whose header id we
-	 * want.
-	 * @return
-	 * The id of the header at the specified position.
-	 */
-	long getHeaderId(int position);
-}
diff --git a/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/StickyListHeadersListView.java b/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/StickyListHeadersListView.java
deleted file mode 100644
index 72780e9d6..000000000
--- a/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/StickyListHeadersListView.java
+++ /dev/null
@@ -1,993 +0,0 @@
-package cx.ring.views.stickylistheaders;
-
-import cx.ring.R;
-import cx.ring.adapters.ContactsAdapter;
-
-import android.annotation.SuppressLint;
-import android.annotation.TargetApi;
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.database.DataSetObserver;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.os.Build;
-import android.util.AttributeSet;
-import android.util.SparseBooleanArray;
-import android.view.View;
-import android.view.ViewGroup;
-import android.widget.AbsListView;
-import android.widget.AbsListView.OnScrollListener;
-import android.widget.AdapterView.OnItemClickListener;
-import android.widget.AdapterView.OnItemLongClickListener;
-import android.widget.FrameLayout;
-import android.widget.ListView;
-import android.widget.SectionIndexer;
-
-/**
- * Even though this is a FrameLayout subclass we it is called a ListView. This
- * is because of 2 reasons. 1. It acts like as ListView 2. It used to be a
- * ListView subclass and i did not was to change to name causing compatibility
- * errors.
- * 
- * @author Emil Sjölander
- */
-public class StickyListHeadersListView extends FrameLayout {
-
-	public interface OnHeaderClickListener {
-		public void onHeaderClick(StickyListHeadersListView l, View header,
-				int itemPosition, long headerId, boolean currentlySticky);
-	}
-
-	/* --- Children --- */
-	private WrapperViewList mList;
-	private View mHeader;
-
-	/* --- Header state --- */
-	private Long mHeaderId;
-	// used to not have to call getHeaderId() all the time
-	private Integer mHeaderPosition;
-	private Integer mHeaderOffset;
-
-	/* --- Delegates --- */
-	private OnScrollListener mOnScrollListenerDelegate;
-
-	/* --- Settings --- */
-	private boolean mAreHeadersSticky = true;
-	private boolean mClippingToPadding = true;
-	private boolean mIsDrawingListUnderStickyHeader = true;
-	private int mPaddingLeft = 0;
-	private int mPaddingTop = 0;
-	private int mPaddingRight = 0;
-	private int mPaddingBottom = 0;
-
-	/* --- Other --- */
-	private AdapterWrapper mAdapter;
-	private OnHeaderClickListener mOnHeaderClickListener;
-	private Drawable mDivider;
-	private int mDividerHeight;
-	private AdapterWrapperDataSetObserver mDataSetObserver;
-
-	public StickyListHeadersListView(Context context) {
-		this(context, null);
-	}
-
-	public StickyListHeadersListView(Context context, AttributeSet attrs) {
-		this(context, attrs, 0);
-	}
-
-	@TargetApi(Build.VERSION_CODES.HONEYCOMB)
-	public StickyListHeadersListView(Context context, AttributeSet attrs,
-			int defStyle) {
-		super(context, attrs, defStyle);
-
-		// Initialize the list
-		mList = new WrapperViewList(context, attrs);
-		mDivider = mList.getDivider();
-		mDividerHeight = mList.getDividerHeight();
-
-		// null out divider, dividers are handled by adapter so they look good
-		// with headers
-		mList.setDivider(null);
-		mList.setDividerHeight(0);
-
-		mList.setLifeCycleListener(new WrapperViewListLifeCycleListener());
-		mList.setOnScrollListener(new WrapperListScrollListener());
-		addView(mList);
-
-		if (attrs != null) {
-			TypedArray a = context.getTheme().obtainStyledAttributes(attrs,
-					R.styleable.StickyListHeadersListView, 0, 0);
-
-			try {
-				// Android attributes
-				if (a.hasValue(R.styleable.StickyListHeadersListView_android_padding)) {
-					int padding = a
-							.getDimensionPixelSize(
-									R.styleable.StickyListHeadersListView_android_padding,
-									0);
-					mPaddingLeft = padding;
-					mPaddingTop = padding;
-					mPaddingRight = padding;
-					mPaddingBottom = padding;
-				} else {
-					mPaddingLeft = a
-							.getDimensionPixelSize(
-									R.styleable.StickyListHeadersListView_android_paddingLeft,
-									0);
-					mPaddingTop = a
-							.getDimensionPixelSize(
-									R.styleable.StickyListHeadersListView_android_paddingTop,
-									0);
-					mPaddingRight = a
-							.getDimensionPixelSize(
-									R.styleable.StickyListHeadersListView_android_paddingRight,
-									0);
-					mPaddingBottom = a
-							.getDimensionPixelSize(
-									R.styleable.StickyListHeadersListView_android_paddingBottom,
-									0);
-				}
-				setPadding(mPaddingLeft, mPaddingTop, mPaddingRight,
-						mPaddingBottom);
-
-				// Set clip to padding on the list and reset value to default on
-				// wrapper
-				mClippingToPadding = a
-						.getBoolean(
-								R.styleable.StickyListHeadersListView_android_clipToPadding,
-								true);
-				super.setClipToPadding(true);
-				mList.setClipToPadding(mClippingToPadding);
-
-				// ListView attributes
-				mList.setFadingEdgeLength(a
-						.getDimensionPixelSize(
-								R.styleable.StickyListHeadersListView_android_fadingEdgeLength,
-								mList.getVerticalFadingEdgeLength()));
-				final int fadingEdge = a
-						.getInt(R.styleable.StickyListHeadersListView_android_requiresFadingEdge,
-								0);
-				if (fadingEdge == 0x00001000) {
-					mList.setVerticalFadingEdgeEnabled(false);
-					mList.setHorizontalFadingEdgeEnabled(true);
-				} else if (fadingEdge == 0x00002000) {
-					mList.setVerticalFadingEdgeEnabled(true);
-					mList.setHorizontalFadingEdgeEnabled(false);
-				} else {
-					mList.setVerticalFadingEdgeEnabled(false);
-					mList.setHorizontalFadingEdgeEnabled(false);
-				}
-				mList.setCacheColorHint(a
-						.getColor(
-								R.styleable.StickyListHeadersListView_android_cacheColorHint,
-								mList.getCacheColorHint()));
-				if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
-					mList.setChoiceMode(a
-							.getInt(R.styleable.StickyListHeadersListView_android_choiceMode,
-									mList.getChoiceMode()));
-				}
-				mList.setDrawSelectorOnTop(a
-						.getBoolean(
-								R.styleable.StickyListHeadersListView_android_drawSelectorOnTop,
-								false));
-				mList.setFastScrollEnabled(a
-						.getBoolean(
-								R.styleable.StickyListHeadersListView_android_fastScrollEnabled,
-								mList.isFastScrollEnabled()));
-				if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
-					mList.setFastScrollAlwaysVisible(a
-							.getBoolean(
-									R.styleable.StickyListHeadersListView_android_fastScrollAlwaysVisible,
-									mList.isFastScrollAlwaysVisible()));
-				}
-				mList.setScrollBarStyle(a
-						.getInt(R.styleable.StickyListHeadersListView_android_scrollbarStyle,
-								0));
-				final Drawable selector = a
-						.getDrawable(R.styleable.StickyListHeadersListView_android_listSelector);
-				if (selector != null) {
-					mList.setSelector(selector);
-				}
-				mList.setScrollingCacheEnabled(a
-						.getBoolean(
-								R.styleable.StickyListHeadersListView_android_scrollingCache,
-								mList.isScrollingCacheEnabled()));
-				final Drawable divider = a
-						.getDrawable(R.styleable.StickyListHeadersListView_android_divider);
-				if (divider != null) {
-					mDivider = divider;
-				}
-				mDividerHeight = a
-						.getDimensionPixelSize(
-								R.styleable.StickyListHeadersListView_android_dividerHeight,
-								mDividerHeight);
-
-				// StickyListHeaders attributes
-				mAreHeadersSticky = a.getBoolean(
-						R.styleable.StickyListHeadersListView_hasStickyHeaders,
-						true);
-				mIsDrawingListUnderStickyHeader = a
-						.getBoolean(
-								R.styleable.StickyListHeadersListView_isDrawingListUnderStickyHeader,
-								true);
-            } finally {
-				a.recycle();
-			}
-		}
-
-        mList.setVerticalScrollBarEnabled(isVerticalScrollBarEnabled());
-        mList.setHorizontalScrollBarEnabled(isHorizontalScrollBarEnabled());
-    }
-
-	@Override
-	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-		super.onMeasure(widthMeasureSpec, heightMeasureSpec);
-		measureHeader(mHeader);
-	}
-
-	private void ensureHeaderHasCorrectLayoutParams(View header) {
-		ViewGroup.LayoutParams lp = header.getLayoutParams();
-		if (lp == null) {
-			lp = new LayoutParams(LayoutParams.MATCH_PARENT, LayoutParams.WRAP_CONTENT);
-		} else if (lp.height == LayoutParams.MATCH_PARENT) {
-			lp.height = LayoutParams.WRAP_CONTENT;
-		}
-		header.setLayoutParams(lp);
-	}
-
-	private void measureHeader(View header) {
-		if (header != null) {
-			final int width = getMeasuredWidth() - mPaddingLeft - mPaddingRight;
-			final int parentWidthMeasureSpec = MeasureSpec.makeMeasureSpec(
-					width, MeasureSpec.EXACTLY);
-			final int parentHeightMeasureSpec = MeasureSpec.makeMeasureSpec(0,
-					MeasureSpec.UNSPECIFIED);
-			measureChild(header, parentWidthMeasureSpec,
-					parentHeightMeasureSpec);
-		}
-	}
-
-	@Override
-	protected void onLayout(boolean changed, int left, int top, int right,
-			int bottom) {
-		mList.layout(0, 0, mList.getMeasuredWidth(), getHeight());
-		if (mHeader != null) {
-			MarginLayoutParams lp = (MarginLayoutParams) mHeader
-					.getLayoutParams();
-			int headerTop = lp.topMargin
-					+ (mClippingToPadding ? mPaddingTop : 0);
-			// The left parameter must for some reason be set to 0.
-			// I think it should be set to mPaddingLeft but apparently not
-			mHeader.layout(mPaddingLeft, headerTop, mHeader.getMeasuredWidth()
-					+ mPaddingLeft, headerTop + mHeader.getMeasuredHeight());
-		}
-	}
-
-	@Override
-	protected void dispatchDraw(Canvas canvas) {
-		// Only draw the list here.
-		// The header should be drawn right after the lists children are drawn.
-		// This is done so that the header is above the list items
-		// but below the list decorators (scroll bars etc).
-		drawChild(canvas, mList, 0);
-	}
-
-	// Reset values tied the header. also remove header form layout
-	// This is called in response to the data set or the adapter changing
-	private void clearHeader() {
-		if (mHeader != null) {
-			removeView(mHeader);
-			mHeader = null;
-			mHeaderId = null;
-			mHeaderPosition = null;
-			mHeaderOffset = null;
-
-			// reset the top clipping length
-			mList.setTopClippingLength(0);
-			updateHeaderVisibilities();
-		}
-	}
-
-	private void updateOrClearHeader(int firstVisiblePosition) {
-		final int adapterCount = mAdapter == null ? 0 : mAdapter.getCount();
-		if (adapterCount == 0 || !mAreHeadersSticky) {
-			return;
-		}
-
-		final int headerViewCount = mList.getHeaderViewsCount();
-		final int realFirstVisibleItem = firstVisiblePosition - headerViewCount;
-
-		// It is not a mistake to call getFirstVisiblePosition() here.
-		// Most of the time getFixedFirstVisibleItem() should be called
-		// but that does not work great together with getChildAt()
-		final boolean doesListHaveChildren = mList.getChildCount() != 0;
-		final boolean isFirstViewBelowTop = doesListHaveChildren && mList.getFirstVisiblePosition() == 0
-				&& mList.getChildAt(0).getTop() > 0;
-		final boolean isFirstVisibleItemOutsideAdapterRange = realFirstVisibleItem > adapterCount - 1
-				|| realFirstVisibleItem < 0;
-		if (!doesListHaveChildren || isFirstVisibleItemOutsideAdapterRange
-				|| isFirstViewBelowTop) {
-			clearHeader();
-			return;
-		}
-
-		updateHeader(realFirstVisibleItem);
-	}
-
-	private void updateHeader(int firstVisiblePosition) {
-
-		// check if there is a new header should be sticky
-		if (mHeaderPosition == null || mHeaderPosition != firstVisiblePosition) {
-			mHeaderPosition = firstVisiblePosition;
-			final long headerId = mAdapter.getHeaderId(firstVisiblePosition);
-			if (mHeaderId == null || mHeaderId != headerId) {
-				mHeaderId = headerId;
-				final View header = mAdapter.getHeaderView(mHeaderPosition,
-						mHeader, this);
-				if (mHeader != header) {
-					if (header == null) {
-						throw new NullPointerException("header may not be null");
-					}
-					swapHeader(header);
-				}
-				
-				ensureHeaderHasCorrectLayoutParams(mHeader);
-				measureHeader(mHeader);
-
-				// Reset mHeaderOffset to null ensuring
-				// that it will be set on the header and
-				// not skipped for performance reasons.
-				mHeaderOffset = null;
-			}
-		}
-
-		int headerOffset = 0;
-
-		// Calculate new header offset
-		// Skip looking at the first view. it never matters because it always
-		// results in a headerOffset = 0
-		int headerBottom = mHeader.getMeasuredHeight()
-				+ (mClippingToPadding ? mPaddingTop : 0);
-		for (int i = 0; i < mList.getChildCount(); i++) {
-			final View child = mList.getChildAt(i);
-			final boolean doesChildHaveHeader = child instanceof WrapperView
-					&& ((WrapperView) child).hasHeader();
-			final boolean isChildFooter = mList.containsFooterView(child);
-			if (child.getTop() >= (mClippingToPadding ? mPaddingTop : 0)
-					&& (doesChildHaveHeader || isChildFooter)) {
-				headerOffset = Math.min(child.getTop() - headerBottom, 0);
-				break;
-			}
-		}
-
-		setHeaderOffet(headerOffset);
-
-		if (!mIsDrawingListUnderStickyHeader) {
-			mList.setTopClippingLength(mHeader.getMeasuredHeight()
-					+ mHeaderOffset);
-		}
-
-		updateHeaderVisibilities();
-	}
-
-	private void swapHeader(View newHeader) {
-		if (mHeader != null) {
-			removeView(mHeader);
-		}
-		mHeader = newHeader;
-		addView(mHeader);
-		mHeader.setOnClickListener(new OnClickListener() {
-
-			@Override
-			public void onClick(View v) {
-				if (mOnHeaderClickListener != null) {
-					mOnHeaderClickListener.onHeaderClick(
-							StickyListHeadersListView.this, mHeader,
-							mHeaderPosition, mHeaderId, true);
-				}
-			}
-
-		});
-	}
-
-	// hides the headers in the list under the sticky header.
-	// Makes sure the other ones are showing
-	private void updateHeaderVisibilities() {
-		int top;
-		if (mHeader != null) {
-			top = mHeader.getMeasuredHeight()
-					+ (mHeaderOffset != null ? mHeaderOffset : 0);
-		} else {
-			top = mClippingToPadding ? mPaddingTop : 0;
-		}
-		int childCount = mList.getChildCount();
-		for (int i = 0; i < childCount; i++) {
-			View child = mList.getChildAt(i);
-			if (child instanceof WrapperView) {
-				WrapperView wrapperViewChild = (WrapperView) child;
-				if (wrapperViewChild.hasHeader()) {
-					View childHeader = wrapperViewChild.mHeader;
-					if (wrapperViewChild.getTop() < top) {
-						if (childHeader.getVisibility() != View.INVISIBLE) {
-							childHeader.setVisibility(View.INVISIBLE);
-						}
-					} else {
-						if (childHeader.getVisibility() != View.VISIBLE) {
-							childHeader.setVisibility(View.VISIBLE);
-						}
-					}
-				}
-			}
-		}
-	}
-
-	// Wrapper around setting the header offset in different ways depending on
-	// the API version
-	@SuppressLint("NewApi")
-	private void setHeaderOffet(int offset) {
-		if (mHeaderOffset == null || mHeaderOffset != offset) {
-			mHeaderOffset = offset;
-			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
-				mHeader.setTranslationY(mHeaderOffset);
-			} else {
-				MarginLayoutParams params = (MarginLayoutParams) mHeader
-						.getLayoutParams();
-				params.topMargin = mHeaderOffset;
-				mHeader.setLayoutParams(params);
-			}
-		}
-	}
-
-	private class AdapterWrapperDataSetObserver extends DataSetObserver {
-
-		@Override
-		public void onChanged() {
-			clearHeader();
-		}
-
-		@Override
-		public void onInvalidated() {
-			clearHeader();
-		}
-
-	}
-
-	private class WrapperListScrollListener implements OnScrollListener {
-
-		@Override
-		public void onScroll(AbsListView view, int firstVisibleItem,
-				int visibleItemCount, int totalItemCount) {
-			if (mOnScrollListenerDelegate != null) {
-				mOnScrollListenerDelegate.onScroll(view, firstVisibleItem,
-						visibleItemCount, totalItemCount);
-			}
-			updateOrClearHeader(mList.getFixedFirstVisibleItem());
-		}
-
-		@Override
-		public void onScrollStateChanged(AbsListView view, int scrollState) {
-			if (mOnScrollListenerDelegate != null) {
-				mOnScrollListenerDelegate.onScrollStateChanged(view,
-						scrollState);
-			}
-		}
-
-	}
-
-	private class WrapperViewListLifeCycleListener implements WrapperViewList.LifeCycleListener {
-
-		@Override
-		public void onDispatchDrawOccurred(Canvas canvas) {
-			// onScroll is not called often at all before froyo
-			// therefor we need to update the header here as well.
-			if (Build.VERSION.SDK_INT < Build.VERSION_CODES.FROYO) {
-				updateOrClearHeader(mList.getFixedFirstVisibleItem());
-			}
-			if (mHeader != null) {
-				if (mClippingToPadding) {
-					canvas.save();
-					canvas.clipRect(0, mPaddingTop, getRight(), getBottom());
-					drawChild(canvas, mHeader, 0);
-					canvas.restore();
-				} else {
-					drawChild(canvas, mHeader, 0);
-				}
-			}
-		}
-
-	}
-
-	private class AdapterWrapperHeaderClickHandler implements
-			AdapterWrapper.OnHeaderClickListener {
-
-		@Override
-		public void onHeaderClick(View header, int itemPosition, long headerId) {
-			mOnHeaderClickListener.onHeaderClick(
-					StickyListHeadersListView.this, header, itemPosition,
-					headerId, false);
-		}
-
-	}
-
-	private boolean isStartOfSection(int position) {
-		return position == 0
-				|| mAdapter.getHeaderId(position) != mAdapter
-						.getHeaderId(position - 1);
-	}
-
-	private int getHeaderOverlap(int position) {
-		boolean isStartOfSection = isStartOfSection(position);
-		if (!isStartOfSection) {
-			View header = mAdapter.getHeaderView(position, null, mList);
-			if (header == null) {
-				throw new NullPointerException("header may not be null");
-			}
-			ensureHeaderHasCorrectLayoutParams(header);
-			measureHeader(header);
-			return header.getMeasuredHeight();
-		}
-		return 0;
-	}
-
-	/* ---------- StickyListHeaders specific API ---------- */
-
-	public void setAreHeadersSticky(boolean areHeadersSticky) {
-		mAreHeadersSticky = areHeadersSticky;
-		if (!areHeadersSticky) {
-			clearHeader();
-		} else {
-			updateOrClearHeader(mList.getFixedFirstVisibleItem());
-		}
-		// invalidating the list will trigger dispatchDraw()
-		mList.invalidate();
-	}
-
-	public boolean areHeadersSticky() {
-		return mAreHeadersSticky;
-	}
-
-	/**
-	 * Use areHeadersSticky() method instead
-	 */
-	@Deprecated
-	public boolean getAreHeadersSticky() {
-		return areHeadersSticky();
-	}
-
-	public void setDrawingListUnderStickyHeader(
-			boolean drawingListUnderStickyHeader) {
-		mIsDrawingListUnderStickyHeader = drawingListUnderStickyHeader;
-		// reset the top clipping length
-		mList.setTopClippingLength(0);
-	}
-
-	public boolean isDrawingListUnderStickyHeader() {
-		return mIsDrawingListUnderStickyHeader;
-	}
-
-	public void setOnHeaderClickListener(
-			OnHeaderClickListener onHeaderClickListener) {
-		mOnHeaderClickListener = onHeaderClickListener;
-		if (mAdapter != null) {
-			if (mOnHeaderClickListener != null) {
-				mAdapter.setOnHeaderClickListener(new AdapterWrapperHeaderClickHandler());
-			} else {
-				mAdapter.setOnHeaderClickListener(null);
-			}
-		}
-	}
-
-	public View getListChildAt(int index) {
-		return mList.getChildAt(index);
-	}
-
-	public int getListChildCount() {
-		return mList.getChildCount();
-	}
-
-	/**
-	 * Use the method with extreme caution!! Changing any values on the
-	 * underlying ListView might break everything.
-	 * 
-	 * @return the ListView backing this view.
-	 */
-	public ListView getWrappedList() {
-		return mList;
-	}
-
-	/* ---------- ListView delegate methods ---------- */
-
-	public void setAdapter(StickyListHeadersAdapter adapter) {
-		if (adapter == null) {
-			mList.setAdapter(null);
-			clearHeader();
-			return;
-		}
-		if (mAdapter != null) {
-			mAdapter.unregisterDataSetObserver(mDataSetObserver);
-		}
-
-		if (adapter instanceof SectionIndexer) {
-			mAdapter = new SectionIndexerAdapterWrapper(getContext(), adapter);
-		} else {
-			mAdapter = new AdapterWrapper(getContext(), adapter);
-		}
-		mDataSetObserver = new AdapterWrapperDataSetObserver();
-		mAdapter.registerDataSetObserver(mDataSetObserver);
-
-		if (mOnHeaderClickListener != null) {
-			mAdapter.setOnHeaderClickListener(new AdapterWrapperHeaderClickHandler());
-		} else {
-			mAdapter.setOnHeaderClickListener(null);
-		}
-
-		mAdapter.setDivider(mDivider, mDividerHeight);
-
-		mList.setAdapter(mAdapter);
-		clearHeader();
-	}
-
-	public StickyListHeadersAdapter getAdapter() {
-		return mAdapter == null ? null : mAdapter.mDelegate;
-	}
-
-	public void setDivider(Drawable divider) {
-		mDivider = divider;
-		if (mAdapter != null) {
-			mAdapter.setDivider(mDivider, mDividerHeight);
-		}
-	}
-
-	public void setDividerHeight(int dividerHeight) {
-		mDividerHeight = dividerHeight;
-		if (mAdapter != null) {
-			mAdapter.setDivider(mDivider, mDividerHeight);
-		}
-	}
-
-	public Drawable getDivider() {
-		return mDivider;
-	}
-
-	public int getDividerHeight() {
-		return mDividerHeight;
-	}
-
-	public void setOnScrollListener(OnScrollListener onScrollListener) {
-		mOnScrollListenerDelegate = onScrollListener;
-	}
-
-	public void setOnItemClickListener(OnItemClickListener listener) {
-		mList.setOnItemClickListener(listener);
-	}
-
-	public void setOnItemLongClickListener(OnItemLongClickListener listener) {
-		mList.setOnItemLongClickListener(listener);
-	}
-
-    public void addHeaderView(View v, Object data, boolean isSelectable) {
-        mList.addHeaderView(v, data, isSelectable);
-    }
-
-	public void addHeaderView(View v) {
-		mList.addHeaderView(v);
-	}
-
-	public void removeHeaderView(View v) {
-		mList.removeHeaderView(v);
-	}
-
-	public int getHeaderViewsCount() {
-		return mList.getHeaderViewsCount();
-	}
-
-	public void addFooterView(View v) {
-		mList.addFooterView(v);
-	}
-
-	public void removeFooterView(View v) {
-		mList.removeFooterView(v);
-	}
-
-	public int getFooterViewsCount() {
-		return mList.getFooterViewsCount();
-	}
-
-	public void setEmptyView(View v) {
-		mList.setEmptyView(v);
-	}
-
-	public View getEmptyView() {
-		return mList.getEmptyView();
-	}
-
-    @Override
-    public void setVerticalScrollBarEnabled(boolean verticalScrollBarEnabled) {
-        mList.setVerticalScrollBarEnabled(verticalScrollBarEnabled);
-    }
-
-    @Override
-    public void setHorizontalScrollBarEnabled(boolean horizontalScrollBarEnabled) {
-        mList.setHorizontalScrollBarEnabled(horizontalScrollBarEnabled);
-    }
-
-	@TargetApi(Build.VERSION_CODES.FROYO)
-	public void smoothScrollBy(int distance, int duration) {
-		requireSdkVersion(Build.VERSION_CODES.FROYO);
-		mList.smoothScrollBy(distance, duration);
-	}
-
-	@TargetApi(Build.VERSION_CODES.HONEYCOMB)
-	public void smoothScrollByOffset(int offset) {
-		requireSdkVersion(Build.VERSION_CODES.HONEYCOMB);
-		mList.smoothScrollByOffset(offset);
-	}
-
-	@SuppressLint("NewApi")
-	@TargetApi(Build.VERSION_CODES.FROYO)
-	public void smoothScrollToPosition(int position) {
-		if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
-			mList.smoothScrollToPosition(position);
-		} else {
-			int offset = mAdapter == null ? 0 : getHeaderOverlap(position);
-			offset -= mClippingToPadding ? 0 : mPaddingTop;
-			mList.smoothScrollToPositionFromTop(position, offset);
-		}
-	}
-
-	@TargetApi(Build.VERSION_CODES.FROYO)
-	public void smoothScrollToPosition(int position, int boundPosition) {
-		requireSdkVersion(Build.VERSION_CODES.FROYO);
-		mList.smoothScrollToPosition(position, boundPosition);
-	}
-
-	@TargetApi(Build.VERSION_CODES.HONEYCOMB)
-	public void smoothScrollToPositionFromTop(int position, int offset) {
-		requireSdkVersion(Build.VERSION_CODES.HONEYCOMB);
-		offset += mAdapter == null ? 0 : getHeaderOverlap(position);
-		offset -= mClippingToPadding ? 0 : mPaddingTop;
-		mList.smoothScrollToPositionFromTop(position, offset);
-	}
-
-	@TargetApi(Build.VERSION_CODES.HONEYCOMB)
-	public void smoothScrollToPositionFromTop(int position, int offset,
-			int duration) {
-		requireSdkVersion(Build.VERSION_CODES.HONEYCOMB);
-		offset += mAdapter == null ? 0 : getHeaderOverlap(position);
-		offset -= mClippingToPadding ? 0 : mPaddingTop;
-		mList.smoothScrollToPositionFromTop(position, offset, duration);
-	}
-
-	public void setSelection(int position) {
-		setSelectionFromTop(position, 0);
-	}
-
-	public void setSelectionAfterHeaderView() {
-		mList.setSelectionAfterHeaderView();
-	}
-
-	public void setSelectionFromTop(int position, int y) {
-		y += mAdapter == null ? 0 : getHeaderOverlap(position);
-		y -= mClippingToPadding ? 0 : mPaddingTop;
-		mList.setSelectionFromTop(position, y);
-	}
-
-	public void setSelector(Drawable sel) {
-		mList.setSelector(sel);
-	}
-
-	public void setSelector(int resID) {
-		mList.setSelector(resID);
-	}
-
-	public int getFirstVisiblePosition() {
-		return mList.getFirstVisiblePosition();
-	}
-
-	public int getLastVisiblePosition() {
-		return mList.getLastVisiblePosition();
-	}
-
-	public void setChoiceMode(int choiceMode) {
-		mList.setChoiceMode(choiceMode);
-	}
-
-	public void setItemChecked(int position, boolean value) {
-		mList.setItemChecked(position, value);
-	}
-
-	@TargetApi(Build.VERSION_CODES.HONEYCOMB)
-	public int getCheckedItemCount() {
-		requireSdkVersion(Build.VERSION_CODES.HONEYCOMB);
-		return mList.getCheckedItemCount();
-	}
-
-	@TargetApi(Build.VERSION_CODES.FROYO)
-	public long[] getCheckedItemIds() {
-		requireSdkVersion(Build.VERSION_CODES.FROYO);
-		return mList.getCheckedItemIds();
-	}
-
-	public int getCheckedItemPosition() {
-		return mList.getCheckedItemPosition();
-	}
-
-	public SparseBooleanArray getCheckedItemPositions() {
-		return mList.getCheckedItemPositions();
-	}
-
-	public int getCount() {
-		return mList.getCount();
-	}
-
-	public Object getItemAtPosition(int position) {
-		return mList.getItemAtPosition(position);
-	}
-
-	public long getItemIdAtPosition(int position) {
-		return mList.getItemIdAtPosition(position);
-	}
-
-	public void setOnCreateContextMenuListener(OnCreateContextMenuListener l) {
-		mList.setOnCreateContextMenuListener(l);
-	}
-
-	public boolean showContextMenu() {
-		return mList.showContextMenu();
-	}
-
-	public void invalidateViews() {
-		mList.invalidateViews();
-	}
-
-	@Override
-	public void setClipToPadding(boolean clipToPadding) {
-		if (mList != null) {
-			mList.setClipToPadding(clipToPadding);
-		}
-		mClippingToPadding = clipToPadding;
-	}
-
-	@Override
-	public void setPadding(int left, int top, int right, int bottom) {
-		mPaddingLeft = left;
-		mPaddingTop = top;
-		mPaddingRight = right;
-		mPaddingBottom = bottom;
-
-		if (mList != null) {
-			mList.setPadding(left, top, right, bottom);
-		}
-		super.setPadding(0, 0, 0, 0);
-		requestLayout();
-	}
-
-	@Override
-	public int getPaddingLeft() {
-		return mPaddingLeft;
-	}
-
-	@Override
-	public int getPaddingTop() {
-		return mPaddingTop;
-	}
-
-	@Override
-	public int getPaddingRight() {
-		return mPaddingRight;
-	}
-
-	@Override
-	public int getPaddingBottom() {
-		return mPaddingBottom;
-	}
-
-	public void setFastScrollEnabled(boolean fastScrollEnabled) {
-		mList.setFastScrollEnabled(fastScrollEnabled);
-	}
-
-	/**
-	 * @see android.widget.AbsListView#setFastScrollAlwaysVisible(boolean)
-	 * @throws ApiLevelTooLowException on pre-Honeycomb device.
-	 */
-	@TargetApi(Build.VERSION_CODES.HONEYCOMB)
-	public void setFastScrollAlwaysVisible(boolean alwaysVisible) {
-		requireSdkVersion(Build.VERSION_CODES.HONEYCOMB);
-		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
-			mList.setFastScrollAlwaysVisible(alwaysVisible);
-		}
-	}
-
-	/**
-	 * @see android.widget.AbsListView#isFastScrollAlwaysVisible()
-	 * @return true if the fast scroller will always show. False on pre-Honeycomb devices.
-	 */
-	@TargetApi(Build.VERSION_CODES.HONEYCOMB)
-	public boolean isFastScrollAlwaysVisible(){
-		if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
-			return false;
-		}
-		return mList.isFastScrollAlwaysVisible();
-	}
-
-	private void requireSdkVersion(int versionCode) {
-		if (Build.VERSION.SDK_INT < versionCode) {
-			throw new ApiLevelTooLowException(versionCode);
-		}
-	}
-
-	public int getPositionForView(View view) {
-		return mList.getPositionForView(view);
-	}
-	
-
-	
-	
-	
-    private int mTotalCount;
-    private int mItemOffsetY[];
-    private boolean scrollIsComputed = false;
-    private int mHeight;
-    
-    
-	public int getListHeight() {
-        return mHeight;
-    }
-
-    public void computeScrollY() {
-        mHeight = 0;
-        mTotalCount = getAdapter().getCount();
-
-        int sectionHeight = 0;
-        int itemHeight = 0;
-        int desiredWidth = MeasureSpec.makeMeasureSpec(getWidth(), MeasureSpec.AT_MOST);
-
-        if (mItemOffsetY == null) {
-            mItemOffsetY = new int[mTotalCount];
-        }
-        for (int i = 0; i < mTotalCount; ++i) {
-
-            if (i == 0) {
-                View view = getAdapter().getView(i, null, this);
-                view.measure(desiredWidth, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
-                sectionHeight = view.getMeasuredHeight();
-                mItemOffsetY[i] = mHeight;
-                mHeight += sectionHeight;
-            } else if (i == 1) {
-                View view = getAdapter().getView(i, null, this);
-                view.measure(desiredWidth, MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
-                itemHeight = view.getMeasuredHeight();
-                mItemOffsetY[i] = mHeight;
-                mHeight += itemHeight;
-            } else {
-                int type = getAdapter().getItemViewType(i);
-                switch (type) {
-                case ContactsAdapter.TYPE_CONTACT:
-                    mHeight += itemHeight;
-                case ContactsAdapter.TYPE_HEADER:
-                    mHeight += sectionHeight;
-                }
-                mItemOffsetY[i] = mHeight;
-                mHeight += sectionHeight;
-            }
-
-            System.out.println(mHeight);
-        }
-        scrollIsComputed = true;
-    }
-
-    public boolean scrollYIsComputed() {
-        return scrollIsComputed;
-    }
-
-    public int getComputedScrollY() {
-        int pos, nScrollY, nItemY;
-        View view = null;
-        pos = getFirstVisiblePosition();
-        view = getChildAt(0);
-        nItemY = view.getTop();
-        nScrollY = mItemOffsetY[pos] - nItemY;
-        return nScrollY;
-    }
-
-}
diff --git a/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/WrapperView.java b/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/WrapperView.java
deleted file mode 100644
index 9ee36ad50..000000000
--- a/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/WrapperView.java
+++ /dev/null
@@ -1,150 +0,0 @@
-package cx.ring.views.stickylistheaders;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.drawable.Drawable;
-import android.os.Build;
-import android.view.View;
-import android.view.ViewGroup;
-import android.view.ViewParent;
-
-/**
- * 
- * the view that wrapps a divider header and a normal list item. The listview sees this as 1 item
- * 
- * @author Emil Sjölander
- */
-public class WrapperView extends ViewGroup {
-
-	View mItem;
-	Drawable mDivider;
-	int mDividerHeight;
-	View mHeader;
-	int mItemTop;
-
-	WrapperView(Context c) {
-		super(c);
-	}
-
-	public boolean hasHeader() {
-		return mHeader != null;
-	}
-	
-	public View getItem() {
-		return mItem;
-	}
-	
-	public View getHeader() {
-		return mHeader;
-	}
-
-	void update(View item, View header, Drawable divider, int dividerHeight) {
-		
-		//every wrapperview must have a list item
-		if (item == null) {
-			throw new NullPointerException("List view item must not be null.");
-		}
-
-		//only remove the current item if it is not the same as the new item. this can happen if wrapping a recycled view
-		if (this.mItem != item) {
-			removeView(this.mItem);
-			this.mItem = item;
-			final ViewParent parent = item.getParent();
-			if(parent != null && parent != this) {
-				if(parent instanceof ViewGroup) {
-					((ViewGroup) parent).removeView(item);
-				}
-			}
-			addView(item);
-		}
-
-		//same logik as above but for the header
-		if (this.mHeader != header) {
-			if (this.mHeader != null) {
-				removeView(this.mHeader);
-			}
-			this.mHeader = header;
-			if (header != null) {
-				addView(header);
-			}
-		}
-
-		if (this.mDivider != divider) {
-			this.mDivider = divider;
-			this.mDividerHeight = dividerHeight;
-			invalidate();
-		}
-	}
-
-	@Override
-	protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
-		int measuredWidth = MeasureSpec.getSize(widthMeasureSpec);
-		int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(measuredWidth,
-				MeasureSpec.EXACTLY);
-		int measuredHeight = 0;
-		
-		//measure header or divider. when there is a header visible it acts as the divider
-		if (mHeader != null) {
-			ViewGroup.LayoutParams params = mHeader.getLayoutParams();
-			if (params != null && params.height > 0) {
-				mHeader.measure(childWidthMeasureSpec,
-						MeasureSpec.makeMeasureSpec(params.height, MeasureSpec.EXACTLY));
-			} else {
-				mHeader.measure(childWidthMeasureSpec,
-						MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
-			}
-			measuredHeight += mHeader.getMeasuredHeight();
-		} else if (mDivider != null) {
-			measuredHeight += mDividerHeight;
-		}
-		
-		//measure item
-		ViewGroup.LayoutParams params = mItem.getLayoutParams();
-		if (params != null && params.height > 0) {
-			mItem.measure(childWidthMeasureSpec,
-					MeasureSpec.makeMeasureSpec(params.height, MeasureSpec.EXACTLY));
-		} else {
-			mItem.measure(childWidthMeasureSpec,
-					MeasureSpec.makeMeasureSpec(0, MeasureSpec.UNSPECIFIED));
-		}
-		measuredHeight += mItem.getMeasuredHeight();
-
-		setMeasuredDimension(measuredWidth, measuredHeight);
-	}
-
-	@Override
-	protected void onLayout(boolean changed, int l, int t, int r, int b) {
-
-		l = 0;
-		t = 0;
-		r = getWidth();
-		b = getHeight();
-
-		if (mHeader != null) {
-			int headerHeight = mHeader.getMeasuredHeight();
-			mHeader.layout(l, t, r, headerHeight);
-			mItemTop = headerHeight;
-			mItem.layout(l, headerHeight, r, b);
-		} else if (mDivider != null) {
-			mDivider.setBounds(l, t, r, mDividerHeight);
-			mItemTop = mDividerHeight;
-			mItem.layout(l, mDividerHeight, r, b);
-		} else {
-			mItemTop = t;
-			mItem.layout(l, t, r, b);
-		}
-	}
-
-	@Override
-	protected void dispatchDraw(Canvas canvas) {
-		super.dispatchDraw(canvas);
-		if (mHeader == null && mDivider != null) {
-			// Drawable.setBounds() does not seem to work pre-honeycomb. So have
-			// to do this instead
-			if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
-				canvas.clipRect(0, 0, getWidth(), mDividerHeight);
-			}
-			mDivider.draw(canvas);
-		}
-	}
-}
diff --git a/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/WrapperViewList.java b/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/WrapperViewList.java
deleted file mode 100644
index c0c95d7e6..000000000
--- a/ring-android/app/src/main/java/cx/ring/views/stickylistheaders/WrapperViewList.java
+++ /dev/null
@@ -1,176 +0,0 @@
-package cx.ring.views.stickylistheaders;
-
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.List;
-
-import android.content.Context;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.os.Build;
-import android.util.AttributeSet;
-import android.view.View;
-import android.widget.AbsListView;
-import android.widget.ListView;
-
-class WrapperViewList extends ListView {
-
-	interface LifeCycleListener {
-		void onDispatchDrawOccurred(Canvas canvas);
-	}
-
-	private LifeCycleListener mLifeCycleListener;
-	private List<View> mFooterViews;
-	private int mTopClippingLength;
-	private Rect mSelectorRect = new Rect();// for if reflection fails
-	private Field mSelectorPositionField;
-	private boolean mClippingToPadding = true;
-
-	public WrapperViewList(Context context, AttributeSet attrs) {
-		super(context, attrs);
-
-		// Use reflection to be able to change the size/position of the list
-		// selector so it does not come under/over the header
-		try {
-			Field selectorRectField = AbsListView.class.getDeclaredField("mSelectorRect");
-			selectorRectField.setAccessible(true);
-			mSelectorRect = (Rect) selectorRectField.get(this);
-
-			if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
-				mSelectorPositionField = AbsListView.class.getDeclaredField("mSelectorPosition");
-				mSelectorPositionField.setAccessible(true);
-			}
-		} catch (NoSuchFieldException e) {
-			e.printStackTrace();
-		} catch (IllegalArgumentException e) {
-			e.printStackTrace();
-		} catch (IllegalAccessException e) {
-			e.printStackTrace();
-		}
-	}
-
-	@Override
-	public boolean performItemClick(View view, int position, long id) {
-		if (view instanceof WrapperView) {
-			view = ((WrapperView) view).mItem;
-		}
-		return super.performItemClick(view, position, id);
-	}
-
-	private void positionSelectorRect() {
-		if (!mSelectorRect.isEmpty()) {
-			int selectorPosition = getSelectorPosition();
-			if (selectorPosition >= 0) {
-				int firstVisibleItem = getFixedFirstVisibleItem();
-				View v = getChildAt(selectorPosition - firstVisibleItem);
-				if (v instanceof WrapperView) {
-					WrapperView wrapper = ((WrapperView) v);
-					mSelectorRect.top = wrapper.getTop() + wrapper.mItemTop;
-				}
-			}
-		}
-	}
-
-	private int getSelectorPosition() {
-		if (mSelectorPositionField == null) { // not all supported andorid
-												// version have this variable
-			for (int i = 0; i < getChildCount(); i++) {
-				if (getChildAt(i).getBottom() == mSelectorRect.bottom) {
-					return i + getFixedFirstVisibleItem();
-				}
-			}
-		} else {
-			try {
-				return mSelectorPositionField.getInt(this);
-			} catch (IllegalArgumentException e) {
-				e.printStackTrace();
-			} catch (IllegalAccessException e) {
-				e.printStackTrace();
-			}
-		}
-		return -1;
-	}
-
-	@Override
-	protected void dispatchDraw(Canvas canvas) {
-		positionSelectorRect();
-		if (mTopClippingLength != 0) {
-			canvas.save();
-			Rect clipping = canvas.getClipBounds();
-			clipping.top = mTopClippingLength;
-			canvas.clipRect(clipping);
-			super.dispatchDraw(canvas);
-			canvas.restore();
-		} else {
-			super.dispatchDraw(canvas);
-		}
-		mLifeCycleListener.onDispatchDrawOccurred(canvas);
-	}
-
-	void setLifeCycleListener(LifeCycleListener lifeCycleListener) {
-		mLifeCycleListener = lifeCycleListener;
-	}
-
-	@Override
-	public void addFooterView(View v) {
-		super.addFooterView(v);
-		if (mFooterViews == null) {
-			mFooterViews = new ArrayList<View>();
-		}
-		mFooterViews.add(v);
-	}
-
-	@Override
-	public boolean removeFooterView(View v) {
-		if (super.removeFooterView(v)) {
-			mFooterViews.remove(v);
-			return true;
-		}
-		return false;
-	}
-
-	boolean containsFooterView(View v) {
-		if (mFooterViews == null) {
-			return false;
-		}
-		return mFooterViews.contains(v);
-	}
-
-	void setTopClippingLength(int topClipping) {
-		mTopClippingLength = topClipping;
-	}
-
-	int getFixedFirstVisibleItem() {
-		int firstVisibleItem = getFirstVisiblePosition();
-		if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
-			return firstVisibleItem;
-		}
-
-		// first getFirstVisiblePosition() reports items
-		// outside the view sometimes on old versions of android
-		for (int i = 0; i < getChildCount(); i++) {
-			if (getChildAt(i).getBottom() >= 0) {
-				firstVisibleItem += i;
-				break;
-			}
-		}
-
-		// work around to fix bug with firstVisibleItem being to high
-		// because list view does not take clipToPadding=false into account
-		// on old versions of android
-		if (!mClippingToPadding && getPaddingTop() > 0 && firstVisibleItem > 0) {
-			if (getChildAt(0).getTop() > 0) {
-				firstVisibleItem -= 1;
-			}
-		}
-
-		return firstVisibleItem;
-	}
-
-	@Override
-	public void setClipToPadding(boolean clipToPadding) {
-		mClippingToPadding = clipToPadding;
-		super.setClipToPadding(clipToPadding);
-	}
-
-}
diff --git a/ring-android/app/src/main/jni/Android.mk b/ring-android/app/src/main/jni/Android.mk
index 37b98fd96..7f63ff540 100644
--- a/ring-android/app/src/main/jni/Android.mk
+++ b/ring-android/app/src/main/jni/Android.mk
@@ -43,7 +43,6 @@ MY_DATADIR=/data/data
 ARCH=$(ANDROID_ABI)
 
 CPP_STATIC= $(ANDROID_NDK)/sources/cxx-stl/gnu-libstdc++$(CXXSTL)/libs/$(ARCH)/libgnustl_static.a \
-			$(RING_CONTRIB)/lib/libexpat.a \
 			$(RING_CONTRIB)/lib/libgnutls.a \
 			$(RING_CONTRIB)/lib/libnettle.a \
 			$(RING_CONTRIB)/lib/libhogweed.a \
@@ -82,12 +81,14 @@ LOCAL_C_INCLUDES += $(LOCAL_PATH) \
 
 LOCAL_MODULE := libringjni
 
+LOCAL_CFLAGS   +=   -fpic
+
 LOCAL_CPPFLAGS += 	-DCCPP_PREFIX \
 					-DPROGSHAREDIR=\"${MY_DATADIR}/ring\" \
 					-DHAVE_CONFIG_H \
 					-DHAVE_SPEEX_CODEC \
 					-DHAVE_GSM_CODEC \
-					-w -frtti \
+					-w -frtti -fpic \
 					-std=c++11 -fexceptions -fpermissive \
 					-DAPP_NAME=\"Ring\" \
 					-DSWIG_JAVA_ATTACH_CURRENT_THREAD_AS_DAEMON \
@@ -127,7 +128,7 @@ LOCAL_LDLIBS += -lpj-arm-unknown-linux-androideabi \
 				-lresample-arm-unknown-linux-androideabi
 endif
 
-LOCAL_LDLIBS	+=	-lexpat -lhogweed \
+LOCAL_LDLIBS	+=	-lhogweed \
 					-lspeexdsp -lvorbisfile -lyaml-cpp \
 					-lFLAC -liax  -lnettle \
 					-logg \
diff --git a/ring-android/app/src/main/jni/Application.mk b/ring-android/app/src/main/jni/Application.mk
index 687227df3..fe89ddc37 100644
--- a/ring-android/app/src/main/jni/Application.mk
+++ b/ring-android/app/src/main/jni/Application.mk
@@ -30,7 +30,7 @@
 
 
 
-APP_PLATFORM := android-15
+APP_PLATFORM := android-16
 APP_OPTIM := debug
 APP_ABI := ${ANDROID_ABI}
 NDK_TOOLCHAIN_VERSION := 4.9
diff --git a/ring-android/app/src/main/res/drawable-hdpi/ic_action_end_call.png b/ring-android/app/src/main/res/drawable-hdpi/ic_action_end_call.png
deleted file mode 100644
index c807fe94bde1f0ada7e592bb7b5710f4f7f87175..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 442
zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4mJh`hH$2z?F<YIk|nMYCBgY=CFO}lsSJ)O
z`AMk?p1FzXsX?iUDV2pMQ*9U+7-KwL978H@y_tTt_mF`=>)VX}B@F=#yh|7~61F#7
zy|<8&YeBCr!$k(x7N$!L+#IY2Y^}wFPcpg79amI%`+Ld7h>4H)JpZr3$^ZsG*1woC
z{r0xAnz|Ox=7>)3-u+6P>u~C9>2q$`wKI<}aK{BskvZxiTe)n7<thnhE2l4$K8u8i
zsCP=r3j8}eaeqcv^hb8-TDOw^3hU|h@fvs1Q@qt)EnpPN7k^OK@FR~;Tm62p)lQj&
zN9{f)?+)|(A1!V9p?v<b)}bZ0Bemng=QouXU)#nlIpN!xi7oFZefu!`V^@#H!cO+w
znad}YWb3%kd3<RbS0|$;tNu5Y9lZyidrtfDcfDYh{mR~)MGNbrq$AI7)JrvNYMfzq
zPKf!ebiAGXmY>@Kg(a@N3(Nd*Zqlh^mN%X?vgWF&7nb+#*z|Z-`?`;^PtP})>`2@7
o>C7xuUbcEia5yk9oSx6X%#ddk$MF6&moG@n)78&qol`;+05syZxBvhE

diff --git a/ring-android/app/src/main/res/drawable-hdpi/ic_call_end_black_24dp.png b/ring-android/app/src/main/res/drawable-hdpi/ic_call_end_black_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..3f193b16abe85c5a9fd67a141cfd0dc32e6af8e7
GIT binary patch
literal 303
zcmeAS@N?(olHy`uVBq!ia0y~yU{C>J4i*Lm25-&)VFm_<Z=NoWAr*{o&+YY6P84Z)
zm_8-b)j;s#F=>II8(rPYHf-7=+B|isz#AovD2|PH%cd_8kkQe7(>s09q+{|do%S2g
z)}(kaB|WxTZhe2|^oghc8cnoJ6%92t4UG;v+tsrmBl=O?_VahF!VOa!PIPhS?_yr2
zyisS;!~WS<elDK2Y?m|pE2*e?!SAn6<M6fimVFy-pk}h}iACx4kPFGa)<1qqMm}pk
zZJnyH>3MMZlmG+yGS@jQuOB)+l)3nG+6C=iyVvEyn?!!M{S)?XO1-Ui^GyZEK93_U
zEBCAM27U0KadCFlro0I0xI;WgUg=HkNxC>Scw>y-_vU>JbyKfRlYLXMhk=2C!PC{x
JWt~$(69A(ugAf1!

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-hdpi/ic_call_end_black_36dp.png b/ring-android/app/src/main/res/drawable-hdpi/ic_call_end_black_36dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..cac21f2190d82e689f071635b86dd526979fd77d
GIT binary patch
literal 403
zcmeAS@N?(olHy`uVBq!ia0y~yU@!w=4i*Lm1~s2WVGIn6QJyZ2Ar*{oFWF`XCrTWD
zs9mzU^n%)jn+Ff>l9mw>=giuw`@?9Lg~ki>04*s|-j2zAN_^|~)wJ{Nd((7v%C0EU
z?gXyAZyzYMKR&FuoUQfwuk+^npMKLnu}SCjCd1%mTV-#=+}@&@ye;B#VXVGRq<AZ@
zPUX7nV@qazi~4Y?ZN&y&{n(Ai1-9*e&?}L&ey;h#P1B<HbxHkRw3;(hSZqz_q`lv-
z$coRsR+v#Nn;vuN^BMNQP5FA#(+#p+MYg?atkl)iEq)g*+WPgZhUv>rjho4#e_z(M
zH~kHB`5W=_*EhxkmaiYJKYHju<bsE70?~5X?^dyyAN5FjD0SamEc)@|6G^9KOa(e)
z!>{H}yumMPG4aPySL@KLTV{C3GSARG`*rS>09oGUI?IEf?%aKhH+gpTOOZ2wr~Q7i
z!K&}a9Iu0a*58TVeP!$I-633jRZEtyw2P{e%lhq~5;-k3@|$ps(!*UB#P+OWU|?YI
MboFyt=akR{0DoP&QUCw|

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-hdpi/ic_call_end_white_24dp.png b/ring-android/app/src/main/res/drawable-hdpi/ic_call_end_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..625b827c44e7d15ce385221dbea4c1733c5ea8f7
GIT binary patch
literal 314
zcmeAS@N?(olHy`uVBq!ia0y~yU{C>J4i*Lm25-&)VFm_9Mo$;VkP61PXKeMI0~wBe
zd_G~F(#5U~KbR)*g(;R8NUmLED5=`p+hX9c?yA=<$4AF9HauRe5WB}k>FcNKO9Y>P
zx%0Z>_MHF5wx|6!-uTaTm_u~cm5A*1$CQkDk^{cA>=*K05;OU#s(Xkehhtl2U!_t=
z_Y_YbIg_KTW!vXmR!E%8EA;AZdH-EWVLOu(ie;~RE;jGF<~=j_jg&}k#x%7&XN~m5
zJ7NQ0I<$qxJv=V3XG4>q^^aDC{kj)_3BL%u^09iEzPQ%JtBo2H9$iaetlgBFSKzJL
zk(bq9ClWEScDm!CW$$J<$KSExm*)|BA99E@^-FJW@u|Fa$4B4016q_s?nyg5%QtiR
Tet04S0|SGntDnm{r-UW|F|&n8

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-hdpi/ic_call_white_24dp.png b/ring-android/app/src/main/res/drawable-hdpi/ic_call_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..4dc5065155baeba719d76845d4398431c289cde0
GIT binary patch
literal 340
zcmeAS@N?(olHy`uVBq!ia0y~yU{C>J4i*Lm25-&)VFm_9X-^l&5D(tB2RG_D2QnOg
z_}{j(#kIYw#lXX+CCER)p!|W_TxoCJh;tXpUo6<UQo_Kag27N=W0&~^sjS50j6XYe
z&ib<L%3I6q{r*y?d7LG?k0xylIeC&d_0p`O!*-eGMThw^`HP%AZfQ5hZ1CI9x-(%~
zo$5}72Q#;{-6`<7weF6<rPX~CrHg7VgdRU3yIkd!#LtAOH`Kj99W~u({Bw~*lJmX{
zfox-S`zM)#yOV?JG%hKY9c=j%pjdcvN>ze|!lENejhhy_J(^ef_kh5~ug8?P%S^mn
zz;eZ7&xV!x5=v~LU+uL@JmzfnIg-C-(*lp~hif(|o>x2^k?P*4{V&N>D$L^HT*t7*
v$+L84*<93~Vx1O|Je#Y!MWQ$L8|x4MzgFurmu_QVU|{fc^>bP0l+XkKc@&W~

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-hdpi/ic_chat_white_24dp.png b/ring-android/app/src/main/res/drawable-hdpi/ic_chat_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..d2cfdf1f6b334c05a8fa691c25ca0f91ffb179c7
GIT binary patch
literal 168
zcmeAS@N?(olHy`uVBq!ia0y~yU{C>J4i*Lm25-&)VFm_<d`}n05Rc<`uR8KI7;vy0
zuzk7xcaz$lDL<ONrma~Xbxq>NJ#|f8h7kU8sk!;Z7k2bcC^R*5+Q;*ggLM+etg5GT
zCak-W`$%Q&#8+AK>rXHRJT&}teZ^a@6F29-esN7<BkRgUy%k5px3w|4@F*l@J!5H2
XS-1Un-UC$z1_lOCS3j3^P6<r_<~2e`

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-hdpi/ic_lock_white_24dp.png b/ring-android/app/src/main/res/drawable-hdpi/ic_lock_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..cd4f04aa1d0283908902ad51f4a9289d5ef7dc13
GIT binary patch
literal 309
zcmeAS@N?(olHy`uVBq!ia0y~yU{C>J4i*Lm25-&)VFm_<Kb|g*Ar*{ouNZn62THJB
zXplIlu*Bn^U4&N0uBjbjW=;jnnOjbCwfRUl{SRw-AhxCNSd~X&OJ?7MB!|N-l{SK{
zcdplppEEhU_HTem>DRkf*Mp+JUz?h%Y}s&UZv7!e_GSB?T}{-uV#dmyY#Z)&?|_dr
zk5r@k+((x_vK&(k2<~e=xBT_K@+VPO7v`PZ{=a$is{r{gVehU#SY~CyAg=x0+u%p{
zg}#twUeAKQ7HNo1+9GqRMMb;aX>()4N|#5LV!O8Q&XH0pybySC?h(gm*X^?Gvf_6$
zWlSzcm{rR?Qi$W>J!@9~t=#!@hizBHi6t_t!tcHD3EFq_;rnoB`FZLe=SwDjb7Wv(
OVDNPHb6Mw<&;$VQj)aN;

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-hdpi/ic_send_black_24dp.png b/ring-android/app/src/main/res/drawable-hdpi/ic_send_black_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..7be098fdeaff304a7a5d9c6b86d43035e540c26c
GIT binary patch
literal 250
zcmeAS@N?(olHy`uVBq!ia0y~yU{C>J4i*Lm25-&)VFm_<gPtyqAr*{ouO8%Wa*%L&
zn7)bCgE48*)f;jzBHu7Y9W>g;VDsQ%Kc}#|_nrq855H{Gceu0hk{Ltni<#FN)ZFs!
zoO~+a@XYaa1mD?k=3aTJg$BkU4rMEvN>*^b43NIGP^!q8HKm1Z#UqhA(~}&c^0|xp
z45sq&PMBep&+%8xiv7h0#@LtB79260*Z9{d%Kz{Ozu@m8r%SfjaLfOfN#5gb<>uhl
z)9^-u_oamVB}1W4Nh~T!J|{XZPU!pjHh$YZ`6|X)oF%H4WN*qaFfcH9y85}Sb4q9e
E0MRjE*8l(j

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-hdpi/ic_share_white_24dp.png b/ring-android/app/src/main/res/drawable-hdpi/ic_share_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..b09a6926de5aa48dee59265aadac32da236f9e1c
GIT binary patch
literal 397
zcmeAS@N?(olHy`uVBq!ia0y~yU{C>J4i*Lm25-&)VFm`q5KkA!5D(tB2W_(_2TCwp
zP!A~)?9{8{Q4-@i$Ca7&Qenr72P#S-iuDJx94>ekyj0@Yb;a>7bI=8o7jFWtH@Upl
z*pV5ed+C~t^dau2WhbkxUs($N7d=yves|aQWy<qk|I^6XDOM?SadYtXhbI;)mKqoB
z&@a_L75p*cmD`l1@0zdhU)4CwssEMtOO95~PN~Jk2V%3?e$BI7weIco`O|!kzKGeF
z^<r<ap;c+|tYt~Fjc>K>n-$s_xH3y~i_NCY2ix2E+$5vQs#9%F1y29<B56vxUzT1`
zhS%LLnRDKyF<mmZ%BpjfP6cgUvLWMMTO;phKG(=sdApO1w$1!-?1DM()EnH>YmK(#
z7=1fb=WEMct1n}ocQ9R++s{3+uX0^}g0KI=)nZRqMox<|6??j}Lcvtn(qu`Rayxg>
z<%x&w;@?~`6sx>aBD&97`sbWaSGq*~=k(Mcj(@Pmyux%{^fv|u1_n=8KbLh*2~7Zv
CvaJsQ

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-hdpi/ic_videocam_white_24dp.png b/ring-android/app/src/main/res/drawable-hdpi/ic_videocam_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..d83e0d50c3dd1aa384568f658f815b35819462a0
GIT binary patch
literal 173
zcmeAS@N?(olHy`uVBq!ia0y~yU{C>J4i*Lm25-&)VFm_<5>FS$5Rc=@2@<S}6AYUE
zzxpr#Po2%?&-%6{-OQI4%=&+%DQkyZ|9{aLY^DOa0nB%1$QzikvNiVp^xx<hkgQ?K
zk;l`@CfgwGywEX%sqTtG6sy_QMf0mTCv`=##4lSKWw_|uf5yOLcYd#L+MXZ{vV?(Q
Z`>EcOA$prnGcYhPc)I$ztaD0e0stz4Jfr{s

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-ldrtl-hdpi/ic_send_black_24dp.png b/ring-android/app/src/main/res/drawable-ldrtl-hdpi/ic_send_black_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..e65515d62b7a9a164a64a2ccd02cc013725d5d93
GIT binary patch
literal 250
zcmeAS@N?(olHy`uVBq!ia0y~yU{C>J4i*Lm25-&)VFm_<gPtyqAr*{ouN~xVau8^J
zXwDkYwuLFSBfa(88aLsM3_1<X>W|m_R6cpQBFW<X`8sJ~&c7MkE=>O$_I&F?FLv2b
z?Q1PrUvI6hT7BpcPgdM)H;u#x^9~=BP&_b0@le5u18{Uks?_)V6esQ(D<fn~4{u~}
ze&4b%VEJYD7xRp!KMh!BDs{!kxBpR%`Ld@sSB4*-zPIF_kxIj@{mKo$6kC2NHh@vf
uFU7W5ifu(F8j4Od9Gm}t)Asj^)pc+Bs2&UL`NP1#z~JfX=d#Wzp$Py$ZEp<#

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-ldrtl-mdpi/ic_send_black_24dp.png b/ring-android/app/src/main/res/drawable-ldrtl-mdpi/ic_send_black_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..d65d82294b084f83fb9395fb0b06e000b42a6191
GIT binary patch
literal 204
zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4i*Lm2CurW#S9D#lRaG=Ln;{0UfIZd$Uws7
z;q<084r-m^jcXdD_ZWJ#Fdkyi)A-jU{A+2m-t=qp|J+G=aQ-cOk4}u{{>IKzt(+1z
z8YX@{416v}co>*`Si~|~n57z-D_zo`>fIM}P&WH=z{_7Raap0-0dCfQ83vh^S5#hV
z{t@$>FB_5Z@8bQ-4*ZuK_)RV_2)}4#i<-b9cH^P{174>oMv|UCV@@$JFfe$!`njxg
HN@xNArX5Hk

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-ldrtl-xhdpi/ic_send_black_24dp.png b/ring-android/app/src/main/res/drawable-ldrtl-xhdpi/ic_send_black_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..3a25fbb866a157759a4c33cad2d9feda224b0e1e
GIT binary patch
literal 341
zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4i*LmhQHi~JPZtsGM+AuAr*{ouLpV^c93v=
z7`*hR)1=lJ+tw{!Yi)4(P|9(xYphpTMMPU14!M5eH_zW$`+mC2DT7$U&teITYHJ^K
z8t<-bm?eCEN=?yw_Og_3YZ!SNTu$0tIL~!OCCcmA??>ktb6)<^$a7dM(bzTFt&@49
z#;&PMA2rNC0=hGs-3l34-Hmvym=^^09B9*%Yn2v{W1qj8>7vH<i{f!R7D_XSc23j!
z)?>x`OQX8$hw(r0jJj3Y9}Jo9En{X-?fl}t=sV+gA<rxMXD9Zx-50O2XT6ZH>%ebK
zfgiq+eO=9LpXJM>H?b8nNuA+;Vfcvsi^3ev3km<CTiHG{OPygqkrg%R|Em=TckR^M
tU-kb3bJg`SW~n!49)Hp=W{mmGcHn)H;Xlb_M+OE422WQ%mvv4FO#oeijYI$d

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-ldrtl-xxhdpi/ic_send_black_24dp.png b/ring-android/app/src/main/res/drawable-ldrtl-xxhdpi/ic_send_black_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..89afc01b5cfe42c07deefa9861ac6ce686b1b70d
GIT binary patch
literal 414
zcmeAS@N?(olHy`uVBq!ia0y~yVDJE84i*LmhW}5h&oD4Brh2+KhEy=Vonf!%5-8*5
zZ@6s!DWB6q9p+Wj9Ga)8UicZjktIt+r*W3RG>2@hEam)pE?;ML-l@5NHovQSAMcz$
z=X^dD&D7;;by|2KwcS0fg;BjHV};_p&~=iR|E%rn|Kf8wN>=jaj6iSIkc=B$PXsS1
z``%Qso20hH{gmz!_e-r`Ja$cx(M)_e(TMx&?TL$8+hPot38r^#IV;?o`po0knTcOs
zPCV1yzl1aNtw*Go+{<?JcNXdMd8fT_b@}zARod@nYA>r*mC9${7LP-`DZgYsPW;Qp
zIdR`t=^qgfKgBQ9kK6gQ$M#y}66dmKmOftJ&e@8~Y&dCTYh-vl>{ox({`qnN`{)0+
z7cbnOSLN`xuF9dd%Hi{uhG(83l1!&|Fu$4sNBj4co|(TdQc{I|&Vt44S6aU`?3$pt
z;GfPLeu)nSdMs-$US$5&`lX>x@vrPT{U!T<{%(EJ!0)p>KtqIU|A{-3G(*b|$ucl7
OFnGH9xvX<aXaWGVBD~H3

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-ldrtl-xxxhdpi/ic_send_black_24dp.png b/ring-android/app/src/main/res/drawable-ldrtl-xxxhdpi/ic_send_black_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..def070fd7fad796ee6d7e18f40132e919fd707b1
GIT binary patch
literal 551
zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4i*Lm29JsRH#0CWzVmc(45?szJImTH+EK#I
zf8vd;+6JmRj4d0pBbYJ|TsSDS;IIu>1k;s0F4HDV@tk-g(&^H(K$WjsC&#F89SQeo
z-1+Ur<bR*nKR6>Z!SuU2N0S0alfs4t=gi~{Q~QML0)rAf+N0a1@CW~JHC|9-)EaDZ
z{Ld1X^cUj2GacsY{+e=9@|SC}(uId=g1zTXXi70N_8#+DFt<<5_K&Ll6%#4_Mm6_8
z3$7FjUdUL(l2!84C-UH*&0T8y9cE{DE@NWcpHcEp+GTRM!{UuX7c$PU%#z765uS4@
z@?ypu785Ds#+#aMi<2dK`w~s8$}aZ&IAwkAX7XHDsmE@`rbjdCj34v`mqnz`3)k;W
zo9xe)KBrIZuw=NC_o9=f#~!;U7aZ%%sH!<%aBQk;a7e+in-R}GMKaa@I23*EMrtps
z;E5AF?8)k1dcVhPI4?adW5UGiIZOU^^uAM<opSlF%71msyZ*W$=9VBw$-Dkm8r{Dy
z&X=@Yen`G*<}m{e*`o#;M-5hVURaX;Ys(79pLXvSy%#^n^eZe^Yk}iTt_6-e>y}<w
z;KOR75zJUS%{<1`gFSUu-sPq5brv{Ea=kFGy*<^K_f&*KxJVAGiN@u#vAm~39Jap(
zar_&PL=`nAiBDPBkQXV<l@TBhi4_jHo$T!Qo(EpAwvAz6U|{fc^>bP0l+XkK)p+hz

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-mdpi/ic_action_end_call.png b/ring-android/app/src/main/res/drawable-mdpi/ic_action_end_call.png
deleted file mode 100644
index ee026de7c7f77e8b0685edd1e7f69bc9577a27a4..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 342
zcmeAS@N?(olHy`uVBq!ia0y~yU{C;I4mJh`hT^KKFANL}k|nMYCBgY=CFO}lsSJ)O
z`AMk?p1FzXsX?iUDV2pMQ*9U+7=C!VIEGZ*dJ}Sy_mF}>>#=yY1B@{ZtP&2-3wo{E
zif=IPau9#PVCBHRqMwCl?NhF0e?P?)?G%W5cX#)6;iiKL2LEI?eQ7V0>G!ZI{5vVg
z&Rn@6iR<JKi=T6v`7Zvx(|9Gog`rjVl4PQJ&@NXKg-erI0&bK>{?7Z}5WJLaqMhpl
z$1~<0(og1|UbV<DaB-2{&X&W9T6r49it8lVvXvL#6Mml=&Yi#0%|$deV9i&j<05UM
zs`gt~HMzf)yB}uU+#z#K(m*opkJ1LUjd}_TjNMF36P+5*Nne<`UQ?mqbG1s2@8qC_
uO#T(|VOa;c<R94{NHCD-+0MYsaQ2n^y#0UgCNeNEFnGH9xvX<aXaWGK5Qeq@

diff --git a/ring-android/app/src/main/res/drawable-mdpi/ic_call_end_black_24dp.png b/ring-android/app/src/main/res/drawable-mdpi/ic_call_end_black_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..3253503d67171641f77f31ddfbe224a30d5357a9
GIT binary patch
literal 235
zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4i*Lm2CurW#S9D#n><|{Ln;{Gp4snpI6#K=
zfxcBov0GtqLBUmV0T%Y;8WzVt?fMJ5?K<q5w>WR-ljT}^*ZK=<l%vZO7sZ%&0!@z;
zES~)KZ7)9m^?TH7J=<9k8Y0h*$<2wrtgvzY;x9J~ma10^xkOhje6xFl^465dtm{)9
zGj^G=rr&#%zx>s@<nOOo-mUs@SmB<o{(dQ&;y232R`QnKPTN>N-7(IW%RI~^vUL5L
odGee_&g}apOIu#~WxkIgDJ8z5j7$GE0|Nttr>mdKI;Vst0FJU<?EnA(

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-mdpi/ic_call_end_black_36dp.png b/ring-android/app/src/main/res/drawable-mdpi/ic_call_end_black_36dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..3f193b16abe85c5a9fd67a141cfd0dc32e6af8e7
GIT binary patch
literal 303
zcmeAS@N?(olHy`uVBq!ia0y~yU{C>J4i*Lm25-&)VFm_<Z=NoWAr*{o&+YY6P84Z)
zm_8-b)j;s#F=>II8(rPYHf-7=+B|isz#AovD2|PH%cd_8kkQe7(>s09q+{|do%S2g
z)}(kaB|WxTZhe2|^oghc8cnoJ6%92t4UG;v+tsrmBl=O?_VahF!VOa!PIPhS?_yr2
zyisS;!~WS<elDK2Y?m|pE2*e?!SAn6<M6fimVFy-pk}h}iACx4kPFGa)<1qqMm}pk
zZJnyH>3MMZlmG+yGS@jQuOB)+l)3nG+6C=iyVvEyn?!!M{S)?XO1-Ui^GyZEK93_U
zEBCAM27U0KadCFlro0I0xI;WgUg=HkNxC>Scw>y-_vU>JbyKfRlYLXMhk=2C!PC{x
JWt~$(69A(ugAf1!

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-mdpi/ic_call_end_white_24dp.png b/ring-android/app/src/main/res/drawable-mdpi/ic_call_end_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..378272ffc15f451e392eb042f955e24c02630763
GIT binary patch
literal 235
zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4i*Lm2CurW#S9D#n><|{Lo5W}9^9{Wgpq;$
z!+XOMHH&km96ZIXky>z0dBy4d?^Giy1m-#Nm^C|g-hIFtFzMZ{`^P`Lo*r*M-B<G6
zXHT_%vntuo*;bhveR_0orfu<0&(piSTMN0wuWk8sc2f3I>EB^nd}m(U_UgjgOH+?d
zdGjme<x<D^r-%K7)L&I)UI;Ijc@L()i`{P1@)x_5aC7r12ldW%if(;pQg}A|iAvn?
n@;pAb_m9){y=Q&?NXM_6{oq@E<jV~V3=9mOu6{1-oD!M<m9}e$

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-mdpi/ic_call_white_24dp.png b/ring-android/app/src/main/res/drawable-mdpi/ic_call_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..77f9de5e3ccb30fb6e580454412c98e2f6c553c1
GIT binary patch
literal 246
zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4i*Lm2CurW#S9D#dp%toLo5W(9^9+voG8KY
z;5$!Jl2u@up35DF$?tqF9Zb!LX*r^zqUYd}zd*2ie#^lJLN6}4`v1Og;<@^k=hDAz
z1V5kJ>hFB^M54}17rxq)iBAgjU%K+CPg=Ni#d6)9TLr$Zk(|9F*iBBnBFIfIx+2s~
zuT{@ac|I@m7UlV}AyFTXE_yn{m3^wMYt4lZ3yPkeXiWR#o_PPrOi|wceS43ZY~#J~
z{mt|l=XQD5AIUMBEB#aPRpi#!H+sdD_s$4^-)a6#PFQG7Is*d(gQu&X%Q~loCIDM+
BXXpR`

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-mdpi/ic_chat_white_24dp.png b/ring-android/app/src/main/res/drawable-mdpi/ic_chat_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..dac4cb9fc4d84eea7685251640e7778ac51daaa6
GIT binary patch
literal 133
zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4i*Lm2CurW#S9D#KAtX)Ar_~T6Bcm)kpJ=j
zX}!~ftM&CQY==%cK2UXHp4d>tYw_2^l=tvO&nwp*e$P;2h?}tN;nDi|5?<aT=?a&o
mG@F`CnC2=i!6wMSpmdkF>ez=Ze;61T7(8A5T-G@yGywqUeJ<Ak

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-mdpi/ic_lock_white_24dp.png b/ring-android/app/src/main/res/drawable-mdpi/ic_lock_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..1127f87f70b7a4ec8a37919cac19e9a8c27b005e
GIT binary patch
literal 208
zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4i*Lm2CurW#S9D#(>+}rLo808y>OC~$x(#m
zg8i`vlO`MNNL7{SQb=2{?9oBqnaxJWpZf}I%?-G+OY}<iF6&2sB_dZ|oyKPQnR7)*
z!k=Fye7m?>FA457iC9>jTdQ+vL73*cwGW@nVOx{`tIeO$x%&L3>JMLz$ZYG^n|x;d
z!I0q7I`SsUN?SfVYAZRZ%b(d&dglMj>6;Gd?Yw`ddEVR4JB{{D<IeZ~dZYBe(02v~
O1_n=8KbLh*2~7YvtXbRu

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-mdpi/ic_send_black_24dp.png b/ring-android/app/src/main/res/drawable-mdpi/ic_send_black_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..83156aa38fc3644b0e394e8ab32ffd916be57ea6
GIT binary patch
literal 205
zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4i*Lm2CurW#S9D#Q#@T9Ln;`LUO33x<RH-c
z@O}%^5(dMIeb-OlV!Cl6h;v&5yRDCp+Q(KK{a-siO`L!8<I_4;DRH+jd7H*o?Wspu
zH%^sqeb#(KrqND;eU}33EeCeC7nV!Y7hG;+w7YIN!T!Q?2j0Gv4eAG666@6GUgl<>
z7_#!t-T8VwHfuJ!wUl0y*~shC!e*2t{epux!^(+y<Nqe{;!rn92JS=87#J8BJYD@<
J);T3K0RY@@Ok4l}

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-mdpi/ic_share_white_24dp.png b/ring-android/app/src/main/res/drawable-mdpi/ic_share_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..e944fd70c428619696e7eb6fd8787959df32a774
GIT binary patch
literal 268
zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4i*Lm2CurW#S9D#mpxq^Lo5W39z3tb!YIS=
z;QpI~?+(sa{v_4)NyqDy@P@?4l55Il&z|&2tE*@$pM}!WyRv-IS@z2_{j81E_vt^H
zpXr%;?ANTo_K<brr6-=a1)iNGzcX>l<qglB7fPq*>^y#BU$L@tY_Vat>Gc`AHppzw
z@JuzTmA$`Xqg?6|uJzkg1O3#@4dt))JXI50JZs;f-LaliE?+S=Dp{s`c<$L1r@Op^
zgTuoX>q+N*e0pJ}_<28*MRShynYTV(k#=zTo#ZPIJ>Mz5x-ikY!%C%(hi8lGNB26$
ZkhN?QS&tXkFfcGMc)I$ztaD0e0sydXa#R2S

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-mdpi/ic_videocam_white_24dp.png b/ring-android/app/src/main/res/drawable-mdpi/ic_videocam_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..d146209a5145962cfa3226918807fb663d2c7267
GIT binary patch
literal 131
zcmeAS@N?(olHy`uVBq!ia0y~yV2}V|4i*Lm2CurW#URSl#WBR<baH|Ot4s5L_5Y8V
z)E8)p1eiWx6nOeye!>FAB{GX9YVZm?U6N7JP#{$(_3v^F^GQFYtCv;SwZC;(HwOO=
hT;rK6@_>~=*sgb#$Ez6|7#J8BJYD@<);T3K0RVT~D%Jo1

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xhdpi/ic_action_end_call.png b/ring-android/app/src/main/res/drawable-xhdpi/ic_action_end_call.png
deleted file mode 100644
index aef6bb0ce4a9486ed31329ced32a9dbc9959398f..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 552
zcmeAS@N?(olHy`uVBq!ia0y~yU~m9o4mJh`hE<t`_ZS!$BuiW)N`mv#O3D+9QW+dm
z@{>{(JaZG%Q-e|yQz{EjrrIztFrM;saSW-r^=8Jw!e#>j*NN}-6ht1dX&iWx$K`R#
zqv-sTc_I_IVi@+di#RZgFt7$N+$>!p$#-OfkdVR8{IuiWc*NdJ-s04y#DD~TxUUc}
zf4S?OgM4+@j7ND-KD8}cmN7Nx>N1vqMROiFx*Hij%vdyGQd4V)%Cfjt2Co^_rdLm@
z8LMbd40@&E;UVqgp#PHn?&a(TcQ?PniKhY%RsQiPjH-;?y@5w4@SKvv`PbpLN4B$Y
zS4giG&r<o>V>hpa^}d#lqB!@0CzbQ|pT8l!Y}V}i&NBkj!uof*-R1VwSi)4)zUtnK
zMIk%ZJ>B)KAU#Fzyz}{qzG4pMsh{UhyZR$Ji*eJ0gXh2I?EJ;k*L3$pz?7nIQ~zw;
zUU%Cr`d@9pEx)3VEPae!w+vetZm*jED)sX9c}my59%$R^azMy-i^pv{mLD~VUQV1D
zGPitexe79OPvlr3`~20x!+*+iH&5fp2)E#kxt*iR6yu*H#m^LTdyPtd)1H)?$U6<~
zH@~kv+y2<(#1}7t=sm0N@Xr;!@rKoB(bS)EkKVj<i+v$~_^+zlHt`pGOXmFY)StRy
p@r>7sC+9rxKnib$4Uu&$5)AJ+CUSRK1ge8%JYD@<);T3K0RR|3>qGzm

diff --git a/ring-android/app/src/main/res/drawable-xhdpi/ic_call_end_black_24dp.png b/ring-android/app/src/main/res/drawable-xhdpi/ic_call_end_black_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..d10890edcce32dd7b95e691c8e8c9d951c30bb55
GIT binary patch
literal 371
zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4i*LmhQHi~JPZtsR-P`7Ar*{oFKp}*4wPVh
zkgs;uZy~?HqN%<S*EzUniEsG8DB>#e)lo&Ekz>(~9L0_##Uw?sjhh8nq;;osd|Sq;
z5#_t7)#_H&%<ji6CEu-|&iyYV;W<g=<g=F+uU6fjH#;)o=T~)YZsXwXF&lNSUvd<;
z`RMz#zvk<WO7;vr<1ZJ2mR5T4&&dd@yOkY!dQXv;+nqxFR`>h9y>qs%UOnNo=&rK4
zhDK|Dw(7rG5xV1L`iGC{&ay|I`psewxA)26<f#eb{2V6yK1<L323te-x6o|9mPjl1
zly&X>Z`qq-CKozy-Pm|)#@}8(ou3l*-_qVTet+{rsCM7t&b=@GI?4B4^_y~Rn@Qk|
zh@-DxtIxAqV#!x6ww_<zYkJDR@MoKh)~ugBLpmcnL2h;XKKFMoBi+x(ewY0?UBz>f
c%1_?48Z}4aJ7oPC7#J8lUHx3vIVCg!0M0a_-~a#s

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xhdpi/ic_call_end_black_36dp.png b/ring-android/app/src/main/res/drawable-xhdpi/ic_call_end_black_36dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..44794a9b9d2dbd58656bf4a0d107de3e830dafb4
GIT binary patch
literal 515
zcmeAS@N?(olHy`uVBq!ia0y~yVDJE84i*LmhW}5h&oD4Bp7L~Y45?szdwI9_w0xQ4
zAFnT7wzOqMZr}s~-b;=d2H74;oV;2uHn?~PCr=P_6mU%NbyXE|xgucVI&uFrdD&$O
zCY=j1inT;#TDY_;*B#n;`0UZQ#fOb!)}Ock@Qgd&bCL=Ksb+tbG|0KK!?XC=)Tw7@
z8)x20HlK4Ty?2t+)fXl&CQ2$6U6zyDu=7)5Y1Lg5-6wa{mCIHK3rfeBsfHxT$8L(N
z^Qy8H)Y=ocd&;LHU#e9_woLza#Qk8{`PQCV<7e9(*-JC8FN!<6{%ZEcyxE7(?MObv
zubBM*waC(=9h*K}*R6QCCXYAC<km~4V{=ch%T~MHcqabUH23&t|KEP~*S;%iwB1$C
zy5-E>OGoCL{ZtT<oU*ap>d&(Y>zyt-O8(BVXHb34vhc)$6?4Oyq7FNSvap6<EeKpO
zYrzAX&7q<uhigJvYai|t*xUQ*hMvoNxwUcJfwMO|$>r|j4y<0>dt(W!`_ob*qjb?D
zs<syrHFw$cp6T?cT7Ue~)HlYGlPAv&F<aue)MTgF#K{v)mbx$fI{WO2lRi?LqXe&2
zN>68Ad#vT?-{qcxvuuUM%qPxeJ}qnhq$A2T>e&o!zl@MjSonHQn(z86QlszCKMn>4
O1_n=8KbLh*2~7YU6X$UN

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xhdpi/ic_call_end_white_24dp.png b/ring-android/app/src/main/res/drawable-xhdpi/ic_call_end_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..a4fe6889d159cac861cac4f885ae3ec28cd9ca44
GIT binary patch
literal 389
zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4i*LmhQHi~JPZtsKAtX)Ar*{o&l-9&CCVKC
z_<wP?`4w(~>?}cJ=7lxPyn7oKbu6k<RBTBQaP@W;aCLTZHo0+4fJN6-#O>`)j#l60
zd{@mEF09$JdG}`NrsuzJ*UKBW&Oe!AB$zrQ)y#6S&r~+~wWceAmK|a9Uecj(S8d1I
z`IdbvKSt}z7<$i_cbNFN!K!Z4&Ga+e3uZj&S`cg0_=>HksPUe*>L;Jcs(r3YOuH>2
zmz@Y+)OOD@GyOo)-11x1O70>rH*q`;$#~zZWGH*$gGah~NBiANH*HtWKVakgBbedU
znHt8f&@W9)RoWVfyiUvu6il31Umaq87yF&(4rk`P!tB$+8+xNdCp8&7^0*<=QOTs!
zWiscz;K7*|i3}e%I{M9hC%AC(hDZlRyX6r_uDus@RM$$G&~Q57=f3NViYFC!t4xra
tme6k7CLqg^%VyBP$dk}e&sf9se8%y!qK{WGGB7YOc)I$ztaD0e0s!;aoi+df

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xhdpi/ic_call_white_24dp.png b/ring-android/app/src/main/res/drawable-xhdpi/ic_call_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..ef45e933a99b720cc5f6127e6da22bc2fa679244
GIT binary patch
literal 420
zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4i*LmhQHi~JPZts*`6+rArYK!5AM$jPLw(R
z@cnHu9SH+(_3ciAN!ogaIwIV$*-a09mU@>>Uo;_fj!JnzjLy<-4!@<&-s=xMlXH5x
zQq?<4;pD@|1vW=2?q&S@b8g!6iO-(-1S+N6&{e&usG>VXR;flTrIpXlGV-C+{LsjS
zjpw~1A4=Qhr?gtxsc$-DXJ;QVg_rAx?Q~wT9m;DDcdaQnbH8fOBw41mubQWYEZ<4K
z_#AcZhsz>=*KZY$kJfHFsJgLu&ZYxqos%{-Jno5@yl2w^tJ)-Yi_}Jbl~t#hPMdU;
z-V70|IAyz0?EDl~EfpuTCr6XJbTXr^cx<^5!o?W7;HWs?jl^Deoh%`XS1P+g3V$&(
z3TAGfVqzy#%GP({wK<d0A17ZX_ufXe)HyB=M?7YUh~DCv^SQ61{=yTDf}=M~c;!CK
zlS{t1MWf)9gbDYy9S`hHw7X<3rKv<dP!zQjo>Zo6Z82}darb?n=Bn9u?nn$TE?!p0
Z=s77q>`q0569WSSgQu&X%Q~loCIEZ{tuz1t

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xhdpi/ic_chat_white_24dp.png b/ring-android/app/src/main/res/drawable-xhdpi/ic_chat_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..ace0bef32ec67afbe5af73db991c704650d394bc
GIT binary patch
literal 205
zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4i*LmhQHi~JPZsBQ#@T9Ln02py&TEs;2_ZQ
z(2lq7rGwDvg948QpSrf3+2d0Zx#%^+|LJFxlBzFGSahgiwe&>=?x(^f7oy}90vw9B
z@^4wy@VU`bw1NK&n+wy${U;boA2hGeNR*$*xRK%SB>8&RdX@s?1@$M{?(kTc1r#-k
zaq<^vFjw-QaIJpwhcn>`KZE*y<~4uVK73MovWLSmzq&x1uT*av!`<&n3=9kmp00i_
I>zopr0A!#`<p2Nx

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xhdpi/ic_lock_white_24dp.png b/ring-android/app/src/main/res/drawable-xhdpi/ic_lock_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..ad8d91a99f9986d0cef4c876f1c3fa43696daeb6
GIT binary patch
literal 372
zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4i*LmhQHi~JPZts)}AhoAr*{ouO0NVa+Enx
z`0>Fcz517`NgqR9J|-wh*o9tjJ`x|e#QFRMMT1CHr6qgX7V5otD*eSdacS<hnUPi|
z_jmsMZ744xaQ5%i4=*kypX-w?{#V@Su6NdRtIKTG<9jb{Vt%qyX{Gn4V-9bAbr|xy
z7#<SH*qrY*`Ox!p)+n1z@9(gDh)}p2(BoT^H!)7*1#|3@mlwY}*(jENX_O24d^(f;
zWt993W&u^3L!8kJ^S(C9GCV%=Q>0<7ox)w!bMGhSF!QZ2NIL8vZLH$K98%%FUA0k4
zBJq*~Z;nCcQZ}FB1Lc+pPE(asvsxk<g#XEwooe~kn3c0SPu}8Jc%r;UD({t~Xx`rr
z9zQn}pE_fv;36wOpUwEYZ`pzOOt06}e`%j_C7hYjyQKQD4=aaZ!qSfxwL9Z@C1lt$
b=I~#1c9^!ObpAXB1_lOCS3j3^P6<r_Eh?I<

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xhdpi/ic_send_black_24dp.png b/ring-android/app/src/main/res/drawable-xhdpi/ic_send_black_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..fd36be8b96d80ceb9336bb2acebfdd42ca6f3cdc
GIT binary patch
literal 333
zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4i*LmhQHi~JPZtsBAzaeAr*{orx_X@3lM4D
z-}FW6(k2$SMd_R-3sX5uoQ?{u2>dbq!)nPk)eBy(y%W=e_8gmWa_Z#UdyB<B?ESv?
z%-Pf<OP1W(=-igPkJChEay8Sgx}u}A<Q2Xp)+Fja443XZVapg8@sj02>rKYM8%$13
z3ny(z$P-axDoJEg;M%=Jgt6`3X5VGZC5dM?o>BWf$MEUQ^^S+Q&df}lSXyTJaF+YM
zlEmbD@2BqapHa8J-){y}L{hV@-^>q3e$Q{<4*S16qg9vB;(6QjIM?<w-05#BpL9k3
z?MdvIqHyKYU5>?zK1qlMdNo?^5|Lfd%UrnNrG0JXp)E}!j0qDKt?4t}dH+-P^dwe^
pGFD!Nx0l=Qa0SIop7e=XkGb;wrX3oS85kHCJYD@<);T3K0RZppkKq6S

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xhdpi/ic_share_white_24dp.png b/ring-android/app/src/main/res/drawable-xhdpi/ic_share_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..22a8783e70f01488cb1396f18645fef00c7bb299
GIT binary patch
literal 496
zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4i*LmhQHi~JPZts+dW+zLn1ie9<<H~PLw(J
z&^)O~XrV=?_?`y~9;oq2x^S@?i-^0c7Zzk6h<^3t*^<edFGYBD+>I%D`640zVa1{)
ziykO6H92qGxK(rE^W~=v+ds`!y<Z>j;<Lx@f7MfVc+a-0Rmu`c?H1mnzV@);&4ov}
ztoJHU5Y5_gXOgH>Ow=YP{^`Dv3)@fY-+aK7y+h}eynE)PrCRnZcarDoC|3S_U^L$&
z=kpBnC9N{oK3E)<VP0>c9k}2W)9aGTvn-Xo-G6Ns`9I<gf6_kZUlRZIpMFV`f4{lB
zLBr4!WN)6Z$DHLy4;1@lRmh~bZrN_q;aRdnLtf<Ngs1H0H?{5W9L$}qE;GU2DJINP
zUHVJG%?YAaJ918N>BfX<o@O&I=$`p(!XLp4YTna5xjr2gRJ!CePiXRw6RJNKIZUnG
z^(SQ>=O>|5F^P(knUTuJL-$R(@kmj5(=iVI8%iI0v!A5&2JcBon7HZR0;gs(L0+v-
z$1UVNj`)1;*%I0H$#tGoc1q?cCia!WkImGir~K^kjt%Q5h@2*>6f-TQl}#^rlN0Oo
zz?+HF=BA}|D*0YY<4EZ>e5JGbh{)nwU-^IWdP<+T;d^)51O^5M22WQ%mvv4FO#n?~
B*^vMM

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xhdpi/ic_videocam_white_24dp.png b/ring-android/app/src/main/res/drawable-xhdpi/ic_videocam_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..1b2583d34e8bafff26a20f89c9d7cacf4525617e
GIT binary patch
literal 178
zcmeAS@N?(olHy`uVBq!ia0y~yU@!n-4i*LmhQHi~JPZsBm7Xq+Ar*{ouNiVN8}hgW
z#v9DI<8i$An~?ohu4ZM4q{B6#w_liczkN8Tc=^%UPp-?UCEI>AemSL7btBuZt6w!5
z8B_%purN(=Xb|EEU}B77U}ih_-`8DnosAY(;nTv{PW!l-{B!MoPyeSP{W@Oyyx2hr
ggAMj<JT;8W9ecyxRax6HFfcH9y85}Sb4q9e08!XHbpQYW

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xxhdpi/ic_action_end_call.png b/ring-android/app/src/main/res/drawable-xxhdpi/ic_action_end_call.png
deleted file mode 100644
index c34a8040b490e429e585d6cdce7327a6e9beb6bb..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001

literal 763
zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4mJh`hDS5XEf^RWBuiW)N`mv#O3D+9QW+dm
z@{>{(JaZG%Q-e|yQz{EjrrIztFwOOJaSW-r^=8&x-^UIjZnk@NGXynkXAo!Dv%WH&
zdjUfk_X36m3|tXhC-&(_H*nt&5#TCdOw8LcagD~IWBVRUsz3Kow(fj#=jT4_{quB~
z8L)zeosWZfvNqp*@-OJc@l9WYZ+;g1+W32F@w$Tzhn>1NaL1q9ukb10$OQBFYgO`B
zCCoQIu->?|Ciq~m1JBR(ZCCD1xEd(&fHi)_4e_e8>6c8+vyR!Drr1g|hm;8J$@==Z
z*gfh<5YI-l!;+nPGizU-J}cPyZ>FUFzCBSrvgZ_TyMB3Z{3=do_e%SuV>7}Yx~2T_
z7nQT?sgO%*kyhB3^5-pQTFrbhMYTOF#s|9V{jZg8XUjjdcPHb-Bl#s4ZpVJ#pC9~Y
z>#4iXm7KEQ<~F_7+;^rxPHk58b**(TxvpMcn6q}*@`%ZQK7HIDCAooTOV-`9D$|13
z*+sAZr1gO3-P!9arE(kCepxqs@V7gV$~AY}`o$cj;s-k9V>?T)Jyx8~C}wnhWyk)r
zhx#Md@%Lyazr3=ppYhu6$t!aX_zFg6CN_M%<|MZuG%|H{sdz|)gg{cmF3$@M0)|h;
z*jg4`s9mCRA!1RE(mdBS-(8(<%Ii*>!4|?P88CMdW9z$B$KKU_(s^XvW5?D~lNhTu
z;jdzHh7M0e;(-;e>6>CNXi6kpV!f((ype^6L((}n(V=Mh$uyTw$qsWHJQR~(Tv>O%
zY>Ut3e{3gsEWdn__`N6Xbwgth>$Ta1;jv#||8{cYIl<1g_tK_wOnY8(C7k$YdG)A6
zvQ+%})faUgnkVu6%-OuE_C{&-`~Q2+^>r{FJ5jmNU6|RV;r6vDZ!=oW4ANHjUw=B&
jk^^gsVK|WaLGJ*AZszIUN9#HsgVcDs`njxgN@xNA+q+JV

diff --git a/ring-android/app/src/main/res/drawable-xxhdpi/ic_call_end_black_24dp.png b/ring-android/app/src/main/res/drawable-xxhdpi/ic_call_end_black_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..44794a9b9d2dbd58656bf4a0d107de3e830dafb4
GIT binary patch
literal 515
zcmeAS@N?(olHy`uVBq!ia0y~yVDJE84i*LmhW}5h&oD4Bp7L~Y45?szdwI9_w0xQ4
zAFnT7wzOqMZr}s~-b;=d2H74;oV;2uHn?~PCr=P_6mU%NbyXE|xgucVI&uFrdD&$O
zCY=j1inT;#TDY_;*B#n;`0UZQ#fOb!)}Ock@Qgd&bCL=Ksb+tbG|0KK!?XC=)Tw7@
z8)x20HlK4Ty?2t+)fXl&CQ2$6U6zyDu=7)5Y1Lg5-6wa{mCIHK3rfeBsfHxT$8L(N
z^Qy8H)Y=ocd&;LHU#e9_woLza#Qk8{`PQCV<7e9(*-JC8FN!<6{%ZEcyxE7(?MObv
zubBM*waC(=9h*K}*R6QCCXYAC<km~4V{=ch%T~MHcqabUH23&t|KEP~*S;%iwB1$C
zy5-E>OGoCL{ZtT<oU*ap>d&(Y>zyt-O8(BVXHb34vhc)$6?4Oyq7FNSvap6<EeKpO
zYrzAX&7q<uhigJvYai|t*xUQ*hMvoNxwUcJfwMO|$>r|j4y<0>dt(W!`_ob*qjb?D
zs<syrHFw$cp6T?cT7Ue~)HlYGlPAv&F<aue)MTgF#K{v)mbx$fI{WO2lRi?LqXe&2
zN>68Ad#vT?-{qcxvuuUM%qPxeJ}qnhq$A2T>e&o!zl@MjSonHQn(z86QlszCKMn>4
O1_n=8KbLh*2~7YU6X$UN

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xxhdpi/ic_call_end_black_36dp.png b/ring-android/app/src/main/res/drawable-xxhdpi/ic_call_end_black_36dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..ab57d9001675c7bf204a25add47241e7e5ed8f67
GIT binary patch
literal 721
zcmeAS@N?(olHy`uVBq!ia0y~yV8{Vs4i*Lm2G#ueZVU`eGdx`!Ln;{Go<E;`jaBBr
z$LpKV)@YnboW4kJnxStQ*EWR?v8h&bZZ1^1kS#Ik$;mToT68=*cfGm5-;uC5nSCSY
zQ^g5p-IJPL1*K)oUc77TqMgq#Tdw%?>95`S&FTE}um9Gs$X-7s$V+o667kAx$LSS!
zzukJ@aG1|JVgKGTY15qMU80N9_8Oj_Ws>VBl5uSdCwp(?`el!=+<m@ba-Fc~ucMsp
zJrQe}@8s?0*X>aIwtMotve~JdPJZ4er2A&hbDoUFb=7A&%)YKvUvssn`QEqojAHJ4
zTOzx!<P=BgB+K7ibnVSbSvz6b3tKKeJKOssW=hsM@nt?z<#z(zWeTqpK31FiY3b=j
zA;#|lZ_4_0Jj(oWZb`G;CeOQ9ujFnyY^+wZTCwXnGqcz3bF0N%7fw4<aWw4jsi@bE
z`j(HoG_J(Qm8}&z79-I5>xQ0r#<aSAD^;%2duB%$-mhL%aNG2@U*L}NnDq<TV??ym
zbYcu1t@<S+n&jHs+9v+>m%RCJmy$;jjeff?)=QXahrNl|@xt$a(scWyU2@#qa-aE4
z^*Jv7OlGxO!FC}#rsQlyg){$`s`!$t5i>3vw!2uGoTz`l<mrv;CcBE>aP2R9dc)>@
z+0z@*cOGq8ab-f<?&y$LlV&Gut_<8Y|4Zh!>=>b?zi%>xL`QFm)$WO0wJkLFEqnCV
zQ)2hSZ>-v2_S|#zmP=aIXF_jiZQS-^hUu-u-ej@WxuWsb*#XwPR?&&8AKY5x{A)|}
zd}p!loT;(a`6r4bza=-W4ayF_7U}oeNA$kdzHhVQPOrWG+I3skdQ+RF!EY{W>}Qpp
zE9^Am`v$*Fm)8g!lH9Jf@c4w|ch|4GyryiuJI^Xll*9o}D^c(A?bzEGdmpFOF)%PN
Nc)I$ztaD0e0s#0iU-19{

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xxhdpi/ic_call_end_white_24dp.png b/ring-android/app/src/main/res/drawable-xxhdpi/ic_call_end_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..e1831d7afd086dcfc741a496d058af3d0308da99
GIT binary patch
literal 553
zcmeAS@N?(olHy`uVBq!ia0y~yVDJE84i*LmhW}5h&oD4Be(-d045?szdv0%bY^hAc
z$M-usJ$)w#OkTSs!9k`;pRrv+mM3X~OTfWx-Y+k$OkU{ey)b~QbxW}KZ2_*OTbvKB
z)Nm93m@4FyB;Z(hIwelQ*+DgH$NWC06PA`ccTTTX-2eP1yItW6@1;R2L$s!PEe$d{
z-aFeQ`P`z^+1o-wb8l|Rxj6mZ&V)OLGjF_K_(#-vSxsW>&1*GzmtJqGYQELGGv9aZ
z+8JN>ef!lAS9p0<)t7eZI6Dpv<7e4l^UhUo`rB+I{LFNfe67N5{ujRYwO`3|%gy?<
zGLgBebj6An7qSmT`|Wx%QT4y(D{1Ga4tvu=-`?9MA7i#Cc*>5`yVuQ}9)2~}wz|=7
zquPGKz{8I}MSo1Rd%@Z-`rXZULAl6xhwpg{uK)21cKDN3p#Gv|f2LH2eeEB6jbheW
zTut3Zg163G5K_on-ST=1Psi%S#Y-JtC$3)VP~Uof%KNLc9P+jAPyVoI{*>&?pG_No
z{aGDj|C&41^R{2Nlzsf9%lb~1mx7xgG4TK1#^c_y*K@z5D7)R~iBI=hD2Ys7wXC$u
z>h4=VL-!V?ORE9{pR4CQDRw!bu4|zs^})OD<l~MFleaMZ@Y<en!FC_B&P#FE1qDYU
zFZ*Q*^Zv0+zf<Hl{RF$|e-^I=Xy`C|6`Q+Y*Y2OkmvA#MFfe$!`njxgN@xNAwpIZY

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xxhdpi/ic_call_white_24dp.png b/ring-android/app/src/main/res/drawable-xxhdpi/ic_call_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..90ead2e4551b165530bd2430b3d69c34263c5c4e
GIT binary patch
literal 597
zcmeAS@N?(olHy`uVBq!ia0y~yVDJE84i*LmhW}5h&oD4B$#}XrhGek5J$Ny@H<97^
z$NSAy_sa~sXI)b>EZnSO?y@>Ft99B3^&JIAJA(9{94j+i>z8(R>LQhxH?DIhS$nQt
znyII;^_G!$N!r4TH>U@Eo40xHciZ&mw&#mK*VzSWP4!y(=)q*g<EP>->)k#f@YH&C
zs<`E%uP5|Ax$M^3{ljyM-A&iN4ChVVo{Ma!#P$g0hLnArl404ClQh9XcT*?#5lg+<
z7Cv(rZ@O?7s-+0Goj;N})wf6Bc}vbCrNVC~)XIe4+PRq}&RDpG!GBv}cMy}!O?P!|
z?hj9xUe8F}$>6{4g7-!S|92baIx)_>^N7=1EMr1;i9ng>y2Of;lPt|nn(_&jMXyV&
z@QYX;lPq32&1X~Gy29oS))G5iZ7;XXos=!3n$uWY)T?;NZewU(;PL1~_bzH|zj4z1
z(6O5e+h3$j+)yYb%6vG^Z<Fg*NB-7(n|%d8NIslz{-wAlt!Glp!ud{{Wdb;Vq-cI?
z4Yx^{5Vx+NEiIJ$ut95Gq158k4=07v=lxwJmMyXDhOJZx!+f2m62V^$VwT?!iT%Yt
zU*~CLh>^u<rK9gIE!qF!WRRI^Yu+;rv-7EDla?}h@mbGE*m*z1#dA^L><~}S#~i^S
zjwct-<Eaeu-0CQOK0@>=AA6<a(GYKmTbwI8viif;eVk}?lJDB3g94Y2oII(<lRM|R
z;N~et3gQMP7mr#R*`!V3uX)N|S;X@|bE?<Upu&F)?~SwFcCSd$W?*1o@O1TaS?83{
F1OV_*3J3rI

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xxhdpi/ic_chat_white_24dp.png b/ring-android/app/src/main/res/drawable-xxhdpi/ic_chat_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..424509055121817e606155f423cb866fb2501373
GIT binary patch
literal 270
zcmeAS@N?(olHy`uVBq!ia0y~yVDJE84i*LmhW}5h&oD4BT=jHu45?szd*z_#u>b+r
zhr6r3eTZJfqMNu%xF_j?7mMPKfd1DyaV`e=Y(?jDA4KygKfm)L!^h^sxr?<Qj>v{*
zSZ}=B+B$J>(O&i}8{=K#QSv3uZrf`w*h<=dbIecK^38Gnk}K@Bb6Ha+IR0AR=*T9y
zW&ZyQ<(2`5cqLONIHvz_uIo`}lWcL^-ymdkLZO*$OBnOns}8}s7o1kJMD180wP5PZ
z&bEJiTqb$70rMwwafNV-tPs)&Pz_k%wZLJjL!(wBQz#SbDi)B0hJ48z9-|Wr<Yjiw
WQ~fV?>;eM=1B0ilpUXO@geCy_?P!w#

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xxhdpi/ic_lock_white_24dp.png b/ring-android/app/src/main/res/drawable-xxhdpi/ic_lock_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..0e52c7c75e58cc7700cedf8e808fcb4f598a2f54
GIT binary patch
literal 540
zcmeAS@N?(olHy`uVBq!ia0y~yVDJE84i*LmhW}5h&oD4BKK68R45?szd*i&9bf8GX
zM~5>#dTVy9{leK5^yjn4Qa#p}Y9$xvYS=YQahSentL6`$Rwwb&%e9<8+TAV&y;v8q
zVe#vfNfYYQjCcAN<-X&w+&N+1d!1swpSf*~Co}(tR;&qH=H#&1m{IiJryi!AZzlgO
znI=@OQhHiD&5buo{XzWQ4Q5sW^PF?ECQoOPJjb3>?H?ys;*qbrN~Uy~SNFYpp3T=f
z%UvhFe7Byz;$ZoswVq9BoCaHOCN9cf?$BvJBX7n;=BY_@p4Z>iKIUN^q|k5udVgi_
z%V|wK8KRd(g_%Ft8`w@|oN6e_p11$V7dN&L#Z@P_9A&<s_NtplLt$0c*8jaL?i(#o
z3v>_rJ-;*SM1zm~+HdxWK@*xprr1o*DRw)tfy*+L+g|&H;B=3YgE3+kRHl2B_Dz@D
z(wj2-rDM8B*(5m;rAS>{4=Ywp4@WMk=zzJgVjn+7CiP!1eWBi;9R4|GH_KJt<<{IL
zcN)ut^}pY36cg5;ez)<@k<*&2rO{q{VhY)BdGE0)VCS0oes}ewPaE5_#i}g!$LzOq
z`WBhC%2-?G!iDLpn?#l<u%_nl*d3pvbhEJPg4m?oCG0<A6t0HbR8N>`d9Kxhe{-G1
w_nS{zqz<n-W++|pWK+|V^goVVK^JWM)#v(WaDLmsz`(%Z>FVdQ&MBb@0GKZ9ZvX%Q

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xxhdpi/ic_send_black_24dp.png b/ring-android/app/src/main/res/drawable-xxhdpi/ic_send_black_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..40b74ebc16e0bf2a85ebc3d920353fc4eb8337aa
GIT binary patch
literal 412
zcmeAS@N?(olHy`uVBq!ia0y~yVDJE84i*LmhW}5h&oD4BCVRR#hEy=Vy<xBC5-8*T
zG5AB3==xO7BNsNaNNv$+JU72fHDGZ9=M`mToyKdcS4{lvCbE6fgxQwo?>w5fyD`6R
ze#gnj+r5?stt>e%CMqc^ajC#%?&SsVzaLaR{gbEbeH^n0+tKR<9&;}*;Mj2_BCGz~
zN5-{|b_)znFp02nHXK^8ky))rkYTH%-2!_JrgKk>HJIXdG&n!yy|Ltwyb8mvW*LXV
z37ji<HZit3S|#)!SvDiRH`Z_G!_M<}7}RH^w&wQjeAIaT9pm5MKO6r2%{lPy{r5wS
z%o+FI+sYc$UXWS+rr?li|DL~=FXp(;&uJ|EX7PC1bCpfC%XaT{{3X5N;1m114h}+j
z3V&ib%{|;!-Kk&4G|AM%!HAvH<K<5eTenkgQkLSLCtQVsCbry(KjrkvKX9R$<jQ52
zqvTJ@t0?_!mg4vPQ82GZMI=OJ;Q}R2R#8ul74rJ6O}}d6R=ii5>a{e;^947v)g;Z3
UrsEqK7#J8lUHx3vIVCg!0HPbS_W%F@

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xxhdpi/ic_share_white_24dp.png b/ring-android/app/src/main/res/drawable-xxhdpi/ic_share_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..a35b3cd14af89804b7c3aab8f9b54cfe88771d19
GIT binary patch
literal 698
zcmeAS@N?(olHy`uVBq!ia0y~yVDJE84i*LmhW}5h&oD4BHF~-@hGek5J!qRTr&NaF
z!TnYhSrcDni<B>m<rQalmrN2$&RVgn`_`huYmRFoR%l#W=yi9o^SYDkny0vEY@O6%
zCb(TJ(@t$^+Qo10+D@~6-jR|Kx2`h3^1uEeTYs1E@azBQb$J$>ZOyrD@VaEm$rYlJ
z+k0FrdonYYzYAHC9&-5cm0p)9tuUDs%S%R@=UtYh_|3~&k`g@ctB0reytE}L?(@=?
zJeg;cJ+Z4!KKq2RaHhrMd44_aA7#pY)5R8N@coYRPS5Idofxv`wSMIGzl-P2n!d=x
zFKX)7<=aDS-it?e_qi7G?9RGg=R4g-vbtw=)b&eS(vDS#99Nvb;`FbB#er<=qo<c%
z*A8S;KXbb3f%D!#5z)!da<Xo2%)I9E#_&bgw7>sM-@er73)J2;P3CIyscCCm^<5_R
zWM({Xyr1&-;aQDofxL4we_av|)DhLT`n)%NQH5IRqrU0Nyv3ic)GRO$+NgQ{F4Qy8
zARjr;vz|C9vhtPPCGnLOYlZh$n+6qnr`MI31Q{$^XM9^vy5o`M(sgt9uRXQv{Twfm
zvmL3C_SIoWEx)JU{gxzhzGYRZukP!#o}+Ti`z~#|zi!n-jsC~$POh?CZ-44>k7;Cf
zT=%CJ<#Dms_6P^c9bR{9Yy4@^=8eY%gIDG4Sof;dInYLZ?WtQvOWo&pOUYgR(E3kf
zmfZWBlfJH2eXCQg)s=q1ysRY6Gk!_J5r3=CkxL%&N`Jb_<EF*8bAjUdn;s{7Z0@^y
z<(=3ppt)1;e9e*+w|Or;PEN7OclT;Dk$JMP(c|=UzE7D;mfhcUeCJB@OU5al*5<OE
zMK6j2&n}kRwZQyT%7w`LQ5zC&S@XGvhlh9mV_tp9v$;dO)t!NXfx*+&&t;ucLK6Vh
CcufKT

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xxhdpi/ic_videocam_white_24dp.png b/ring-android/app/src/main/res/drawable-xxhdpi/ic_videocam_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..44c28e2f2830f927973beaa3a143ddfe439f20ed
GIT binary patch
literal 234
zcmeAS@N?(olHy`uVBq!ia0y~yVDJE84i*LmhW}5h&oD4BZ1i+-45?szd&7|Huz`R}
zVCXs1qNL^n>}Pm;{0uag3!TVd7XDE$U0%1OU`y5)6D1`jrAyw^+g3@vvbqv>ynmke
z)vqUC-_KsK@YOrc=bPDnISThFIXrV|IMc~6Q<%|6ohikS<-{DB36_Ei#Yzs(S{lx9
zGI9ziI5hk)X!~DkGTEXoN9KaXp;;=|7OZuh7<y~T|2=&#SG~KldxO=LQt^LQ&o^uD
m-N4Ag0n)<2$RuJG|K`QJx(|o>yBQc57(8A5T-G@yGywo(w_QR2

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xxxhdpi/ic_call_end_black_24dp.png b/ring-android/app/src/main/res/drawable-xxxhdpi/ic_call_end_black_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..3a0ef395717b0c28bf3c0c298027501da08b59ec
GIT binary patch
literal 663
zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4i*Lm29JsRH#0CW#d*3ohEy=Vy>z}iv{d5w
z$Ll+d7hknltL42(%yUBU0*^rLa95wr+*=elloc~4PETC6KY^oZf$KE~vD7UaqEc9t
zT&5Wan5<s0W9HMSjq$-ZQ_kAFO@49b_uGFnxX-`d`|r?aOPQxZUYbj%z=)l<@_wJK
zyvf-er5Cj=>Fg}g(|TEvC5HryzukPQC4D6Ad#2Sp>D7yx!?wy?FIj(<ZIMytG0pmp
z|2I?BP2YyRoP0{|yruT8nA3Y=_s-jRwMXBT|F_fSuT_ua@_&1OS*YE2b8)v;u$b$7
z>&J|t=6&<Gsjyv1mkSAemp8v-+wKQjSc~O0USE={*0U<)n9q&0OL4!?Mity*y;vrH
zbL|P<dpV!`ZIkb9kuH6tcKKQDEC0aTv#!T1SLS8^tC98VpthV*U(w@bGKHR3N=^!E
z<?gzA+^Lp(*V7dN_cd={T_v+Y$LvYNht0?TEZ4m!l(d04tLm=ln)iIV8y~W_tiO{d
z8(b&oY^d<(N!|aV8?z*4F+R-qXAY>0>o~}#krBtLd{4mHQbFcwLKx56h6_)AFO>VB
zYj}k@%+me}^SO^}G~TG*-K4-}eP+dXmq7nl)0`KrNR~1PGkIwJcvouoXV>Tb3_X?M
zC08chF1gG%fBM{bqla^9rFN}-n3&Fe{(Zus{IuLl+OyC6*!reM;<Mk`!;|waX5X%j
zD60G0a++`D7w4x7?!P|&KF8_w++Uf?*L$C9zgVhP^C0T4*~7oTKHr}GVUb|-g%3_A
ze;T|BRcz5t3t@XMsl9amM?HVb2WidQt}d3_?u;DIOQ#4ukpEu&G3{DW_A&+r1_n=8
KKbLh*2~7ZxMnkIr

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xxxhdpi/ic_call_end_black_36dp.png b/ring-android/app/src/main/res/drawable-xxxhdpi/ic_call_end_black_36dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..58888d833235bac9afeb4f183245acf9c69f94d4
GIT binary patch
literal 954
zcmeAS@N?(olHy`uVBq!ia0y~yV3+{H94rhB48Hza#taP1jh-%!Ar*{o4mL6{FfcSM
z_`6bkB@>7V#cA8`#jVkLY{6%rZG2lo%~;W3wxf1y&?e!)mm-qB?4C1Eavb&x;&hzg
zG9_S^XNY;LVq8m!%w`!4%}pL$`dt$yNS$(C+8EfY&}1}u*Ilb$*ILc_c3#|izc%9B
zzncHe?e~-Rn(94g3cj1YFm>13%@@mRzr6@A__AO0%k9PI%cR$So|h^%>v2``({m|P
zI(O+@N?yHaLXm6qnvEXIIn%kWX>5;t<o&zl#O>GI-K7@pYNvN!?A}-Iv*JVFt&Ejr
zKi}Lr^Y@yRz^XlU@-w6Fe=k|rUi)rCz+utaw0VKA*398sE!tvr({c43o#lE~_l4>?
zN_Wf^lU}?mHhJn{C)xEcV#8NDc1G?KHrkYbX2Oan%krOrCvKR{4CP(oGJSq)&${bp
zPASDck5)Xy_IATPukN$gSKdv@b<4h{GBM*)&K9%DTVI>p{~Q*T-|nb*$ZSWH>#hq@
z3)g)8d4>C(nP=RrPkN@eh35Z=*2sP@t)8W96MalOeYNPb4B^dT-y`0sD?a6`aEn{A
z?Dn)zAMZa_Ob*>-_-^y9IK`u8yB%-#e%dx6OJ90nlxd}>$JVKCT8sJWxir78$odu`
z`Tp(8psPu(3Mm{Kf8(ydF`4}+Jn;qtYqU?%DOI^Zfi}^Af&<KcE5+_MO|V_SQ5|f&
zRC;;1#5RY6YHPhr&gLaXFthHCd97l*LW8Gz!Gj4qd2~O{Q7~!fd!MO3Wphjh!`uzw
zPZ`{P1YBT{+Lc%7@r8qT!T-DLLTTK*3ns7YUN7ySx@}&)l!NNE^BdU$I(av3W(-N%
zzj+U1NYeU?X$}JQ#i5%kn||C**Etg)vgp0h)i+*>zxZbH85mn#<QKZCb5VNkbFmdX
z7X^bucW3s6^r`Dztc%SGT;BM@W@9JY-qbl!S6}sVl!r*167J7f>wRTcXVs(6M-*<o
zQTrOS`(B5QU<Y4?*W{{ICz*aP{@|i;>p{}j8x`?$)%@9ys9L2o&Z*M<xWmb0o`}nB
zpTPIN+f=#yxfWfGN?9m&cVdNK^NSVgs+)oyaW<<~<h9OlVSYDZYo58l)a5J}^}<gi
zO@G~embskoC;y*kN|CvH;@fICWtB`$9zXs*V|#edl&9ymU5P(lc+W6y%Q+***>j8+
w9;uA_ds|Khl<gE4xPJZLskrj2AT(=1C^j$UxGAaHcRN8`Pgg&ebxsLQ0Q@Pgpa1{>

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xxxhdpi/ic_call_end_white_24dp.png b/ring-android/app/src/main/res/drawable-xxxhdpi/ic_call_end_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..8801d0ded431c21d4d6e3e092e56d540b699962f
GIT binary patch
literal 712
zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4i*Lm29JsRH#0CW^?SNFhEy=Vy>PyJYO2KX
zhrex&vrPR~pPIDARp^O`M$na0p@Ns+FzIp}^6-dyk~rg~zC@Ek#zfNzu9CWI#3UOz
zCaUtV?Ck2A9Jx;Px9L>hVB_#^F;^Me_djj*@63PytMPZ0(&<e)$mq3A`0dQ~k@}Wt
zj)z&hr>%+FnsSkqm%Gn0<(iyzjB3^93wO<Sgx?K}kG|-qE!DSb_wlxe3|zv?=6=|n
zxBJPCU2nS_8M$`byzYs+Zjj!-Xn%w6vf737YuCN|^^f7*w`umgi&EX+yi#3Yka=){
z_0u}n?+u5hTyDF%TrQx5dB^GFr^@eneonK^+0Hq;S2|Q<jd9*)&fRZKlka&xpZea}
z+M4;!1K!lAvQu+3&AZIXCTkYkeQdwBw(4r>TgI$!za3Za`@V_2w^Pq7?UJJS)>n&;
zi>5Me|KTz7nQMPp#7w^%m!tx2q)#;Ee4ySRC%NI`><wv*A7*9ivG0g&Hsycdz1@`A
z=hsXxh94Je|Fg?%@k(X*^K@lBW9#z;K@2m3I}9F`YH>c;5H(}rCWcoJcY87K<J97f
z;C!ydYau=FVy6B#9)tCl`Pu^CzgnYS#b&W!bKi>A4eOK-Z9i7UcH>2i`}6*e5Bv{h
z-<IB5yQuy4v(0|z#23~cimblk(jWeLg7MpV`cBm?@n<9Se{K1??C+&>Kb8JW|4`Q5
zemqyS_MVvh6#Mv=O)cJh8ZQ5rZ@8cT^qlxYnS~Ge3=iaf4}JZ4HshfT;X}XIi89~Y
z@jYt3zEk!gZnq->VV`SOe|F9At6<%b6Q$U;ZMkmjPig)CU;O-UJx?=ylKZLSc#iN{
zajktUDhiCE@k~M!8oKluIXxU)r#FCvI6WLdVjyNca~Y56glFq_lrk_dFnGH9xvX<a
GXaWEZHAol$

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xxxhdpi/ic_call_white_24dp.png b/ring-android/app/src/main/res/drawable-xxxhdpi/ic_call_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..b0e020573d37e8b4acac23fcd3e01cc39531b5e4
GIT binary patch
literal 778
zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4i*Lm29JsRH#0CWUG#Ku45?szd(b;0Bwgm%
z!|yF7aSAK1`+D!*;B@tY>B*j4%_fo8Rw2!z;ft(YC+chxarxf0-8IxnJ9f(@7eUdD
z8eWb9xf?a|M2<+aJWpD5G3}S|n`QGXh4)K7_xUGZb6%O%QGmr!fQ56$d4}^6=Q);V
zO!qyryrEl(J4KLrhtw2To5NQ-bQZPjR=ata`;PA<Tag0u*l!<L%8OI@w--#GY8!Lx
zZuzG6`vupvt1TLK%ct<~-LYG%I-+@ZU{nh4=@o8n*9=;P-c_aYZ!akK`}V>3UEC$L
z>>GZjyHa^2S8a5@_JQ$y;dR|=i{{nUKGSS-4xbI4c1p?axN9HZO_w9G_f*}Nzey5*
zeEPEH>4*~*TqP&Xl=6Z+8++a)OP}mYdCHvjX;P8vwA12$JYpv5KjEJySRPdOkf~7e
zXUo+iu_}}7JAO3p*!qd{zCii>u%FEx+(+I{^^b7s-2V6U^-rAbox8nf|2de`*6~_>
zlKl;boxPvf1=BmFmwNwu5d7(g?E~eX&2pz=7l;0PAo29vC8c<SsrH)RxzB!Loj-B$
zox)j9x%Z{^6z#vXNbAC>?_Vw+HZhf(?OD_pW~p>q`QK;${g;nV_X$(p*sgN@X9VAg
zAcc3L*Dbu{ZEKFkq#3rVEp6{`R;l!Gd+#ufDbLNqb@wGl;lC=9sm2qvl$;y0L?RcI
zT=20!S@+0URmpi?7O$4BN#TT)?-2`)N+vF^Qug8(+`TfzKKGaWt`ot+OS^r0Cca^O
z-SLHO?vs@hFCEjG7j#l}laTC_6*Dg#m&psbsbG1pS*mfRjG}6m$hAqztXVR44|z(L
zyD25vI$xP8)f*|Zz~yd+(uR)DS31?Ww0AnmW;_zu*!6jjy06K!3+FXVC$pYO(5?>@
zzUgRfz0<d}EtR+U=Aq2CLSu#58Oxg2$~;#~4hc(`w<cMr`(+yYZ;OMj|DG9I&I?YO
m!T3y*qe+3INx|cTRKtW{e}zw|yklTsVDNPHb6Mw<&;$TO%3S*Z

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xxxhdpi/ic_chat_white_24dp.png b/ring-android/app/src/main/res/drawable-xxxhdpi/ic_chat_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..d708e15803ad3d231842aeacffdcad7310a930fd
GIT binary patch
literal 344
zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4i*Lm29JsRH#0CW%6qyvhEy=Vy?oa9aDag8
z!<$F<Du{T^5er~)6Jfq`KuIHYL-CKwc2R5YXczx8qTlau*=4HDDL%Jz=Z>T&Cp!1P
zJ2G*iuHpWKJm&8vT32@@M{rA2EJ^a`dCjmrBsYe6$AZAE$I2uNe4pk`V>}=7E>-e_
z*VARG2V7oGV^n9ZN^4+blMtAjeju6=#7b~z3}Iy3bDEiD-i?Mj;{y!LJU<o`u!)>#
zuqbAeNN`9$u$+<Y3+tD&49q+R3nUW`@cX`MXtqjN&YKaF#r&<s=s{zz-hz$k&TAM$
zvL79I_xsy<c9p<{{cI`=c|4pXC$tzTaHcv4ooY~-!sw~NJShOHL<aLCc}5-su<cBi
Y>!hs|PcKwtU|?YIboFyt=akR{05>~**8l(j

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xxxhdpi/ic_lock_white_24dp.png b/ring-android/app/src/main/res/drawable-xxxhdpi/ic_lock_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..a55147be1c9ac2a2b274453c3a163b46331a138d
GIT binary patch
literal 702
zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4i*Lm29JsRH#0CWwR*ZZhEy=Vy|v$4I#J@l
zN0k{zO5XG@&3d^=<I*y|rFyQv{I@)KHDLkYBJWpmuhyAuY|)YRZoLq+UFk2gibsG+
z!rFr;)2{rHcz65jJ!Q+{ouBVnSL}QL$L2%hbn#~KiF^Debr_zu+8vU4VWD%g*8Pg}
z+DR^Z?BeuglAFD&LZ2%uA7r&jY3JL1RqcGU0@Jh13;F*m#C06zoVR!@?Ci*R=dpV8
zm*x-whQe<WTi)|zvfqfACza|oMI(4|`0ZVcpG#i%gq|+8JSFwK<n>y=1IkhnyVI5)
zKiaYR81J=pJJ$1WXx>`9ELVMAapP9q*akzZ6@L@ITwAGrB{2JA1b+ha*6d}!XH`22
zZ{@dQFw_f-epzkSev38mKjY>Vb1f?_3ttJWercZ|yEWAPvgMVcf6Qfp(uF2}MYgX0
z$GmFBYRh^5yLUSOXXHIIRrdV*#CNCa9oUOikAIFgxc*IkL0ExJyo)ablRyIli$Kl+
z9#+51;_F*275#5TJ9H`iOAAQ2q3zIh|3$|9#C!(VlBwUB44U`xTzbdITC(k}TtU~l
zzPrq~UaWa4x4@c_!vSKBLW2Pl-w6Z1CKln8l`Y%_hnrHpr|_KJz>rsQxAd~i*#ZW!
zs&}W_7z+|MYkR5wXy|#n?dSvMW4YUX+2ki|xI0bcz+7gvobA4>@)Ne+-6m7x(7NKR
zan%a>2hS8^n+zCcohiNhr7g^Y;ev|um7>aN8Lh9+zvSxnnWS=3<h0Bwekmk}Fixs3
znZIDO^7jTCtJ@{~9?1)|o73MhTG{Wosq~07VMcAqm+mFf4PF`v57OD9RrdaUV|3Q+
x_?DUqi~buS@Ah#w98+e9?_*$5U|{^i-qoklH_vD31O^5M22WQ%mvv4FO#n*UHN^k`

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xxxhdpi/ic_send_black_24dp.png b/ring-android/app/src/main/res/drawable-xxxhdpi/ic_send_black_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..761929f4319ed27f6d1f995d09eb2b9bc2de316a
GIT binary patch
literal 543
zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4i*Lm29JsRH#0CWKJ#>O45?szJImHD+EK*K
zf8q^O(Hp8dj4cOEbs9|)UL<f{NaSJFVSM#RGtw!@DKTdngKisB)_+3}pXMF2m|AS!
zPky&k+rrr0-+%FGZJFbRGRF(&aBtI4_L+ac);*+^H7@Ny{;N|=g}bU8c{%c*^*OKF
z#H6MX*k~bZrrFK;g4I-I#zx1#i`MBRG*1!~;K*|E@UvQx>d7b^;u)^s*DofT+UUe$
zs#bF-=F);CItk4}A{~x@=adBavsimMMlx<(u%;m*Ak0B$g~7y^g$}O%2iUf%XeKmY
z65il=R)hP-f=}E}xU;${uibb$r9Q?ug#Q)y<~1A68rHw~WN>gn-IAuDUGvSPI~SC^
zQ<t4`?(dNWSt=8D&Myh@`d;j9EI8%D-!I7lKUtqeq_zwHD?0jkH_N`wGt?Kd?%Q}=
z^8e1C1x~+x#DDi(zMM99{ZaeJB_>SibN;;(`PXy#;*_qsV=ptZexA4RHc`BP<9;g-
z)6e=FO(7;?8#8pYE<UM`$_biSd&l(R362}v+x{^9yuY}&A<Sgj#wZgv2VE)U1){yF
zQ~u7hX>RCr3tZsrTzXf{O?h|GwXTaAoHH`Musk}|aO2VHPB+g3F3Kti<`2KHB$*g}
yx%%yDZ$q3(m_nXQchNeb-p3Ywk1hH>^LS`J4|G^lGmn9Rfx*+&&t;ucLK6VqkLx=C

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xxxhdpi/ic_share_white_24dp.png b/ring-android/app/src/main/res/drawable-xxxhdpi/ic_share_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..e351c7beb089e9513ef5ddaa2ac3f1a6638474cf
GIT binary patch
literal 938
zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4i*Lm29JsRH#0CW7kaulhEy=VJ?QUozf|V<
z$LV~MC)VGQKXFrku2rOKd+ev6<x5_;w?9kV;`~<qpqQ+fa`>8DmYv?yj%+xschlgM
z<i811b)&i#wC}l+x#8I@j?~|w(oy@D?Y#f~`TO5JOPv4xsH^{7TQ~jv?H_h>K`KI>
zF8}OTEQ^vB<iC8_g!@l&W9GfY?PgrJEc)FI`vap=<@G;{J5KXFW!6`$e>_DzcFJSd
zn=aa?rzCgI-P9rSRBD>-mPdi>n9go$o4ljK`<g*xclV|?6TQ3>QbjvXoRSJFEDXO^
zz%2fGQ(I<Cjjne^59ghd(_Gsw_{*7BKHAif75C8W-MLdt^PaG4eYCa~F?+-lDB17V
z+I@CT3TOTPM}c0A;i7t0JNx#FR;^e%*|kY$Q+VQ|z<sJ7U2~(HnVFwxPJ68UN>uKZ
zg|A%w^a`)n7Y+#Sdtz07;)C$>%3fJ6{;M)i#Qup{o>7ZDCS23MpDF!@-sy@7{+vcf
z<y!l-SQCto?`+;*`AysB&7)kkpS?_S+h;ssIUCjfd}kZT%Fv1o#a8!?OwJ}*y!{_|
z9fM4?ePj}5DoB1Sw3nZ7_`a%@h~B*=CjG2`bc<&Aa*68)&SXlzv2Me~GeT2mB=ze&
zD86%cbG+FFCq{GaIg7%=3Yg3_XQgsJ-XSsFbV;G1diIHjN>E})XSZeKVb_?R(^7p8
zpK+I+6q*%r^la=sRW<7$Jmuz=4pVa$OtfElq})bNx`MIatAgi4gU$mExuq3%j@_3p
z310kRV?U3h*iG-AxJ^HPPi#5lKF2>|X~ew#%nMStB$Q7`<Z{Uu?)up^KQgV=QtyLR
z;acY=?H{K<$r;{s=XF2%K;L(g)=hU?=87M)7sg66zCH8c{9~Q3oBFjTE%`Y8A#YZS
zykXVJNBPs9hqQ?CeNsHkbMd@lR0?BmkKhxg-Cy<RrFJD<R!L#xT=zi#^zS>z#oRcI
zPMNj#OZ81Ucwawe@s!mjCz)PJ9#|~2IcF;G7Gq~sw-nY;70<`-GH*Ke#BJI!bBgX3
z!#3`Ix5&eqF(oIZ{2njzzh=<W?HGAjK#whz_wSAulTBp~xdvUk;Plhx(WdsyQ>KdD
z9s%q4ZXVHiYN5XR#<9?MPmM}9b*rUmJ~iS$X|~PCX+rUpOyviXY9D{-_j6ipnRvlN
qyq3qvL*DaImy6Owk0m_y%+EZkv|Zo6JkP+uz~JfX=d#Wzp$Pz~IH^?t

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable-xxxhdpi/ic_videocam_white_24dp.png b/ring-android/app/src/main/res/drawable-xxxhdpi/ic_videocam_white_24dp.png
new file mode 100644
index 0000000000000000000000000000000000000000..ed20c0706292403018b019329a4608db85d99e06
GIT binary patch
literal 290
zcmeAS@N?(olHy`uVBq!ia0y~yU`POA4i*Lm29JsRH#0CWy!3Q&45?szd&@Vg)j@zE
zQD68-^tVnC+X$W&uTNQZrxY0U@`i4%nf>p9?z7_u&p^SObf27<KjrG$%Fge9{axOv
zzv-6beD<7_Z6<8JzZ<&G^d0+ghh62m#C`*X1x7?5GX_Q`Ij;r=MkW@H0^{dpR{tFy
zPrT$@+x+0@wD9iy{dc}r?REUndD4B~oAhg&e>s2mO8fkIzEsbfl&>e<{~wpD7ZmGj
uu|I#uwvPG3KUD{aK>`YJ#)9%%<{C?e$g0J%KN%Pp7(8A5T-G@yGywpp?sRYf

literal 0
HcmV?d00001

diff --git a/ring-android/app/src/main/res/drawable/call_button.xml b/ring-android/app/src/main/res/drawable/call_button.xml
index 7e07ee47d..0a5c97189 100644
--- a/ring-android/app/src/main/res/drawable/call_button.xml
+++ b/ring-android/app/src/main/res/drawable/call_button.xml
@@ -1,11 +1,15 @@
 <?xml version="1.0" encoding="utf-8"?>
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <item android:state_enabled="true" android:state_pressed="true"><shape android:shape="oval">
+    <item android:state_enabled="true" android:state_pressed="true">
+        <shape android:shape="oval">
             <solid android:color="@color/sfl_light_blue" />
-        </shape></item>
-    <item><shape android:shape="oval">
-            <solid android:color="@color/sfl_dark_blue" />
-        </shape></item>
+        </shape>
+    </item>
+    <item>
+        <shape android:shape="oval">
+            <solid android:color="@color/color_primary_dark" />
+        </shape>
+    </item>
 
 </selector>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/drawable/drawer_disc_handle.xml b/ring-android/app/src/main/res/drawable/drawer_disc_handle.xml
index 6d0063863..bf5d4b91f 100644
--- a/ring-android/app/src/main/res/drawable/drawer_disc_handle.xml
+++ b/ring-android/app/src/main/res/drawable/drawer_disc_handle.xml
@@ -1,14 +1,20 @@
 <?xml version="1.0" encoding="utf-8"?>
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <item android:state_enabled="true" android:state_pressed="true"><shape android:shape="oval">
-            <solid android:color="@color/sfl_dark_blue" />
-        </shape></item>
-    <item android:state_enabled="false"><shape android:shape="oval">
-            <solid android:color="@color/sfl_dark_blue" />
-        </shape></item>
-    <item><shape android:shape="oval">
-            <solid android:color="@color/sfl_dark_blue" />
-        </shape></item>
+    <item android:state_enabled="true" android:state_pressed="true">
+        <shape android:shape="oval">
+            <solid android:color="@color/color_primary_dark" />
+        </shape>
+    </item>
+    <item android:state_enabled="false">
+        <shape android:shape="oval">
+            <solid android:color="@color/color_primary_dark" />
+        </shape>
+    </item>
+    <item>
+        <shape android:shape="oval">
+            <solid android:color="@color/color_primary_dark" />
+        </shape>
+    </item>
 
 </selector>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/drawable/item_contact_selector.xml b/ring-android/app/src/main/res/drawable/item_contact_selector.xml
index 222289ec4..432c3fa25 100644
--- a/ring-android/app/src/main/res/drawable/item_contact_selector.xml
+++ b/ring-android/app/src/main/res/drawable/item_contact_selector.xml
@@ -1,20 +1,23 @@
 <?xml version="1.0" encoding="utf-8"?>
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <item android:state_pressed="true"><shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true">
+        <shape>
             <solid android:color="@color/sfl_pantone631_blue" />
-
-            <padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" />
-        </shape></item>
-    <item android:state_focused="true"><shape xmlns:android="http://schemas.android.com/apk/res/android">
+            <padding android:bottom="@dimen/padding_large" android:left="@dimen/padding_large" android:right="@dimen/padding_large" android:top="@dimen/padding_large" />
+        </shape>
+    </item>
+    <item android:state_focused="true">
+        <shape>
             <solid android:color="@color/sfl_pantone631_blue" />
-
-            <padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" />
-        </shape></item>
-    <item><shape xmlns:android="http://schemas.android.com/apk/res/android">
+            <padding android:bottom="@dimen/padding_large" android:left="@dimen/padding_large" android:right="@dimen/padding_large" android:top="@dimen/padding_large" />
+        </shape>
+    </item>
+    <item>
+        <shape>
             <solid android:color="@color/sfl_blue_0" />
-
-            <padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" />
-        </shape></item>
+            <padding android:bottom="@dimen/padding_large" android:left="@dimen/padding_large" android:right="@dimen/padding_large" android:top="@dimen/padding_large" />
+        </shape>
+    </item>
 
 </selector>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/drawable/item_generic_selector.xml b/ring-android/app/src/main/res/drawable/item_generic_selector.xml
index da0ba9513..231cdf47f 100644
--- a/ring-android/app/src/main/res/drawable/item_generic_selector.xml
+++ b/ring-android/app/src/main/res/drawable/item_generic_selector.xml
@@ -4,17 +4,17 @@
     <item android:state_pressed="true"><shape xmlns:android="http://schemas.android.com/apk/res/android">
             <solid android:color="@color/darker_gray" />
 
-            <padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" />
+            <padding android:bottom="@dimen/padding_large" android:left="@dimen/padding_large" android:right="@dimen/padding_large" android:top="@dimen/padding_large" />
         </shape></item>
     <item android:state_focused="true"><shape xmlns:android="http://schemas.android.com/apk/res/android">
             <solid android:color="@color/light" />
 
-            <padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" />
+            <padding android:bottom="@dimen/padding_large" android:left="@dimen/padding_large" android:right="@dimen/padding_large" android:top="@dimen/padding_large" />
         </shape></item>
     <item><shape xmlns:android="http://schemas.android.com/apk/res/android">
             <solid android:color="@color/light" />
 
-            <padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" />
+            <padding android:bottom="@dimen/padding_large" android:left="@dimen/padding_large" android:right="@dimen/padding_large" android:top="@dimen/padding_large" />
         </shape></item>
 
 </selector>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/drawable/item_history_selector.xml b/ring-android/app/src/main/res/drawable/item_history_selector.xml
index 77f7649a1..ee1120e12 100644
--- a/ring-android/app/src/main/res/drawable/item_history_selector.xml
+++ b/ring-android/app/src/main/res/drawable/item_history_selector.xml
@@ -1,20 +1,23 @@
 <?xml version="1.0" encoding="utf-8"?>
 <selector xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <item android:state_pressed="true"><shape xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:state_pressed="true">
+        <shape xmlns:android="http://schemas.android.com/apk/res/android">
             <solid android:color="@color/transparent_grey" />
-
-            <padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" />
-        </shape></item>
-    <item android:state_focused="true"><shape xmlns:android="http://schemas.android.com/apk/res/android">
+            <padding android:bottom="@dimen/padding_large" android:left="@dimen/padding_large" android:right="@dimen/padding_large" android:top="@dimen/padding_large" />
+        </shape>
+    </item>
+    <item android:state_focused="true">
+        <shape xmlns:android="http://schemas.android.com/apk/res/android">
             <solid android:color="@color/transparent_grey" />
-
-            <padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" />
-        </shape></item>
-    <item><shape xmlns:android="http://schemas.android.com/apk/res/android">
-            <solid android:color="@color/transparent_light" />
-
-            <padding android:bottom="10dp" android:left="10dp" android:right="10dp" android:top="10dp" />
-        </shape></item>
+            <padding android:bottom="@dimen/padding_large" android:left="@dimen/padding_large" android:right="@dimen/padding_large" android:top="@dimen/padding_large" />
+        </shape>
+    </item>
+    <item>
+        <shape xmlns:android="http://schemas.android.com/apk/res/android">
+            <solid android:color="@android:color/transparent" />
+            <padding android:bottom="@dimen/padding_large" android:left="@dimen/padding_large" android:right="@dimen/padding_large" android:top="@dimen/padding_large" />
+        </shape>
+    </item>
 
 </selector>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/drawable/toggle_speaker_selector.xml b/ring-android/app/src/main/res/drawable/toggle_speaker_selector.xml
index 7fed3f3f7..8160c5daf 100644
--- a/ring-android/app/src/main/res/drawable/toggle_speaker_selector.xml
+++ b/ring-android/app/src/main/res/drawable/toggle_speaker_selector.xml
@@ -16,7 +16,7 @@
         </layer-list></item>
     <item android:state_checked="true"><layer-list>
             <item><shape android:shape="rectangle">
-                    <solid android:color="@color/sfl_action_blue" />
+                    <solid android:color="@color/color_primary_light" />
 
                     <stroke android:width="1dp" android:color="@color/sfl_blue_lines" />
 
diff --git a/ring-android/app/src/main/res/layout/activity_account_settings.xml b/ring-android/app/src/main/res/layout/activity_account_settings.xml
index 13d726a2c..f9473ad64 100644
--- a/ring-android/app/src/main/res/layout/activity_account_settings.xml
+++ b/ring-android/app/src/main/res/layout/activity_account_settings.xml
@@ -1,20 +1,22 @@
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical" >
+    android:orientation="vertical"
+    tools:context=".client.AccountEditionActivity">
 
     <com.astuetz.PagerSlidingTabStrip
         android:id="@+id/pager_sliding_strip"
         android:layout_width="match_parent"
         android:layout_height="?android:attr/actionBarSize"
         android:layout_alignParentTop="true"
-        android:background="@color/sfl_blue_0"
         android:textColor="@color/white"
-        app:pstsIndicatorColor="@color/sfl_light_blue"
-        app:pstsUnderlineColor="@color/sfl_light_blue"
+        android:background="@color/color_primary_light_shadow"
+        app:pstsIndicatorColor="@color/color_primary_light"
+        app:pstsShouldExpand="true"
+        app:pstsUnderlineColor="@color/color_primary_light"
         />
-        <!---->
 
     <android.support.v4.view.ViewPager
         android:id="@+id/pager"
diff --git a/ring-android/app/src/main/res/layout/activity_call_layout.xml b/ring-android/app/src/main/res/layout/activity_call_layout.xml
index 8f1878a66..6649ef3de 100644
--- a/ring-android/app/src/main/res/layout/activity_call_layout.xml
+++ b/ring-android/app/src/main/res/layout/activity_call_layout.xml
@@ -30,11 +30,14 @@ shall include the source code for the parts of OpenSSL used as well
 as that of the covered work.
 -->
 
-<cx.ring.views.CallPaneLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/slidingpanelayout"
     android:layout_width="match_parent"
-    android:layout_height="match_parent" >
+    android:layout_height="match_parent"
+    tools:context=".client.CallActivity">
 
+    <!--
     <FrameLayout
         android:id="@+id/message_list_frame"
         android:layout_width="300dp"
@@ -43,6 +46,14 @@ as that of the covered work.
     <FrameLayout
         android:id="@+id/ongoingcall_pane"
         android:layout_width="match_parent"
-        android:layout_height="match_parent" />
+        android:layout_height="match_parent"
+        android:layout_gravity="right|center_vertical" />
+-->
+    <fragment
+        android:id="@+id/ongoingcall_pane"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:name="cx.ring.fragments.CallFragment"
+        tools:layout="@layout/frag_call" />
 
-</cx.ring.views.CallPaneLayout>
\ No newline at end of file
+</FrameLayout>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/layout/activity_home.xml b/ring-android/app/src/main/res/layout/activity_home.xml
index 5bbadcc73..8efc6e34e 100644
--- a/ring-android/app/src/main/res/layout/activity_home.xml
+++ b/ring-android/app/src/main/res/layout/activity_home.xml
@@ -32,20 +32,22 @@ as that of the covered work.
 
 <android.support.v4.widget.DrawerLayout xmlns:android="http://schemas.android.com/apk/res/android"
     xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/drawer_layout"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:fitsSystemWindows="true">
-
-    <cx.ring.views.SlidingUpPanelLayout
-        android:id="@+id/contact_panel"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent">
+    android:fitsSystemWindows="true"
+    tools:context=".client.HomeActivity">
 
         <RelativeLayout
             android:layout_width="match_parent"
             android:layout_height="match_parent">
 
+            <ViewStub
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:id="@+id/viewStub" />
+
             <android.support.v7.widget.Toolbar
                 android:id="@+id/main_toolbar"
                 android:layout_width="match_parent"
@@ -53,53 +55,47 @@ as that of the covered work.
                 android:layout_alignParentLeft="true"
                 android:layout_alignParentStart="true"
                 android:layout_alignParentTop="true"
+                android:background="@color/actionbar"
 
-                android:background="@color/sfl_dark_blue"
                 android:elevation="4dp"
                 android:gravity="bottom"
                 android:longClickable="true"
-                android:minHeight="?android:attr/actionBarSize"
+                android:minHeight="?attr/actionBarSize"
                 android:popupTheme="@style/Theme.AppCompat.Light.NoActionBar"
-                android:theme="@style/MyActionBar"
+                android:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
                 app:contentInsetStart="72dp"
                 app:elevation="4dp"
                 app:popupTheme="@style/Theme.AppCompat.Light.NoActionBar"
-                app:titleMarginBottom="16dp" />
-
-            <FrameLayout
-                android:id="@+id/main_frame"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:layout_alignParentLeft="true"
-                android:layout_alignParentStart="true"
-                android:layout_below="@id/main_toolbar"
-                android:orientation="vertical" />
+                app:theme="@style/ThemeOverlay.AppCompat.Dark.ActionBar"
+                app:titleMarginBottom="@dimen/action_bar_title_margin_bottom" />
 
             <android.support.design.widget.FloatingActionButton
                 android:id="@+id/action_button"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_alignBottom="@id/main_toolbar"
+                android:layout_alignBottom="@+id/main_toolbar"
                 android:layout_alignParentLeft="true"
                 android:layout_alignParentStart="true"
-                android:layout_centerVertical="true"
-                android:layout_marginBottom="-20dp"
+                android:layout_marginBottom="@dimen/action_button_bpadding"
                 android:layout_marginLeft="16dp"
-                android:layout_marginStart="20dp"
+                android:layout_marginStart="16dp"
+                android:adjustViewBounds="false"
+                android:baselineAlignBottom="false"
                 android:elevation="4dp"
                 android:visibility="gone"
                 app:elevation="4dp"
                 app:fabSize="mini" />
-        </RelativeLayout>
 
-        <FrameLayout
-            android:id="@+id/contacts_frame"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:clickable="true"
-            android:focusable="true"
-            android:focusableInTouchMode="true" />
-    </cx.ring.views.SlidingUpPanelLayout>
+            <FrameLayout
+                android:id="@+id/main_frame"
+                android:layout_width="match_parent"
+                android:layout_height="match_parent"
+                android:layout_alignParentLeft="true"
+                android:layout_alignParentStart="true"
+                android:layout_below="@id/main_toolbar"
+                android:orientation="vertical" />
+
+        </RelativeLayout>
 
     <android.support.design.widget.NavigationView
         android:id="@+id/left_drawer"
diff --git a/ring-android/app/src/main/res/layout/activity_new_conversation.xml b/ring-android/app/src/main/res/layout/activity_new_conversation.xml
new file mode 100644
index 000000000..89be1eedf
--- /dev/null
+++ b/ring-android/app/src/main/res/layout/activity_new_conversation.xml
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context="cx.ring.client.NewConversationActivity">
+
+    <fragment
+        android:layout_width="fill_parent"
+        android:layout_height="fill_parent"
+        android:name="cx.ring.fragments.ContactListFragment"
+        android:id="@+id/fragment"
+        android:layout_alignParentTop="true"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentStart="true"
+        tools:layout="@layout/frag_contact_list" />
+</RelativeLayout>
diff --git a/ring-android/app/src/main/res/layout/frag_accounts_list.xml b/ring-android/app/src/main/res/layout/frag_accounts_list.xml
index 22d71dceb..ead1b9627 100644
--- a/ring-android/app/src/main/res/layout/frag_accounts_list.xml
+++ b/ring-android/app/src/main/res/layout/frag_accounts_list.xml
@@ -3,9 +3,7 @@
     xmlns:dslv="http://schemas.android.com/apk/res-auto"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical"
-    android:background="@color/white"
-    >
+    android:orientation="vertical">
 
         <TextView
             android:layout_width="match_parent"
@@ -33,7 +31,7 @@
                dslv:drag_scroll_start="0.33"
                dslv:drag_start_mode="onDown"
                dslv:float_alpha="0.6"
-               dslv:float_background_color="@color/sfl_action_blue"
+               dslv:float_background_color="@color/action_blue"
                dslv:remove_enabled="false"
                dslv:slide_shuffle_speed="0.3" />
 
diff --git a/ring-android/app/src/main/res/layout/frag_audio_mgmt.xml b/ring-android/app/src/main/res/layout/frag_audio_mgmt.xml
index 672492bf0..b89a291a0 100644
--- a/ring-android/app/src/main/res/layout/frag_audio_mgmt.xml
+++ b/ring-android/app/src/main/res/layout/frag_audio_mgmt.xml
@@ -60,7 +60,7 @@
                 dslv:drag_scroll_start="0.33"
                 dslv:drag_start_mode="onDown"
                 dslv:float_alpha="0.6"
-                dslv:float_background_color="@color/sfl_action_blue"
+                dslv:float_background_color="@color/action_blue"
                 dslv:remove_enabled="false"
                 dslv:slide_shuffle_speed="0.3" />
         </LinearLayout>
diff --git a/ring-android/app/src/main/res/layout/frag_call.xml b/ring-android/app/src/main/res/layout/frag_call.xml
index ce4d2b06a..fae787b81 100644
--- a/ring-android/app/src/main/res/layout/frag_call.xml
+++ b/ring-android/app/src/main/res/layout/frag_call.xml
@@ -1,84 +1,195 @@
 <?xml version="1.0" encoding="utf-8"?>
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:background="@drawable/bg_72"
-                android:divider="@drawable/divider">
-
-    <cx.ring.model.BubblesView
-            android:id="@+id/main_view"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_above="@+id/speaker_toggle"/>
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    tools:context=".client.CallActivity">
 
     <RelativeLayout
-            android:id="@+id/call_status_bar"
-            android:layout_width="match_parent"
-            android:layout_height="?android:attr/actionBarSize"
-            android:layout_alignParentTop="true">
+        android:id="@+id/main_view"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:layout_alignParentTop="true"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentStart="true">
 
-        <ImageView
-                android:id="@+id/image_call"
-                android:layout_width="wrap_content"
+        <!--
+        <Button
+            android:id="@+id/call_accept_btn"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentBottom="true"
+            android:layout_toLeftOf="@+id/call_refuse_btn"
+            android:layout_toStartOf="@+id/call_refuse_btn"
+            android:backgroundTint="#447542"
+            android:text="Accept" />
+
+        <Button
+            android:id="@+id/call_refuse_btn"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentEnd="true"
+            android:layout_alignParentRight="true"
+            android:layout_alignTop="@+id/call_accept_btn"
+            android:layout_marginEnd="58dp"
+            android:layout_marginRight="58dp"
+            android:backgroundTint="#ff6e6e"
+            android:text="Refuse" />
+-->
+        <RelativeLayout
+            android:id="@+id/contact_bubble_layout"
+            android:layout_width="fill_parent"
+            android:layout_height="200dp"
+            android:layout_centerHorizontal="true"
+            android:layout_centerVertical="true"
+            android:layout_marginBottom="16dp">
+
+            <ImageView
+                android:id="@+id/contact_bubble"
+                android:layout_width="200dp"
+                android:layout_height="fill_parent"
+                android:layout_above="@+id/contact_bubble_txt"
+                android:layout_centerHorizontal="true" />
+
+            <TextView
+                android:id="@+id/contact_bubble_txt"
+                android:layout_width="fill_parent"
                 android:layout_height="wrap_content"
-                android:layout_centerVertical="true"
-                android:layout_gravity="left"
-                android:layout_marginLeft="15dp"
-                android:layout_marginRight="10dp"
-                android:src="@drawable/ic_action_call"/>
+                android:layout_alignParentBottom="true"
+                android:layout_centerHorizontal="true"
+                android:gravity="center_horizontal"
+                android:text="Adrien Béraud"
+                android:textAlignment="gravity"
+                android:textAppearance="?android:attr/textAppearanceLarge"
+                android:textIsSelectable="true"
+                android:textColor="@color/text_color_primary" />
 
-        <TextView
-                android:id="@+id/call_status_txt"
+        </RelativeLayout>
+
+        <LinearLayout
+            android:orientation="horizontal"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentBottom="false"
+            android:layout_centerHorizontal="true"
+            android:layout_below="@+id/contact_bubble_layout">
+
+            <android.support.design.widget.FloatingActionButton
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_centerVertical="true"
-                android:layout_toRightOf="@+id/image_call"
-                android:textSize="12sp"
-                android:textColor="@color/white"/>
+                android:id="@+id/call_refuse_btn"
+                android:src="@drawable/ic_call_end_white_24dp"
+                app:backgroundTint="@color/error_red"
+                app:rippleColor="@android:color/white"
+                app:elevation="6dp"
+                app:pressedTranslationZ="12dp"
+                android:layout_below="@+id/contact_bubble_layout"
+                android:layout_centerHorizontal="true"
+                android:layout_margin="8dp" />
 
-        <ViewSwitcher
-                android:id="@+id/security_switcher"
+            <android.support.design.widget.FloatingActionButton
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_centerVertical="true"
-                android:visibility="gone"
-                android:layout_toLeftOf="@+id/dialpad_btn">
+                android:id="@+id/call_accept_btn"
+                android:src="@drawable/ic_call_white_24dp"
+                app:backgroundTint="#4caf50"
+                app:rippleColor="@android:color/white"
+                app:elevation="6dp"
+                app:pressedTranslationZ="12dp"
+                android:layout_below="@+id/contact_bubble_layout"
+                android:layout_toLeftOf="@+id/call_refuse_btn"
+                android:layout_toStartOf="@+id/call_refuse_btn"
+                android:layout_margin="8dp" />
+        </LinearLayout>
+
+        <android.support.design.widget.FloatingActionButton
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/call_hangup_btn"
+            android:src="@drawable/ic_call_end_white_24dp"
+            app:backgroundTint="@color/error_red"
+            app:rippleColor="@android:color/white"
+            app:elevation="6dp"
+            app:pressedTranslationZ="12dp"
+            android:layout_below="@+id/contact_bubble_layout"
+            android:layout_centerHorizontal="true"
+            android:layout_margin="8dp"
+            android:visibility="gone" />
+
+    </RelativeLayout>
+
+    <RelativeLayout
+        android:id="@+id/call_status_bar"
+        android:layout_width="match_parent"
+        android:layout_height="?android:attr/actionBarSize"
+        android:layout_alignParentTop="true"
+        android:visibility="visible">
+
+        <ImageView
+            android:id="@+id/image_call"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:layout_gravity="left"
+            android:layout_marginLeft="15dp"
+            android:layout_marginRight="10dp"
+            android:src="@drawable/ic_action_call" />
+
+        <TextView
+            android:id="@+id/call_status_txt"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:layout_toRightOf="@+id/image_call"
+            android:textColor="@color/text_color_primary"
+            android:textSize="12sp" />
+
+        <ViewSwitcher
+            android:id="@+id/security_switcher"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_centerVertical="true"
+            android:visibility="gone">
 
             <Button
-                    android:id="@+id/confirm_sas"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_gravity="center"
-                    android:textSize="12sp"
-                    android:textColor="@color/white"/>
+                android:id="@+id/confirm_sas"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="center"
+                android:textColor="@color/white"
+                android:textSize="12sp" />
 
             <ImageView
-                    android:id="@+id/lock_image"
-                    android:layout_gravity="end|center_vertical"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"/>
+                android:id="@+id/lock_image"
+                android:layout_width="wrap_content"
+                android:layout_height="wrap_content"
+                android:layout_gravity="end|center_vertical" />
         </ViewSwitcher>
 
 
-        <ImageButton
-                android:id="@+id/dialpad_btn"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_alignParentRight="true"
-                android:layout_centerVertical="true"
-                android:layout_marginRight="10dp"
-                android:background="@null"
-                android:src="@drawable/ic_action_dial_pad_light"/>
+        <ImageView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:id="@+id/security_indicator"
+            android:src="@drawable/ic_lock_white_24dp"
+            android:tint="#4caf50"
+            android:layout_centerVertical="true"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
+            android:layout_margin="16dp"
+            android:visibility="gone" />
 
     </RelativeLayout>
 
     <ToggleButton
-            android:id="@+id/speaker_toggle"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:textOn=""
-            android:textOff=""
-            android:background="@drawable/toggle_speaker_selector"
-            android:layout_alignParentBottom="true"/>
+        android:id="@+id/speaker_toggle"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:background="@drawable/toggle_speaker_selector"
+        android:textOff=""
+        android:textOn=""
+        android:visibility="gone" />
 
 </RelativeLayout>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/layout/frag_call_list.xml b/ring-android/app/src/main/res/layout/frag_call_list.xml
index 3be66f9e7..91d868629 100644
--- a/ring-android/app/src/main/res/layout/frag_call_list.xml
+++ b/ring-android/app/src/main/res/layout/frag_call_list.xml
@@ -31,30 +31,34 @@ as that of the covered work.
 -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent">
+    xmlns:app="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    android:paddingTop="@dimen/padding_small"
+    android:background="@android:color/white">
 
-    <RelativeLayout
-            android:id="@+id/confs_layouts"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:layout_margin="10dp"
-            android:background="@drawable/item_generic_selector">
+    <ListView
+        android:id="@+id/confs_list"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:divider="@null"
+        tools:listitem="@layout/item_calllist">
+    </ListView>
 
-        <TextView
-                android:id="@+id/confs_counter"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:gravity="center"
-                android:layout_alignParentTop="true"
-                android:textSize="30sp"/>
-
-        <ListView
-                android:id="@+id/confs_list"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:layout_below="@+id/confs_counter">
-        </ListView>
-    </RelativeLayout>
+    <android.support.design.widget.FloatingActionButton
+        android:id="@+id/newconv_fab"
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        android:layout_alignParentBottom="true"
+        android:layout_alignParentEnd="true"
+        android:layout_alignParentRight="true"
+        android:layout_gravity="bottom|end"
+        android:layout_margin="@dimen/fab_compat_margin"
+        android:src="@drawable/ic_add_white_24dp"
+        app:backgroundTint="@color/error_red"
+        app:rippleColor="@android:color/white"
+        app:elevation="6dp"
+        app:pressedTranslationZ="12dp" />
 
 </RelativeLayout>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/layout/frag_contact_list.xml b/ring-android/app/src/main/res/layout/frag_contact_list.xml
index 740e72f7f..f056e77fa 100644
--- a/ring-android/app/src/main/res/layout/frag_contact_list.xml
+++ b/ring-android/app/src/main/res/layout/frag_contact_list.xml
@@ -32,65 +32,21 @@ as that of the covered work.
 -->
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:swipe="http://schemas.android.com/apk/res-auto"
+    xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/drag_view"
     android:layout_width="match_parent"
     android:layout_height="match_parent"
-    android:orientation="vertical" >
+    android:orientation="vertical"
+    tools:context=".client.DetailHistoryActivity">
 
-    <RelativeLayout
-        android:id="@+id/slider_button"
-        android:layout_width="match_parent"
-        android:layout_height="68dp" >
-
-        <RelativeLayout
-            android:layout_width="match_parent"
-            android:layout_height="@dimen/contact_drawer_handle_height"
-            android:layout_alignParentBottom="true"
-            android:background="@color/sfl_dark_blue" >
-
-            <TextView
-                android:id="@+id/handle_title"
-                android:layout_width="match_parent"
-                android:layout_height="match_parent"
-                android:layout_alignParentBottom="true"
-                android:layout_centerInParent="true"
-                android:gravity="center"
-                android:text="Contacts"
-                android:textColor="@color/white"
-                android:textStyle="bold" />
-
-            <ImageButton
-                android:id="@+id/contact_search_button"
-                android:layout_width="wrap_content"
-                android:layout_height="wrap_content"
-                android:layout_alignParentBottom="true"
-                android:layout_alignParentRight="true"
-                android:background="@color/sfl_dark_blue"
-                android:gravity="center"
-                android:src="@drawable/ic_btn_search" >
-            </ImageButton>
-        </RelativeLayout>
-
-        <!-- Declared after for implicit z order -->
-
-        <cx.ring.views.HalfCircleImageView
-            android:id="@+id/hello"
-            android:layout_width="112dp"
-            android:layout_height="68dp"
-            android:layout_alignParentBottom="true"
-            android:layout_centerHorizontal="true"
-            android:src="@drawable/ic_action_group" />
-    </RelativeLayout>
-
-    <cx.ring.views.stickylistheaders.StickyListHeadersListView
+    <se.emilsjolander.stickylistheaders.StickyListHeadersListView
         android:id="@+id/contacts_stickylv"
         android:layout_width="match_parent"
         android:layout_height="match_parent"
-        android:background="@color/sfl_dark_blue"
         android:drawSelectorOnTop="true"
         android:fastScrollEnabled="true"
-        android:scrollbarStyle="outsideOverlay" />
+        android:scrollbarStyle="outsideOverlay"
+        android:divider="@null" />
 
     <TextView
         android:id="@android:id/empty"
diff --git a/ring-android/app/src/main/res/layout/frag_contact_list_header.xml b/ring-android/app/src/main/res/layout/frag_contact_list_header.xml
index 873e92cf8..d2ee4d899 100644
--- a/ring-android/app/src/main/res/layout/frag_contact_list_header.xml
+++ b/ring-android/app/src/main/res/layout/frag_contact_list_header.xml
@@ -1,42 +1,53 @@
 <?xml version="1.0" encoding="utf-8"?>
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-              android:id="@+id/container"
-              android:layout_width="match_parent"
-              android:layout_height="wrap_content"
-              android:background="@color/sfl_dark_blue"
-              android:orientation="vertical">
+    xmlns:tools="http://schemas.android.com/tools"
+    android:id="@+id/container"
+    android:layout_width="match_parent"
+    android:layout_height="wrap_content"
+    android:orientation="vertical">
 
-    <SearchView
-            android:id="@+id/contact_search"
-            android:layout_width="match_parent"
-            android:queryHint="@string/searchbar_hint"
-            android:layout_height="?android:attr/actionBarSize"
-            android:background="@color/lighter_gray"/>
+    <include
+        android:layout_width="wrap_content"
+        android:layout_height="wrap_content"
+        layout="@layout/item_contact"
+        android:layout_gravity="center_horizontal"
+        android:id="@+id/newcontact_element" />
 
     <TextView
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:drawableLeft="@drawable/ic_action_important"
-            android:gravity="center_vertical"
-            android:text="@string/starred_contacts_title"
-            android:textColor="@color/white"
-            android:textStyle="bold"/>
+        android:layout_width="match_parent"
+        android:layout_height="48dp"
+        android:background="@android:color/white"
+        android:gravity="center_vertical"
+        android:text="@string/starred_contacts_title"
+        android:textColor="@color/text_color_secondary"
+        android:id="@+id/fav_head_label"
+        android:textStyle="bold"
+        android:textSize="16sp"
+        android:paddingLeft="16dp" />
+
+    <ImageView
+        android:layout_width="fill_parent"
+        android:layout_height="1dp"
+        android:id="@+id/imageView3"
+        android:layout_gravity="bottom"
+        android:background="#e0e0e0" />
 
     <LinearLayout
-            android:id="@+id/llMain"
-            android:layout_width="match_parent"
-            android:layout_height="wrap_content"
-            android:background="@color/sfl_blue_0"
-            android:padding="10dp">
+        android:id="@+id/llMain"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:padding="8dp"
+        android:background="@android:color/white">
 
         <GridView
-                android:id="@+id/favorites_grid"
-                android:layout_width="match_parent"
-                android:layout_height="wrap_content"
-                android:columnWidth="80dp"
-                android:numColumns="auto_fit"
-                android:stretchMode="spacingWidth"
-                android:verticalSpacing="@dimen/contact_vertical_spacing"/>
+            android:id="@+id/favorites_grid"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:columnWidth="80dp"
+            android:numColumns="auto_fit"
+            android:stretchMode="spacingWidth"
+            android:verticalSpacing="@dimen/contact_vertical_spacing"
+            tools:listitem="@layout/item_contact_starred" />
     </LinearLayout>
 
 </LinearLayout>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/layout/frag_conversation.xml b/ring-android/app/src/main/res/layout/frag_conversation.xml
new file mode 100644
index 000000000..b2f8ee6a7
--- /dev/null
+++ b/ring-android/app/src/main/res/layout/frag_conversation.xml
@@ -0,0 +1,68 @@
+<?xml version="1.0" encoding="utf-8"?>
+<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:orientation="vertical" android:layout_width="match_parent"
+    android:layout_height="match_parent"
+    tools:context=".client.ConversationActivity">
+
+    <ListView
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:id="@+id/hist_list"
+        android:layout_weight="1"
+        android:transcriptMode="alwaysScroll"
+        android:stackFromBottom="true"
+        android:divider="@null"
+        android:background="#ebeff0"
+        android:listSelector="@android:color/transparent"
+        tools:listitem="@layout/item_textmsg" />
+
+    <RelativeLayout
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_gravity="center_horizontal"
+        android:background="#e3c1c1"
+        android:id="@+id/ongoingcall_pane">
+
+        <TextView
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:textAppearance="?android:attr/textAppearanceMedium"
+            android:text="Ongoing call"
+            android:id="@+id/textView2"
+            android:layout_centerVertical="true"
+            android:layout_centerHorizontal="true"
+            android:layout_margin="10dp" />
+    </RelativeLayout>
+
+    <ImageView
+        android:layout_width="fill_parent"
+        android:layout_height="1dp"
+        android:id="@+id/divider"
+        android:layout_gravity="center_horizontal"
+        android:background="#bdbdbd" />
+
+    <LinearLayout
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@android:color/white"
+        android:elevation="6dp">
+
+        <EditText
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:id="@+id/msg_input_txt"
+            android:layout_weight="1" />
+
+        <ImageButton
+            android:layout_width="wrap_content"
+            android:layout_height="fill_parent"
+            android:id="@+id/msg_send"
+            android:src="@drawable/ic_send_black_24dp"
+            android:tint="@android:color/darker_gray"
+            android:background="@android:color/transparent"
+            android:padding="8dp" />
+    </LinearLayout>
+
+</LinearLayout>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/layout/frag_home.xml b/ring-android/app/src/main/res/layout/frag_home.xml
index c3ddd10f0..fc63c4335 100644
--- a/ring-android/app/src/main/res/layout/frag_home.xml
+++ b/ring-android/app/src/main/res/layout/frag_home.xml
@@ -3,23 +3,22 @@
     android:layout_width="match_parent"
     android:layout_height="match_parent"
     android:orientation="vertical" >
-
+<!--
     <ImageView
         android:layout_width="match_parent"
         android:layout_height="?android:attr/actionBarSize"
         android:layout_alignParentTop="true"
         android:background="@color/sfl_dark_blue" />
-
+-->
     <com.astuetz.PagerSlidingTabStrip
         android:id="@+id/pts_main"
         android:layout_width="match_parent"
         android:layout_height="?android:attr/actionBarSize"
         android:layout_alignParentTop="true"
-        android:background="@color/sfl_blue_0"
-        app:pstsIndicatorColor="@color/sfl_light_blue"
+        android:background="@color/color_primary_light_shadow"
+        app:pstsIndicatorColor="@color/color_primary_light"
         app:pstsShouldExpand="true"
-        app:pstsUnderlineColor="@color/sfl_light_blue"
-         />
+        app:pstsUnderlineColor="@color/color_primary_light" />
 
     <android.support.v4.view.ViewPager
         android:id="@+id/pager"
diff --git a/ring-android/app/src/main/res/layout/frag_imessaging.xml b/ring-android/app/src/main/res/layout/frag_imessaging.xml
index e975a7518..cc569d027 100644
--- a/ring-android/app/src/main/res/layout/frag_imessaging.xml
+++ b/ring-android/app/src/main/res/layout/frag_imessaging.xml
@@ -10,7 +10,7 @@
         android:layout_above="@+id/form"
         android:stackFromBottom="true"
         android:transcriptMode="alwaysScroll"
-        android:background="@color/sfl_dark_blue"
+        android:background="@color/color_primary_dark"
         android:layout_alignParentTop="true" >
     </ListView>
 
diff --git a/ring-android/app/src/main/res/layout/frag_menu_header.xml b/ring-android/app/src/main/res/layout/frag_menu_header.xml
index 43686adbd..6a6f118ad 100644
--- a/ring-android/app/src/main/res/layout/frag_menu_header.xml
+++ b/ring-android/app/src/main/res/layout/frag_menu_header.xml
@@ -2,7 +2,7 @@
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
     android:layout_height="wrap_content"
-    android:background="@color/sfl_blue_0"
+    android:background="@color/color_primary_dark"
     android:paddingBottom="8dp"
     android:paddingRight="5dp"
     android:paddingTop="40dp"
diff --git a/ring-android/app/src/main/res/layout/header.xml b/ring-android/app/src/main/res/layout/header.xml
index d9c5b4788..36fc52c54 100644
--- a/ring-android/app/src/main/res/layout/header.xml
+++ b/ring-android/app/src/main/res/layout/header.xml
@@ -1,8 +1,8 @@
 <?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
-    android:background="@null"
+    android:layout_height="48dp"
+    android:background="@android:color/white"
     android:clickable="false"
     android:focusable="false"
     android:orientation="vertical" >
@@ -13,10 +13,21 @@
         android:layout_height="wrap_content"
         android:clickable="false"
         android:focusable="false"
-        android:textColor="@color/white"
-        android:background="@color/sfl_dark_blue"
+        android:textColor="@color/text_color_secondary"
         android:paddingLeft="5dp"
-        android:textSize="14sp"
-        android:textStyle="bold" />
+        android:textSize="16sp"
+        android:textStyle="bold"
+        android:layout_marginLeft="16dp"
+        android:text="A"
+        android:layout_gravity="center_vertical" />
 
-</LinearLayout>
\ No newline at end of file
+    <ImageView
+        android:layout_width="fill_parent"
+        android:layout_height="1dp"
+        android:id="@+id/imageView2"
+        android:layout_gravity="bottom"
+        android:background="#e0e0e0"
+        android:layout_marginLeft="16dp"
+        android:layout_marginRight="16dp" />
+
+</FrameLayout>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/layout/item_account.xml b/ring-android/app/src/main/res/layout/item_account.xml
index 9629be8ad..d6a902038 100644
--- a/ring-android/app/src/main/res/layout/item_account.xml
+++ b/ring-android/app/src/main/res/layout/item_account.xml
@@ -20,7 +20,11 @@
         android:layout_alignParentLeft="true"
         android:layout_below="@+id/account_alias"
         android:textAppearance="@style/ListSecondary"
-        android:text="hostname" />
+        android:text="hostnamehostnamehostnamehostnamehostnamehostnamehostnamehostname"
+        android:ellipsize="middle"
+        android:singleLine="true"
+        android:layout_toLeftOf="@+id/error_indicator"
+        android:layout_toStartOf="@+id/error_indicator" />
 
     <ImageView
         android:id="@+id/error_indicator"
@@ -31,6 +35,8 @@
         android:clickable="false"
         android:focusable="false"
         android:src="@drawable/ic_error_white_24dp"
-        android:focusableInTouchMode="false" />
+        android:focusableInTouchMode="false"
+        android:tint="@android:color/holo_red_light"
+        android:layout_marginLeft="16dp" />
 
 </RelativeLayout>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/layout/item_account_pref.xml b/ring-android/app/src/main/res/layout/item_account_pref.xml
index 92f0ae126..ee774ce51 100644
--- a/ring-android/app/src/main/res/layout/item_account_pref.xml
+++ b/ring-android/app/src/main/res/layout/item_account_pref.xml
@@ -27,13 +27,16 @@
 
     <TextView
         android:id="@+id/account_host"
-        android:layout_width="wrap_content"
+        android:layout_width="fill_parent"
         android:layout_height="wrap_content"
         android:layout_below="@+id/account_alias"
         android:layout_marginLeft="72dp"
         android:textAppearance="@style/ListSecondary"
-        android:text="hostname"
-        android:layout_alignParentLeft="true" />
+        android:text="hostnamehostnamehostnamehostnamehostname"
+        android:layout_alignParentLeft="true"
+        android:ellipsize="middle"
+        android:singleLine="true"
+        android:layout_marginRight="56dp" />
 
     <CheckBox
         android:id="@+id/account_checked"
@@ -64,6 +67,7 @@
         android:layout_marginRight="16dp"
         android:layout_centerVertical="true"
         android:layout_toStartOf="@+id/account_checked"
-        android:layout_toLeftOf="@+id/loading_indicator" />
+        android:layout_toLeftOf="@+id/loading_indicator"
+        android:tint="@color/error_red" />
 
 </RelativeLayout>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/layout/item_account_selected.xml b/ring-android/app/src/main/res/layout/item_account_selected.xml
index 3c2a19897..6abbe19e7 100644
--- a/ring-android/app/src/main/res/layout/item_account_selected.xml
+++ b/ring-android/app/src/main/res/layout/item_account_selected.xml
@@ -24,8 +24,12 @@
         android:layout_alignParentLeft="true"
         android:layout_below="@+id/account_alias"
         android:textAppearance="?android:attr/textAppearanceSmall"
-        android:textColor="@color/white"
-        android:text="hostname" />
+        android:textColor="@color/secondary_text_default_material_dark"
+        android:text="hostnamehostnamehostnamehostnamehostnamehostnamehostname"
+        android:singleLine="true"
+        android:ellipsize="middle"
+        android:layout_toLeftOf="@+id/error_indicator"
+        android:layout_toStartOf="@+id/error_indicator" />
 
     <ImageView
         android:id="@+id/error_indicator"
@@ -35,6 +39,7 @@
         android:layout_centerVertical="true"
         android:clickable="false"
         android:focusable="false"
-        android:src="@drawable/ic_error_white_24dp" />
+        android:src="@drawable/ic_error_white_24dp"
+        android:layout_marginLeft="16dp" />
 
 </RelativeLayout>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/layout/item_calllist.xml b/ring-android/app/src/main/res/layout/item_calllist.xml
index aa426e411..7cfe3e50c 100644
--- a/ring-android/app/src/main/res/layout/item_calllist.xml
+++ b/ring-android/app/src/main/res/layout/item_calllist.xml
@@ -1,42 +1,66 @@
 <?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2004-2015 Savoir-Faire Linux Inc.
+
+Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-->
+
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/call_entry"
-    android:layout_width="wrap_content"
-    android:layout_height="wrap_content"
-    android:layout_alignParentLeft="true"
-    android:layout_centerVertical="true"
-    android:background="@drawable/item_generic_selector" >
+    android:layout_width="match_parent"
+    android:layout_height="72dp"
+    android:background="@drawable/item_history_selector"
+    android:descendantFocusability="blocksDescendants">
+
+    <ImageView
+        android:id="@+id/photo"
+        android:layout_width="40dp"
+        android:layout_height="40dp"
+        android:background="@null"
+        android:scaleType="centerCrop"
+        android:layout_centerVertical="true"
+        android:layout_alignParentLeft="true"
+        android:layout_alignParentStart="true"
+        android:layout_marginRight="16dp" />
 
     <TextView
-        android:id="@+id/call_title"
+        android:id="@+id/msg_txt"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_alignParentLeft="true"
+        android:layout_alignParentLeft="false"
         android:layout_alignParentTop="true"
         android:ellipsize="marquee"
         android:marqueeRepeatLimit="marquee_forever"
         android:scrollHorizontally="true"
         android:singleLine="true"
-        android:text=""
-        android:textSize="20sp" />
+        android:textSize="16sp"
+        android:layout_toRightOf="@+id/photo"
+        android:textColor="@color/text_color_primary"
+        android:layout_marginTop="2dp" />
 
     <TextView
         android:id="@+id/call_status"
         android:layout_width="wrap_content"
         android:layout_height="wrap_content"
-        android:layout_alignParentLeft="true"
-        android:layout_below="@+id/call_title"
-        android:text=""
-        android:textSize="12sp" />
-
-    <TextView
-        android:id="@+id/call_time"
-        android:layout_width="wrap_content"
-        android:layout_height="wrap_content"
-        android:layout_below="@+id/call_title"
-        android:layout_toRightOf="@+id/call_status"
-        android:paddingLeft="10dp"
-        android:text=""
-        android:textSize="12sp" />
+        android:layout_alignParentLeft="false"
+        android:layout_below="@+id/msg_txt"
+        android:textSize="14sp"
+        android:layout_toRightOf="@+id/photo"
+        android:textColor="@color/text_color_secondary" />
 
 </RelativeLayout>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/layout/item_codec.xml b/ring-android/app/src/main/res/layout/item_codec.xml
index a604aa1cf..cd0bd51a4 100644
--- a/ring-android/app/src/main/res/layout/item_codec.xml
+++ b/ring-android/app/src/main/res/layout/item_codec.xml
@@ -1,8 +1,10 @@
 <?xml version="1.0" encoding="utf-8"?>
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/codec_container"
     android:layout_width="match_parent"
-    android:layout_height="?android:attr/listPreferredItemHeight" >
+    android:layout_height="?android:attr/listPreferredItemHeight"
+    tools:context=".client.AccountEditionActivity">
 
     <ImageView
             android:id="@+id/drag_handle"
@@ -11,7 +13,7 @@
             android:layout_centerVertical="true"
             android:layout_alignParentLeft="true"
             android:layout_marginLeft="10dp"
-            android:src="@drawable/handle"/>
+            android:src="@drawable/ic_reorder_black_24dp"/>
 
     <TextView
         android:id="@+id/codec_name"
diff --git a/ring-android/app/src/main/res/layout/item_contact.xml b/ring-android/app/src/main/res/layout/item_contact.xml
index 8b961b0fd..4d2647e47 100644
--- a/ring-android/app/src/main/res/layout/item_contact.xml
+++ b/ring-android/app/src/main/res/layout/item_contact.xml
@@ -33,110 +33,63 @@ as that of the covered work.
 
 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:layout_width="match_parent"
-    android:layout_height="match_parent" >
+    android:layout_height="wrap_content" >
 
     <RelativeLayout
+        android:id="@+id/contactview"
         android:layout_width="match_parent"
-        android:layout_height="match_parent"
-        android:background="@color/sfl_action_blue"
+        android:layout_height="wrap_content"
+        android:padding="16dp"
+        android:background="@android:color/white"
         android:descendantFocusability="blocksDescendants" >
 
-        <LinearLayout
-            android:id="@+id/contact_underview"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:layout_alignParentBottom="true"
-            android:layout_alignParentTop="true"
-            android:layout_centerVertical="true"
-            android:orientation="horizontal"
-            android:weightSum="6" >
+        <ImageView
+            android:id="@+id/photo"
+            android:layout_width="40dp"
+            android:layout_height="40dp"
+            android:contentDescription="@string/contact_picture_description"
+            android:scaleType="centerCrop" />
 
-            <ImageButton
-                android:id="@+id/quick_starred"
-                android:layout_width="0dp"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                android:background="@null"
-                android:contentDescription="@string/contact_quick_starred_description"
-                android:src="@drawable/ic_action_not_important" />
+        <TextView
+            android:id="@+id/display_name"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:gravity="center_vertical"
+            android:textColor="@color/text_color_primary"
+            android:textIsSelectable="false"
+            android:layout_centerVertical="true"
+            android:layout_toRightOf="@+id/photo"
+            android:layout_toEndOf="@+id/photo"
+            android:textSize="16sp"
+            android:layout_marginLeft="16dp" />
 
-            <ImageButton
-                android:id="@+id/quick_edit"
-                android:layout_width="0dp"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                android:background="@null"
-                android:contentDescription="@string/contact_quick_edit_description"
-                android:src="@drawable/ic_action_edit" />
+        <LinearLayout
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentRight="true"
+            android:layout_centerVertical="true"
+            android:divider="@drawable/divider"
+            android:showDividers="middle"
+            android:visibility="gone">
 
             <ImageButton
-                android:id="@+id/quick_discard"
-                android:layout_width="0dp"
-                android:layout_height="match_parent"
-                android:layout_weight="1"
-                android:background="@null"
-                android:contentDescription="@string/contact_quick_discard_description"
-                android:src="@drawable/ic_action_discard" />
-
-            <Space
-                android:layout_width="0dp"
-                android:layout_height="match_parent"
-                android:layout_weight="3" />
-        </LinearLayout>
-
-        <RelativeLayout
-            android:id="@+id/contactview"
-            android:layout_width="match_parent"
-            android:layout_height="match_parent"
-            android:background="@drawable/item_contact_selector" >
-
-            <ImageView
-                android:id="@+id/photo"
-                android:layout_width="70dp"
-                android:layout_height="70dp"
-                android:contentDescription="@string/contact_picture_description"
-                android:scaleType="centerCrop" />
-
-            <TextView
-                android:id="@+id/display_name"
+                android:id="@+id/quick_call"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_alignBottom="@+id/photo"
-                android:layout_alignTop="@+id/photo"
-                android:layout_marginLeft="15dp"
-                android:layout_toRightOf="@+id/photo"
-                android:gravity="center_vertical"
-                android:textAppearance="?android:attr/textAppearanceMedium"
-                android:textColor="@color/white"
-                android:textSize="14sp" />
+                android:layout_margin="5dp"
+                android:background="@null"
+                android:contentDescription="@string/contact_quick_call_description"
+                android:src="@drawable/ic_action_call" />
 
-            <LinearLayout
+            <ImageButton
+                android:id="@+id/quick_message"
                 android:layout_width="wrap_content"
                 android:layout_height="wrap_content"
-                android:layout_alignParentRight="true"
-                android:layout_centerVertical="true"
-                android:divider="@drawable/divider"
-                android:showDividers="middle" >
-
-                <ImageButton
-                    android:id="@+id/quick_call"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_margin="5dp"
-                    android:background="@null"
-                    android:contentDescription="@string/contact_quick_call_description"
-                    android:src="@drawable/ic_action_call" />
-
-                <ImageButton
-                    android:id="@+id/quick_message"
-                    android:layout_width="wrap_content"
-                    android:layout_height="wrap_content"
-                    android:layout_margin="5dp"
-                    android:background="@null"
-                    android:contentDescription="@string/contact_quick_msg_description"
-                    android:src="@drawable/ic_action_chat" />
-            </LinearLayout>
-        </RelativeLayout>
+                android:layout_margin="5dp"
+                android:background="@null"
+                android:contentDescription="@string/contact_quick_msg_description"
+                android:src="@drawable/ic_action_chat" />
+        </LinearLayout>
     </RelativeLayout>
 
 </LinearLayout>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/layout/item_contact_starred.xml b/ring-android/app/src/main/res/layout/item_contact_starred.xml
index d3426a757..6b9e396b9 100644
--- a/ring-android/app/src/main/res/layout/item_contact_starred.xml
+++ b/ring-android/app/src/main/res/layout/item_contact_starred.xml
@@ -1,32 +1,30 @@
 <?xml version="1.0" encoding="utf-8"?>
-<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
-    android:layout_width="match_parent"
-    android:layout_height="match_parent" >
-
-    <RelativeLayout
-        android:id="@+id/contactview"
-        android:layout_width="match_parent"
-        android:layout_height="match_parent" >
+<LinearLayout
+    xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="fill_parent"
+    android:layout_height="fill_parent"
+    android:id="@+id/contactview"
+    android:orientation="vertical">
 
         <ImageView
             android:id="@+id/photo"
-            android:layout_width="70dp"
-            android:layout_height="70dp"
+            android:layout_width="40dp"
+            android:layout_height="40dp"
             android:layout_centerHorizontal="true"
             android:contentDescription="@string/contact_picture_description"
-            android:scaleType="centerCrop" />
+            android:scaleType="centerCrop"
+            android:layout_gravity="center_horizontal" />
 
         <TextView
             android:id="@+id/display_name"
-            android:layout_width="wrap_content"
+            android:layout_width="match_parent"
             android:layout_height="wrap_content"
             android:layout_alignParentBottom="true"
             android:layout_below="@+id/photo"
             android:layout_centerHorizontal="true"
             android:gravity="center"
             android:singleLine="true"
-            android:textColor="@color/white"
+            android:textColor="@color/text_color_primary"
             android:textSize="12sp" />
-    </RelativeLayout>
 
 </LinearLayout>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/layout/item_history.xml b/ring-android/app/src/main/res/layout/item_history.xml
index d56455ae2..129787393 100644
--- a/ring-android/app/src/main/res/layout/item_history.xml
+++ b/ring-android/app/src/main/res/layout/item_history.xml
@@ -17,25 +17,15 @@ GNU General Public License for more details.
 You should have received a copy of the GNU General Public License   
 along with this program; if not, write to the Free Software         
  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.          
-                                                                    
-Additional permission under GNU GPL version 3 section 7:            
-                                                                    
-If you modify this program, or any covered work, by linking or      
-combining it with the OpenSSL project's OpenSSL library (or a       
-modified version of that library), containing parts covered by the  
-terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.    
-grants you additional permission to convey the resulting work.      
-Corresponding Source for a non-source form of such a combination    
-shall include the source code for the parts of OpenSSL used as well 
-as that of the covered work.
 -->
 
 <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
     android:id="@+id/contactview"
     android:layout_width="match_parent"
-    android:layout_height="match_parent"
+    android:layout_height="100dp"
     android:background="@drawable/item_history_selector"
-    android:descendantFocusability="blocksDescendants" >
+    android:descendantFocusability="blocksDescendants">
 
     <ImageButton
         android:id="@+id/photo"
@@ -54,7 +44,8 @@ as that of the covered work.
         android:layout_toRightOf="@+id/photo"
         android:paddingLeft="@dimen/padding_small"
         android:singleLine="true"
-        android:textAppearance="?android:attr/textAppearanceMedium" />
+        android:textAppearance="?android:attr/textAppearanceMedium"
+        android:text="Adrien" />
 
     <TextView
         android:id="@+id/date_start"
diff --git a/ring-android/app/src/main/res/layout/item_textmsg.xml b/ring-android/app/src/main/res/layout/item_textmsg.xml
new file mode 100644
index 000000000..ddef7b47a
--- /dev/null
+++ b/ring-android/app/src/main/res/layout/item_textmsg.xml
@@ -0,0 +1,155 @@
+<?xml version="1.0" encoding="utf-8"?><!--
+Copyright (C) 2004-2015 Savoir-Faire Linux Inc.
+
+Author: Adrien Béraud <adrien.beraud@savoirfairelinux.com>
+
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3 of the License, or
+(at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+-->
+<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="wrap_content"
+    android:layout_height="wrap_content">
+
+    <RelativeLayout
+        android:id="@+id/txt_entry_right"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@android:color/transparent"
+        android:padding="@dimen/padding_large"
+        android:focusable="false"
+        android:layout_gravity="right"
+        android:visibility="gone">
+
+        <TextView
+            android:id="@+id/msg_txt_right"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:background="@android:color/white"
+            android:ellipsize="marquee"
+            android:marqueeRepeatLimit="marquee_forever"
+            android:padding="12dp"
+            android:scrollHorizontally="true"
+            android:singleLine="false"
+            android:text="Ceci est un long message sur plusieurs lignes. Il apparaitera en multilignes"
+            android:textColor="@color/text_color_primary"
+            android:textSize="16sp"
+            android:focusable="true"
+            android:textIsSelectable="true"
+            android:layout_alignParentTop="true"
+            android:layout_alignParentRight="true"
+            android:layout_alignParentEnd="true"
+            android:layout_marginLeft="48dp" />
+
+        <TextView
+            android:id="@+id/msg_details_txt_right"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:text="Adrien - 12 mars"
+            android:textColor="@color/text_color_secondary"
+            android:textSize="14sp"
+            android:layout_below="@+id/msg_txt_right"
+            android:layout_alignRight="@+id/msg_txt_right"
+            android:layout_alignEnd="@+id/msg_txt_right" />
+    </RelativeLayout>
+
+    <RelativeLayout
+        android:id="@+id/txt_entry"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:background="@android:color/transparent"
+        android:padding="@dimen/padding_large"
+        android:focusable="false">
+
+        <ImageView
+            android:id="@+id/photo"
+            android:layout_width="40dp"
+            android:layout_height="40dp"
+            android:layout_alignParentLeft="true"
+            android:layout_alignParentStart="true"
+            android:layout_alignParentTop="true"
+            android:layout_marginRight="16dp"
+            android:background="@null"
+            android:scaleType="centerCrop" />
+
+        <TextView
+            android:id="@+id/msg_txt"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentTop="true"
+            android:layout_toEndOf="@+id/photo"
+            android:layout_toRightOf="@+id/photo"
+            android:background="@android:color/white"
+            android:ellipsize="marquee"
+            android:marqueeRepeatLimit="marquee_forever"
+            android:padding="12dp"
+            android:scrollHorizontally="true"
+            android:singleLine="false"
+            android:text="Ceci est un long message sur plusieurs lignes. Il apparaitera en multilignes"
+            android:textColor="@color/text_color_primary"
+            android:textSize="16sp"
+            android:focusable="true"
+            android:textIsSelectable="true"
+            android:layout_marginRight="48dp" />
+
+        <TextView
+            android:id="@+id/msg_details_txt"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentLeft="false"
+            android:layout_below="@+id/msg_txt"
+            android:layout_toRightOf="@+id/photo"
+            android:text="Adrien - 12 mars"
+            android:textColor="@color/text_color_secondary"
+            android:textSize="14sp" />
+
+    </RelativeLayout>
+
+    <RelativeLayout
+        android:id="@+id/call_entry"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:focusable="false"
+        android:descendantFocusability="blocksDescendants"
+        android:background="#ced8da"
+        android:padding="12dp"
+        android:layout_marginBottom="16dp"
+        android:layout_gravity="right|bottom"
+        android:visibility="gone">
+
+        <TextView
+            android:id="@+id/call_hist_txt"
+            android:layout_width="fill_parent"
+            android:layout_height="wrap_content"
+            android:ellipsize="marquee"
+            android:marqueeRepeatLimit="marquee_forever"
+            android:scrollHorizontally="true"
+            android:singleLine="false"
+            android:text="Appel manqué"
+            android:textColor="@color/text_color_primary"
+            android:textSize="14sp"
+            />
+
+        <TextView
+            android:id="@+id/call_details_txt"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content"
+            android:layout_alignParentLeft="false"
+            android:text="Adrien - 12 mars"
+            android:textColor="@color/text_color_secondary"
+            android:textSize="12sp"
+            android:layout_below="@+id/call_hist_txt" />
+
+    </RelativeLayout>
+</FrameLayout>
diff --git a/ring-android/app/src/main/res/menu/ac_call.xml b/ring-android/app/src/main/res/menu/ac_call.xml
index 7e7469926..eff7bf789 100644
--- a/ring-android/app/src/main/res/menu/ac_call.xml
+++ b/ring-android/app/src/main/res/menu/ac_call.xml
@@ -4,7 +4,7 @@
     <item
         android:id="@+id/menuitem_chat"
         android:showAsAction="always"
-        android:icon="@drawable/ic_action_chat"
+        android:icon="@drawable/ic_chat_white_24dp"
         android:title="@string/ab_action_chat"/>
 
 </menu>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/menu/conversation_actions.xml b/ring-android/app/src/main/res/menu/conversation_actions.xml
new file mode 100644
index 000000000..601faf44d
--- /dev/null
+++ b/ring-android/app/src/main/res/menu/conversation_actions.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:app="http://schemas.android.com/apk/res-auto">
+        <item
+            android:id="@+id/conv_action_videocall"
+            android:icon="@drawable/ic_videocam_white_24dp"
+            android:title="Video call"
+            android:showAsAction="always"
+            />
+        <item
+            android:id="@+id/conv_action_audiocall"
+            android:icon="@drawable/ic_call_white_24dp"
+            android:title="Audio call"
+            android:showAsAction="always"/>
+</menu>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/menu/newconv_option_menu.xml b/ring-android/app/src/main/res/menu/newconv_option_menu.xml
new file mode 100644
index 000000000..9ef81223b
--- /dev/null
+++ b/ring-android/app/src/main/res/menu/newconv_option_menu.xml
@@ -0,0 +1,8 @@
+<?xml version="1.0" encoding="utf-8"?>
+<menu xmlns:android="http://schemas.android.com/apk/res/android">
+    <item android:id="@+id/contact_search"
+        android:title="Nom d'un contact ou numéro"
+        android:icon="@drawable/ic_btn_search"
+        android:showAsAction="collapseActionView|ifRoom"
+        android:actionViewClass="android.widget.SearchView" />
+</menu>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/values-land/dimens.xml b/ring-android/app/src/main/res/values-land/dimens.xml
new file mode 100644
index 000000000..b2c3f525d
--- /dev/null
+++ b/ring-android/app/src/main/res/values-land/dimens.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2004-2014 Savoir-Faire Linux Inc.                     
+                                                                    
+Author: Adrien Beraud <adrien.beraud@gmail.com>                     
+                                                                    
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3 of the License, or   
+(at your option) any later version.
+                                                                    
+This program is distributed in the hope that it will be useful,     
+but WITHOUT ANY WARRANTY; without even the implied warranty of      
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the       
+GNU General Public License for more details.                        
+                                                                    
+You should have received a copy of the GNU General Public License   
+along with this program; if not, write to the Free Software         
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.          
+                                                                    
+Additional permission under GNU GPL version 3 section 7:            
+                                                                    
+If you modify this program, or any covered work, by linking or      
+combining it with the OpenSSL project's OpenSSL library (or a       
+modified version of that library), containing parts covered by the  
+terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.    
+grants you additional permission to convey the resulting work.      
+Corresponding Source for a non-source form of such a combination    
+shall include the source code for the parts of OpenSSL used as well 
+as that of the covered work.
+-->
+<resources>
+
+    <dimen name="action_bar_title_margin_bottom">10dp</dimen>
+
+</resources>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/values-sw600dp/dimens.xml b/ring-android/app/src/main/res/values-sw600dp/dimens.xml
new file mode 100644
index 000000000..bcb3ccb03
--- /dev/null
+++ b/ring-android/app/src/main/res/values-sw600dp/dimens.xml
@@ -0,0 +1,36 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2004-2014 Savoir-Faire Linux Inc.                     
+                                                                    
+Author: Adrien Beraud <adrien.beraud@gmail.com>                     
+                                                                    
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3 of the License, or   
+(at your option) any later version.
+                                                                    
+This program is distributed in the hope that it will be useful,     
+but WITHOUT ANY WARRANTY; without even the implied warranty of      
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the       
+GNU General Public License for more details.                        
+                                                                    
+You should have received a copy of the GNU General Public License   
+along with this program; if not, write to the Free Software         
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.          
+                                                                    
+Additional permission under GNU GPL version 3 section 7:            
+                                                                    
+If you modify this program, or any covered work, by linking or      
+combining it with the OpenSSL project's OpenSSL library (or a       
+modified version of that library), containing parts covered by the  
+terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.    
+grants you additional permission to convey the resulting work.      
+Corresponding Source for a non-source form of such a combination    
+shall include the source code for the parts of OpenSSL used as well 
+as that of the covered work.
+-->
+<resources>
+
+    <dimen name="action_bar_title_margin_bottom">20dp</dimen>
+
+</resources>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/values-v21/dimens.xml b/ring-android/app/src/main/res/values-v21/dimens.xml
new file mode 100644
index 000000000..f3c4cba48
--- /dev/null
+++ b/ring-android/app/src/main/res/values-v21/dimens.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="utf-8"?>
+<!--
+Copyright (C) 2004-2014 Savoir-Faire Linux Inc.                     
+                                                                    
+Author: Adrien Beraud <adrien.beraud@gmail.com>                     
+                                                                    
+This program is free software; you can redistribute it and/or modify
+it under the terms of the GNU General Public License as published by
+the Free Software Foundation; either version 3 of the License, or   
+(at your option) any later version.
+                                                                    
+This program is distributed in the hope that it will be useful,     
+but WITHOUT ANY WARRANTY; without even the implied warranty of      
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the       
+GNU General Public License for more details.                        
+                                                                    
+You should have received a copy of the GNU General Public License   
+along with this program; if not, write to the Free Software         
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.          
+                                                                    
+Additional permission under GNU GPL version 3 section 7:            
+                                                                    
+If you modify this program, or any covered work, by linking or      
+combining it with the OpenSSL project's OpenSSL library (or a       
+modified version of that library), containing parts covered by the  
+terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.    
+grants you additional permission to convey the resulting work.      
+Corresponding Source for a non-source form of such a combination    
+shall include the source code for the parts of OpenSSL used as well 
+as that of the covered work.
+-->
+<resources>
+
+    <dimen name="action_button_bpadding">-20dp</dimen>
+    <dimen name="fab_compat_margin">16dp</dimen>
+
+</resources>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/values-v21/styles.xml b/ring-android/app/src/main/res/values-v21/styles.xml
index cbf5228c9..89b7d60e2 100644
--- a/ring-android/app/src/main/res/values-v21/styles.xml
+++ b/ring-android/app/src/main/res/values-v21/styles.xml
@@ -1,22 +1,23 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
 
     <style name="AppThemeWithOverlay" parent="AppThemeBase">
-        <item name="android:actionBarStyle">@style/MyActionBar</item>
-        <item name="android:windowActionBarOverlay">true</item>
-        <item name="windowActionBarOverlay">true</item>
-        <item name="android:windowBackground">@drawable/bg_72</item>
         <item name="android:windowDrawsSystemBarBackgrounds">true</item>
-        <item name="android:statusBarColor">@android:color/transparent</item>
+        <item name="android:statusBarColor">@color/color_primary_light</item>
         <item name="android:windowTranslucentStatus">true</item>
     </style>
 
     <style name="AppThemeWithoutOverlay" parent="@android:style/Theme.Material.Light.DarkActionBar">
         <item name="android:actionBarStyle">@style/NativeActionBar</item>
+        <item name="android:colorAccent">@color/color_primary_light</item>
+        <item name="android:colorPrimary">@color/color_primary_light</item>
+        <item name="android:colorPrimaryDark">@color/color_primary_dark</item>
+
     </style>
 
     <style name="NativeActionBar" parent="@android:style/Widget.ActionBar">
-        <item name="android:background">@color/sfl_dark_blue</item>
+        <item name="android:background">@color/actionbar</item>
         <item name="android:titleTextStyle">@style/NativeActionBar.Text</item>
+        <item name="android:elevation">4dp</item>
     </style>
 
     <style name="NativeActionBar.Text" parent="@android:style/TextAppearance.Material.Widget.ActionBar.Title">
diff --git a/ring-android/app/src/main/res/values/colors.xml b/ring-android/app/src/main/res/values/colors.xml
index b21f6b043..bb377d68b 100644
--- a/ring-android/app/src/main/res/values/colors.xml
+++ b/ring-android/app/src/main/res/values/colors.xml
@@ -1,14 +1,24 @@
 <?xml version="1.0" encoding="utf-8"?>
 <resources>
-    
-    
-    <!-- SFL colors -->
+
+    <color name="color_primary_light">#3AC0D2</color>
+    <color name="color_primary_light_shadow">#40b5c6</color>
+
+    <color name="color_primary_dark">#004C60</color>
+
+
+    <color name="action_blue">#004C60</color>
+
+    <color name="actionbar">@color/color_primary_light</color>
+
+
+    <!-- SFL colors-->
     <color name="sfl_pantone631_blue">#56B0C9</color>
-    <color name="sfl_dark_blue">#09353c</color>
+    <!-- <color name="sfl_dark_blue">#09353c</color>
     
     <color name="sfl_another_blue">#051d21</color>
     <color name="sfl_action_blue">#AA2eadda</color>
-    
+     -->
     
     <color name="sfl_blue_0">#002930</color>
     
@@ -51,8 +61,12 @@
     <color name="holo_orange_dark">#ffff8800</color>
     <!-- A really bright Holo shade of blue -->
     <color name="holo_blue_bright">#ff00ddff</color>
-    
-    
+
     <color name="transparent_grey">#AACCCCCC</color>
-    
+
+    <color name="text_color_primary">@color/abc_primary_text_material_light</color>
+    <color name="text_color_secondary">@color/abc_secondary_text_material_light</color>
+    <color name="text_color_primary_dark">@color/abc_primary_text_material_dark</color>
+    <color name="text_color_secondary_dark">@color/abc_secondary_text_material_dark</color>
+
 </resources>
diff --git a/ring-android/app/src/main/res/values/dimens.xml b/ring-android/app/src/main/res/values/dimens.xml
index 2d3ac13ef..31e5c9287 100644
--- a/ring-android/app/src/main/res/values/dimens.xml
+++ b/ring-android/app/src/main/res/values/dimens.xml
@@ -47,8 +47,14 @@ as that of the covered work.
     <dimen name="contact_drawer_handle_height">36dp</dimen>
     <dimen name="contact_drawer_handle_height_with_shadow">40dp</dimen>
 
-    <dimen name="contact_vertical_spacing">10dp</dimen>
+    <dimen name="contact_vertical_spacing">16dp</dimen>
     
     
     <dimen name="header_history_detail">200dp</dimen>
+
+    <dimen name="action_button_bpadding">-35dp</dimen>
+    <dimen name="fab_compat_margin">0dp</dimen>
+
+    <dimen name="action_bar_title_margin_bottom">12dp</dimen>
+
 </resources>
\ No newline at end of file
diff --git a/ring-android/app/src/main/res/values/strings.xml b/ring-android/app/src/main/res/values/strings.xml
index b2584e7bd..597891934 100644
--- a/ring-android/app/src/main/res/values/strings.xml
+++ b/ring-android/app/src/main/res/values/strings.xml
@@ -63,8 +63,8 @@ as that of the covered work.
 
     <!-- Dialing Fragment -->
     <string name="dial_action_call">Call</string>
-    <string name="dial_error_no_number_dialed">Dial a number</string>
-    <string name="dial_hint">Type phone number</string>
+    <string name="dial_error_no_number_dialed">Dial a mNumber</string>
+    <string name="dial_hint">Type phone mNumber</string>
 
     <!-- History Fragment -->
     <string name="hist_replay_button">Replay</string>
@@ -89,7 +89,7 @@ as that of the covered work.
     <!-- ContactList Fragment -->
     <string name="no_contact_found">No contact found</string>
     <string name="starred_contacts_title">Favorites</string>
-    <string name="searchbar_hint">Enter name or phone number&#8230;</string>
+    <string name="searchbar_hint">Enter name or phone mNumber&#8230;</string>
 
     <!-- FileExplorerDFragement -->
     <string name="file_explorer_title">Select a file</string>
@@ -97,7 +97,7 @@ as that of the covered work.
     <!-- TransferDFragment -->
     <string name="transfer_to_another_call">Transfer to another current call:</string>
     <string name="transfer_no_other_call">No other calls pending</string>
-    <string name="transfer_type_number">Type number to transfer to:</string>
+    <string name="transfer_type_number">Type mNumber to transfer to:</string>
 
     <!-- Notifications -->
     <string name="notif_missed_call_title">Missed call</string>
diff --git a/ring-android/app/src/main/res/values/styles.xml b/ring-android/app/src/main/res/values/styles.xml
index 89379e3f8..0e1b43b60 100644
--- a/ring-android/app/src/main/res/values/styles.xml
+++ b/ring-android/app/src/main/res/values/styles.xml
@@ -1,16 +1,15 @@
 <resources xmlns:android="http://schemas.android.com/apk/res/android">
 
-    <style name="AppThemeBase" parent="Theme.AppCompat.Light.NoActionBar">
-
+    <style name="AppThemeBase" parent="@style/Theme.AppCompat.Light.NoActionBar">
+        <item name="actionBarStyle">@style/MyActionBar</item>
+        <item name="colorAccent">@color/color_primary_dark</item>
+        <item name="colorPrimary">@color/color_primary_light</item>
+        <item name="colorPrimaryDark">@color/color_primary_dark</item>
+        <item name="android:windowActionBarOverlay">true</item>
+        <item name="windowActionBarOverlay">true</item>
     </style>
 
     <style name="AppThemeWithOverlay" parent="AppThemeBase">
-
-        <item name="android:actionBarStyle">@style/MyActionBar</item>
-
-        <item name="android:windowActionBarOverlay">true</item>
-        <item name="windowActionBarOverlay">true</item>
-        <item name="android:windowBackground">@drawable/bg_72</item>
         <item name="android:activatedBackgroundIndicator">@drawable/navigation_selector</item>
     </style>
 
@@ -24,22 +23,26 @@
         <item name="android:actionBarStyle">@style/NativeActionBar</item>
     </style>
 
-    <style name="NativeActionBar" parent="@android:style/Widget.ActionBar">
-        <item name="android:background">@color/sfl_dark_blue</item>
-        <item name="titleTextStyle">@style/TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse</item>
-
-    </style>
-
-    <style name="NativeActionBar.Text" parent="@android:style/TextAppearance.Holo.Widget.ActionBar.Title">
+    <style name="NativeActionBar" parent="@android:style/Widget.DeviceDefault.Light.ActionBar.Solid.Inverse">
+        <item name="android:background">@color/color_primary_light</item>
+        <item name="elevation">4dp</item>
     </style>
 
-    <style name="MyActionBar" parent="@style/Widget.AppCompat.Light.ActionBar.Solid">
+    <style name="MyActionBar" parent="@style/Widget.AppCompat.ActionBar.Solid">
         <item name="android:textColorPrimary">@android:color/primary_text_dark</item>
+        <item name="android:textColorHighlight">@android:color/primary_text_dark</item>
         <item name="android:textColorSecondary">@android:color/secondary_text_dark</item>
+        <item name="colorControlNormal">@color/white</item>
         <item name="selectableItemBackground">?android:selectableItemBackground</item>
         <item name="selectableItemBackgroundBorderless">?android:selectableItemBackground</item>
-        <item name="actionMenuTextColor">@color/abc_primary_text_material_light</item>
+        <item name="titleTextStyle">@style/MyTitleTextStyle</item>
+        <item name="elevation">4dp</item>
     </style>
+
+    <style name="MyTitleTextStyle" parent="@style/TextAppearance.AppCompat.Widget.ActionBar.Title">
+        <item name="android:textColor">@color/error_red</item>
+    </style>
+
     <style name="MenuHeader" parent="Theme.AppCompat.Light.NoActionBar">
         <item name="android:textColorPrimary">@android:color/primary_text_dark</item>
         <item name="android:textColorSecondary">@android:color/secondary_text_dark</item>
diff --git a/ring-android/build.gradle b/ring-android/build.gradle
index cb5115855..f0c9817f0 100644
--- a/ring-android/build.gradle
+++ b/ring-android/build.gradle
@@ -4,7 +4,7 @@ buildscript {
         jcenter()
     }
     dependencies {
-        classpath 'com.android.tools.build:gradle:1.2.3'
+        classpath 'com.android.tools.build:gradle:1.3.+'
 
         // NOTE: Do not place your application dependencies here; they belong
         // in the individual module build.gradle files
diff --git a/ring-android/gradle/wrapper/gradle-wrapper.properties b/ring-android/gradle/wrapper/gradle-wrapper.properties
index 9e4462dda..62354ba52 100644
--- a/ring-android/gradle/wrapper/gradle-wrapper.properties
+++ b/ring-android/gradle/wrapper/gradle-wrapper.properties
@@ -1,6 +1,6 @@
-#Wed Jun 17 16:19:43 EDT 2015
+#Wed Jun 17 18:34:27 EDT 2015
 distributionBase=GRADLE_USER_HOME
 distributionPath=wrapper/dists
 zipStoreBase=GRADLE_USER_HOME
 zipStorePath=wrapper/dists
-distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-bin.zip
+distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip
diff --git a/ring-android/project.properties b/ring-android/project.properties
index 00cf62bac..916037e33 100644
--- a/ring-android/project.properties
+++ b/ring-android/project.properties
@@ -11,4 +11,4 @@
 #proguard.config=${sdk.dir}/tools/proguard/proguard-android.txt:proguard-project.txt
 
 # Project target.
-target=android-22
+target=android-23
diff --git a/ring-android/ring-android.iml b/ring-android/ring-android.iml
index aa770af9c..c30d36ecf 100644
--- a/ring-android/ring-android.iml
+++ b/ring-android/ring-android.iml
@@ -8,14 +8,14 @@
       </configuration>
     </facet>
   </component>
-  <component name="NewModuleRootManager" inherit-compiler-output="true">
+  <component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_7" inherit-compiler-output="true">
     <output url="file://$MODULE_DIR$/build/intermediates/classes/debug" />
     <output-test url="file://$MODULE_DIR$/build/intermediates/classes/androidTest/debug" />
     <exclude-output />
     <content url="file://$MODULE_DIR$">
       <excludeFolder url="file://$MODULE_DIR$/.gradle" />
     </content>
-    <orderEntry type="jdk" jdkName="Android API 22 Platform" jdkType="Android SDK" />
+    <orderEntry type="jdk" jdkName="Android API 23 Platform" jdkType="Android SDK" />
     <orderEntry type="sourceFolder" forTests="false" />
   </component>
 </module>
\ No newline at end of file
-- 
GitLab