Improve the Connectivity section of the Dev Tools app.

1. Remove one more usage of startUsingNetworkFeature.
2. Use new APIs for bound HTTP requests.

Bug: 25824776
Change-Id: Ic2f30ce9ffc873be198f6ad29cf928dc33574d84
diff --git a/apps/Development/res/layout/connectivity.xml b/apps/Development/res/layout/connectivity.xml
index c596f19..23bbb2e 100644
--- a/apps/Development/res/layout/connectivity.xml
+++ b/apps/Development/res/layout/connectivity.xml
@@ -303,35 +303,10 @@
       android:orientation="horizontal"
       android:layout_width="match_parent"
       android:layout_height="wrap_content">
-        <TextView
-          android:layout_width="wrap_content"
-          android:layout_height="wrap_content"
-          android:text="@string/netid" />
-        <EditText android:id="@+id/netid"
-          android:layout_width="wrap_content"
-          android:layout_height="wrap_content"
-          android:minEms="5" />
-        <Button android:id="@+id/add_default_route"
-          android:layout_width="wrap_content"
-          android:layout_height="wrap_content"
-          android:text="@string/add_default_route" />
-        <Button android:id="@+id/remove_default_route"
-          android:layout_width="wrap_content"
-          android:layout_height="wrap_content"
-          android:text="@string/remove_default_route" />
-    </LinearLayout>
-    <LinearLayout
-      android:orientation="horizontal"
-      android:layout_width="match_parent"
-      android:layout_height="wrap_content">
         <Button android:id="@+id/default_request"
           android:layout_width="wrap_content"
           android:layout_height="wrap_content"
           android:text="@string/default_request" />
-        <Button android:id="@+id/default_socket"
-          android:layout_width="wrap_content"
-          android:layout_height="wrap_content"
-          android:text="@string/default_socket" />
     </LinearLayout>
     <LinearLayout
       android:orientation="horizontal"
@@ -346,22 +321,24 @@
           android:layout_height="wrap_content"
           android:text="@string/bound_socket_request" />
     </LinearLayout>
+
     <LinearLayout
-      android:orientation="horizontal"
-      android:layout_width="match_parent"
-      android:layout_height="wrap_content">
-        <Button android:id="@+id/routed_http_request"
-          android:layout_width="wrap_content"
-          android:layout_height="wrap_content"
-          android:text="@string/routed_http_request" />
-        <Button android:id="@+id/routed_socket_request"
-          android:layout_width="wrap_content"
-          android:layout_height="wrap_content"
-          android:text="@string/routed_socket_request" />
+        android:orientation="horizontal"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content">
+        <TextView
+            android:id="@+id/http_response"
+            android:layout_width="wrap_content"
+            android:layout_height="wrap_content" />
     </LinearLayout>
 
     <!-- divider line -->
     <View android:background="#FFFFFFFF"
+      android:layout_width="match_parent"
+      android:layout_height="3dip" />
+
+    <!-- divider line -->
+    <View android:background="#FFFFFFFF"
         android:layout_width="match_parent"
         android:layout_height="3dip" />
     <LinearLayout
diff --git a/apps/Development/res/values/strings.xml b/apps/Development/res/values/strings.xml
index dd6cefd..bbcb30d 100644
--- a/apps/Development/res/values/strings.xml
+++ b/apps/Development/res/values/strings.xml
@@ -48,16 +48,9 @@
     <string name="release_cell">Release cell</string>
     <string name="report_all_bad">Report all bad</string>
 
-    <string name="netid">NetId</string>
-    <string name="add_default_route">Add Default Route</string>
-    <string name="remove_default_route">Remove Default Route</string>
-    <string name="default_request">Make a http request</string>
-    <string name="default_socket">Make a raw request</string>
+    <string name="default_request">Make http request</string>
     <string name="bound_http_request">Make bound http request</string>
     <string name="bound_socket_request">Make bound socket request</string>
-    <string name="routed_http_request">Make routed http request</string>
-    <string name="routed_socket_request">Make routed socket request</string>
-
 
         <string name="device_info_default">unknown</string>
         <string name="device_info_uptime">Uptime</string>
