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