/** ** ** Copyright 2006, 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.development; import android.app.Activity; import android.app.AlarmManager; import android.app.PendingIntent; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.net.ConnectivityManager; import android.net.ConnectivityManager.NetworkCallback; import android.net.EthernetManager; import android.net.IpConfiguration; import android.net.LinkProperties; import android.net.Network; import android.net.NetworkCapabilities; import android.net.NetworkRequest; import android.net.wifi.ScanResult; import android.net.wifi.WifiManager; import android.os.Handler; import android.os.Message; import android.os.IBinder; import android.os.INetworkManagementService; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.os.ServiceManager; import android.os.SystemClock; import android.os.Bundle; import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; import android.view.View; import android.widget.Button; import android.widget.CheckBox; import android.widget.EditText; import android.widget.TextView; import libcore.io.IoUtils; import java.io.BufferedReader; import java.io.InputStreamReader; import java.io.IOException; import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.InetAddress; import java.net.Proxy; import java.net.Socket; import java.net.URL; import java.util.ArrayList; import java.util.List; import java.util.Random; import static android.net.ConnectivityManager.CONNECTIVITY_ACTION; import static android.net.NetworkCapabilities.*; import com.android.internal.util.MessageUtils; public class Connectivity extends Activity { 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"; private static final long SCAN_CYCLES = 15; private static final int EVENT_TOGGLE_WIFI = 1; private static final int EVENT_TOGGLE_SCREEN = 2; private EditText mDCOnDurationEdit; private EditText mDCOffDurationEdit; private TextView mDCCycleCountView; private long mDCOnDuration = 120000; private long mDCOffDuration = 120000; private int mDCCycleCount = 0; private EditText mSCOnDurationEdit; private EditText mSCOffDurationEdit; private TextView mSCCycleCountView; private long mSCOnDuration = 120000; private long mSCOffDuration = 12000; private int mSCCycleCount = 0; private boolean mDelayedCycleStarted = false; private Button mScanButton; private TextView mScanResults; private EditText mScanCyclesEdit; private CheckBox mScanDisconnect; private long mScanCycles = SCAN_CYCLES; private long mScanCur = -1; private long mStartTime = -1; private long mStopTime; private long mTotalScanTime = 0; private long mTotalScanCount = 0; private TextView mLinkStatsResults; private TextView mHttpRequestResults; private String mTdlsAddr = null; private WifiManager mWm; private WifiManager.MulticastLock mWml; private PowerManager mPm; private ConnectivityManager mCm; private INetworkManagementService mNetd; private EthernetManager mEm; private WifiScanReceiver mScanRecv; IntentFilter mIntentFilter; private WakeLock mWakeLock = null; private WakeLock mScreenonWakeLock = null; private boolean mScreenOffToggleRunning = false; private boolean mScreenOff = false; private static final String CONNECTIVITY_TEST_ALARM = "com.android.development.CONNECTIVITY_TEST_ALARM"; private static final String TEST_ALARM_EXTRA = "CONNECTIVITY_TEST_EXTRA"; private static final String TEST_ALARM_ON_EXTRA = "CONNECTIVITY_TEST_ON_EXTRA"; private static final String TEST_ALARM_OFF_EXTRA = "CONNECTIVITY_TEST_OFF_EXTRA"; private static final String TEST_ALARM_CYCLE_EXTRA = "CONNECTIVITY_TEST_CYCLE_EXTRA"; private static final String SCREEN_ON = "SCREEN_ON"; private static final String SCREEN_OFF = "SCREEN_OFF"; private static final String NETWORK_CONDITIONS_MEASURED = "android.net.conn.NETWORK_CONDITIONS_MEASURED"; private void logBroadcast(Intent intent) { StringBuilder sb = new StringBuilder(); Bundle b = intent.getExtras(); for (String key : b.keySet()) { sb.append(String.format(" %s=%s", key, b.get(key))); } Log.d(TAG, "Got broadcast " + intent.getAction() + " extras:" + sb.toString()); } public BroadcastReceiver mReceiver = new BroadcastReceiver() { public void onReceive(Context context, Intent intent) { logBroadcast(intent); if (intent.getAction().equals(CONNECTIVITY_TEST_ALARM)) { String extra = (String)intent.getExtra(TEST_ALARM_EXTRA); PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); Long on = new Long(120000); Long off = new Long(120000); int cycle = 0; try { on = Long.parseLong((String)intent.getExtra(TEST_ALARM_ON_EXTRA)); off = Long.parseLong((String)intent.getExtra(TEST_ALARM_OFF_EXTRA)); cycle = Integer.parseInt((String)intent.getExtra(TEST_ALARM_CYCLE_EXTRA)); } catch (Exception e) {} if (extra.equals(SCREEN_ON)) { mScreenonWakeLock = mPm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "ConnectivityTest"); mScreenonWakeLock.acquire(); mSCCycleCount = cycle+1; mSCOnDuration = on; mSCOffDuration = off; mSCCycleCountView.setText(Integer.toString(mSCCycleCount)); scheduleAlarm(mSCOnDuration, SCREEN_OFF); } else if (extra.equals(SCREEN_OFF)) { mSCCycleCount = cycle; mSCOnDuration = on; mSCOffDuration = off; mScreenonWakeLock.release(); mScreenonWakeLock = null; scheduleAlarm(mSCOffDuration, SCREEN_ON); pm.goToSleep(SystemClock.uptimeMillis()); } } } }; public Handler mHandler2 = new Handler() { public void handleMessage(Message msg) { switch(msg.what) { case EVENT_TOGGLE_WIFI: Log.e(TAG, "EVENT_TOGGLE_WIFI"); if (mDelayedCycleStarted && mWm != null) { long delay; switch (mWm.getWifiState()) { case WifiManager.WIFI_STATE_ENABLED: case WifiManager.WIFI_STATE_ENABLING: mWm.setWifiEnabled(false); delay = mDCOffDuration; break; default: mWm.setWifiEnabled(true); delay = mDCOnDuration; mDCCycleCount++; mDCCycleCountView.setText(Integer.toString(mDCCycleCount)); } sendMessageDelayed(obtainMessage(EVENT_TOGGLE_WIFI), delay); } break; } } }; /** * Wifi Scan Listener */ private class WifiScanReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { mStopTime = SystemClock.elapsedRealtime(); if (mStartTime != -1) { mTotalScanTime += (mStopTime - mStartTime); mStartTime = -1; } Log.d(TAG, "Scan: READY " + mScanCur); mScanResults.setVisibility(View.INVISIBLE); List wifiScanResults = mWm.getScanResults(); if (wifiScanResults != null) { mTotalScanCount += wifiScanResults.size(); mScanResults.setText("Current scan = " + Long.toString(wifiScanResults.size())); mScanResults.setVisibility(View.VISIBLE); Log.d(TAG, "Scan: Results = " + wifiScanResults.size()); } mScanCur--; mScanCyclesEdit.setText(Long.toString(mScanCur)); if (mScanCur == 0) { unregisterReceiver(mScanRecv); mScanButton.setText(GET_SCAN_RES); mScanResults.setVisibility(View.INVISIBLE); } else { Log.d(TAG, "Scan: START " + mScanCur); mStartTime = SystemClock.elapsedRealtime(); mWm.startScan(); } } } } private static class DevToolsNetworkCallback extends NetworkCallback { private static final String TAG = "DevToolsNetworkCallback"; public void onAvailable(Network network) { Log.d(TAG, "onAvailable: " + network); } public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) { Log.d(TAG, "onCapabilitiesChanged: " + network + " " + nc.toString()); } public void onLinkPropertiesChanged(Network network, LinkProperties lp) { Log.d(TAG, "onLinkPropertiesChanged: " + network + " " + lp.toString()); } public void onLosing(Network network, int maxMsToLive) { Log.d(TAG, "onLosing: " + network + " " + maxMsToLive); } public void onLost(Network network) { Log.d(TAG, "onLost: " + network); } } private DevToolsNetworkCallback mCallback; private class RequestableNetwork { private final NetworkRequest mRequest; private final int mRequestButton, mReleaseButton, mProgressBar; private NetworkCallback mCallback; private Network mNetwork; public RequestableNetwork(NetworkRequest request, int requestButton, int releaseButton, int progressBar) { mRequest = request; mRequestButton = requestButton; mReleaseButton = releaseButton; mProgressBar = progressBar; } public RequestableNetwork(int capability, int requestButton, int releaseButton, int progressBar) { this(new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR) .addCapability(capability) .build(), requestButton, releaseButton, progressBar); } public void addOnClickListener() { findViewById(mRequestButton).setOnClickListener( new View.OnClickListener() { public void onClick(View v) { request(); }}); findViewById(mReleaseButton).setOnClickListener( new View.OnClickListener() { public void onClick(View v) { release(); }}); } public void setRequested(boolean requested) { findViewById(mRequestButton).setEnabled(!requested); findViewById(mReleaseButton).setEnabled(requested); findViewById(mProgressBar).setVisibility( requested ? View.VISIBLE : View.GONE); } public void request() { if (mCallback == null) { mCallback = new NetworkCallback() { @Override public void onAvailable(Network network) { mNetwork = network; onHttpRequestResults(null); runOnUiThread(() -> findViewById(mProgressBar).setVisibility(View.GONE)); } @Override public void onLost(Network network) { mNetwork = null; onHttpRequestResults(null); } }; mCm.requestNetwork(mRequest, mCallback); setRequested(true); } } 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 mRequestableNetworks = new ArrayList<>(); private final RequestableNetwork mBoundTestNetwork; private boolean mRequestRunning; private void addRequestableNetwork(RequestableNetwork network) { mRequestableNetworks.add(network); } private void addRequestableNetwork(int capability, int requestButton, int releaseButton, int progressBar) { mRequestableNetworks.add(new RequestableNetwork(capability, requestButton, releaseButton, progressBar)); } private static class DevToolsEthListener implements EthernetManager.InterfaceStateListener { private static final String TAG = DevToolsEthListener.class.getSimpleName(); private static final SparseArray STATE_NAMES = MessageUtils.findMessageNames( new Class[]{EthernetManager.class}, new String[]{"STATE_"}); private static final SparseArray ROLE_NAMES = MessageUtils.findMessageNames( new Class[]{EthernetManager.class}, new String[]{"ROLE_"}); private String stateName(int state) { return STATE_NAMES.get(state, Integer.toString(state)); } private String roleName(int role) { return ROLE_NAMES.get(role, Integer.toString(role)); } @Override public void onInterfaceStateChanged(String iface, int state, int role, IpConfiguration configuration) { Log.d(TAG, iface + " " + stateName(state) + " " + roleName(role) + " " + configuration); } } private final DevToolsEthListener mEthListener = new DevToolsEthListener(); public Connectivity() { super(); addRequestableNetwork(NET_CAPABILITY_MMS, R.id.request_mms, R.id.release_mms, R.id.mms_progress); addRequestableNetwork(NET_CAPABILITY_SUPL, R.id.request_supl, R.id.release_supl, R.id.supl_progress); addRequestableNetwork(NET_CAPABILITY_INTERNET, R.id.request_cell, R.id.release_cell, R.id.cell_progress); // Make bound requests use cell data. mBoundTestNetwork = mRequestableNetworks.get(mRequestableNetworks.size() - 1); NetworkRequest wifiRequest = new NetworkRequest.Builder() .addTransportType(NetworkCapabilities.TRANSPORT_WIFI) .build(); addRequestableNetwork(new RequestableNetwork(wifiRequest, R.id.request_wifi, R.id.release_wifi, R.id.wifi_progress)); } final NetworkRequest mEmptyRequest = new NetworkRequest.Builder().clearCapabilities().build(); @Override public void onCreate(Bundle icicle) { super.onCreate(icicle); setContentView(R.layout.connectivity); mWm = (WifiManager)getSystemService(Context.WIFI_SERVICE); mWml = mWm.createMulticastLock(TAG); mWml.setReferenceCounted(false); mPm = (PowerManager)getSystemService(Context.POWER_SERVICE); mCm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE); IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE); mNetd = INetworkManagementService.Stub.asInterface(b); mEm = getSystemService(EthernetManager.class); findViewById(R.id.enableWifi).setOnClickListener(mClickListener); findViewById(R.id.disableWifi).setOnClickListener(mClickListener); findViewById(R.id.acquireWifiMulticastLock).setOnClickListener(mClickListener); findViewById(R.id.releaseWifiMulticastLock).setOnClickListener(mClickListener); findViewById(R.id.releaseWifiMulticastLock).setEnabled(false); findViewById(R.id.startDelayedCycle).setOnClickListener(mClickListener); findViewById(R.id.stopDelayedCycle).setOnClickListener(mClickListener); mDCOnDurationEdit = (EditText)findViewById(R.id.dc_wifi_on_duration); mDCOnDurationEdit.setText(Long.toString(mDCOnDuration)); mDCOffDurationEdit = (EditText)findViewById(R.id.dc_wifi_off_duration); mDCOffDurationEdit.setText(Long.toString(mDCOffDuration)); mDCCycleCountView = (TextView)findViewById(R.id.dc_wifi_cycles_done); mDCCycleCountView.setText(Integer.toString(mDCCycleCount)); findViewById(R.id.startScreenCycle).setOnClickListener(mClickListener); findViewById(R.id.stopScreenCycle).setOnClickListener(mClickListener); mSCOnDurationEdit = (EditText)findViewById(R.id.sc_wifi_on_duration); mSCOnDurationEdit.setText(Long.toString(mSCOnDuration)); mSCOffDurationEdit = (EditText)findViewById(R.id.sc_wifi_off_duration); mSCOffDurationEdit.setText(Long.toString(mSCOffDuration)); mSCCycleCountView = (TextView)findViewById(R.id.sc_wifi_cycles_done); mSCCycleCountView.setText(Integer.toString(mSCCycleCount)); mScanButton = (Button)findViewById(R.id.startScan); mScanButton.setOnClickListener(mClickListener); mScanCyclesEdit = (EditText)findViewById(R.id.sc_scan_cycles); mScanCyclesEdit.setText(Long.toString(mScanCycles)); mScanDisconnect = (CheckBox)findViewById(R.id.scanDisconnect); mScanDisconnect.setChecked(true); mScanResults = (TextView)findViewById(R.id.sc_scan_results); mScanResults.setVisibility(View.INVISIBLE); mScanRecv = new WifiScanReceiver(); mIntentFilter = new IntentFilter(); mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); findViewById(R.id.startTdls).setOnClickListener(mClickListener); findViewById(R.id.stopTdls).setOnClickListener(mClickListener); findViewById(R.id.report_all_bad).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.link_stats).setOnClickListener(mClickListener); for (RequestableNetwork network : mRequestableNetworks) { network.setRequested(false); network.addOnClickListener(); } onHttpRequestResults(null); IntentFilter broadcastFilter = new IntentFilter(); broadcastFilter.addAction(CONNECTIVITY_ACTION); broadcastFilter.addAction(CONNECTIVITY_TEST_ALARM); broadcastFilter.addAction(NETWORK_CONDITIONS_MEASURED); registerReceiver(mReceiver, broadcastFilter); 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); mEm.addInterfaceStateListener(this::runOnUiThread, mEthListener); } @Override public void onDestroy() { super.onDestroy(); for (RequestableNetwork network : mRequestableNetworks) { network.release(); } mCm.unregisterNetworkCallback(mCallback); mCallback = null; mEm.removeInterfaceStateListener(mEthListener); unregisterReceiver(mReceiver); mWml.release(); } @Override public void onResume() { super.onResume(); findViewById(R.id.connectivity_layout).requestFocus(); } private View.OnClickListener mClickListener = new View.OnClickListener() { public void onClick(View v) { switch (v.getId()) { case R.id.enableWifi: mWm.setWifiEnabled(true); break; case R.id.disableWifi: mWm.setWifiEnabled(false); break; case R.id.acquireWifiMulticastLock: case R.id.releaseWifiMulticastLock: onWifiMulticastLock(v.getId() == R.id.acquireWifiMulticastLock); break; case R.id.startDelayedCycle: onStartDelayedCycle(); break; case R.id.stopDelayedCycle: onStopDelayedCycle(); break; case R.id.startScreenCycle: onStartScreenCycle(); break; case R.id.stopScreenCycle: onStopScreenCycle(); break; case R.id.startScan: onStartScanCycle(); break; case R.id.startTdls: onStartTdls(); break; case R.id.stopTdls: onStopTdls(); break; case R.id.default_request: onHttpRequest(DEFAULT); break; case R.id.bound_http_request: onHttpRequest(HTTPS); break; case R.id.bound_socket_request: onHttpRequest(SOCKET); break; case R.id.report_all_bad: onReportAllBad(); break; case R.id.link_stats: onLinkStats(); break; } } }; private void onStartDelayedCycle() { if (!mDelayedCycleStarted) { mDelayedCycleStarted = true; try { mDCOnDuration = Long.parseLong(mDCOnDurationEdit.getText().toString()); mDCOffDuration = Long.parseLong(mDCOffDurationEdit.getText().toString()); } catch (Exception e) { }; mDCCycleCount = 0; mWakeLock = mPm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "ConnectivityTest"); mWakeLock.acquire(); mHandler2.sendMessage(mHandler2.obtainMessage(EVENT_TOGGLE_WIFI)); } } private void onStopDelayedCycle() { if (mDelayedCycleStarted) { mDelayedCycleStarted = false; mWakeLock.release(); mWakeLock = null; if(mHandler2.hasMessages(EVENT_TOGGLE_WIFI)) { mHandler2.removeMessages(EVENT_TOGGLE_WIFI); } } } private void onStartScreenCycle() { try { mSCOnDuration = Long.parseLong(mSCOnDurationEdit.getText().toString()); mSCOffDuration = Long.parseLong(mSCOffDurationEdit.getText().toString()); } catch (Exception e) { }; mSCCycleCount = 0; mScreenonWakeLock = mPm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "ConnectivityTest"); mScreenonWakeLock.acquire(); scheduleAlarm(10, SCREEN_OFF); } private void scheduleAlarm(long delayMs, String eventType) { AlarmManager am = (AlarmManager)getSystemService(Context.ALARM_SERVICE); Intent i = new Intent(CONNECTIVITY_TEST_ALARM); i.putExtra(TEST_ALARM_EXTRA, eventType); i.putExtra(TEST_ALARM_ON_EXTRA, Long.toString(mSCOnDuration)); i.putExtra(TEST_ALARM_OFF_EXTRA, Long.toString(mSCOffDuration)); i.putExtra(TEST_ALARM_CYCLE_EXTRA, Integer.toString(mSCCycleCount)); PendingIntent p = PendingIntent.getBroadcast(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT|PendingIntent.FLAG_IMMUTABLE); am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + delayMs, p); } private void onStopScreenCycle() { } private void onReportAllBad() { Network[] networks = mCm.getAllNetworks(); for (Network network : networks) { mCm.reportBadNetwork(network); } } private void onStartScanCycle() { if (mScanCur == -1) { try { mScanCur = Long.parseLong(mScanCyclesEdit.getText().toString()); mScanCycles = mScanCur; } catch (Exception e) { }; if (mScanCur <= 0) { mScanCur = -1; mScanCycles = SCAN_CYCLES; return; } } if (mScanCur > 0) { registerReceiver(mScanRecv, mIntentFilter); mScanButton.setText(PROGRESS_SCAN); mScanResults.setVisibility(View.INVISIBLE); if (mScanDisconnect.isChecked()) mWm.disconnect(); mTotalScanTime = 0; mTotalScanCount = 0; Log.d(TAG, "Scan: START " + mScanCur); mStartTime = SystemClock.elapsedRealtime(); mWm.startScan(); } else { // Show results mScanResults.setText("Average Scan Time = " + Long.toString(mTotalScanTime / mScanCycles) + " ms ; Average Scan Amount = " + Long.toString(mTotalScanCount / mScanCycles)); mScanResults.setVisibility(View.VISIBLE); mScanButton.setText(START_SCAN); mScanCur = -1; mScanCyclesEdit.setText(Long.toString(mScanCycles)); if (mScanDisconnect.isChecked()) mWm.reassociate(); } } private void onStartTdls() { mTdlsAddr = ((EditText)findViewById(R.id.sc_ip_mac)).getText().toString(); Log.d(TAG, "TDLS: START " + mTdlsAddr); InetAddress inetAddress = null; try { inetAddress = InetAddress.getByName(mTdlsAddr); mWm.setTdlsEnabled(inetAddress, true); } catch (Exception e) { mWm.setTdlsEnabledWithMacAddress(mTdlsAddr, true); } } private void onStopTdls() { if (mTdlsAddr == null) return; Log.d(TAG, "TDLS: STOP " + mTdlsAddr); InetAddress inetAddress = null; try { inetAddress = InetAddress.getByName(mTdlsAddr); mWm.setTdlsEnabled(inetAddress, false); } catch (Exception e) { mWm.setTdlsEnabledWithMacAddress(mTdlsAddr, false); } } private void onLinkStats() { Log.e(TAG, "LINK STATS: "); try { mWm.getWifiActivityEnergyInfoAsync(getMainExecutor(), info -> { if (info != null) { mLinkStatsResults.setText(" power " + info.toString()); } else { mLinkStatsResults.setText(" null! "); } }); } catch (Exception e) { mLinkStatsResults.setText(" failed! " + e.toString()); } } private final static int DEFAULT = 0; private final static int SOCKET = 1; private final static int HTTPS = 2; private void onHttpRequestResults(final String results) { runOnUiThread(new Runnable() { @Override public void run() { boolean enabled = !mRequestRunning; findViewById(R.id.default_request).setEnabled(enabled); enabled = !mRequestRunning && mBoundTestNetwork.getNetwork() != null; findViewById(R.id.bound_http_request).setEnabled(enabled); findViewById(R.id.bound_socket_request).setEnabled(enabled); if (!TextUtils.isEmpty(results) || !mRequestRunning) { ((TextView) findViewById(R.id.http_response)).setText(results); } } }); } private String doSocketRequest(Network network, String host, String path) throws IOException { Socket sock = network.getSocketFactory().createSocket(host, 80); try { 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); } } } 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(); } } }; requestThread.start(); } private void onWifiMulticastLock(boolean enable) { Log.d(TAG, (enable ? "Acquiring" : "Releasing") + " wifi multicast lock"); if (enable) { mWml.acquire(); } else { mWml.release(); } findViewById(R.id.acquireWifiMulticastLock).setEnabled(!enable); findViewById(R.id.releaseWifiMulticastLock).setEnabled(enable); } }