Report VVM error to VoicemailContract#Status

Cause of error is identified and set in the DATA_CHANNEL_STATE so the
UI can tell the user what went wrong and give solutions if possible.

Change-Id: Ifa5cde23beb6ec5300cd484243519ba8a314f8f9
diff --git a/src/com/android/phone/VoicemailUtils.java b/src/com/android/phone/VoicemailUtils.java
new file mode 100644
index 0000000..f67c64b
--- /dev/null
+++ b/src/com/android/phone/VoicemailUtils.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2016 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License
+ */
+
+package com.android.phone;
+
+import android.content.Context;
+import android.provider.VoicemailContract;
+import android.provider.VoicemailContract.Status;
+import android.telecom.PhoneAccountHandle;
+
+public class VoicemailUtils {
+
+    public static void setConfigurationState(Context context, PhoneAccountHandle accountHandle,
+            int configurationState) {
+        VoicemailContract.Status.setStatus(context, accountHandle,
+                configurationState,
+                Status.DATA_CHANNEL_STATE_IGNORE,
+                Status.NOTIFICATION_CHANNEL_STATE_IGNORE);
+    }
+
+    public static void setDataChannelState(Context context, PhoneAccountHandle accountHandle,
+            int dataChannelState) {
+        VoicemailContract.Status.setStatus(context, accountHandle,
+                Status.CONFIGURATION_STATE_IGNORE,
+                dataChannelState,
+                Status.NOTIFICATION_CHANNEL_STATE_IGNORE);
+    }
+
+    public static void setNotificationChannelState(Context context,
+            PhoneAccountHandle accountHandle, int notificationChannelState) {
+        VoicemailContract.Status.setStatus(context, accountHandle,
+                Status.CONFIGURATION_STATE_IGNORE,
+                Status.DATA_CHANNEL_STATE_IGNORE,
+                notificationChannelState);
+    }
+}
diff --git a/src/com/android/phone/common/mail/MailTransport.java b/src/com/android/phone/common/mail/MailTransport.java
index a303036..f452bab 100644
--- a/src/com/android/phone/common/mail/MailTransport.java
+++ b/src/com/android/phone/common/mail/MailTransport.java
@@ -17,10 +17,12 @@
 
 import android.content.Context;
 import android.net.Network;
+import android.provider.VoicemailContract.Status;
 
 import com.android.internal.annotations.VisibleForTesting;
 import com.android.phone.common.mail.store.ImapStore;
 import com.android.phone.common.mail.utils.LogUtils;
+import com.android.phone.vvm.omtp.imap.ImapHelper;
 
 import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
@@ -30,6 +32,7 @@
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.Socket;
+import java.net.SocketAddress;
 import java.util.ArrayList;
 import java.util.List;
 
@@ -53,18 +56,21 @@
     private static final HostnameVerifier HOSTNAME_VERIFIER =
             HttpsURLConnection.getDefaultHostnameVerifier();
 
-    private Context mContext;
-    private Network mNetwork;
-    private String mHost;
-    private int mPort;
+    private final Context mContext;
+    private final ImapHelper mImapHelper;
+    private final Network mNetwork;
+    private final String mHost;
+    private final int mPort;
     private Socket mSocket;
     private BufferedInputStream mIn;
     private BufferedOutputStream mOut;
-    private int mFlags;
+    private final int mFlags;
     private SocketCreator mSocketCreator;
 
-    public MailTransport(Context context, Network network, String address, int port, int flags) {
+    public MailTransport(Context context, ImapHelper imapHelper, Network network, String address,
+            int port, int flags) {
         mContext = context;
+        mImapHelper = imapHelper;
         mNetwork = network;
         mHost = address;
         mPort = port;
@@ -77,7 +83,7 @@
      */
     @Override
     public MailTransport clone() {
-        return new MailTransport(mContext, mNetwork, mHost, mPort, mFlags);
+        return new MailTransport(mContext, mImapHelper, mNetwork, mHost, mPort, mFlags);
     }
 
     public boolean canTrySslSecurity() {
@@ -111,6 +117,7 @@
                 }
             } catch (IOException ioe) {
                 LogUtils.d(TAG, ioe.toString());
+                mImapHelper.setDataChannelState(Status.DATA_CHANNEL_STATE_SERVER_CONNECTION_ERROR);
                 throw new MessagingException(MessagingException.IOERROR, ioe.toString());
             }
         }
