Home | History | Annotate | Download | only in development
      1 /**
      2 **
      3 ** Copyright 2006, The Android Open Source Project
      4 **
      5 ** Licensed under the Apache License, Version 2.0 (the "License");
      6 ** you may not use this file except in compliance with the License.
      7 ** You may obtain a copy of the License at
      8 **
      9 **     http://www.apache.org/licenses/LICENSE-2.0
     10 **
     11 ** Unless required by applicable law or agreed to in writing, software
     12 ** distributed under the License is distributed on an "AS IS" BASIS,
     13 ** WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     14 ** See the License for the specific language governing permissions and
     15 ** limitations under the License.
     16 */
     17 
     18 package com.android.development;
     19 
     20 import android.app.Activity;
     21 import android.app.AlarmManager;
     22 import android.app.PendingIntent;
     23 import android.content.BroadcastReceiver;
     24 import android.content.Context;
     25 import android.content.Intent;
     26 import android.content.IntentFilter;
     27 import android.content.SharedPreferences;
     28 import android.content.pm.PackageManager.NameNotFoundException;
     29 import android.net.ConnectivityManager;
     30 import android.net.ConnectivityManager.NetworkCallback;
     31 import android.net.LinkAddress;
     32 import android.net.LinkProperties;
     33 import android.net.Network;
     34 import android.net.NetworkCapabilities;
     35 import android.net.NetworkRequest;
     36 import android.net.NetworkUtils;
     37 import android.net.RouteInfo;
     38 import android.net.wifi.ScanResult;
     39 import android.net.wifi.WifiActivityEnergyInfo;
     40 import android.net.wifi.WifiManager;
     41 import android.os.RemoteException;
     42 import android.os.Handler;
     43 import android.os.Message;
     44 import android.os.IBinder;
     45 import android.os.INetworkManagementService;
     46 import android.os.Parcel;
     47 import android.os.PowerManager;
     48 import android.os.PowerManager.WakeLock;
     49 import android.os.ServiceManager;
     50 import android.os.ServiceManagerNative;
     51 import android.os.SystemClock;
     52 import android.provider.Settings;
     53 import android.os.Bundle;
     54 import android.text.TextUtils;
     55 import android.util.Log;
     56 import android.view.IWindowManager;
     57 import android.view.View;
     58 import android.widget.ArrayAdapter;
     59 import android.widget.Button;
     60 import android.widget.CheckBox;
     61 import android.widget.CompoundButton;
     62 import android.widget.EditText;
     63 import android.widget.Spinner;
     64 import android.widget.TextView;
     65 import android.widget.Toast;
     66 import android.widget.AdapterView.OnItemSelectedListener;
     67 
     68 import com.android.internal.telephony.Phone;
     69 import libcore.io.IoUtils;
     70 
     71 import java.io.BufferedReader;
     72 import java.io.FileInputStream;
     73 import java.io.FileOutputStream;
     74 import java.io.InputStreamReader;
     75 import java.io.IOException;
     76 import java.io.OutputStreamWriter;
     77 import java.io.PrintWriter;
     78 import java.net.HttpURLConnection;
     79 import java.net.InetAddress;
     80 import java.net.Proxy;
     81 import java.net.Socket;
     82 import java.net.URL;
     83 import java.util.ArrayList;
     84 import java.util.Enumeration;
     85 import java.util.List;
     86 import java.util.Random;
     87 
     88 import static android.net.NetworkCapabilities.*;
     89 
     90 public class Connectivity extends Activity {
     91     private static final String TAG = "DevToolsConnectivity";
     92     private static final String GET_SCAN_RES = "Get Results";
     93     private static final String START_SCAN = "Start Scan";
     94     private static final String PROGRESS_SCAN = "In Progress";
     95 
     96     private static final long SCAN_CYCLES = 15;
     97 
     98     private static final int EVENT_TOGGLE_WIFI = 1;
     99     private static final int EVENT_TOGGLE_SCREEN = 2;
    100 
    101     private EditText mDCOnDurationEdit;
    102     private EditText mDCOffDurationEdit;
    103     private TextView mDCCycleCountView;
    104     private long mDCOnDuration = 120000;
    105     private long mDCOffDuration = 120000;
    106     private int mDCCycleCount = 0;
    107 
    108     private EditText mSCOnDurationEdit;
    109     private EditText mSCOffDurationEdit;
    110     private TextView mSCCycleCountView;
    111     private long mSCOnDuration = 120000;
    112     private long mSCOffDuration = 12000;
    113     private int mSCCycleCount = 0;
    114 
    115     private boolean mDelayedCycleStarted = false;
    116 
    117     private Button mScanButton;
    118     private TextView mScanResults;
    119     private EditText mScanCyclesEdit;
    120     private CheckBox mScanDisconnect;
    121     private long mScanCycles = SCAN_CYCLES;
    122     private long mScanCur = -1;
    123     private long mStartTime = -1;
    124     private long mStopTime;
    125     private long mTotalScanTime = 0;
    126     private long mTotalScanCount = 0;
    127 
    128     private TextView mLinkStatsResults;
    129     private TextView mHttpRequestResults;
    130 
    131     private String mTdlsAddr = null;
    132 
    133     private WifiManager mWm;
    134     private WifiManager.MulticastLock mWml;
    135     private PowerManager mPm;
    136     private ConnectivityManager mCm;
    137     private INetworkManagementService mNetd;
    138 
    139     private WifiScanReceiver mScanRecv;
    140     IntentFilter mIntentFilter;
    141 
    142     private WakeLock mWakeLock = null;
    143     private WakeLock mScreenonWakeLock = null;
    144 
    145     private boolean mScreenOffToggleRunning = false;
    146     private boolean mScreenOff = false;
    147 
    148     private static final String CONNECTIVITY_TEST_ALARM =
    149             "com.android.development.CONNECTIVITY_TEST_ALARM";
    150     private static final String TEST_ALARM_EXTRA = "CONNECTIVITY_TEST_EXTRA";
    151     private static final String TEST_ALARM_ON_EXTRA = "CONNECTIVITY_TEST_ON_EXTRA";
    152     private static final String TEST_ALARM_OFF_EXTRA = "CONNECTIVITY_TEST_OFF_EXTRA";
    153     private static final String TEST_ALARM_CYCLE_EXTRA = "CONNECTIVITY_TEST_CYCLE_EXTRA";
    154     private static final String SCREEN_ON = "SCREEN_ON";
    155     private static final String SCREEN_OFF = "SCREEN_OFF";
    156     public BroadcastReceiver mReceiver = new BroadcastReceiver() {
    157         public void onReceive(Context context, Intent intent) {
    158             if (intent.getAction().equals(CONNECTIVITY_TEST_ALARM)) {
    159                 String extra = (String)intent.getExtra(TEST_ALARM_EXTRA);
    160                 PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
    161                 Long on = new Long(120000);
    162                 Long off = new Long(120000);
    163                 int cycle = 0;
    164                 try {
    165                     on = Long.parseLong((String)intent.getExtra(TEST_ALARM_ON_EXTRA));
    166                     off = Long.parseLong((String)intent.getExtra(TEST_ALARM_OFF_EXTRA));
    167                     cycle = Integer.parseInt((String)intent.getExtra(TEST_ALARM_CYCLE_EXTRA));
    168                 } catch (Exception e) {}
    169 
    170                 if (extra.equals(SCREEN_ON)) {
    171                     mScreenonWakeLock = mPm.newWakeLock(PowerManager.FULL_WAKE_LOCK |
    172                             PowerManager.ACQUIRE_CAUSES_WAKEUP,
    173                             "ConnectivityTest");
    174                     mScreenonWakeLock.acquire();
    175 
    176                     mSCCycleCount = cycle+1;
    177                     mSCOnDuration = on;
    178                     mSCOffDuration = off;
    179                     mSCCycleCountView.setText(Integer.toString(mSCCycleCount));
    180 
    181                     scheduleAlarm(mSCOnDuration, SCREEN_OFF);
    182                 } else if (extra.equals(SCREEN_OFF)) {
    183 
    184                     mSCCycleCount = cycle;
    185                     mSCOnDuration = on;
    186                     mSCOffDuration = off;
    187 
    188                     mScreenonWakeLock.release();
    189                     mScreenonWakeLock = null;
    190                     scheduleAlarm(mSCOffDuration, SCREEN_ON);
    191                     pm.goToSleep(SystemClock.uptimeMillis());
    192                 }
    193             }
    194         }
    195     };
    196 
    197     public Handler mHandler2 = new Handler() {
    198         public void handleMessage(Message msg) {
    199             switch(msg.what) {
    200                 case EVENT_TOGGLE_WIFI:
    201                     Log.e(TAG, "EVENT_TOGGLE_WIFI");
    202                     if (mDelayedCycleStarted && mWm != null) {
    203                         long delay;
    204                         switch (mWm.getWifiState()) {
    205                             case WifiManager.WIFI_STATE_ENABLED:
    206                             case WifiManager.WIFI_STATE_ENABLING:
    207                                 mWm.setWifiEnabled(false);
    208                                 delay = mDCOffDuration;
    209                                 break;
    210                             default:
    211                                 mWm.setWifiEnabled(true);
    212                                 delay = mDCOnDuration;
    213                                 mDCCycleCount++;
    214                                 mDCCycleCountView.setText(Integer.toString(mDCCycleCount));
    215                         }
    216                         sendMessageDelayed(obtainMessage(EVENT_TOGGLE_WIFI),
    217                                 delay);
    218                     }
    219                     break;
    220             }
    221         }
    222     };
    223 
    224    /**
    225      * Wifi Scan Listener
    226      */
    227     private class WifiScanReceiver extends BroadcastReceiver {
    228         @Override
    229         public void onReceive(Context context, Intent intent) {
    230             String action = intent.getAction();
    231 
    232             if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
    233                 mStopTime = SystemClock.elapsedRealtime();
    234                 if (mStartTime != -1) {
    235                     mTotalScanTime += (mStopTime - mStartTime);
    236                     mStartTime = -1;
    237                 }
    238                 Log.d(TAG, "Scan: READY " + mScanCur);
    239                 mScanResults.setVisibility(View.INVISIBLE);
    240 
    241                 List<ScanResult> wifiScanResults = mWm.getScanResults();
    242                 if (wifiScanResults != null) {
    243                     mTotalScanCount += wifiScanResults.size();
    244                     mScanResults.setText("Current scan = " + Long.toString(wifiScanResults.size()));
    245                     mScanResults.setVisibility(View.VISIBLE);
    246                     Log.d(TAG, "Scan: Results = " + wifiScanResults.size());
    247                 }
    248 
    249                 mScanCur--;
    250                 mScanCyclesEdit.setText(Long.toString(mScanCur));
    251                 if (mScanCur == 0) {
    252                     unregisterReceiver(mScanRecv);
    253                     mScanButton.setText(GET_SCAN_RES);
    254                     mScanResults.setVisibility(View.INVISIBLE);
    255                 } else {
    256                     Log.d(TAG, "Scan: START " + mScanCur);
    257                     mStartTime = SystemClock.elapsedRealtime();
    258                     mWm.startScan();
    259                 }
    260             }
    261         }
    262     }
    263 
    264     private static class DevToolsNetworkCallback extends NetworkCallback {
    265         private static final String TAG = "DevToolsNetworkCallback";
    266 
    267         public void onPreCheck(Network network) {
    268             Log.d(TAG, "onPreCheck: " + network.netId);
    269         }
    270 
    271         public void onAvailable(Network network) {
    272             Log.d(TAG, "onAvailable: " + network.netId);
    273         }
    274 
    275         public void onCapabilitiesChanged(Network network, NetworkCapabilities nc) {
    276             Log.d(TAG, "onCapabilitiesChanged: " + network.netId + " " + nc.toString());
    277         }
    278 
    279         public void onLinkPropertiesChanged(Network network, LinkProperties lp) {
    280             Log.d(TAG, "onLinkPropertiesChanged: " + network.netId + " " + lp.toString());
    281         }
    282 
    283         public void onLosing(Network network, int maxMsToLive) {
    284             Log.d(TAG, "onLosing: " + network.netId + " " + maxMsToLive);
    285         }
    286 
    287         public void onLost(Network network) {
    288             Log.d(TAG, "onLost: " + network.netId);
    289         }
    290     }
    291     private DevToolsNetworkCallback mCallback;
    292 
    293     private class RequestableNetwork {
    294         private final NetworkRequest mRequest;
    295         private final int mRequestButton, mReleaseButton, mProgressBar;
    296         private NetworkCallback mCallback;
    297         private Network mNetwork;
    298 
    299         public RequestableNetwork(NetworkRequest request, int requestButton, int releaseButton,
    300                 int progressBar) {
    301             mRequest = request;
    302             mRequestButton = requestButton;
    303             mReleaseButton = releaseButton;
    304             mProgressBar = progressBar;
    305         }
    306 
    307         public RequestableNetwork(int capability, int requestButton, int releaseButton,
    308                 int progressBar) {
    309             this(new NetworkRequest.Builder()
    310                     .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)
    311                     .addCapability(capability)
    312                     .build(),
    313                     requestButton, releaseButton, progressBar);
    314         }
    315 
    316         public void addOnClickListener() {
    317             findViewById(mRequestButton).setOnClickListener(
    318                     new View.OnClickListener() { public void onClick(View v) { request(); }});
    319             findViewById(mReleaseButton).setOnClickListener(
    320                     new View.OnClickListener() { public void onClick(View v) { release(); }});
    321         }
    322 
    323         public void setRequested(boolean requested) {
    324             findViewById(mRequestButton).setEnabled(!requested);
    325             findViewById(mReleaseButton).setEnabled(requested);
    326             findViewById(mProgressBar).setVisibility(
    327                     requested ? View.VISIBLE : View.GONE);
    328         }
    329 
    330         public void request() {
    331             if (mCallback == null) {
    332                 mCallback = new NetworkCallback() {
    333                     @Override
    334                     public void onAvailable(Network network) {
    335                         mNetwork = network;
    336                         onHttpRequestResults(null);
    337                         runOnUiThread(() -> findViewById(mProgressBar).setVisibility(View.GONE));
    338                     }
    339                     @Override
    340                     public void onLost(Network network) {
    341                         mNetwork = null;
    342                         onHttpRequestResults(null);
    343                     }
    344                 };
    345                 mCm.requestNetwork(mRequest, mCallback);
    346                 setRequested(true);
    347             }
    348         }
    349 
    350         public void release() {
    351             if (mCallback != null) {
    352                 mNetwork = null;
    353                 onHttpRequestResults(null);
    354                 mCm.unregisterNetworkCallback(mCallback);
    355                 mCallback = null;
    356                 setRequested(false);
    357             }
    358         }
    359 
    360         public Network getNetwork() {
    361             return mNetwork;
    362         }
    363     }
    364 
    365     private final ArrayList<RequestableNetwork> mRequestableNetworks = new ArrayList<>();
    366     private final RequestableNetwork mBoundTestNetwork;
    367     private boolean mRequestRunning;
    368 
    369     private void addRequestableNetwork(RequestableNetwork network) {
    370         mRequestableNetworks.add(network);
    371     }
    372 
    373     private void addRequestableNetwork(int capability, int requestButton, int releaseButton,
    374             int progressBar) {
    375         mRequestableNetworks.add(new RequestableNetwork(capability, requestButton, releaseButton,
    376                 progressBar));
    377     }
    378 
    379     public Connectivity() {
    380         super();
    381         addRequestableNetwork(NET_CAPABILITY_MMS, R.id.request_mms, R.id.release_mms,
    382                 R.id.mms_progress);
    383         addRequestableNetwork(NET_CAPABILITY_SUPL, R.id.request_supl, R.id.release_supl,
    384                 R.id.supl_progress);
    385         addRequestableNetwork(NET_CAPABILITY_INTERNET, R.id.request_cell, R.id.release_cell,
    386                 R.id.cell_progress);
    387 
    388         // Make bound requests use cell data.
    389         mBoundTestNetwork = mRequestableNetworks.get(mRequestableNetworks.size() - 1);
    390 
    391         NetworkRequest wifiRequest = new NetworkRequest.Builder()
    392             .addTransportType(NetworkCapabilities.TRANSPORT_WIFI)
    393             .build();
    394         addRequestableNetwork(new RequestableNetwork(wifiRequest,
    395                 R.id.request_wifi, R.id.release_wifi, R.id.wifi_progress));
    396     }
    397 
    398     final NetworkRequest mEmptyRequest = new NetworkRequest.Builder().clearCapabilities().build();
    399 
    400     @Override
    401     public void onCreate(Bundle icicle) {
    402         super.onCreate(icicle);
    403 
    404         setContentView(R.layout.connectivity);
    405 
    406         mWm = (WifiManager)getSystemService(Context.WIFI_SERVICE);
    407         mWml = mWm.createMulticastLock(TAG);
    408         mWml.setReferenceCounted(false);
    409         mPm = (PowerManager)getSystemService(Context.POWER_SERVICE);
    410         mCm = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
    411         IBinder b = ServiceManager.getService(Context.NETWORKMANAGEMENT_SERVICE);
    412         mNetd = INetworkManagementService.Stub.asInterface(b);
    413 
    414         findViewById(R.id.enableWifi).setOnClickListener(mClickListener);
    415         findViewById(R.id.disableWifi).setOnClickListener(mClickListener);
    416         findViewById(R.id.acquireWifiMulticastLock).setOnClickListener(mClickListener);
    417         findViewById(R.id.releaseWifiMulticastLock).setOnClickListener(mClickListener);
    418         findViewById(R.id.releaseWifiMulticastLock).setEnabled(false);
    419 
    420         findViewById(R.id.startDelayedCycle).setOnClickListener(mClickListener);
    421         findViewById(R.id.stopDelayedCycle).setOnClickListener(mClickListener);
    422         mDCOnDurationEdit = (EditText)findViewById(R.id.dc_wifi_on_duration);
    423         mDCOnDurationEdit.setText(Long.toString(mDCOnDuration));
    424         mDCOffDurationEdit = (EditText)findViewById(R.id.dc_wifi_off_duration);
    425         mDCOffDurationEdit.setText(Long.toString(mDCOffDuration));
    426         mDCCycleCountView = (TextView)findViewById(R.id.dc_wifi_cycles_done);
    427         mDCCycleCountView.setText(Integer.toString(mDCCycleCount));
    428 
    429         findViewById(R.id.startScreenCycle).setOnClickListener(mClickListener);
    430         findViewById(R.id.stopScreenCycle).setOnClickListener(mClickListener);
    431         mSCOnDurationEdit = (EditText)findViewById(R.id.sc_wifi_on_duration);
    432         mSCOnDurationEdit.setText(Long.toString(mSCOnDuration));
    433         mSCOffDurationEdit = (EditText)findViewById(R.id.sc_wifi_off_duration);
    434         mSCOffDurationEdit.setText(Long.toString(mSCOffDuration));
    435         mSCCycleCountView = (TextView)findViewById(R.id.sc_wifi_cycles_done);
    436         mSCCycleCountView.setText(Integer.toString(mSCCycleCount));
    437 
    438         mScanButton = (Button)findViewById(R.id.startScan);
    439         mScanButton.setOnClickListener(mClickListener);
    440         mScanCyclesEdit = (EditText)findViewById(R.id.sc_scan_cycles);
    441         mScanCyclesEdit.setText(Long.toString(mScanCycles));
    442         mScanDisconnect = (CheckBox)findViewById(R.id.scanDisconnect);
    443         mScanDisconnect.setChecked(true);
    444         mScanResults = (TextView)findViewById(R.id.sc_scan_results);
    445         mScanResults.setVisibility(View.INVISIBLE);
    446 
    447         mScanRecv = new WifiScanReceiver();
    448         mIntentFilter = new IntentFilter();
    449         mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
    450 
    451         findViewById(R.id.startTdls).setOnClickListener(mClickListener);
    452         findViewById(R.id.stopTdls).setOnClickListener(mClickListener);
    453 
    454         findViewById(R.id.report_all_bad).setOnClickListener(mClickListener);
    455 
    456         findViewById(R.id.default_request).setOnClickListener(mClickListener);
    457         findViewById(R.id.bound_http_request).setOnClickListener(mClickListener);
    458         findViewById(R.id.bound_socket_request).setOnClickListener(mClickListener);
    459 
    460         findViewById(R.id.link_stats).setOnClickListener(mClickListener);
    461 
    462         for (RequestableNetwork network : mRequestableNetworks) {
    463             network.setRequested(false);
    464             network.addOnClickListener();
    465         }
    466         onHttpRequestResults(null);
    467 
    468         registerReceiver(mReceiver, new IntentFilter(CONNECTIVITY_TEST_ALARM));
    469 
    470         mLinkStatsResults = (TextView)findViewById(R.id.stats);
    471         mLinkStatsResults.setVisibility(View.VISIBLE);
    472 
    473         mHttpRequestResults = (TextView)findViewById(R.id.http_response);
    474         mHttpRequestResults.setVisibility(View.VISIBLE);
    475 
    476         mCallback = new DevToolsNetworkCallback();
    477         mCm.registerNetworkCallback(mEmptyRequest, mCallback);
    478     }
    479 
    480     @Override
    481     public void onDestroy() {
    482         super.onDestroy();
    483         for (RequestableNetwork network : mRequestableNetworks) {
    484             network.release();
    485         }
    486         mCm.unregisterNetworkCallback(mCallback);
    487         mCallback = null;
    488         unregisterReceiver(mReceiver);
    489         mWml.release();
    490     }
    491 
    492     @Override
    493     public void onResume() {
    494         super.onResume();
    495         findViewById(R.id.connectivity_layout).requestFocus();
    496     }
    497 
    498     private View.OnClickListener mClickListener = new View.OnClickListener() {
    499         public void onClick(View v) {
    500             switch (v.getId()) {
    501                 case R.id.enableWifi:
    502                     mWm.setWifiEnabled(true);
    503                     break;
    504                 case R.id.disableWifi:
    505                     mWm.setWifiEnabled(false);
    506                     break;
    507                 case R.id.acquireWifiMulticastLock:
    508                 case R.id.releaseWifiMulticastLock:
    509                     onWifiMulticastLock(v.getId() == R.id.acquireWifiMulticastLock);
    510                     break;
    511                 case R.id.startDelayedCycle:
    512                     onStartDelayedCycle();
    513                     break;
    514                 case R.id.stopDelayedCycle:
    515                     onStopDelayedCycle();
    516                     break;
    517                 case R.id.startScreenCycle:
    518                     onStartScreenCycle();
    519                     break;
    520                 case R.id.stopScreenCycle:
    521                     onStopScreenCycle();
    522                     break;
    523                 case R.id.startScan:
    524                     onStartScanCycle();
    525                     break;
    526                 case R.id.startTdls:
    527                     onStartTdls();
    528                     break;
    529                 case R.id.stopTdls:
    530                     onStopTdls();
    531                     break;
    532                 case R.id.default_request:
    533                     onHttpRequest(DEFAULT);
    534                     break;
    535                 case R.id.bound_http_request:
    536                     onHttpRequest(HTTPS);
    537                     break;
    538                 case R.id.bound_socket_request:
    539                     onHttpRequest(SOCKET);
    540                     break;
    541                 case R.id.report_all_bad:
    542                     onReportAllBad();
    543                     break;
    544                 case R.id.link_stats:
    545                     onLinkStats();
    546                     break;
    547             }
    548         }
    549     };
    550 
    551 
    552     private void onStartDelayedCycle() {
    553         if (!mDelayedCycleStarted) {
    554             mDelayedCycleStarted = true;
    555             try {
    556                 mDCOnDuration = Long.parseLong(mDCOnDurationEdit.getText().toString());
    557                 mDCOffDuration = Long.parseLong(mDCOffDurationEdit.getText().toString());
    558             } catch (Exception e) { };
    559             mDCCycleCount = 0;
    560 
    561             mWakeLock = mPm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "ConnectivityTest");
    562             mWakeLock.acquire();
    563             mHandler2.sendMessage(mHandler2.obtainMessage(EVENT_TOGGLE_WIFI));
    564         }
    565     }
    566 
    567     private void onStopDelayedCycle() {
    568         if (mDelayedCycleStarted) {
    569             mDelayedCycleStarted = false;
    570             mWakeLock.release();
    571             mWakeLock = null;
    572             if(mHandler2.hasMessages(EVENT_TOGGLE_WIFI)) {
    573                 mHandler2.removeMessages(EVENT_TOGGLE_WIFI);
    574             }
    575         }
    576     }
    577 
    578     private void onStartScreenCycle() {
    579         try {
    580             mSCOnDuration = Long.parseLong(mSCOnDurationEdit.getText().toString());
    581             mSCOffDuration = Long.parseLong(mSCOffDurationEdit.getText().toString());
    582         } catch (Exception e) { };
    583         mSCCycleCount = 0;
    584 
    585         mScreenonWakeLock = mPm.newWakeLock(PowerManager.FULL_WAKE_LOCK,
    586                 "ConnectivityTest");
    587         mScreenonWakeLock.acquire();
    588 
    589         scheduleAlarm(10, SCREEN_OFF);
    590     }
    591 
    592     private void scheduleAlarm(long delayMs, String eventType) {
    593         AlarmManager am = (AlarmManager)getSystemService(Context.ALARM_SERVICE);
    594         Intent i = new Intent(CONNECTIVITY_TEST_ALARM);
    595 
    596         i.putExtra(TEST_ALARM_EXTRA, eventType);
    597         i.putExtra(TEST_ALARM_ON_EXTRA, Long.toString(mSCOnDuration));
    598         i.putExtra(TEST_ALARM_OFF_EXTRA, Long.toString(mSCOffDuration));
    599         i.putExtra(TEST_ALARM_CYCLE_EXTRA, Integer.toString(mSCCycleCount));
    600 
    601         PendingIntent p = PendingIntent.getBroadcast(this, 0, i, PendingIntent.FLAG_UPDATE_CURRENT);
    602 
    603         am.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + delayMs, p);
    604     }
    605 
    606     private void onStopScreenCycle() {
    607     }
    608 
    609     private void onReportAllBad() {
    610         Network[] networks = mCm.getAllNetworks();
    611         for (Network network : networks) {
    612             mCm.reportBadNetwork(network);
    613         }
    614     }
    615 
    616     private void onStartScanCycle() {
    617         if (mScanCur == -1) {
    618             try {
    619                 mScanCur = Long.parseLong(mScanCyclesEdit.getText().toString());
    620                 mScanCycles = mScanCur;
    621             } catch (Exception e) { };
    622             if (mScanCur <= 0) {
    623                 mScanCur = -1;
    624                 mScanCycles = SCAN_CYCLES;
    625                 return;
    626             }
    627         }
    628         if (mScanCur > 0) {
    629             registerReceiver(mScanRecv, mIntentFilter);
    630             mScanButton.setText(PROGRESS_SCAN);
    631             mScanResults.setVisibility(View.INVISIBLE);
    632             if (mScanDisconnect.isChecked())
    633                 mWm.disconnect();
    634             mTotalScanTime = 0;
    635             mTotalScanCount = 0;
    636             Log.d(TAG, "Scan: START " + mScanCur);
    637             mStartTime = SystemClock.elapsedRealtime();
    638             mWm.startScan();
    639         } else {
    640             // Show results
    641             mScanResults.setText("Average Scan Time = " +
    642                 Long.toString(mTotalScanTime / mScanCycles) + " ms ; Average Scan Amount = " +
    643                 Long.toString(mTotalScanCount / mScanCycles));
    644             mScanResults.setVisibility(View.VISIBLE);
    645             mScanButton.setText(START_SCAN);
    646             mScanCur = -1;
    647             mScanCyclesEdit.setText(Long.toString(mScanCycles));
    648             if (mScanDisconnect.isChecked())
    649                 mWm.reassociate();
    650         }
    651     }
    652 
    653     private void onStartTdls() {
    654         mTdlsAddr = ((EditText)findViewById(R.id.sc_ip_mac)).getText().toString();
    655         Log.d(TAG, "TDLS: START " + mTdlsAddr);
    656         InetAddress inetAddress = null;
    657         try {
    658             inetAddress = InetAddress.getByName(mTdlsAddr);
    659             mWm.setTdlsEnabled(inetAddress, true);
    660         } catch (Exception e) {
    661             mWm.setTdlsEnabledWithMacAddress(mTdlsAddr, true);
    662         }
    663     }
    664 
    665     private void onStopTdls() {
    666         if (mTdlsAddr == null) return;
    667         Log.d(TAG, "TDLS: STOP " + mTdlsAddr);
    668         InetAddress inetAddress = null;
    669         try {
    670             inetAddress = InetAddress.getByName(mTdlsAddr);
    671             mWm.setTdlsEnabled(inetAddress, false);
    672         } catch (Exception e) {
    673             mWm.setTdlsEnabledWithMacAddress(mTdlsAddr, false);
    674         }
    675     }
    676 
    677     private void onLinkStats() {
    678         Log.e(TAG, "LINK STATS:  ");
    679         try {
    680             WifiActivityEnergyInfo info =
    681                     mWm.getControllerActivityEnergyInfo(0);
    682             if (info != null) {
    683                 mLinkStatsResults.setText(" power " + info.toString());
    684             } else {
    685                 mLinkStatsResults.setText(" null! ");
    686             }
    687         } catch (Exception e) {
    688             mLinkStatsResults.setText(" failed! " + e.toString());
    689         }
    690     }
    691 
    692 
    693     private final static int DEFAULT = 0;
    694     private final static int SOCKET = 1;
    695     private final static int HTTPS  = 2;
    696 
    697     private void onHttpRequestResults(final String results) {
    698         runOnUiThread(new Runnable() {
    699             @Override
    700             public void run() {
    701                 boolean enabled = !mRequestRunning;
    702                 findViewById(R.id.default_request).setEnabled(enabled);
    703 
    704                 enabled = !mRequestRunning && mBoundTestNetwork.getNetwork() != null;
    705                 findViewById(R.id.bound_http_request).setEnabled(enabled);
    706                 findViewById(R.id.bound_socket_request).setEnabled(enabled);
    707 
    708                 if (!TextUtils.isEmpty(results) || !mRequestRunning) {
    709                     ((TextView) findViewById(R.id.http_response)).setText(results);
    710                 }
    711             }
    712         });
    713     }
    714 
    715     private String doSocketRequest(Network network, String host, String path) throws IOException {
    716         Socket sock = network.getSocketFactory().createSocket(host, 80);
    717         try {
    718           sock.setSoTimeout(5000);
    719           OutputStreamWriter writer = new OutputStreamWriter(sock.getOutputStream());
    720           String request = String.format(
    721                   "GET %s HTTP/1.1\nHost: %s\nConnection: close\n\n", path, host);
    722           writer.write(request);
    723           writer.flush();
    724           BufferedReader reader = new BufferedReader(new InputStreamReader(sock.getInputStream()));
    725           String line = reader.readLine();
    726 
    727           if (line == null || !line.startsWith("HTTP/1.1 200")) {
    728               // Error.
    729               return "Error: " + line;
    730           }
    731 
    732           do {
    733               // Consume headers.
    734               line = reader.readLine();
    735           } while (!TextUtils.isEmpty(line));
    736 
    737           // Return first line of body.
    738           return reader.readLine();
    739         } finally {
    740             if (sock != null) {
    741                 IoUtils.closeQuietly(sock);
    742             }
    743         }
    744     }
    745 
    746     private void onHttpRequest(final int type) {
    747         mRequestRunning = true;
    748         onHttpRequestResults(null);
    749 
    750         Thread requestThread = new Thread() {
    751             public void run() {
    752                 final String path = "/ip.js?fmt=text";
    753                 final String randomHost =
    754                         "h" + Integer.toString(new Random().nextInt()) + ".ds.ipv6test.google.com";
    755                 final String fixedHost = "google-ipv6test.appspot.com";
    756 
    757                 Network network = mBoundTestNetwork.getNetwork();
    758                 HttpURLConnection conn = null;
    759                 InputStreamReader in = null;
    760 
    761                 try {
    762                     final URL httpsUrl = new URL("https", fixedHost, path);
    763                     BufferedReader reader;
    764 
    765                     switch (type) {
    766                         case DEFAULT:
    767                             conn = (HttpURLConnection) httpsUrl.openConnection(Proxy.NO_PROXY);
    768                             in = new InputStreamReader(conn.getInputStream());
    769                             reader = new BufferedReader(in);
    770                             onHttpRequestResults(reader.readLine());
    771                             break;
    772                         case SOCKET:
    773                             String response = doSocketRequest(network, randomHost, path);
    774                             onHttpRequestResults(response);
    775                             break;
    776                         case HTTPS:
    777                             conn = (HttpURLConnection) network.openConnection(httpsUrl,
    778                                     Proxy.NO_PROXY);
    779                             in = new InputStreamReader(conn.getInputStream());
    780                             reader = new BufferedReader(in);
    781                             onHttpRequestResults(reader.readLine());
    782                             break;
    783                         default:
    784                             throw new IllegalArgumentException("Cannot happen");
    785                     }
    786                 } catch(IOException e) {
    787                     onHttpRequestResults("Error! ");
    788                 } finally {
    789                     mRequestRunning = false;
    790                     if (in != null) IoUtils.closeQuietly(in);
    791                     if (conn != null) conn.disconnect();
    792                 }
    793             }
    794         };
    795         requestThread.start();
    796     }
    797 
    798     private void onWifiMulticastLock(boolean enable) {
    799         Log.d(TAG, (enable ? "Acquiring" : "Releasing") + " wifi multicast lock");
    800         if (enable) {
    801             mWml.acquire();
    802         } else {
    803             mWml.release();
    804         }
    805         findViewById(R.id.acquireWifiMulticastLock).setEnabled(!enable);
    806         findViewById(R.id.releaseWifiMulticastLock).setEnabled(enable);
    807     }
    808 }
    809