1 /* 2 * Copyright (C) 2019 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.car.developeroptions.wifi; 18 19 import android.app.Activity; 20 import android.content.BroadcastReceiver; 21 import android.content.Context; 22 import android.content.Intent; 23 import android.content.IntentFilter; 24 import android.net.NetworkInfo; 25 import android.net.wifi.ScanResult; 26 import android.net.wifi.SupplicantState; 27 import android.net.wifi.WifiConfiguration; 28 import android.net.wifi.WifiInfo; 29 import android.net.wifi.WifiManager; 30 import android.os.Bundle; 31 import android.os.Handler; 32 import android.text.TextUtils; 33 import android.util.Log; 34 import android.view.View; 35 import android.view.View.OnClickListener; 36 import android.widget.Button; 37 import android.widget.TextView; 38 39 import com.android.car.developeroptions.R; 40 import com.android.settingslib.wifi.AccessPoint; 41 42 import java.io.IOException; 43 import java.net.HttpURLConnection; 44 import java.net.URL; 45 import java.net.UnknownHostException; 46 import java.util.List; 47 48 49 /** 50 * Show the current status details of Wifi related fields 51 */ 52 public class WifiStatusTest extends Activity { 53 54 private static final String TAG = "WifiStatusTest"; 55 56 private Button updateButton; 57 private TextView mWifiState; 58 private TextView mNetworkState; 59 private TextView mSupplicantState; 60 private TextView mRSSI; 61 private TextView mBSSID; 62 private TextView mSSID; 63 private TextView mHiddenSSID; 64 private TextView mIPAddr; 65 private TextView mMACAddr; 66 private TextView mNetworkId; 67 private TextView mTxLinkSpeed; 68 private TextView mRxLinkSpeed; 69 private TextView mScanList; 70 71 72 private TextView mPingHostname; 73 private TextView mHttpClientTest; 74 private Button pingTestButton; 75 76 private String mPingHostnameResult; 77 private String mHttpClientTestResult; 78 79 80 private WifiManager mWifiManager; 81 private IntentFilter mWifiStateFilter; 82 83 84 //============================ 85 // Activity lifecycle 86 //============================ 87 88 private final BroadcastReceiver mWifiStateReceiver = new BroadcastReceiver() { 89 @Override 90 public void onReceive(Context context, Intent intent) { 91 if (intent.getAction().equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) { 92 handleWifiStateChanged(intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE, 93 WifiManager.WIFI_STATE_UNKNOWN)); 94 } else if (intent.getAction().equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) { 95 handleNetworkStateChanged( 96 (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO)); 97 } else if (intent.getAction().equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) { 98 handleScanResultsAvailable(); 99 } else if (intent.getAction().equals(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION)) { 100 /* TODO: handle supplicant connection change later */ 101 } else if (intent.getAction().equals(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION)) { 102 handleSupplicantStateChanged( 103 (SupplicantState) intent.getParcelableExtra(WifiManager.EXTRA_NEW_STATE), 104 intent.hasExtra(WifiManager.EXTRA_SUPPLICANT_ERROR), 105 intent.getIntExtra(WifiManager.EXTRA_SUPPLICANT_ERROR, 0)); 106 } else if (intent.getAction().equals(WifiManager.RSSI_CHANGED_ACTION)) { 107 handleSignalChanged(intent.getIntExtra(WifiManager.EXTRA_NEW_RSSI, 0)); 108 } else if (intent.getAction().equals(WifiManager.NETWORK_IDS_CHANGED_ACTION)) { 109 /* TODO: handle network id change info later */ 110 } else { 111 Log.e(TAG, "Received an unknown Wifi Intent"); 112 } 113 } 114 }; 115 116 @Override onCreate(Bundle savedInstanceState)117 protected void onCreate(Bundle savedInstanceState) { 118 super.onCreate(savedInstanceState); 119 120 mWifiManager = (WifiManager) getSystemService(WIFI_SERVICE); 121 122 mWifiStateFilter = new IntentFilter(WifiManager.WIFI_STATE_CHANGED_ACTION); 123 mWifiStateFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION); 124 mWifiStateFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION); 125 mWifiStateFilter.addAction(WifiManager.SUPPLICANT_STATE_CHANGED_ACTION); 126 mWifiStateFilter.addAction(WifiManager.RSSI_CHANGED_ACTION); 127 mWifiStateFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 128 129 registerReceiver(mWifiStateReceiver, mWifiStateFilter); 130 131 setContentView(R.layout.wifi_status_test); 132 133 updateButton = (Button) findViewById(R.id.update); 134 updateButton.setOnClickListener(updateButtonHandler); 135 136 mWifiState = (TextView) findViewById(R.id.wifi_state); 137 mNetworkState = (TextView) findViewById(R.id.network_state); 138 mSupplicantState = (TextView) findViewById(R.id.supplicant_state); 139 mRSSI = (TextView) findViewById(R.id.rssi); 140 mBSSID = (TextView) findViewById(R.id.bssid); 141 mSSID = (TextView) findViewById(R.id.ssid); 142 mHiddenSSID = (TextView) findViewById(R.id.hidden_ssid); 143 mIPAddr = (TextView) findViewById(R.id.ipaddr); 144 mMACAddr = (TextView) findViewById(R.id.macaddr); 145 mNetworkId = (TextView) findViewById(R.id.networkid); 146 mTxLinkSpeed = (TextView) findViewById(R.id.tx_link_speed); 147 mRxLinkSpeed = (TextView) findViewById(R.id.rx_link_speed); 148 mScanList = (TextView) findViewById(R.id.scan_list); 149 150 151 mPingHostname = (TextView) findViewById(R.id.pingHostname); 152 mHttpClientTest = (TextView) findViewById(R.id.httpClientTest); 153 154 pingTestButton = (Button) findViewById(R.id.ping_test); 155 pingTestButton.setOnClickListener(mPingButtonHandler); 156 } 157 158 @Override onResume()159 protected void onResume() { 160 super.onResume(); 161 registerReceiver(mWifiStateReceiver, mWifiStateFilter); 162 } 163 164 @Override onPause()165 protected void onPause() { 166 super.onPause(); 167 unregisterReceiver(mWifiStateReceiver); 168 } 169 170 OnClickListener mPingButtonHandler = new OnClickListener() { 171 public void onClick(View v) { 172 updatePingState(); 173 } 174 }; 175 176 OnClickListener updateButtonHandler = new OnClickListener() { 177 public void onClick(View v) { 178 final WifiInfo wifiInfo = mWifiManager.getConnectionInfo(); 179 180 setWifiStateText(mWifiManager.getWifiState()); 181 mBSSID.setText(wifiInfo.getBSSID()); 182 mHiddenSSID.setText(String.valueOf(wifiInfo.getHiddenSSID())); 183 int ipAddr = wifiInfo.getIpAddress(); 184 StringBuffer ipBuf = new StringBuffer(); 185 ipBuf.append(ipAddr & 0xff).append('.'). 186 append((ipAddr >>>= 8) & 0xff).append('.'). 187 append((ipAddr >>>= 8) & 0xff).append('.'). 188 append((ipAddr >>>= 8) & 0xff); 189 190 mIPAddr.setText(ipBuf); 191 mTxLinkSpeed.setText(String.valueOf(wifiInfo.getTxLinkSpeedMbps())+" Mbps"); 192 mRxLinkSpeed.setText(String.valueOf(wifiInfo.getRxLinkSpeedMbps())+" Mbps"); 193 mMACAddr.setText(wifiInfo.getMacAddress()); 194 mNetworkId.setText(String.valueOf(wifiInfo.getNetworkId())); 195 mRSSI.setText(String.valueOf(wifiInfo.getRssi())); 196 mSSID.setText(wifiInfo.getSSID()); 197 198 SupplicantState supplicantState = wifiInfo.getSupplicantState(); 199 setSupplicantStateText(supplicantState); 200 } 201 }; 202 setSupplicantStateText(SupplicantState supplicantState)203 private void setSupplicantStateText(SupplicantState supplicantState) { 204 if(SupplicantState.FOUR_WAY_HANDSHAKE.equals(supplicantState)) { 205 mSupplicantState.setText("FOUR WAY HANDSHAKE"); 206 } else if(SupplicantState.ASSOCIATED.equals(supplicantState)) { 207 mSupplicantState.setText("ASSOCIATED"); 208 } else if(SupplicantState.ASSOCIATING.equals(supplicantState)) { 209 mSupplicantState.setText("ASSOCIATING"); 210 } else if(SupplicantState.COMPLETED.equals(supplicantState)) { 211 mSupplicantState.setText("COMPLETED"); 212 } else if(SupplicantState.DISCONNECTED.equals(supplicantState)) { 213 mSupplicantState.setText("DISCONNECTED"); 214 } else if(SupplicantState.DORMANT.equals(supplicantState)) { 215 mSupplicantState.setText("DORMANT"); 216 } else if(SupplicantState.GROUP_HANDSHAKE.equals(supplicantState)) { 217 mSupplicantState.setText("GROUP HANDSHAKE"); 218 } else if(SupplicantState.INACTIVE.equals(supplicantState)) { 219 mSupplicantState.setText("INACTIVE"); 220 } else if(SupplicantState.INVALID.equals(supplicantState)) { 221 mSupplicantState.setText("INVALID"); 222 } else if(SupplicantState.SCANNING.equals(supplicantState)) { 223 mSupplicantState.setText("SCANNING"); 224 } else if(SupplicantState.UNINITIALIZED.equals(supplicantState)) { 225 mSupplicantState.setText("UNINITIALIZED"); 226 } else { 227 mSupplicantState.setText("BAD"); 228 Log.e(TAG, "supplicant state is bad"); 229 } 230 } 231 setWifiStateText(int wifiState)232 private void setWifiStateText(int wifiState) { 233 String wifiStateString; 234 switch(wifiState) { 235 case WifiManager.WIFI_STATE_DISABLING: 236 wifiStateString = getString(R.string.wifi_state_disabling); 237 break; 238 case WifiManager.WIFI_STATE_DISABLED: 239 wifiStateString = getString(R.string.wifi_state_disabled); 240 break; 241 case WifiManager.WIFI_STATE_ENABLING: 242 wifiStateString = getString(R.string.wifi_state_enabling); 243 break; 244 case WifiManager.WIFI_STATE_ENABLED: 245 wifiStateString = getString(R.string.wifi_state_enabled); 246 break; 247 case WifiManager.WIFI_STATE_UNKNOWN: 248 wifiStateString = getString(R.string.wifi_state_unknown); 249 break; 250 default: 251 wifiStateString = "BAD"; 252 Log.e(TAG, "wifi state is bad"); 253 break; 254 } 255 256 mWifiState.setText(wifiStateString); 257 } 258 handleSignalChanged(int rssi)259 private void handleSignalChanged(int rssi) { 260 mRSSI.setText(String.valueOf(rssi)); 261 } 262 handleWifiStateChanged(int wifiState)263 private void handleWifiStateChanged(int wifiState) { 264 setWifiStateText(wifiState); 265 } 266 handleScanResultsAvailable()267 private void handleScanResultsAvailable() { 268 List<ScanResult> list = mWifiManager.getScanResults(); 269 270 StringBuffer scanList = new StringBuffer(); 271 if (list != null) { 272 for (int i = list.size() - 1; i >= 0; i--) { 273 final ScanResult scanResult = list.get(i); 274 275 if (scanResult == null) { 276 continue; 277 } 278 279 if (TextUtils.isEmpty(scanResult.SSID)) { 280 continue; 281 } 282 283 scanList.append(scanResult.SSID+" "); 284 } 285 } 286 mScanList.setText(scanList); 287 } 288 handleSupplicantStateChanged(SupplicantState state, boolean hasError, int error)289 private void handleSupplicantStateChanged(SupplicantState state, boolean hasError, int error) { 290 if (hasError) { 291 mSupplicantState.setText("ERROR AUTHENTICATING"); 292 } else { 293 setSupplicantStateText(state); 294 } 295 } 296 handleNetworkStateChanged(NetworkInfo networkInfo)297 private void handleNetworkStateChanged(NetworkInfo networkInfo) { 298 if (mWifiManager.isWifiEnabled()) { 299 WifiInfo info = mWifiManager.getConnectionInfo(); 300 String summary = AccessPoint.getSummary(this, info.getSSID(), 301 networkInfo.getDetailedState(), 302 info.getNetworkId() == WifiConfiguration.INVALID_NETWORK_ID, 303 /* suggestionOrSpecifierPackageName */ null); 304 mNetworkState.setText(summary); 305 } 306 } 307 updatePingState()308 private final void updatePingState() { 309 final Handler handler = new Handler(); 310 // Set all to unknown since the threads will take a few secs to update. 311 mPingHostnameResult = getResources().getString(R.string.radioInfo_unknown); 312 mHttpClientTestResult = getResources().getString(R.string.radioInfo_unknown); 313 314 mPingHostname.setText(mPingHostnameResult); 315 mHttpClientTest.setText(mHttpClientTestResult); 316 317 final Runnable updatePingResults = new Runnable() { 318 public void run() { 319 mPingHostname.setText(mPingHostnameResult); 320 mHttpClientTest.setText(mHttpClientTestResult); 321 } 322 }; 323 324 Thread hostnameThread = new Thread() { 325 @Override 326 public void run() { 327 pingHostname(); 328 handler.post(updatePingResults); 329 } 330 }; 331 hostnameThread.start(); 332 333 Thread httpClientThread = new Thread() { 334 @Override 335 public void run() { 336 httpClientTest(); 337 handler.post(updatePingResults); 338 } 339 }; 340 httpClientThread.start(); 341 } 342 pingHostname()343 private final void pingHostname() { 344 try { 345 // TODO: Hardcoded for now, make it UI configurable 346 Process p = Runtime.getRuntime().exec("ping -c 1 -w 100 www.google.com"); 347 int status = p.waitFor(); 348 if (status == 0) { 349 mPingHostnameResult = "Pass"; 350 } else { 351 mPingHostnameResult = "Fail: Host unreachable"; 352 } 353 } catch (UnknownHostException e) { 354 mPingHostnameResult = "Fail: Unknown Host"; 355 } catch (IOException e) { 356 mPingHostnameResult= "Fail: IOException"; 357 } catch (InterruptedException e) { 358 mPingHostnameResult = "Fail: InterruptedException"; 359 } 360 } 361 httpClientTest()362 private void httpClientTest() { 363 HttpURLConnection urlConnection = null; 364 try { 365 // TODO: Hardcoded for now, make it UI configurable 366 URL url = new URL("https://www.google.com"); 367 urlConnection = (HttpURLConnection) url.openConnection(); 368 if (urlConnection.getResponseCode() == 200) { 369 mHttpClientTestResult = "Pass"; 370 } else { 371 mHttpClientTestResult = "Fail: Code: " + urlConnection.getResponseMessage(); 372 } 373 } catch (IOException e) { 374 mHttpClientTestResult = "Fail: IOException"; 375 } finally { 376 if (urlConnection != null) { 377 urlConnection.disconnect(); 378 } 379 } 380 } 381 382 } 383