1f04335f899f2cce69f843692a3cb9cec229683c2tturney/*
2f04335f899f2cce69f843692a3cb9cec229683c2tturney * Copyright (C) 2017 The Android Open Source Project
3f04335f899f2cce69f843692a3cb9cec229683c2tturney *
4f04335f899f2cce69f843692a3cb9cec229683c2tturney * Licensed under the Apache License, Version 2.0 (the "License");
5f04335f899f2cce69f843692a3cb9cec229683c2tturney * you may not use this file except in compliance with the License.
6f04335f899f2cce69f843692a3cb9cec229683c2tturney * You may obtain a copy of the License at
7f04335f899f2cce69f843692a3cb9cec229683c2tturney *
8f04335f899f2cce69f843692a3cb9cec229683c2tturney *      http://www.apache.org/licenses/LICENSE-2.0
9f04335f899f2cce69f843692a3cb9cec229683c2tturney *
10f04335f899f2cce69f843692a3cb9cec229683c2tturney * Unless required by applicable law or agreed to in writing, software
11f04335f899f2cce69f843692a3cb9cec229683c2tturney * distributed under the License is distributed on an "AS IS" BASIS,
12f04335f899f2cce69f843692a3cb9cec229683c2tturney * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13f04335f899f2cce69f843692a3cb9cec229683c2tturney * See the License for the specific language governing permissions and
14f04335f899f2cce69f843692a3cb9cec229683c2tturney * limitations under the License.
15f04335f899f2cce69f843692a3cb9cec229683c2tturney */
169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Lipackage com.googlecode.android_scripting.facade.wifi;
189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
19df001fb1e68108b33b4020a2bd52cb3346588377Betty Zhouimport com.googlecode.android_scripting.FileUtils;
20df001fb1e68108b33b4020a2bd52cb3346588377Betty Zhouimport com.googlecode.android_scripting.Log;
21df001fb1e68108b33b4020a2bd52cb3346588377Betty Zhouimport com.googlecode.android_scripting.facade.FacadeManager;
22df001fb1e68108b33b4020a2bd52cb3346588377Betty Zhouimport com.googlecode.android_scripting.jsonrpc.RpcReceiver;
23df001fb1e68108b33b4020a2bd52cb3346588377Betty Zhouimport com.googlecode.android_scripting.rpc.Rpc;
24df001fb1e68108b33b4020a2bd52cb3346588377Betty Zhouimport com.googlecode.android_scripting.rpc.RpcOptional;
25df001fb1e68108b33b4020a2bd52cb3346588377Betty Zhouimport com.googlecode.android_scripting.rpc.RpcParameter;
26df001fb1e68108b33b4020a2bd52cb3346588377Betty Zhou
279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.io.BufferedInputStream;
289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.io.BufferedReader;
299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.io.File;
309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.io.FileOutputStream;
319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.io.IOException;
329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.io.InputStream;
339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.io.InputStreamReader;
349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.io.OutputStream;
359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.net.HttpURLConnection;
369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.net.ServerSocket;
379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.net.Socket;
389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.net.SocketException;
399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.net.URL;
409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.net.UnknownHostException;
419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.nio.charset.StandardCharsets;
429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Liimport java.util.HashMap;
439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li/**
469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li * Basic http operations.
479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li */
489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Lipublic class HttpFacade extends RpcReceiver {
499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private ServerSocket mServerSocket = null;
519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private int mServerTimeout = -1;
529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private HashMap<Integer, Socket> mSockets = null;
539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private int socketCnt = 0;
549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public HttpFacade(FacadeManager manager) throws IOException {
569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        super(manager);
579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        mSockets = new HashMap<Integer, Socket>();
589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
609f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private void inputStreamToOutputStream(InputStream in, OutputStream out) throws IOException {
619f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (in == null) {
629f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            Log.e("InputStream is null.");
639f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            return;
649f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
659f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (out == null) {
669f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            Log.e("OutputStream is null.");
679f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            return;
689f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
699f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        try {
709f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            int read = 0;
719f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            byte[] bytes = new byte[1024];
729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            while ((read = in.read(bytes)) != -1) {
739f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                out.write(bytes, 0, read);
749f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            }
759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        } catch (IOException e) {
769f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            e.printStackTrace();
779f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        } finally {
789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            in.close();
799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            out.close();
809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private String inputStreamToString(InputStream in) throws IOException {
859f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        BufferedReader r = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8));
869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        StringBuilder sb = new StringBuilder();
879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        String str = null;
889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        while ((str = r.readLine()) != null) {
899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            sb.append(str);
909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
9175588767020acfdf994a064091ab6b10a8a6f779Betty Zhou        r.close();
929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return sb.toString();
939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    /**
969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * Send an http request and get the response.
979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     *
989f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @param url The url to send request to.
999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     * @return The HttpURLConnection object.
1009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li     */
1019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    private HttpURLConnection httpRequest(String url) throws IOException {
1029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        URL targetURL = new URL(url);
1039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        HttpURLConnection urlConnection = null;
1049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        try {
1059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            urlConnection = (HttpURLConnection) targetURL.openConnection();
1069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            urlConnection.connect();
1079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            int respCode = urlConnection.getResponseCode();
1089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            String respMsg = urlConnection.getResponseMessage();
1099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            Log.d("Got response code: " + respCode + " and response msg: " + respMsg);
1109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        } catch (IOException e) {
1119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            Log.e("Failed to open a connection to " + url);
1129f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            Log.e(e.toString());
1139f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
1149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return urlConnection;
1159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
1169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
1179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    @Rpc(description = "Start waiting for a connection request on a specified port.",
1189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            returns = "The index of the connection.")
119b0dd09a6aba592846940b856bea5cff47b41b8e4David Kao    public Integer httpAcceptConnection(@RpcParameter(name = "port") Integer port) throws IOException {
1209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        mServerSocket = new ServerSocket(port);
1219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        if (mServerTimeout > 0) {
1229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            mServerSocket.setSoTimeout(mServerTimeout);
1239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
1249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        Socket sock = mServerSocket.accept();
1259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        socketCnt += 1;
1269f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        mSockets.put(socketCnt, sock);
1279f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return socketCnt;
1289f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
1299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
130d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao    @Rpc(description = "Download a file from specified url, to an (optionally) specified path.")
131d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao    public void httpDownloadFile(@RpcParameter(name = "url") String url,
132d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao            @RpcParameter(name="outPath") @RpcOptional String outPath) throws IOException {
133d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao        // Create the input stream
1349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        HttpURLConnection urlConnection = httpRequest(url);
135d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao        // Parse destination path and create the output stream. The function assumes that the path
136d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao        // is specified relative to the system default Download dir.
137d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao        File outFile = FileUtils.getExternalDownload();
138df001fb1e68108b33b4020a2bd52cb3346588377Betty Zhou        if (outPath != null && outPath.trim().length() != 0) {
139d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao            // Check to see if the path is absolute.
140d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao            if (outPath.startsWith("/")) {
141d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao                outFile = new File(outPath);
142d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao            } else {
143d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao                outFile = new File(outFile, outPath);
144d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao            }
145d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao            // Check to see if specified path should be a dir.
146d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao            if (outPath.endsWith("/")) {
147d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao                if (!outFile.isDirectory() && !outFile.mkdirs()) {
148d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao                    throw new IOException("Failed to create the path: " + outPath);
149d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao                }
1509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            }
1519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
152d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao        // If no filename was specified, use the filename provided by the server.
153d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao        if (outFile.isDirectory()) {
154df001fb1e68108b33b4020a2bd52cb3346588377Betty Zhou            String filename = "";
155d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao            String contentDisposition = urlConnection.getHeaderField("Content-Disposition");
156d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao            // Try to figure out the name of the file being downloaded.
157d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao            // If the server returned a filename, use it.
158d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao            if (contentDisposition != null) {
159d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao                int idx = contentDisposition.toLowerCase().indexOf("filename");
160d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao                if (idx != -1) {
161d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao                    filename = contentDisposition.substring(idx + 9);
162d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao                    Log.d("Using filename returned by server: " + filename);
163d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao                }
164d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao            }
165d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao            // If the server did not provide a filename to us, use the last part of url.
166df001fb1e68108b33b4020a2bd52cb3346588377Betty Zhou            if (filename.trim().length() == 0) {
167d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao               int lastIdx = url.lastIndexOf('/');
168d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao                filename = url.substring(lastIdx + 1);
169d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao                Log.d("Using name from url: " + filename);
170d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao            }
171d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao            outFile = new File(outFile, filename);
1729f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
17375588767020acfdf994a064091ab6b10a8a6f779Betty Zhou        InputStream in = new BufferedInputStream(urlConnection.getInputStream());
174d77cb97c8506c789f4152e47e68dcd5a31c3d078David Kao        OutputStream output = new FileOutputStream(outFile);
1759f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        inputStreamToOutputStream(in, output);
176df001fb1e68108b33b4020a2bd52cb3346588377Betty Zhou        Log.d("Downloaded file from " + url + " to " + outPath);
17775588767020acfdf994a064091ab6b10a8a6f779Betty Zhou        urlConnection.disconnect();
1789f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
1799f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
1809f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    @Rpc(description = "Make an http request and return the response message.")
1819f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public HttpURLConnection httpPing(@RpcParameter(name = "url") String url) throws IOException {
1829f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        try {
1839f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            HttpURLConnection urlConnection = null;
1849f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            urlConnection = httpRequest(url);
18575588767020acfdf994a064091ab6b10a8a6f779Betty Zhou            urlConnection.disconnect();
1869f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            return urlConnection;
1879f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        } catch (UnknownHostException e) {
1889f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            return null;
1899f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
1909f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
1919f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
1929f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    @Rpc(description = "Make an http request and return the response content as a string.")
1939f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public String httpRequestString(@RpcParameter(name = "url") String url) throws IOException {
1949f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        HttpURLConnection urlConnection = httpRequest(url);
1959f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        InputStream in = new BufferedInputStream(urlConnection.getInputStream());
1969f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        String result = inputStreamToString(in);
1979f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        Log.d("Fetched: " + result);
19875588767020acfdf994a064091ab6b10a8a6f779Betty Zhou        urlConnection.disconnect();
1999f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        return result;
2009f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
2019f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
2029f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    @Rpc(description = "Set how many milliseconds to wait for an incoming connection.")
2039f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public void httpSetServerTimeout(@RpcParameter(name = "timeout") Integer timeout)
2049f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            throws SocketException {
2059f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        mServerSocket.setSoTimeout(timeout);
2069f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        mServerTimeout = timeout;
2079f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
2089f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
2099f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    @Rpc(description = "Ping to host(URL or IP), return success (true) or fail (false).")
2109f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    // The optional timeout parameter is in unit of second.
2119f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public Boolean pingHost(@RpcParameter(name = "host") String hostString,
2125924fafb30d81b920252897910fb1659af5187a6Girish Moturu            @RpcParameter(name = "timeout") @RpcOptional Integer timeout,
2135924fafb30d81b920252897910fb1659af5187a6Girish Moturu            @RpcParameter(name = "ping") @RpcOptional String pingType) {
2149f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        try {
2159f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            String host;
2169f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            try {
2179f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                URL url = new URL(hostString);
2189f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                host = url.getHost();
2199f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            } catch (java.net.MalformedURLException e) {
2209f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                Log.d("hostString is not URL, it may be IP address.");
2219f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                host = hostString;
2229f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            }
2239f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
2249f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            Log.d("Host:" + host);
2259f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            String pingCmdString = "ping -c 1 ";
2265924fafb30d81b920252897910fb1659af5187a6Girish Moturu            if(pingType!=null && pingType.equals("ping6")) {
2275924fafb30d81b920252897910fb1659af5187a6Girish Moturu                pingCmdString = "ping6 -c 1 ";
2285924fafb30d81b920252897910fb1659af5187a6Girish Moturu            }
2299f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            if (timeout != null) {
2309f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                pingCmdString = pingCmdString + "-W " + timeout + " ";
2319f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            }
2329f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            pingCmdString = pingCmdString + host;
2339f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            Log.d("Execute command: " + pingCmdString);
2349f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            Process p1 = java.lang.Runtime.getRuntime().exec(pingCmdString);
2359f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            int returnVal = p1.waitFor();
2369f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            boolean reachable = (returnVal == 0);
2379f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            Log.d("Ping return Value:" + returnVal);
2389f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            return reachable;
2399f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        } catch (Exception e){
2409f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            e.printStackTrace();
2419f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            return false;
2429f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
2439f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        /*TODO see b/18899134 for more information.
2449f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        */
2459f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
2469f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li
2479f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    @Override
2489f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    public void shutdown() {
2499f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        for (int key : mSockets.keySet()) {
2509f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            Socket sock = mSockets.get(key);
2519f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            try {
2529f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                sock.close();
2539f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            } catch (IOException e) {
2549f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                Log.e("Failed to close socket " + key + " on port " + sock.getLocalPort());
2559f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li                e.printStackTrace();
2569f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li            }
2579f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li        }
2589f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li    }
2599f32db87b486c93a0ea71eb1781ee45676b8bf8bXin Li}
260