Tweak visual voicemail
b/30513337 NPE when connection lost
ImapConnection will try to log out when the connection closes, even
when the connection is interrupted and logging out cannot be done.
Doing so will cause a NPE.
In this CL log out will only commence if the transport is still valid.
b/30514504 Don't show "Activating" if VVM has been activated before
The activating message is shown upon every boot but most of the time
the account should be already activated, activation is just for book
keeping.
After this CL the activating message will only be shown if the account
is never activated before on the device. Error message will still be
posted if activation fails.
b/30483028 getCallCapablePhoneAccounts() returns null
This is working as intended, comments updated
b/29363739 Unable to fetch voicemail from Marshmallow
PhoneAccountHandle is stored in the database to determine which account
to fetch voicemail from. Between M and N the PhoneAccountHandle value
has changed, causing the entry in M voicemails to mismatch.
In this CL if the phone account of the voicemail cannot be found, the
client will try to search it as the M format
+ Fix NPE while updating quota when the preceding operations on the
ImapHelper has already failed.
Change-Id: Ia17e345c772892e17a005ae8f0c6c08255a0ef1f
Fixes: 29363739
Fixes: 30513337
Fixes: 30514504
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 d5e627f..5ba0fb3 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 87b68e5..4628fa4 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();