Reset user changes to voicemails if the sync doesn't go through.

If a delete/read command doesn't get properly synced to the server,
simply set it back to the previous state so the user can try to
read/delete it later.
Also run a sync if signal goes back to "in service" since something may
have been missed while the signal was down.

Bug: 21978479
Change-Id: I1e40a7ff1d64f981be65516beff8f95b06fc1647
diff --git a/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java b/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
index 867a14f..1467e41 100644
--- a/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
+++ b/src/com/android/phone/vvm/omtp/sms/OmtpMessageReceiver.java
@@ -66,8 +66,13 @@
         if (messageData != null) {
             if (messageData.getPrefix() == OmtpConstants.SYNC_SMS_PREFIX) {
                 SyncMessage message = new SyncMessage(messageData);
+
+                Log.v(TAG, "Received SYNC sms for " + mPhoneAccount.getId() +
+                        " with event" + message.getSyncTriggerEvent());
+
                 processSync(message);
             } else if (messageData.getPrefix() == OmtpConstants.STATUS_SMS_PREFIX) {
+                Log.v(TAG, "Received STATUS sms for " + mPhoneAccount.getId());
                 StatusMessage message = new StatusMessage(messageData);
                 updateSource(message);
             } else {
@@ -121,8 +126,7 @@
                 VoicemailContract.Status.DATA_CHANNEL_STATE_OK,
                 VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_OK);
 
-        // Save the IMAP credentials in the corresponding account object so they are
-        // persistent and can be retrieved.
+        // Save the IMAP credentials in preferences so they are persistent and can be retrieved.
         VisualVoicemailSettingsUtil.setVisualVoicemailCredentialsFromStatusMessage(
                 mContext,
                 mPhoneAccount,
diff --git a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
index 59f5120..5af912c 100644
--- a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
+++ b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
@@ -162,15 +162,22 @@
         List<Voicemail> readVoicemails = mQueryHelper.getReadVoicemails();
         List<Voicemail> deletedVoicemails = mQueryHelper.getDeletedVoicemails();
 
-        if (deletedVoicemails != null &&
-                imapHelper.markMessagesAsDeleted(deletedVoicemails)) {
-            // We want to delete selectively instead of all the voicemails for this provider
-            // in case the state changed since the IMAP query was completed.
-            mQueryHelper.deleteFromDatabase(deletedVoicemails);
+        if (deletedVoicemails != null) {
+            if (imapHelper.markMessagesAsDeleted(deletedVoicemails)) {
+                // We want to delete selectively instead of all the voicemails for this provider
+                // in case the state changed since the IMAP query was completed.
+                mQueryHelper.deleteFromDatabase(deletedVoicemails);
+            } else {
+                mQueryHelper.markUndeletedInDatabase(deletedVoicemails);
+            }
         }
 
-        if (readVoicemails != null && imapHelper.markMessagesAsRead(readVoicemails)) {
-            mQueryHelper.markReadInDatabase(readVoicemails);
+        if (readVoicemails != null) {
+            if (imapHelper.markMessagesAsRead(readVoicemails)) {
+                mQueryHelper.markReadInDatabase(readVoicemails);
+            } else {
+                mQueryHelper.markUnreadInDatabase(readVoicemails);
+            }
         }
     }
 
diff --git a/src/com/android/phone/vvm/omtp/sync/VoicemailsQueryHelper.java b/src/com/android/phone/vvm/omtp/sync/VoicemailsQueryHelper.java
index f45adf7..2a30216 100644
--- a/src/com/android/phone/vvm/omtp/sync/VoicemailsQueryHelper.java
+++ b/src/com/android/phone/vvm/omtp/sync/VoicemailsQueryHelper.java
@@ -166,12 +166,38 @@
      * Utility method to mark single message as read.
      */
     public void markReadInDatabase(Voicemail voicemail) {
-        Uri uri = ContentUris.withAppendedId(mSourceUri, voicemail.getId());
-        ContentValues contentValues = new ContentValues();
-        contentValues.put(Voicemails.IS_READ, "1");
-        mContentResolver.update(uri, contentValues, null, null);
+        updateInDatabase(voicemail, Voicemails.IS_READ, "1");
     }
 
+    /**
+     * Undelete in database. This will be called if sync to server fails.
+     */
+    public void markUndeletedInDatabase(List<Voicemail> voicemails) {
+        int count = voicemails.size();
+        for (int i = 0; i < count; i++) {
+            updateInDatabase(voicemails.get(i), Voicemails.DELETED, "0");
+        }
+    }
+
+    /**
+     * Unread in database. This will be called if sync to server fails.
+     */
+    public void markUnreadInDatabase(List<Voicemail> voicemails) {
+        int count = voicemails.size();
+        for (int i = 0; i < count; i++) {
+            updateInDatabase(voicemails.get(i), Voicemails.IS_READ, "0");
+        }
+    }
+
+    /**
+     * Make an update of the requested field in the database.
+     */
+    private void updateInDatabase(Voicemail voicemail, String field, String value) {
+        Uri uri = ContentUris.withAppendedId(mSourceUri, voicemail.getId());
+        ContentValues contentValues = new ContentValues();
+        contentValues.put(field, value);
+        mContentResolver.update(uri, contentValues, null, null);
+    }
 
     /**
      * Check if a particular voicemail has already been inserted. If not, insert the new voicemail.
diff --git a/src/com/android/phone/vvm/omtp/sync/VvmPhoneStateListener.java b/src/com/android/phone/vvm/omtp/sync/VvmPhoneStateListener.java
index c7c1116..f51a2f0 100644
--- a/src/com/android/phone/vvm/omtp/sync/VvmPhoneStateListener.java
+++ b/src/com/android/phone/vvm/omtp/sync/VvmPhoneStateListener.java
@@ -16,6 +16,7 @@
 package com.android.phone.vvm.omtp.sync;
 
 import android.content.Context;
+import android.content.Intent;
 import android.provider.VoicemailContract;
 import android.telecom.PhoneAccountHandle;
 import android.telephony.PhoneStateListener;
@@ -38,10 +39,20 @@
     @Override
     public void onServiceStateChanged(ServiceState serviceState) {
         if (serviceState.getState() == ServiceState.STATE_IN_SERVICE) {
-            VoicemailContract.Status.setStatus(mContext, mPhoneAccount,
-                    VoicemailContract.Status.CONFIGURATION_STATE_OK,
-                    VoicemailContract.Status.DATA_CHANNEL_STATE_OK,
-                    VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_OK);
+            VoicemailStatusQueryHelper voicemailStatusQueryHelper =
+                    new VoicemailStatusQueryHelper(mContext);
+            if (!voicemailStatusQueryHelper.isNotificationsChannelActive(mPhoneAccount)) {
+                VoicemailContract.Status.setStatus(mContext, mPhoneAccount,
+                        VoicemailContract.Status.CONFIGURATION_STATE_OK,
+                        VoicemailContract.Status.DATA_CHANNEL_STATE_OK,
+                        VoicemailContract.Status.NOTIFICATION_CHANNEL_STATE_OK);
+
+                // Run a full sync in case something was missed while signal was down.
+                Intent serviceIntent = new Intent(mContext, OmtpVvmSyncService.class);
+                serviceIntent.setAction(OmtpVvmSyncService.SYNC_FULL_SYNC);
+                serviceIntent.putExtra(OmtpVvmSyncService.EXTRA_PHONE_ACCOUNT, mPhoneAccount);
+                mContext.startService(serviceIntent);
+            }
         } else {
             VoicemailContract.Status.setStatus(mContext, mPhoneAccount,
                     VoicemailContract.Status.CONFIGURATION_STATE_OK,