Merge "Replace transcription for unsupported VVM message type" into nyc-mr1-dev
diff --git a/src/com/android/phone/common/mail/store/ImapConnection.java b/src/com/android/phone/common/mail/store/ImapConnection.java
index 6945b94..af8773b 100644
--- a/src/com/android/phone/common/mail/store/ImapConnection.java
+++ b/src/com/android/phone/common/mail/store/ImapConnection.java
@@ -17,7 +17,6 @@
 
 import android.util.ArraySet;
 import android.util.Base64;
-
 import com.android.phone.common.mail.AuthenticationFailedException;
 import com.android.phone.common.mail.CertificateValidationException;
 import com.android.phone.common.mail.MailTransport;
@@ -31,14 +30,12 @@
 import com.android.phone.common.mail.utils.LogUtils;
 import com.android.phone.vvm.omtp.OmtpEvents;
 import com.android.phone.vvm.omtp.VvmLog;
-
 import java.io.IOException;
 import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.concurrent.atomic.AtomicInteger;
-
 import javax.net.ssl.SSLException;
 
 /**
@@ -158,8 +155,8 @@
      * until {@link #setStore(ImapStore)} is called.
      */
     void close() {
-        logout();
         if (mTransport != null) {
+            logout();
             mTransport.close();
             mTransport = null;
         }
diff --git a/src/com/android/phone/vvm/omtp/ActivationTask.java b/src/com/android/phone/vvm/omtp/ActivationTask.java
index 716140c..89cb149 100644
--- a/src/com/android/phone/vvm/omtp/ActivationTask.java
+++ b/src/com/android/phone/vvm/omtp/ActivationTask.java
@@ -24,6 +24,7 @@
 import android.os.Bundle;
 import android.provider.Settings;
 import android.provider.Settings.Global;
+import android.provider.VoicemailContract.Status;
 import android.telecom.PhoneAccountHandle;
 import android.telephony.ServiceState;
 import android.telephony.TelephonyManager;
@@ -141,11 +142,21 @@
         }
         if (!OmtpVvmSourceManager.getInstance(getContext())
                 .isVvmSourceRegistered(phoneAccountHandle)) {
-            // Only show the "activating" message if activation has not been completed before in
-            // this boot. Subsequent activations are more of a status check and usually does not
-            // concern the user.
-            helper.handleEvent(VoicemailStatus.edit(getContext(), phoneAccountHandle),
-                    OmtpEvents.CONFIG_ACTIVATING);
+            VisualVoicemailPreferences preferences = new VisualVoicemailPreferences(getContext(),
+                    phoneAccountHandle);
+            if (preferences.getString(OmtpConstants.SERVER_ADDRESS, null) == null) {
+                // Only show the "activating" message if activation has not been completed before.
+                // Subsequent activations are more of a status check and usually does not
+                // concern the user.
+                helper.handleEvent(VoicemailStatus.edit(getContext(), phoneAccountHandle),
+                        OmtpEvents.CONFIG_ACTIVATING);
+            } else {
+                // The account has been activated on this device before. Pretend it is already
+                // activated. If there are any activation error it will overwrite this status.
+                VoicemailStatus.edit(getContext(), phoneAccountHandle)
+                        .setConfigurationState(Status.CONFIGURATION_STATE_OK);
+            }
+
         }
 
         helper.activateSmsFilter();