@@ -148,6 +155,8 @@
                 LogUtils.d(TAG, ioe.toString());
                 if (socketAddresses.size() == 0) {
                     // Only throw an error when there are no more sockets to try.
+                    mImapHelper
+                            .setDataChannelState(Status.DATA_CHANNEL_STATE_SERVER_CONNECTION_ERROR);
                     throw new MessagingException(MessagingException.IOERROR, ioe.toString());
                 }
             } finally {
@@ -167,6 +176,7 @@
     // For testing. We need something that can replace the behavior of "new Socket()"
     @VisibleForTesting
     interface SocketCreator {
+
         Socket createSocket() throws MessagingException;
     }
 
@@ -211,7 +221,7 @@
      * @throws IOException if something goes wrong handshaking with the server
      * @throws SSLPeerUnverifiedException if the server cannot prove its identity
       */
-    private static void verifyHostname(Socket socket, String hostname) throws IOException {
+    private void verifyHostname(Socket socket, String hostname) throws IOException {
         // The code at the start of OpenSSLSocketImpl.startHandshake()
         // ensures that the call is idempotent, so we can safely call it.
         SSLSocket ssl = (SSLSocket) socket;
@@ -219,6 +229,7 @@
 
         SSLSession session = ssl.getSession();
         if (session == null) {
+            mImapHelper.setDataChannelState(Status.DATA_CHANNEL_STATE_COMMUNICATION_ERROR);
             throw new SSLException("Cannot verify SSL socket without session");
         }
         // TODO: Instead of reporting the name of the server we think we're connecting to,
@@ -226,6 +237,7 @@
         // in the verifier code and is not available in the verifier API, and extracting the
         // CN & alts is beyond the scope of this patch.
         if (!HOSTNAME_VERIFIER.verify(hostname, session)) {
+            mImapHelper.setDataChannelState(Status.DATA_CHANNEL_STATE_COMMUNICATION_ERROR);
             throw new SSLPeerUnverifiedException("Certificate hostname not useable for server: "
                     + session.getPeerPrincipal());
         }
diff --git a/src/com/android/phone/common/mail/store/ImapConnection.java b/src/com/android/phone/common/mail/store/ImapConnection.java
index ace7029..9207aa9 100644
--- a/src/com/android/phone/common/mail/store/ImapConnection.java
+++ b/src/com/android/phone/common/mail/store/ImapConnection.java
@@ -15,6 +15,7 @@
  */
 package com.android.phone.common.mail.store;
 
+import android.provider.VoicemailContract.Status;
 import android.text.TextUtils;
 
 import com.android.phone.common.mail.AuthenticationFailedException;
@@ -105,9 +106,12 @@
             doLogin();
         } catch (SSLException e) {
             LogUtils.d(TAG, "SSLException ", e);
+            mImapStore.getImapHelper().setDataChannelState(Status.DATA_CHANNEL_STATE_SERVER_ERROR);
             throw new CertificateValidationException(e.getMessage(), e);
         } catch (IOException ioe) {
             LogUtils.d(TAG, "IOException", ioe);
+            mImapStore.getImapHelper()
+                    .setDataChannelState(Status.DATA_CHANNEL_STATE_COMMUNICATION_ERROR);
             throw ioe;
         } finally {
             destroyResponses();
@@ -144,6 +148,8 @@
             if (ImapConstants.AUTHENTICATIONFAILED.equals(code) ||
                     ImapConstants.EXPIRED.equals(code) ||
                     (ImapConstants.NO.equals(status) && TextUtils.isEmpty(code))) {
+                mImapStore.getImapHelper()
+                        .setDataChannelState(Status.DATA_CHANNEL_STATE_BAD_CONFIGURATION);
                 throw new AuthenticationFailedException(alertText, ie);
             }
 
@@ -233,12 +239,12 @@
             final String alert = response.getAlertTextOrEmpty().getString();
             final String responseCode = response.getResponseCodeOrEmpty().getString();
             destroyResponses();
-
+            mImapStore.getImapHelper().setDataChannelState(Status.DATA_CHANNEL_STATE_SERVER_ERROR);
             // if the response code indicates an error occurred within the server, indicate that
             if (ImapConstants.UNAVAILABLE.equals(responseCode)) {
+
                 throw new MessagingException(MessagingException.SERVER_ERROR, alert);
             }
-
             throw new ImapException(toString, status, alert, responseCode);
         }
         return responses;
diff --git a/src/com/android/phone/common/mail/store/ImapFolder.java b/src/com/android/phone/common/mail/store/ImapFolder.java
index 1d17ea9..90c552d 100644
--- a/src/com/android/phone/common/mail/store/ImapFolder.java
+++ b/src/com/android/phone/common/mail/store/ImapFolder.java
@@ -19,6 +19,8 @@
 import android.content.SharedPreferences;
 import android.preference.PreferenceManager;
 import android.provider.VoicemailContract;
+import android.provider.VoicemailContract.Status;
+import android.telecom.Voicemail;
 import android.text.TextUtils;
 import android.util.Base64DataException;
 import android.util.Log;
@@ -727,6 +729,7 @@
                     mMode = MODE_READ_WRITE;
                 }
             } else if (response.isTagged()) { // Not OK
+                mStore.getImapHelper().setDataChannelState(Status.DATA_CHANNEL_STATE_SERVER_ERROR);
                 throw new MessagingException("Can't open mailbox: "
                         + response.getStatusResponseTextOrEmpty());
             }
