Merge "Proper IMAP logout" 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 0360e3e..6945b94 100644
--- a/src/com/android/phone/common/mail/store/ImapConnection.java
+++ b/src/com/android/phone/common/mail/store/ImapConnection.java
@@ -30,6 +30,7 @@
import com.android.phone.common.mail.store.imap.ImapUtility;
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;
@@ -110,7 +111,7 @@
// The server should greet us with something like
// * OK IMAP4rev1 Server
// consume the response before doing anything else.
- ImapResponse response = mParser.readResponse();
+ ImapResponse response = mParser.readResponse(false);
if (!response.isOk()) {
mImapStore.getImapHelper()
.handleEvent(OmtpEvents.DATA_INVALID_INITIAL_SERVER_RESPONSE);
@@ -138,11 +139,26 @@
}
}
+ void logout() {
+ try {
+ sendCommand(ImapConstants.LOGOUT, false);
+ if (!mParser.readResponse(true).is(0, ImapConstants.BYE)) {
+ VvmLog.e(TAG, "Server did not respond LOGOUT with BYE");
+ }
+ if (!mParser.readResponse(false).isOk()) {
+ VvmLog.e(TAG, "Server did not respond OK after LOGOUT");
+ }
+ } catch (IOException | MessagingException e) {
+ VvmLog.e(TAG, "Error while logging out:" + e);
+ }
+ }
+
/**
* Closes the connection and releases all resources. This connection can not be used again
* until {@link #setStore(ImapStore)} is called.
*/
void close() {
+ logout();
if (mTransport != null) {
mTransport.close();
mTransport = null;
@@ -323,7 +339,7 @@
}
public ImapResponse readResponse() throws IOException, MessagingException {
- return mParser.readResponse();
+ return mParser.readResponse(false);
}
public List<ImapResponse> executeSimpleCommand(String command)
@@ -377,11 +393,12 @@
* @throws IOException
* @throws MessagingException
*/
- List<ImapResponse> getCommandResponses() throws IOException, MessagingException {
+ List<ImapResponse> getCommandResponses()
+ throws IOException, MessagingException {
final List<ImapResponse> responses = new ArrayList<ImapResponse>();
ImapResponse response;
do {
- response = mParser.readResponse();
+ response = mParser.readResponse(false);
responses.add(response);
} while (!(response.isTagged() || response.isContinuationRequest()));
diff --git a/src/com/android/phone/common/mail/store/ImapFolder.java b/src/com/android/phone/common/mail/store/ImapFolder.java
index fe3df30..9b51f34 100644
--- a/src/com/android/phone/common/mail/store/ImapFolder.java
+++ b/src/com/android/phone/common/mail/store/ImapFolder.java
@@ -161,7 +161,6 @@
}
mMessageCount = -1;
synchronized (this) {
- mStore.closeConnection();
mConnection = null;
}
}
diff --git a/src/com/android/phone/common/mail/store/imap/ImapResponseParser.java b/src/com/android/phone/common/mail/store/imap/ImapResponseParser.java
index a6d2df6..6fc5abe 100644
--- a/src/com/android/phone/common/mail/store/imap/ImapResponseParser.java
+++ b/src/com/android/phone/common/mail/store/imap/ImapResponseParser.java
@@ -136,10 +136,12 @@
* is stored in the internal storage. When the {@link ImapResponse} is no longer used
* {@link #destroyResponses} should be called to destroy all the responses in the array.
*
+ * @param byeExpected is a untagged BYE response expected? If not proper cleanup will be done
+ * and {@link ByeException} will be thrown.
* @return the parsed {@link ImapResponse} object.
- * @exception ByeException when detects BYE.
+ * @exception ByeException when detects BYE and <code>byeExpected</code> is false.
*/
- public ImapResponse readResponse() throws IOException, MessagingException {
+ public ImapResponse readResponse(boolean byeExpected) throws IOException, MessagingException {
ImapResponse response = null;
try {
response = parseResponse();
@@ -154,7 +156,7 @@
}
// Handle this outside of try-catch. We don't have to dump protocol log when getting BYE.
- if (response.is(0, ImapConstants.BYE)) {
+ if (!byeExpected && response.is(0, ImapConstants.BYE)) {
Log.w(TAG, ByeException.MESSAGE);
response.destroy();
throw new ByeException();
diff --git a/src/com/android/phone/settings/VoicemailChangePinDialogPreference.java b/src/com/android/phone/settings/VoicemailChangePinDialogPreference.java
index e4230ff..3411228 100644
--- a/src/com/android/phone/settings/VoicemailChangePinDialogPreference.java
+++ b/src/com/android/phone/settings/VoicemailChangePinDialogPreference.java
@@ -175,8 +175,7 @@
@Override
public void onAvailable(Network network) {
super.onAvailable(network);
- ImapHelper helper = new ImapHelper(getContext(), mPhoneAccountHandle, network);
- try {
+ try (ImapHelper helper = new ImapHelper(getContext(), mPhoneAccountHandle, network)) {
@ChangePinResult int result =
helper.changePin(mOldPin.getText().toString(),
mNewPin.getText().toString());
diff --git a/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java b/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java
index fe3911c..d267e68 100644
--- a/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java
+++ b/src/com/android/phone/vvm/omtp/fetch/FetchVoicemailReceiver.java
@@ -159,19 +159,21 @@
try {
while (mRetryCount > 0) {
VvmLog.i(TAG, "fetching voicemail, retry count=" + mRetryCount);
- ImapHelper imapHelper = new ImapHelper(mContext, mPhoneAccount, network);
- if (!imapHelper.isSuccessfullyInitialized()) {
- VvmLog.w(TAG, "Can't retrieve Imap credentials.");
- return;
- }
+ try (ImapHelper imapHelper = new ImapHelper(mContext, mPhoneAccount,
+ network)) {
+ if (!imapHelper.isSuccessfullyInitialized()) {
+ VvmLog.w(TAG, "Can't retrieve Imap credentials.");
+ return;
+ }
- boolean success = imapHelper.fetchVoicemailPayload(
- new VoicemailFetchedCallback(mContext, mUri), mUid);
- if (!success && mRetryCount > 0) {
- VvmLog.i(TAG, "fetch voicemail failed, retrying");
- mRetryCount--;
- } else {
- return;
+ boolean success = imapHelper.fetchVoicemailPayload(
+ new VoicemailFetchedCallback(mContext, mUri), mUid);
+ if (!success && mRetryCount > 0) {
+ VvmLog.i(TAG, "fetch voicemail failed, retrying");
+ mRetryCount--;
+ } else {
+ return;
+ }
}
}
} finally {
diff --git a/src/com/android/phone/vvm/omtp/imap/ImapHelper.java b/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
index 216b6a4..908d0f7 100644
--- a/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
+++ b/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
@@ -57,6 +57,7 @@
import java.io.BufferedOutputStream;
import java.io.ByteArrayOutputStream;
+import java.io.Closeable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
@@ -66,7 +67,7 @@
/**
* A helper interface to abstract commands sent across IMAP interface for a given account.
*/
-public class ImapHelper {
+public class ImapHelper implements Closeable {
private static final String TAG = "ImapHelper";
@@ -126,6 +127,11 @@
VoicemailContract.Status.QUOTA_UNAVAILABLE);
}
+ @Override
+ public void close() {
+ mImapStore.closeConnection();
+ }
+
/**
* If mImapStore is null, this means that there was a missing or badly formatted port number,
* which means there aren't sufficient credentials for login. If mImapStore is succcessfully
diff --git a/src/com/android/phone/vvm/omtp/protocol/Vvm3Protocol.java b/src/com/android/phone/vvm/omtp/protocol/Vvm3Protocol.java
index 306006d..b238c8d 100644
--- a/src/com/android/phone/vvm/omtp/protocol/Vvm3Protocol.java
+++ b/src/com/android/phone/vvm/omtp/protocol/Vvm3Protocol.java
@@ -148,9 +148,7 @@
super.onAvailable(network);
VvmLog.i(TAG, "new user: network available");
ImapHelper helper = new ImapHelper(mContext, mPhoneAccount, network);
-
try {
-
// VVM3 has inconsistent error language code to OMTP. Just issue a raw command
// here.
// TODO(b/29082671): use LocaleList
@@ -176,7 +174,10 @@
} catch (MessagingException | IOException e) {
helper.handleEvent(OmtpEvents.VVM3_NEW_USER_SETUP_FAILED);
VvmLog.e(TAG, e.toString());
+ } finally {
+ helper.close();
}
+
}
private boolean setPin(ImapHelper helper) throws IOException, MessagingException {
diff --git a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
index 74b1f66..9884e9d 100644
--- a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
+++ b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
@@ -235,35 +235,36 @@
int retryCount = NETWORK_RETRY_COUNT;
try {
while (retryCount > 0) {
- ImapHelper imapHelper = new ImapHelper(this, phoneAccount, network);
- if (!imapHelper.isSuccessfullyInitialized()) {
- VvmLog.w(TAG, "Can't retrieve Imap credentials.");
- VisualVoicemailSettingsUtil.resetVisualVoicemailRetryInterval(this,
- phoneAccount);
- return;
- }
+ try (ImapHelper imapHelper = new ImapHelper(this, phoneAccount, network)) {
+ if (!imapHelper.isSuccessfullyInitialized()) {
+ VvmLog.w(TAG, "Can't retrieve Imap credentials.");
+ VisualVoicemailSettingsUtil.resetVisualVoicemailRetryInterval(this,
+ phoneAccount);
+ return;
+ }
- boolean success = true;
- if (voicemail == null) {
- success = syncAll(action, imapHelper, phoneAccount);
- } else {
- success = syncOne(imapHelper, voicemail, phoneAccount);
- }
- imapHelper.updateQuota();
+ boolean success = true;
+ if (voicemail == null) {
+ success = syncAll(action, imapHelper, phoneAccount);
+ } else {
+ success = syncOne(imapHelper, voicemail, phoneAccount);
+ }
+ imapHelper.updateQuota();
- // Need to check again for whether visual voicemail is enabled because it could have
- // been disabled while waiting for the response from the network.
- if (VisualVoicemailSettingsUtil.isVisualVoicemailEnabled(this, phoneAccount) &&
- !success) {
- retryCount--;
- VvmLog.v(TAG, "Retrying " + action);
- } else {
- // Nothing more to do here, just exit.
- VisualVoicemailSettingsUtil.resetVisualVoicemailRetryInterval(this,
- phoneAccount);
+ // Need to check again for whether visual voicemail is enabled because it could
+ // have been disabled while waiting for the response from the network.
+ if (VisualVoicemailSettingsUtil.isVisualVoicemailEnabled(this, phoneAccount) &&
+ !success) {
+ retryCount--;
+ VvmLog.v(TAG, "Retrying " + action);
+ } else {
+ // Nothing more to do here, just exit.
+ VisualVoicemailSettingsUtil.resetVisualVoicemailRetryInterval(this,
+ phoneAccount);
- imapHelper.handleEvent(OmtpEvents.DATA_IMAP_OPERATION_COMPLETED);
- return;
+ imapHelper.handleEvent(OmtpEvents.DATA_IMAP_OPERATION_COMPLETED);
+ return;
+ }
}
}
} finally {