=== modified file 'CMakeLists.txt'
--- CMakeLists.txt	2014-08-12 15:38:08 +0000
+++ CMakeLists.txt	2014-09-23 22:54:58 +0000
@@ -63,6 +63,7 @@
 add_subdirectory(lib)
 add_subdirectory(src)
 add_subdirectory(contacts)
+add_subdirectory(upstart)
 if(CMAKE_SYSTEM_PROCESSOR STREQUAL "ppc")
     # Some tests fail when running on PPPC check bug #1294229
     message(STATUS "Tests disable for ppc")

=== modified file 'contacts/CMakeLists.txt'
--- contacts/CMakeLists.txt	2014-03-19 12:21:35 +0000
+++ contacts/CMakeLists.txt	2014-09-23 22:54:58 +0000
@@ -4,7 +4,7 @@
 
 set(QCONTACTS_BACKEND_SRCS
     qcontact-backend.cpp
-    qcontact-engineid.cpp    
+    qcontact-engineid.cpp
     qcontactfetchrequest-data.cpp
     qcontactfetchbyidrequest-data.cpp
     qcontactremoverequest-data.cpp

=== modified file 'contacts/contacts-service.cpp'
--- contacts/contacts-service.cpp	2014-09-05 20:58:28 +0000
+++ contacts/contacts-service.cpp	2014-09-23 22:54:58 +0000
@@ -50,6 +50,9 @@
 #include <QtVersit/QVersitContactExporter>
 #include <QtVersit/QVersitWriter>
 
+// FIXME: remove use of QtGuiApp
+#include <QtGui/QGuiApplication>
+
 #define ALTERNATIVE_CPIM_SERVICE_PAGE_SIZE  "CANONICAL_PIM_SERVICE_PAGE_SIZE"
 #define FETCH_PAGE_SIZE                     25
 
@@ -101,8 +104,7 @@
 namespace galera
 {
 GaleraContactsService::GaleraContactsService(const QString &managerUri)
-    : m_selfContactId(),
-      m_managerUri(managerUri),
+    : m_managerUri(managerUri),
       m_serviceIsReady(false),
       m_iface(0)
 {
@@ -127,12 +129,16 @@
     connect(m_serviceWatcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)),
             this, SLOT(serviceOwnerChanged(QString,QString,QString)));
 
-    initialize();
+    initialize(true);
+
+    // FIXME: Remove use of QtGuiApp
+    connect(QGuiApplication::instance(),
+            SIGNAL(applicationStateChanged(Qt::ApplicationState)),
+            SLOT(onAppStateChanged(Qt::ApplicationState)));
 }
 
 GaleraContactsService::GaleraContactsService(const GaleraContactsService &other)
-    : m_selfContactId(other.m_selfContactId),
-      m_managerUri(other.m_managerUri),
+    : m_managerUri(other.m_managerUri),
       m_iface(other.m_iface)
 {
 }
@@ -157,10 +163,12 @@
     if (name == m_serviceName) {
         if (!newOwner.isEmpty()) {
             // service appear
-            initialize();
+            qDebug() << "Service appeared";
+            initialize(true);
         } else if (!m_iface.isNull()) {
             // lost service
-            deinitialize();
+            qDebug() << "Service disappeared";
+            deinitialize(true);
         }
     }
 }
@@ -176,7 +184,7 @@
     }
 }
 