@@ -789,6 +792,7 @@
             mConnection = null; // To prevent close() from returning the connection to the pool.
             close(false);
         }
+        mStore.getImapHelper().setDataChannelState(Status.DATA_CHANNEL_STATE_COMMUNICATION_ERROR);
         return new MessagingException(MessagingException.IOERROR, "IO Error", ioe);
     }
 
diff --git a/src/com/android/phone/common/mail/store/ImapStore.java b/src/com/android/phone/common/mail/store/ImapStore.java
index 63a5c36..c8095e5 100644
--- a/src/com/android/phone/common/mail/store/ImapStore.java
+++ b/src/com/android/phone/common/mail/store/ImapStore.java
@@ -23,6 +23,7 @@
 import com.android.phone.common.mail.Message;
 import com.android.phone.common.mail.MessagingException;
 import com.android.phone.common.mail.internet.MimeMessage;
+import com.android.phone.vvm.omtp.imap.ImapHelper;
 
 import java.io.IOException;
 import java.io.InputStream;
@@ -33,10 +34,11 @@
      * should be returned on FetchProfile.Item.BODY_SANE requests. We'll use 125k now.
      */
     public static final int FETCH_BODY_SANE_SUGGESTED_SIZE = (125 * 1024);
-    private Context mContext;
-    private String mUsername;
-    private String mPassword;
-    private MailTransport mTransport;
+    private final Context mContext;
+    private final ImapHelper mHelper;
+    private final String mUsername;
+    private final String mPassword;
+    private final MailTransport mTransport;
     private ImapConnection mConnection;
 
     public static final int FLAG_NONE         = 0x00;    // No flags
@@ -49,18 +51,24 @@
     /**
      * Contains all the information necessary to log into an imap server
      */
-    public ImapStore(Context context, String username, String password, int port,
+    public ImapStore(Context context, ImapHelper helper, String username, String password, int port,
             String serverName, int flags, Network network) {
         mContext = context;
+        mHelper = helper;
         mUsername = username;
         mPassword = password;
-        mTransport = new MailTransport(context, network, serverName, port, flags);
+        mTransport = new MailTransport(context, this.getImapHelper(),
+                network, serverName, port, flags);
     }
 
     public Context getContext() {
         return mContext;
     }
 
+    public ImapHelper getImapHelper() {
+        return mHelper;
+    }
+
     public String getUsername() {
         return mUsername;
     }
diff --git a/src/com/android/phone/vvm/omtp/imap/ImapHelper.java b/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
index fd56c77..da2d34b 100644
--- a/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
+++ b/src/com/android/phone/vvm/omtp/imap/ImapHelper.java
@@ -20,6 +20,7 @@
 import android.net.Network;
 import android.preference.PreferenceManager;
 import android.provider.VoicemailContract;
+import android.provider.VoicemailContract.Status;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.Voicemail;
 import android.telephony.TelephonyManager;
@@ -27,6 +28,7 @@
 import android.util.Log;
 
 import com.android.phone.PhoneUtils;
+import com.android.phone.VoicemailUtils;
 import com.android.phone.common.mail.Address;
 import com.android.phone.common.mail.Body;
 import com.android.phone.common.mail.BodyPart;
@@ -100,8 +102,10 @@
             }
 
             mImapStore = new ImapStore(
-                    context, username, password, port, serverName, auth, network);
+                    context, this, username, password, port, serverName, auth, network);
         } catch (NumberFormatException e) {
+            VoicemailUtils.setDataChannelState(
+                    mContext, mPhoneAccount, Status.DATA_CHANNEL_STATE_BAD_CONFIGURATION);
             LogUtils.w(TAG, "Could not parse port number");
         }
 
