Wait for IPv4 provisioned when connecting to IPv4 MMS URL
am: eeb364a1e8

* commit 'eeb364a1e8916609bee877b893443bd940ea87da':
  Wait for IPv4 provisioned when connecting to IPv4 MMS URL

Change-Id: I4cfd00e1995cb3dc7e95e0acc10074b05b7ef202
diff --git a/src/com/android/mms/service/MmsHttpClient.java b/src/com/android/mms/service/MmsHttpClient.java
index b4d3ba6..1c88bbf 100644
--- a/src/com/android/mms/service/MmsHttpClient.java
+++ b/src/com/android/mms/service/MmsHttpClient.java
@@ -17,6 +17,8 @@
 package com.android.mms.service;
 
 import android.content.Context;
+import android.net.ConnectivityManager;
+import android.net.LinkProperties;
 import android.net.Network;
 import android.os.Bundle;
 import android.telephony.SmsManager;
@@ -25,7 +27,6 @@
 import android.text.TextUtils;
 import android.util.Base64;
 import android.util.Log;
-
 import com.android.mms.service.exception.MmsHttpException;
 
 import java.io.BufferedInputStream;
@@ -36,6 +37,8 @@
 import java.io.OutputStream;
 import java.io.UnsupportedEncodingException;
 import java.net.HttpURLConnection;
+import java.net.Inet4Address;
+import java.net.InetAddress;
 import java.net.InetSocketAddress;
 import java.net.MalformedURLException;
 import java.net.ProtocolException;
@@ -68,18 +71,24 @@
     private static final String HEADER_VALUE_CONTENT_TYPE_WITHOUT_CHARSET =
             "application/vnd.wap.mms-message";
 
+    private static final int IPV4_WAIT_ATTEMPTS = 15;
+    private static final long IPV4_WAIT_DELAY_MS = 1000; // 1 seconds
+
     private final Context mContext;
     private final Network mNetwork;
+    private final ConnectivityManager mConnectivityManager;
 
     /**
      * Constructor
-     *
-     * @param context The Context object
+     *  @param context The Context object
      * @param network The Network for creating an OKHttp client
+     * @param connectivityManager
      */
-    public MmsHttpClient(Context context, Network network) {
+    public MmsHttpClient(Context context, Network network,
+            ConnectivityManager connectivityManager) {
         mContext = context;
         mNetwork = network;
+        mConnectivityManager = connectivityManager;
     }
 
     /**
@@ -113,6 +122,7 @@
                         new InetSocketAddress(mNetwork.getByName(proxyHost), proxyPort));
             }
             final URL url = new URL(urlString);
+            maybeWaitForIpv4(requestId, url);
             // Now get the connection
             connection = (HttpURLConnection) mNetwork.openConnection(url, proxy);
             connection.setDoInput(true);
@@ -209,6 +219,40 @@
         }
     }
 
+    private void maybeWaitForIpv4(final String requestId, final URL url) {
+        // If it's a literal IPv4 address and we're on an IPv6-only network,
+        // wait until IPv4 is available.
+        Inet4Address ipv4Literal = null;
+        try {
+            ipv4Literal = (Inet4Address) InetAddress.parseNumericAddress(url.getHost());
+        } catch (IllegalArgumentException | ClassCastException e) {
+            // Ignore
+        }
+        if (ipv4Literal == null) {
+            // Not an IPv4 address.
+            return;
+        }
+        for (int i = 0; i < IPV4_WAIT_ATTEMPTS; i++) {
+            final LinkProperties lp = mConnectivityManager.getLinkProperties(mNetwork);
+            if (lp != null) {
+                if (!lp.isReachable(ipv4Literal)) {
+                    LogUtil.w(requestId, "HTTP: IPv4 not yet provisioned");
+                    try {
+                        Thread.sleep(IPV4_WAIT_DELAY_MS);
+                    } catch (InterruptedException e) {
+                        // Ignore
+                    }
+                } else {
+                    LogUtil.i(requestId, "HTTP: IPv4 provisioned");
+                    break;
+                }
+            } else {
+                LogUtil.w(requestId, "HTTP: network disconnected, skip ipv4 check");
+                break;
+            }
+        }
+    }
+
     private static void logHttpHeaders(Map<String, List<String>> headers, String requestId) {
         final StringBuilder sb = new StringBuilder();
         if (headers != null) {
diff --git a/src/com/android/mms/service/MmsNetworkManager.java b/src/com/android/mms/service/MmsNetworkManager.java
index ed78258..67b0af6 100644
--- a/src/com/android/mms/service/MmsNetworkManager.java
+++ b/src/com/android/mms/service/MmsNetworkManager.java
@@ -229,7 +229,7 @@
             if (mMmsHttpClient == null) {
                 if (mNetwork != null) {
                     // Create new MmsHttpClient for the current Network
-                    mMmsHttpClient = new MmsHttpClient(mContext, mNetwork);
+                    mMmsHttpClient = new MmsHttpClient(mContext, mNetwork, mConnectivityManager);
                 }
             }
             return mMmsHttpClient;
diff --git a/src/com/android/mms/service/SendRequest.java b/src/com/android/mms/service/SendRequest.java
index 435e12c..21cd43c 100644
--- a/src/com/android/mms/service/SendRequest.java
+++ b/src/com/android/mms/service/SendRequest.java
@@ -242,7 +242,7 @@
             return ;
         }
         if (!(pdu instanceof SendReq)) {
-            LogUtil.e(requestId, "updateDestinationAddress: not SendReq");
+            LogUtil.i(requestId, "updateDestinationAddress: not SendReq");
             return;
         }