-void GaleraContactsService::initialize()
+void GaleraContactsService::initialize(bool notify)
 {
     if (m_iface.isNull()) {
         m_iface = QSharedPointer<QDBusInterface>(new QDBusInterface(m_serviceName,
@@ -189,8 +197,9 @@
             connect(m_iface.data(), SIGNAL(contactsAdded(QStringList)), this, SLOT(onContactsAdded(QStringList)));
             connect(m_iface.data(), SIGNAL(contactsRemoved(QStringList)), this, SLOT(onContactsRemoved(QStringList)));
             connect(m_iface.data(), SIGNAL(contactsUpdated(QStringList)), this, SLOT(onContactsUpdated(QStringList)));
-
-            Q_EMIT serviceChanged();
+            if (notify) {
+                Q_EMIT serviceChanged();
+            }
         } else {
             qWarning() << "Fail to connect with service:"  << m_iface->lastError();
             m_iface.clear();
@@ -198,28 +207,29 @@
     }
 }
 
-void GaleraContactsService::deinitialize()
+void GaleraContactsService::deinitialize(bool clearIface)
 {
     Q_FOREACH(QContactRequestData* rData, m_runningRequests) {
         rData->cancel();
         rData->request()->waitForFinished();
         rData->finish(QContactManager::UnspecifiedError);
     }
-
-    if (!m_iface.isNull()) {
-        m_id.clear();
-        Q_EMIT serviceChanged();
-    }
+    m_runningRequests.clear();
 
     // this will make the service re-initialize
-    m_iface->call("ping");
-    if (m_iface->lastError().isValid()) {
+    if (!clearIface) {
+        m_iface->call("ping");
+    }
+
+    if (clearIface || m_iface->lastError().isValid()) {
         qWarning() << m_iface->lastError();
         m_iface.clear();
         m_serviceIsReady = false;
     } else {
         m_serviceIsReady = m_iface.data()->property("isReady").toBool();
     }
+
+    Q_EMIT serviceChanged();
 }
 
 bool GaleraContactsService::isOnline() const
@@ -429,6 +439,20 @@
     sender->deleteLater();
 }
 
+void GaleraContactsService::onAppStateChanged(Qt::ApplicationState state)
+{
+    switch(state) {
+    case Qt::ApplicationInactive:
+        suspend();
+        break;
+    case Qt::ApplicationActive:
+        resume();
+        break;
+    default:
+        break;
+    }
+}
+
 void GaleraContactsService::fetchContactsGroupsContinue(QContactFetchRequestData *data,
                                                         QDBusPendingCallWatcher *call)
 {
@@ -822,6 +846,58 @@
     return contactIds;
 }
 
+void GaleraContactsService::suspend()
+{
+    disconnect(m_serviceWatcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)),
+            this, SLOT(serviceOwnerChanged(QString,QString,QString)));
+
+    if (m_iface.isNull()) {
+        qDebug() << "Application already suspended" << this;
+        return;
+    }
+    Q_FOREACH(QContactRequestData* rData, m_runningRequests) {
+        rData->request()->waitForFinished();
+    }
+    m_runningRequests.clear();
+    m_serviceIsReady = false;
+    m_lastKnownUuid = m_iface.data()->property("uuid").toString();
+    m_iface.clear();
+    qDebug() << "Contacts in suspended state" << m_iface.isNull() << (void*) this;
+}
+
+void GaleraContactsService::resume()
+{
+    if (!m_iface.isNull()) {
+        return;
+    }
+
+    qDebug() << "Contacts starting the resume" << (void*) this;
+    qDebug() << "Last uuid" << m_lastKnownUuid;
+    initialize(false);
+    bool notify = false;
+
+    if (!m_iface.isNull()) {
+        QString newUuid = m_iface.data()->property("uuid").toString();
+        if (newUuid != m_lastKnownUuid) {
+            qDebug() << "Service has changed will notify";
+            notify = true;
+        }
+    } else {
+        qDebug() << "service is down will notify";
+        notify = true;
+    }
+
+    m_lastKnownUuid.clear();
+    connect(m_serviceWatcher, SIGNAL(serviceOwnerChanged(QString,QString,QString)),
+            this, SLOT(serviceOwnerChanged(QString,QString,QString)));
+
+    if (notify) {
+        Q_EMIT serviceChanged();
+    }
+
+    qDebug() << "Contacts resume completed";
+}
+
 void GaleraContactsService::onContactsAdded(const QStringList &ids)
 {
     Q_EMIT contactsAdded(parseIds(ids));

=== modified file 'contacts/contacts-service.h'
--- contacts/contacts-service.h	2014-05-27 14:41:55 +0000
+++ contacts/contacts-service.h	2014-09-23 22:54:58 +0000
@@ -77,22 +77,22 @@
     void serviceOwnerChanged(const QString &name, const QString &oldOwner, const QString &newOwner);
     void onServiceReady();
     void onVCardsParsed(QList<QtContacts::QContact> contacts);
+    void onAppStateChanged(Qt::ApplicationState state);
 
 private:
-    QString m_id;
-    QtContacts::QContactId m_selfContactId;                     // the "MyCard" contact id
     QString m_managerUri;                                       // for faster lookup.
     QDBusServiceWatcher *m_serviceWatcher;
     bool m_serviceIsReady;
     int m_pageSize;
+    QString m_lastKnownUuid;
 
     QSharedPointer<QDBusInterface> m_iface;
     QString m_serviceName;
     QSet<QContactRequestData*> m_runningRequests;
     QQueue<QPointer<QtContacts::QContactAbstractRequest> > m_pendingRequests;
 
-    Q_INVOKABLE void initialize();
-    Q_INVOKABLE void deinitialize();
+    Q_INVOKABLE void initialize(bool notify);
+    Q_INVOKABLE void deinitialize(bool clearIface);
 
     bool isOnline() const;
 
@@ -119,6 +119,9 @@
     void destroyRequest(QContactRequestData *request);
 
     QList<QContactId> parseIds(const QStringList &ids) const;
+
+    void suspend();
+    void resume();
 };
 
 }