@@ -133,6 +137,10 @@
         return setFlags(voicemails, Flag.DELETED);
     }
 
+    public void setDataChannelState(int dataChannelState) {
+        VoicemailUtils.setDataChannelState(mContext, mPhoneAccount, dataChannelState);
+    }
+
     /**
      * Set flags on the server for a given set of voicemails.
      *
diff --git a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
index b3659ae..3985069 100644
--- a/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
+++ b/src/com/android/phone/vvm/omtp/sync/OmtpVvmSyncService.java
@@ -22,12 +22,15 @@
 import android.content.Intent;
 import android.net.Network;
 import android.net.NetworkInfo;
+import android.net.Uri;
 import android.provider.VoicemailContract;
+import android.provider.VoicemailContract.Status;
 import android.telecom.PhoneAccountHandle;
 import android.telecom.Voicemail;
 import android.text.TextUtils;
 import android.util.Log;
 
+import com.android.phone.VoicemailUtils;
 import com.android.phone.settings.VisualVoicemailSettingsUtil;
 import com.android.phone.vvm.omtp.LocalLogHelper;
 import com.android.phone.vvm.omtp.imap.ImapHelper;
@@ -223,6 +226,8 @@
                     // Nothing more to do here, just exit.
                     VisualVoicemailSettingsUtil.resetVisualVoicemailRetryInterval(this,
                             phoneAccount);
+                    VoicemailUtils.setDataChannelState(
+                            this, phoneAccount, Status.DATA_CHANNEL_STATE_OK);
                     return;
                 }
             }
diff --git a/src/com/android/phone/vvm/omtp/sync/VvmNetworkRequestCallback.java b/src/com/android/phone/vvm/omtp/sync/VvmNetworkRequestCallback.java
index 8bef9dc..884bec9 100644
--- a/src/com/android/phone/vvm/omtp/sync/VvmNetworkRequestCallback.java
+++ b/src/com/android/phone/vvm/omtp/sync/VvmNetworkRequestCallback.java
@@ -23,10 +23,13 @@
 import android.net.NetworkRequest;
 import android.os.Handler;
 import android.os.Looper;
+import android.provider.VoicemailContract;
+import android.provider.VoicemailContract.Status;
 import android.telecom.PhoneAccountHandle;
 import android.util.Log;
 
 import com.android.phone.PhoneUtils;
+import com.android.phone.VoicemailUtils;
 import com.android.phone.vvm.omtp.OmtpVvmCarrierConfigHelper;
 
 /**
@@ -47,32 +50,32 @@
     protected PhoneAccountHandle mPhoneAccount;
     protected NetworkRequest mNetworkRequest;
     private ConnectivityManager mConnectivityManager;
-
+    private final OmtpVvmCarrierConfigHelper mCarrierConfigHelper;
+    private final int mSubId;
     private boolean mRequestSent = false;
     private boolean mResultReceived = false;
 
     public VvmNetworkRequestCallback(Context context, PhoneAccountHandle phoneAccount) {
         mContext = context;
         mPhoneAccount = phoneAccount;
-        mNetworkRequest = getNetworkRequest(context, phoneAccount);
+        mSubId = PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccount);
+        mCarrierConfigHelper = new OmtpVvmCarrierConfigHelper(context, mSubId);
+        mNetworkRequest = createNetworkRequest();
     }
 
     /**
      * @return NetworkRequest for a proper transport type. Use only cellular network if the carrier
      * requires it. Otherwise use whatever available.
      */