diff --git a/apps/Development/src/com/android/development/Connectivity.java b/apps/Development/src/com/android/development/Connectivity.java
index 347612a..06bd06e 100644
--- a/apps/Development/src/com/android/development/Connectivity.java
+++ b/apps/Development/src/com/android/development/Connectivity.java
@@ -52,6 +52,7 @@
 import android.os.SystemClock;
 import android.provider.Settings;
 import android.os.Bundle;
+import android.text.TextUtils;
 import android.util.Log;
 import android.view.IWindowManager;
 import android.view.View;
@@ -66,29 +67,29 @@
 import android.widget.AdapterView.OnItemSelectedListener;
 
 import com.android.internal.telephony.Phone;
+import libcore.io.IoUtils;
 
+import java.io.BufferedReader;
 import java.io.FileInputStream;
 import java.io.FileOutputStream;
+import java.io.InputStreamReader;
+import java.io.IOException;
+import java.io.OutputStreamWriter;
 import java.io.PrintWriter;
+import java.net.HttpURLConnection;
 import java.net.InetAddress;
-import java.net.NetworkInterface;
+import java.net.Proxy;
 import java.net.Socket;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.Enumeration;
 import java.util.List;
-
-import org.apache.http.client.HttpClient;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.conn.params.ConnRouteParams;
-import org.apache.http.params.BasicHttpParams;
-import org.apache.http.params.HttpParams;
-import org.apache.http.HttpResponse;
-import org.apache.http.impl.client.DefaultHttpClient;
+import java.util.Random;
 
 import static android.net.NetworkCapabilities.*;
 
 public class Connectivity extends Activity {
-    private static final String TAG = "DevTools - Connectivity";
+    private static final String TAG = "DevToolsConnectivity";
     private static final String GET_SCAN_RES = "Get Results";
     private static final String START_SCAN = "Start Scan";
     private static final String PROGRESS_SCAN = "In Progress";
@@ -126,6 +127,7 @@
     private long mTotalScanCount = 0;
 
     private TextView mLinkStatsResults;
+    private TextView mHttpRequestResults;
 
     private String mTdlsAddr = null;
 
@@ -292,6 +294,7 @@
         private final NetworkRequest mRequest;
         private final int mRequestButton, mReleaseButton;
         private NetworkCallback mCallback;
+        private Network mNetwork;
 
         public RequestableNetwork(NetworkRequest request, int requestButton, int releaseButton) {
             mRequest = request;
@@ -321,7 +324,18 @@
 
         public void request() {
             if (mCallback == null) {
-                mCallback = new NetworkCallback();
+                mCallback = new NetworkCallback() {
+                    @Override
+                    public void onAvailable(Network network) {
+                        mNetwork = network;
+                        onHttpRequestResults(null);
+                    }
+                    @Override
+                    public void onLost(Network network) {
+                        mNetwork = null;
+                        onHttpRequestResults(null);
+                    }
+                };
                 mCm.requestNetwork(mRequest, mCallback);
                 setRequested(true);
             }
@@ -329,14 +343,22 @@
 
         public void release() {
             if (mCallback != null) {
+                mNetwork = null;
+                onHttpRequestResults(null);
                 mCm.unregisterNetworkCallback(mCallback);
                 mCallback = null;
                 setRequested(false);
             }
         }
+
+        public Network getNetwork() {
+            return mNetwork;
+        }
     }
 
     private final ArrayList<RequestableNetwork> mRequestableNetworks = new ArrayList<>();
+    private final RequestableNetwork mBoundTestNetwork;
+    private boolean mRequestRunning;
 
     private void addRequestableNetwork(int capability, int requestButton, int releaseButton) {
         mRequestableNetworks.add(new RequestableNetwork(capability, requestButton, releaseButton));
@@ -347,6 +369,7 @@
         addRequestableNetwork(NET_CAPABILITY_MMS, R.id.request_mms, R.id.release_mms);
         addRequestableNetwork(NET_CAPABILITY_SUPL, R.id.request_supl, R.id.release_supl);
         addRequestableNetwork(NET_CAPABILITY_INTERNET, R.id.request_cell, R.id.release_cell);
+        mBoundTestNetwork = mRequestableNetworks.get(mRequestableNetworks.size() - 1);
     }
 
     final NetworkRequest mEmptyRequest = new NetworkRequest.Builder().clearCapabilities().build();
@@ -402,26 +425,26 @@
 
         findViewById(R.id.report_all_bad).setOnClickListener(mClickListener);
 
-        findViewById(R.id.add_default_route).setOnClickListener(mClickListener);
-        findViewById(R.id.remove_default_route).setOnClickListener(mClickListener);
+        findViewById(R.id.default_request).setOnClickListener(mClickListener);
         findViewById(R.id.bound_http_request).setOnClickListener(mClickListener);
         findViewById(R.id.bound_socket_request).setOnClickListener(mClickListener);
-        findViewById(R.id.routed_http_request).setOnClickListener(mClickListener);
-        findViewById(R.id.routed_socket_request).setOnClickListener(mClickListener);
-        findViewById(R.id.default_request).setOnClickListener(mClickListener);
-        findViewById(R.id.default_socket).setOnClickListener(mClickListener);
+
         findViewById(R.id.link_stats).setOnClickListener(mClickListener);
 
         for (RequestableNetwork network : mRequestableNetworks) {
             network.setRequested(false);
             network.addOnClickListener();
         }
+        onHttpRequestResults(null);
 
         registerReceiver(mReceiver, new IntentFilter(CONNECTIVITY_TEST_ALARM));
 
         mLinkStatsResults = (TextView)findViewById(R.id.stats);
         mLinkStatsResults.setVisibility(View.VISIBLE);
 
+        mHttpRequestResults = (TextView)findViewById(R.id.http_response);
+        mHttpRequestResults.setVisibility(View.VISIBLE);
+
         mCallback = new DevToolsNetworkCallback();
         mCm.registerNetworkCallback(mEmptyRequest, mCallback);
     }
@@ -473,29 +496,14 @@
                 case R.id.stopTdls:
                     onStopTdls();
                     break;
-                case R.id.default_socket:
-                    onDefaultSocket();
-                    break;
                 case R.id.default_request:
-                    onDefaultRequest();
-                    break;
-                case R.id.routed_socket_request:
-                    onRoutedSocketRequest();
-                    break;
-                case R.id.routed_http_request:
-                    onRoutedHttpRequest();
-                    break;
-                case R.id.bound_socket_request:
-                    onBoundSocketRequest();
+                    onHttpRequest(DEFAULT);
                     break;
                 case R.id.bound_http_request:
-                    onBoundHttpRequest();
+                    onHttpRequest(HTTPS);
                     break;
-                case R.id.remove_default_route:
-                    onRemoveDefaultRoute();
-                    break;
-                case R.id.add_default_route:
-                    onAddDefaultRoute();
+                case R.id.bound_socket_request:
+                    onHttpRequest(SOCKET);
                     break;
                 case R.id.report_all_bad:
                     onReportAllBad();
@@ -649,190 +657,108 @@
     }
 
 