=== modified file 'debian/address-book-service.install'
--- debian/address-book-service.install	2014-08-12 15:38:08 +0000
+++ debian/address-book-service.install	2014-09-23 22:54:58 +0000
@@ -1,2 +1,2 @@
 usr/lib/*/address-book-service/address-book-service
-upstart/address-book-service.conf /usr/share/upstart/sessions
+usr/share/upstart/sessions/address-book-service.conf

=== modified file 'lib/addressbook-adaptor.cpp'
--- lib/addressbook-adaptor.cpp	2014-04-09 19:45:40 +0000
+++ lib/addressbook-adaptor.cpp	2014-09-23 22:54:58 +0000
@@ -30,6 +30,13 @@
 {
     setAutoRelaySignals(true);
     connect(m_addressBook, SIGNAL(ready()), SIGNAL(ready()));
+
+    // notify any data change
+    connect(this, SIGNAL(contactsAdded(QStringList)), SLOT(serverDataChanged()));
+    connect(this, SIGNAL(contactsRemoved(QStringList)), SLOT(serverDataChanged()));
+    connect(this, SIGNAL(contactsUpdated(QStringList)), SLOT(serverDataChanged()));
+    connect(this, SIGNAL(reloaded()), SLOT(serverDataChanged()));
+    m_uuid = QUuid::createUuid();
 }
 
 AddressBookAdaptor::~AddressBookAdaptor()
@@ -139,4 +146,15 @@
     return true;
 }
 
+QString AddressBookAdaptor::uuid()
+{
+    return m_uuid.toString();
+}
+
+void AddressBookAdaptor::serverDataChanged()
+{
+    m_uuid = QUuid::createUuid();
+    Q_EMIT uuidChanged();
+}
+
 } //namespace

=== modified file 'lib/addressbook-adaptor.h'
--- lib/addressbook-adaptor.h	2014-09-05 20:58:28 +0000
+++ lib/addressbook-adaptor.h	2014-09-23 22:54:58 +0000
@@ -24,6 +24,7 @@
 #include <QtCore/QList>
 #include <QtCore/QString>
 #include <QtCore/QStringList>
+#include <QtCore/QUuid>
 
 #include "common/source.h"
 #include "common/dbus-service-defs.h"
@@ -38,6 +39,7 @@
     Q_CLASSINFO("D-Bus Introspection", ""
 "  <interface name=\"com.canonical.pim.AddressBook\">\n"
 "    <property name=\"isReady\" type=\"b\" access=\"read\"/>\n"
+"    <property name=\"uuid\" type=\"s\" access=\"read\"/>\n"
 "    <signal name=\"contactsUpdated\">\n"
 "      <arg direction=\"out\" type=\"as\" name=\"ids\"/>\n"
 "    </signal>\n"
@@ -52,6 +54,7 @@
 "    </signal>\n"
 "    <signal name=\"ready\"/>\n"
 "    <signal name=\"reloaded\"/>\n"
+"    <signal name=\"uuidChanged\"/>\n"
 "    <method name=\"ping\">\n"
 "      <arg direction=\"out\" type=\"b\"/>\n"
 "    </method>\n"
@@ -107,6 +110,7 @@
 "  </interface>\n"
         "")
     Q_PROPERTY(bool isReady READ isReady NOTIFY ready)
+    Q_PROPERTY(QString uuid READ uuid NOTIFY uuidChanged)
 public:
     AddressBookAdaptor(const QDBusConnection &connection, AddressBook *parent);
     virtual ~AddressBookAdaptor();
@@ -125,6 +129,7 @@
     bool unlinkContacts(const QString &parentId, const QStringList &contactsIds);
     bool isReady();
     bool ping();
+    QString uuid();
 
 Q_SIGNALS:
     void contactsAdded(const QStringList &ids);
@@ -133,10 +138,15 @@
     void asyncOperationResult(QMap<QString, QString> errors);
     void ready();
     void reloaded();
+    void uuidChanged();
+
+private Q_SLOTS:
+    void serverDataChanged();
 
 private:
     AddressBook *m_addressBook;
     QDBusConnection m_connection;
+    QUuid m_uuid;
 };
 
 } //namespace

=== modified file 'lib/addressbook.cpp'
--- lib/addressbook.cpp	2014-09-10 13:02:56 +0000
+++ lib/addressbook.cpp	2014-09-23 22:54:58 +0000
@@ -172,6 +172,7 @@
 
 void AddressBook::unprepareFolks()
 {
+    qDebug() << "Unprepare folks";
     // remove all contacts
     // flusing any pending notification
     m_notifyContactUpdate->flush();
@@ -200,6 +201,19 @@
         g_signal_handler_disconnect(m_individualAggregator,
                                     m_notifyIsQuiescentHandlerId);
         m_individualsChangedDetailedId = m_notifyIsQuiescentHandlerId = 0;
+
+        // make it sync
+        GMainLoop *waitLoop = g_main_loop_new(NULL, FALSE);
+        folks_individual_aggregator_unprepare(m_individualAggregator,
+                                              AddressBook::folksUnprepared,
+                                              waitLoop);
+        guint timeoutId = g_timeout_add_seconds(3,
+                                                AddressBook::folksUnprepareTimeout,
+                                                waitLoop);
+        // wait unprepare
+        g_main_loop_run(waitLoop);
+        g_main_loop_unref(waitLoop);
+        g_source_remove(timeoutId);
         g_clear_object(&m_individualAggregator);
     }
 }
@@ -226,6 +240,7 @@
 
 void AddressBook::prepareFolks()
 {
+    qDebug() << "Initialize folks";
     m_contacts = new ContactsMap;
     m_individualAggregator = folks_individual_aggregator_dup();
     g_object_get(G_OBJECT(m_individualAggregator), "is-quiescent", &m_ready, NULL);
@@ -390,6 +405,19 @@
     delete rData;
 }
 
+void AddressBook::folksUnprepared(GObject *source, GAsyncResult *res, void *data)
+{
+    GMainLoop *waitLoop = static_cast<GMainLoop*>(data);
+    folks_individual_aggregator_unprepare_finish(FOLKS_INDIVIDUAL_AGGREGATOR(source), res, NULL);
+    g_main_loop_quit(waitLoop);
+}
+
+gboolean AddressBook::folksUnprepareTimeout(gpointer data)
+{
+    GMainLoop *waitLoop = static_cast<GMainLoop*>(data);
+    g_main_loop_quit(waitLoop);
+    return FALSE;
+}
 
 void AddressBook::createSourceDone(GObject *source,
                                    GAsyncResult *res,
@@ -993,9 +1021,12 @@
 void AddressBook::checkForEds()
 {
     // Use maxRetry value to avoid infinite loop
-    static const int maxRerty = 10;
+    static const int maxRetry = 10;
     static int retryCount = 0;
-    if (retryCount >= maxRerty) {
+    if (retryCount >= maxRetry) {
+        // abort when reach the maxRetry
+        qWarning() << "Fail to start EDS the service will abort";
+        shutdown();
         return;
     }
     retryCount++;
@@ -1003,7 +1034,7 @@
     if (!m_edsIsLive) {
         // wait some ms to restart folks, this ms increase 500ms for each retryCount
         QTimer::singleShot(500 * retryCount, this, SLOT(reloadFolks()));
-        qWarning() << "EDS did not start, trying to reload folks;";
+        qWarning() << QDateTime::currentDateTime().toString() << "EDS did not start, trying to reload folks";
     } else {
         retryCount = 0;
     }
@@ -1011,6 +1042,7 @@
 
 void AddressBook::reloadFolks()
 {
+    qWarning() << "Trying to reload folks";
     unprepareFolks();
     prepareFolks();
 }

=== modified file 'lib/addressbook.h'
--- lib/addressbook.h	2014-09-10 13:02:56 +0000
+++ lib/addressbook.h	2014-09-23 22:54:58 +0000
@@ -166,6 +166,10 @@
     static void removeSourceDone(GObject *source,
                                  GAsyncResult *res,
                                  void *data);
+    static void folksUnprepared(GObject *source,
+                               GAsyncResult *res,
+                               void *data);
+    static gboolean folksUnprepareTimeout(gpointer data);
     friend class DirtyContactsNotify;
 };
 

=== renamed file 'upstart/address-book-service.conf' => 'upstart/address-book-service.conf.in'
--- upstart/address-book-service.conf	2014-09-11 18:56:47 +0000
+++ upstart/address-book-service.conf.in	2014-09-23 22:54:58 +0000
@@ -16,4 +16,4 @@
     echo "STOP `date`"
 end script
 
-exec /usr/lib/arm-linux-gnueabihf/address-book-service/address-book-service
+exec @CMAKE_INSTALL_FULL_LIBEXECDIR@/address-book-service/address-book-service