-    private NetworkRequest getNetworkRequest(Context context, PhoneAccountHandle phoneAccount) {
-        int subId = PhoneUtils.getSubIdForPhoneAccountHandle(phoneAccount);
-        OmtpVvmCarrierConfigHelper carrierConfigHelper =
-                new OmtpVvmCarrierConfigHelper(context, subId);
+    private NetworkRequest createNetworkRequest() {
 
         NetworkRequest.Builder builder = new NetworkRequest.Builder()
                 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET);
 
-        if (carrierConfigHelper.isCellularDataRequired()) {
+        if (mCarrierConfigHelper.isCellularDataRequired()) {
             Log.d(TAG, "Transport type: CELLULAR");
             builder.addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
-                    .setNetworkSpecifier(Integer.toString(subId));
+                    .setNetworkSpecifier(Integer.toString(mSubId));
         } else {
             Log.d(TAG, "Transport type: ANY");
         }
@@ -143,7 +146,14 @@
     @CallSuper
     public void onFailed(String reason) {
         Log.d(TAG, "onFailed: " + reason);
-        // TODO: Notify the user sync has failed?
+        if (mCarrierConfigHelper.isCellularDataRequired()) {
+            VoicemailUtils.setDataChannelState(
+                    mContext, mPhoneAccount,
+                    Status.DATA_CHANNEL_STATE_NO_CONNECTION_CELLULAR_REQUIRED);
+        } else {
+            VoicemailUtils.setDataChannelState(
+                    mContext, mPhoneAccount, Status.DATA_CHANNEL_STATE_NO_CONNECTION);
+        }
         releaseNetwork();
     }
 }
diff --git a/tests/src/com/android/phone/common/mail/MailTransportTest.java b/tests/src/com/android/phone/common/mail/MailTransportTest.java
index 1fd6596..6acd517 100644
--- a/tests/src/com/android/phone/common/mail/MailTransportTest.java
+++ b/tests/src/com/android/phone/common/mail/MailTransportTest.java
@@ -26,12 +26,15 @@
 import com.android.phone.MockitoHelper;
 import com.android.phone.common.mail.MailTransport.SocketCreator;
 import com.android.phone.common.mail.store.ImapStore;
+import com.android.phone.vvm.omtp.imap.ImapHelper;
 
 import junit.framework.AssertionFailedError;
 
 import org.mockito.MockitoAnnotations;
 
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
 import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.Socket;
@@ -71,7 +74,8 @@
     public void testCreateSocket_anyNetwork() throws MessagingException {
         // With no network, Socket#Socket() should be called.
         MailTransport transport =
-                new MailTransport(getContext(), null, HOST_ADDRESS, HOST_PORT, HOST_FLAGS);
+                new MailTransport(getContext(), createMockImapHelper(), null, HOST_ADDRESS,
+                        HOST_PORT, HOST_FLAGS);
         Socket socket = transport.createSocket();
         assertTrue(socket != null);
     }
@@ -80,7 +84,8 @@
         // Network#getSocketFactory should be used to create socket.
         Network mockNetwork = createMockNetwork();
         MailTransport transport =
-                new MailTransport(getContext(), mockNetwork, HOST_ADDRESS, HOST_PORT, HOST_FLAGS);
+                new MailTransport(getContext(), createMockImapHelper(), mockNetwork, HOST_ADDRESS,
+                        HOST_PORT, HOST_FLAGS);
         Socket socket = transport.createSocket();
         assertTrue(socket != null);
         verify(mockNetwork).getSocketFactory();
@@ -99,7 +104,8 @@
         };
 
         MailTransport transport = new
-                MailTransport(getContext(), null, HOST_ADDRESS, HOST_PORT, HOST_FLAGS);
+                MailTransport(getContext(), createMockImapHelper(), null, HOST_ADDRESS, HOST_PORT,
+                HOST_FLAGS);
 
         transport.setSocketCreator(socketCreator);
 