-    private void onAddDefaultRoute() {
-        try {
-            int netId = Integer.valueOf(((TextView) findViewById(R.id.netid)).getText().toString());
-            mNetd.addRoute(netId, new RouteInfo((LinkAddress) null,
-                    NetworkUtils.numericToInetAddress("8.8.8.8")));
-        } catch (Exception e) {
-            Log.e(TAG, "onAddDefaultRoute got exception: " + e.toString());
-        }
-    }
-
-    private void onRemoveDefaultRoute() {
-        try {
-            int netId = Integer.valueOf(((TextView) findViewById(R.id.netid)).getText().toString());
-            mNetd.removeRoute(netId, new RouteInfo((LinkAddress) null,
-                    NetworkUtils.numericToInetAddress("8.8.8.8")));
-        } catch (Exception e) {
-            Log.e(TAG, "onRemoveDefaultRoute got exception: " + e.toString());
-        }
-    }
-
-    private void onRoutedHttpRequest() {
-        onRoutedRequest(HTTP);
-    }
-
-    private void onRoutedSocketRequest() {
-        onRoutedRequest(SOCKET);
-    }
-
+    private final static int DEFAULT = 0;
     private final static int SOCKET = 1;
-    private final static int HTTP   = 2;
+    private final static int HTTPS  = 2;
 
