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