@@ -108,7 +114,8 @@
     }
 
     public void testOpen() throws MessagingException {
-        MailTransport transport = new MailTransport(getContext(), null, HOST_ADDRESS,
+        MailTransport transport = new MailTransport(getContext(), createMockImapHelper(), null,
+                HOST_ADDRESS,
                 HOST_PORT, HOST_FLAGS);
         transport.setSocketCreator(new TestSocketCreator());
         transport.open();
@@ -118,8 +125,8 @@
 
     public void testOpen_Ssl() throws MessagingException {
         //opening with ssl support.
-        MailTransport transport = new MailTransport(getContext(), null, HOST_ADDRESS,
-                HOST_PORT, HOST_FLAGS_SSL);
+        MailTransport transport = new MailTransport(getContext(), createMockImapHelper(), null,
+                HOST_ADDRESS, HOST_PORT, HOST_FLAGS_SSL);
         transport.setSocketCreator(new TestSocketCreator());
         transport.open();
         assertTrue(transport.isOpen());
@@ -129,7 +136,8 @@
     public void testOpen_MultiIp() throws MessagingException {
         //In case of round robin DNS, try all resolved address until one succeeded.
         Network network = createMultiIpMockNetwork();
-        MailTransport transport = new MailTransport(getContext(), network, HOST_ADDRESS,
+        MailTransport transport = new MailTransport(getContext(), createMockImapHelper(), network,
+                HOST_ADDRESS,
                 HOST_PORT, HOST_FLAGS);
         transport.setSocketCreator(new TestSocketCreator());
         transport.open();
@@ -139,7 +147,8 @@
     public void testOpen_MultiIp_SSL() throws MessagingException {
         Network network = createMultiIpMockNetwork();
 
-        MailTransport transport = new MailTransport(getContext(), network, HOST_ADDRESS,
+        MailTransport transport = new MailTransport(getContext(), createMockImapHelper(), network,
+                HOST_ADDRESS,
                 HOST_PORT, HOST_FLAGS_SSL);
         transport.setSocketCreator(new TestSocketCreator());
         transport.open();
@@ -156,7 +165,8 @@
             //ignored
         }
 
-        MailTransport transport = new MailTransport(getContext(), network, HOST_ADDRESS,
+        MailTransport transport = new MailTransport(getContext(), createMockImapHelper(), network,
+                HOST_ADDRESS,
                 HOST_PORT, HOST_FLAGS);
         try {
             transport.open();
@@ -169,7 +179,8 @@
 
     public void testOpen_createSocketFailed() {
         // Unable to create socket. Open() should fail.
-        MailTransport transport = new MailTransport(getContext(), null, HOST_ADDRESS,
+        MailTransport transport = new MailTransport(getContext(), createMockImapHelper(), null,
+                HOST_ADDRESS,
                 HOST_PORT, HOST_FLAGS);
         transport.setSocketCreator(new SocketCreator() {
             @Override
@@ -199,8 +210,8 @@
         }
         when(network.getSocketFactory()).thenReturn(mockSocketFactory);
 
-        MailTransport transport = new MailTransport(getContext(), network, HOST_ADDRESS,
-                HOST_PORT, HOST_FLAGS);
+        MailTransport transport = new MailTransport(getContext(), createMockImapHelper(), network,
+                HOST_ADDRESS, HOST_PORT, HOST_FLAGS);
 
         try {
             transport.open();
@@ -214,8 +225,8 @@
     public void testOpen_connectFailed_one() {
         // There is only one IP for this host, and we failed to connect to it. Open() should fail.
 
-        MailTransport transport = new MailTransport(getContext(), null, HOST_ADDRESS,
-                HOST_PORT, HOST_FLAGS);
+        MailTransport transport = new MailTransport(getContext(), createMockImapHelper(), null,
+                HOST_ADDRESS, HOST_PORT, HOST_FLAGS);
         transport.setSocketCreator(new SocketCreator() {
             @Override
             public Socket createSocket() throws MessagingException {
@@ -239,9 +250,8 @@
     public void testOpen_connectFailed_multi() {
         // There are multiple IP for this host, and we failed to connect to any of it.
         // Open() should fail.
-        MailTransport transport = new MailTransport(getContext(), createMultiIpMockNetwork(),
-                HOST_ADDRESS,
-                HOST_PORT, HOST_FLAGS);
+        MailTransport transport = new MailTransport(getContext(), createMockImapHelper(),
+                createMultiIpMockNetwork(), HOST_ADDRESS, HOST_PORT, HOST_FLAGS);
         transport.setSocketCreator(new SocketCreator() {
             @Override
             public Socket createSocket() throws MessagingException {
@@ -305,6 +315,16 @@
         }
 
         @Override
+        public InputStream getInputStream() {
+            return null;
+        }
+
+        @Override
+        public OutputStream getOutputStream() {
+            return null;
+        }
+
+        @Override
         public boolean isConnected() {
             return mConnected;
         }
@@ -322,6 +342,10 @@
 
     }
 
+    private ImapHelper createMockImapHelper() {
+        return mock(ImapHelper.class);
+    }
+
     /**
      * @return a mock Network that can create a TestSocket with {@code getSocketFactory()
      * .createSocket()}