-    private void onRoutedRequest(int type) {
-        String url = "www.google.com";
+    private void onHttpRequestResults(final String results) {
+        runOnUiThread(new Runnable() {
+            @Override
+            public void run() {
+                boolean enabled = !mRequestRunning;
+                findViewById(R.id.default_request).setEnabled(enabled);
 
-        InetAddress inetAddress = null;
-        try {
-            inetAddress = InetAddress.getByName(url);
-        } catch (Exception e) {
-            Log.e(TAG, "error fetching address for " + url);
-            return;
-        }
+                enabled = !mRequestRunning && mBoundTestNetwork.getNetwork() != null;
+                findViewById(R.id.bound_http_request).setEnabled(enabled);
+                findViewById(R.id.bound_socket_request).setEnabled(enabled);
 
-        mCm.requestRouteToHostAddress(ConnectivityManager.TYPE_MOBILE_HIPRI, inetAddress);
-
-        switch (type) {
-            case SOCKET:
-                onBoundSocketRequest();
-                break;
-            case HTTP:
-                HttpGet get = new HttpGet("http://" + url);
-                HttpClient client = new DefaultHttpClient();
-                try {
-                    HttpResponse httpResponse = client.execute(get);
-                    Log.d(TAG, "routed http request gives " + httpResponse.getStatusLine());
-                } catch (Exception e) {
-                    Log.e(TAG, "routed http request exception = " + e);
+                if (!TextUtils.isEmpty(results) || !mRequestRunning) {
+                    ((TextView) findViewById(R.id.http_response)).setText(results);
                 }
-        }
-
+            }
+        });
     }
 
-    private void onBoundHttpRequest() {
-        NetworkInterface networkInterface = null;
+    private String doSocketRequest(Network network, String host, String path) throws IOException {
+        Socket sock = network.getSocketFactory().createSocket(host, 80);
         try {
-            networkInterface = NetworkInterface.getByName("rmnet0");
-            Log.d(TAG, "networkInterface is " + networkInterface);
-        } catch (Exception e) {
-            Log.e(TAG, " exception getByName: " + e);
-            return;
-        }
-        if (networkInterface != null) {
-            Enumeration inetAddressess = networkInterface.getInetAddresses();
-            while(inetAddressess.hasMoreElements()) {
-                Log.d(TAG, " inetAddress:" + ((InetAddress)inetAddressess.nextElement()));
+          sock.setSoTimeout(5000);
+          OutputStreamWriter writer = new OutputStreamWriter(sock.getOutputStream());
+          String request = String.format(
+                  "GET %s HTTP/1.1\nHost: %s\nConnection: close\n\n", path, host);
+          writer.write(request);
+          writer.flush();
+          BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream()));
+          String line = reader.readLine();
+
+          if (line == null || !line.startsWith("HTTP/1.1 200")) {
+              // Error.
+              return "Error: " + line;
+          }
+
+          do {
+              // Consume headers.
+              line = reader.readLine();
+          } while (!TextUtils.isEmpty(line));
+
+          // Return first line of body.
+          return reader.readLine();
+        } finally {
+            if (sock != null) {
+                IoUtils.closeQuietly(sock);
             }
         }
-
-        HttpParams httpParams = new BasicHttpParams();
-        if (networkInterface != null) {
-            ConnRouteParams.setLocalAddress(httpParams,
-                    networkInterface.getInetAddresses().nextElement());
-        }
-        HttpGet get = new HttpGet("http://www.bbc.com");
-        HttpClient client = new DefaultHttpClient(httpParams);
-        try {
-            HttpResponse response = client.execute(get);
-            Log.d(TAG, "response code = " + response.getStatusLine());
-        } catch (Exception e) {
-            Log.e(TAG, "Exception = "+ e );
-        }
     }
 
-    private void onBoundSocketRequest() {
-        NetworkInterface networkInterface = null;
-        try {
-            networkInterface = NetworkInterface.getByName("rmnet0");
-        } catch (Exception e) {
-            Log.e(TAG, "exception getByName: " + e);
-            return;
-        }
-        if (networkInterface == null) {
-            try {
-                Log.d(TAG, "getting any networkInterface");
-                networkInterface = NetworkInterface.getNetworkInterfaces().nextElement();
-            } catch (Exception e) {
-                Log.e(TAG, "exception getting any networkInterface: " + e);
-                return;
+    private void onHttpRequest(final int type) {
+        mRequestRunning = true;
+        onHttpRequestResults(null);
+
+        Thread requestThread = new Thread() {
+            public void run() {
+                final String path = "/ip.js?fmt=text";
+                final String randomHost =
+                        "h" + Integer.toString(new Random().nextInt()) + ".ds.ipv6test.google.com";
+                final String fixedHost = "google-ipv6test.appspot.com";
+
+                Network network = mBoundTestNetwork.getNetwork();
+                HttpURLConnection conn = null;
+                InputStreamReader in = null;
+
+                try {
+                    final URL httpsUrl = new URL("https", fixedHost, path);
+                    BufferedReader reader;
+
+                    switch (type) {
+                        case DEFAULT:
+                            conn = (HttpURLConnection) httpsUrl.openConnection(Proxy.NO_PROXY);
+                            in = new InputStreamReader(conn.getInputStream());
+                            reader = new BufferedReader(in);
+                            onHttpRequestResults(reader.readLine());
+                            break;
+                        case SOCKET:
+                            String response = doSocketRequest(network, randomHost, path);
+                            onHttpRequestResults(response);
+                            break;
+                        case HTTPS:
+                            conn = (HttpURLConnection) network.openConnection(httpsUrl,
+                                    Proxy.NO_PROXY);
+                            in = new InputStreamReader(conn.getInputStream());
+                            reader = new BufferedReader(in);
+                            onHttpRequestResults(reader.readLine());
+                            break;
+                        default:
+                            throw new IllegalArgumentException("Cannot happen");
+                    }
+                } catch(IOException e) {
+                    onHttpRequestResults("Error! ");
+                } finally {
+                    mRequestRunning = false;
+                    if (in != null) IoUtils.closeQuietly(in);
+                    if (conn != null) conn.disconnect();
+                }
             }
-        }
-        if (networkInterface == null) {
-            Log.e(TAG, "couldn't find a local interface");
-            return;
-        }
-        Enumeration inetAddressess = networkInterface.getInetAddresses();
-        while(inetAddressess.hasMoreElements()) {
-            Log.d(TAG, " addr:" + ((InetAddress)inetAddressess.nextElement()));
-        }
-        InetAddress local = null;
-        InetAddress remote = null;
-        try {
-            local = networkInterface.getInetAddresses().nextElement();
-        } catch (Exception e) {
-            Log.e(TAG, "exception getting local InetAddress: " + e);
-            return;
-        }
-        try {
-            remote = InetAddress.getByName("www.flickr.com");
-        } catch (Exception e) {
-            Log.e(TAG, "exception getting remote InetAddress: " + e);
-            return;
-        }
-        Log.d(TAG, "remote addr ="+remote);
-        Log.d(TAG, "local addr ="+local);
-        Socket socket = null;
-        try {
-            socket = new Socket(remote, 80, local, 6000);
-        } catch (Exception e) {
-            Log.e(TAG, "Exception creating socket: " + e);
-            return;
-        }
-        try {
-            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
-            out.println("Hi flickr");
-        } catch (Exception e) {
-            Log.e(TAG, "Exception writing to socket: " + e);
-            return;
-        }
-    }
-
-    private void onDefaultRequest() {
-        HttpParams params = new BasicHttpParams();
-        HttpGet get = new HttpGet("http://www.cnn.com");
-        HttpClient client = new DefaultHttpClient(params);
-        try {
-            HttpResponse response = client.execute(get);
-            Log.e(TAG, "response code = " + response.getStatusLine());
-        } catch (Exception e) {
-            Log.e(TAG, "Exception = " + e);
-        }
-    }
-
-    private void onDefaultSocket() {
-        InetAddress remote = null;
-        try {
-            remote = InetAddress.getByName("www.flickr.com");
-        } catch (Exception e) {
-            Log.e(TAG, "exception getting remote InetAddress: " + e);
-            return;
-        }
-        Log.e(TAG, "remote addr =" + remote);
-        Socket socket = null;
-        try {
-            socket = new Socket(remote, 80);
-        } catch (Exception e) {
-            Log.e(TAG, "Exception creating socket: " + e);
-            return;
-        }
-        try {
-            PrintWriter out = new PrintWriter(socket.getOutputStream(), true);
-            out.println("Hi flickr");
-            Log.e(TAG, "written");
-        } catch (Exception e) {
-            Log.e(TAG, "Exception writing to socket: " + e);
-            return;
-        }
+        };
+        requestThread.start();
     }
 }