diff --git a/src/com/android/phone/vvm/omtp/VvmBootCompletedReceiver.java b/src/com/android/phone/vvm/omtp/VvmBootCompletedReceiver.java
index 6bd7fa1..9809c64 100644
--- a/src/com/android/phone/vvm/omtp/VvmBootCompletedReceiver.java
+++ b/src/com/android/phone/vvm/omtp/VvmBootCompletedReceiver.java
@@ -50,8 +50,8 @@
                 .getCallCapablePhoneAccounts()) {
             int subId = PhoneAccountHandleConverter.toSubId(handle);
             if (!SubscriptionManager.isValidSubscriptionId(subId)) {
-                // b/30474294 getCallCapablePhoneAccounts() might return a PhoneAccountHandle with
-                // invalid subId if no SIM is inserted.
+                // getCallCapablePhoneAccounts() might return a PhoneAccountHandle with invalid
+                // subId if no SIM is inserted. This is intended as it is for emergency calls.
                 VvmLog.e(TAG, "phone account " + handle + " has invalid subId " + subId);
                 continue;
             }
diff --git a/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java b/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java
index 4b595ab..9bda638 100644
--- a/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java
+++ b/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java
@@ -15,6 +15,7 @@
  */
 package com.android.phone.vvm.omtp.fetch;
 
+import android.annotation.Nullable;
 import android.content.BroadcastReceiver;
 import android.content.ComponentName;
 import android.content.ContentResolver;
@@ -30,6 +31,7 @@
 import android.telecom.PhoneAccountHandle;
 import android.telephony.TelephonyManager;
 import android.text.TextUtils;
+import com.android.internal.telephony.Phone;
 import com.android.phone.PhoneUtils;
 import com.android.phone.VoicemailStatus;
 import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
@@ -119,8 +121,12 @@
                             cursor.getString(PHONE_ACCOUNT_ID));
                     if (!OmtpVvmSourceManager.getInstance(context)
                             .isVvmSourceRegistered(mPhoneAccount)) {
-                        VvmLog.w(TAG, "Account not registered - cannot retrieve message.");
-                        return;
+                        mPhoneAccount = getAccountFromMarshmallowAccount(context, mPhoneAccount);
+                        if (mPhoneAccount == null) {
+                            VvmLog.w(TAG, "Account not registered - cannot retrieve message.");
+                            return;
+                        }
+                        VvmLog.i(TAG, "Fetching voicemail with Marshmallow PhoneAccountHandle");
                     }
 
                     int subId = PhoneUtils.getSubIdForPhoneAccountHandle(mPhoneAccount);
@@ -137,6 +143,29 @@
         }
     }
 
+    /**
+     * In ag/930496 the format of PhoneAccountHandle has changed between Marshmallow and Nougat.
+     * This method attempts to search the account from the old database in registered sources using
+     * the old format. There's a chance of M phone account collisions on multi-SIM devices, but
+     * visual voicemail is not supported on M multi-SIM.
+     */
+    @Nullable
+    private static PhoneAccountHandle getAccountFromMarshmallowAccount(Context context,
+            PhoneAccountHandle oldAccount) {
+        for (PhoneAccountHandle handle : OmtpVvmSourceManager.getInstance(context)
+                .getOmtpVvmSources()) {
+            Phone phone = PhoneUtils.getPhoneForPhoneAccountHandle(handle);
+            if (phone == null) {
+                continue;
+            }
+            // getIccSerialNumber() is used for ID before N, and getFullIccSerialNumber() after.
+            if (phone.getIccSerialNumber().equals(oldAccount.getId())) {
+                return handle;
+            }
+        }
+        return null;
+    }
+
     private class fetchVoicemailNetworkRequestCallback extends VvmNetworkRequestCallback {
 
         public fetchVoicemailNetworkRequestCallback(Context context,
diff --git a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
index 4f7efd3..3cc25c3 100644
--- a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
+++ b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
@@ -127,9 +127,9 @@
             } else {
                 success = syncOne(imapHelper, voicemail, phoneAccount);
             }
-            imapHelper.updateQuota();
-
             if (success) {
+                // TODO: b/30569269 failure should interrupt all subsequent task via exceptions
+                imapHelper.updateQuota();
                 imapHelper.handleEvent(OmtpEvents.DATA_IMAP_OPERATION_COMPLETED);
             } else {
                 task.fail();
diff --git a/src/com/android/services/telephony/TelephonyConnection.java b/src/com/android/services/telephony/TelephonyConnection.java
index 241d54c..cefd6c0 100644
--- a/src/com/android/services/telephony/TelephonyConnection.java
+++ b/src/com/android/services/telephony/TelephonyConnection.java
@@ -384,6 +384,10 @@
             Log.i(this, "onCallPullFailed - pull failed; swapping back to call: %s",
                     externalConnection);
 
+            // Inform the InCallService of the fact that the call pull failed (it may choose to
+            // display a message informing the user of the pull failure).
+            sendConnectionEvent(Connection.EVENT_CALL_PULL_FAILED, null);
+
             // Swap the ImsPhoneConnection we used to do the pull for the ImsExternalConnection
             // which originally represented the call.
             setOriginalConnection(externalConnection);