1/*
2 * Copyright (C) 2010, 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.connectivitymanagertest;
18
19import com.android.connectivitymanagertest.R;
20import android.app.Activity;
21import android.content.Context;
22import android.content.res.Resources;
23import android.content.BroadcastReceiver;
24import android.content.Intent;
25import android.content.IntentFilter;
26import android.os.Bundle;
27import android.os.IPowerManager;
28import android.os.PowerManager;
29import android.os.ServiceManager;
30import android.os.SystemClock;
31import android.provider.Settings;
32import android.util.Log;
33import android.view.KeyEvent;
34
35import java.io.IOException;
36import java.io.InputStream;
37import java.net.UnknownHostException;
38import java.util.ArrayList;
39import java.util.HashMap;
40import java.util.List;
41import android.widget.LinearLayout;
42import android.net.ConnectivityManager;
43import android.net.DhcpInfo;
44import android.net.NetworkInfo;
45import android.net.NetworkInfo.State;
46
47import android.net.wifi.SupplicantState;
48import android.net.wifi.WifiConfiguration;
49import android.net.wifi.WifiManager;
50import android.net.wifi.WifiInfo;
51import android.net.wifi.ScanResult;
52import android.net.wifi.WifiConfiguration.KeyMgmt;
53
54/**
55 * An activity registered with connectivity manager broadcast
56 * provides network connectivity information and
57 * can be used to set device states: Cellular, Wifi, Airplane mode.
58 */
59public class ConnectivityManagerTestActivity extends Activity {
60
61    public static final String LOG_TAG = "ConnectivityManagerTestActivity";
62    public static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; //10 seconds
63    public static final int WIFI_SCAN_TIMEOUT = 50 * 1000;
64    public static final int SHORT_TIMEOUT = 5 * 1000;
65    public static final long LONG_TIMEOUT = 50 * 1000;
66    public static final int SUCCESS = 0;  // for Wifi tethering state change
67    public static final int FAILURE = 1;
68    public static final int INIT = -1;
69    private static final String ACCESS_POINT_FILE = "accesspoints.xml";
70    public ConnectivityReceiver mConnectivityReceiver = null;
71    public WifiReceiver mWifiReceiver = null;
72    private AccessPointParserHelper mParseHelper = null;
73    public boolean scanResultAvailable = false;
74    /*
75     * Track network connectivity information
76     */
77    public State mState;
78    public NetworkInfo mNetworkInfo;
79    public NetworkInfo mOtherNetworkInfo;
80    public boolean mIsFailOver;
81    public String mReason;
82    public boolean mScanResultIsAvailable = false;
83    public ConnectivityManager mCM;
84    public Object wifiObject = new Object();
85    public Object connectivityObject = new Object();
86    public int mWifiState;
87    public NetworkInfo mWifiNetworkInfo;
88    public String mBssid;
89    public String mPowerSsid = "opennet"; //Default power SSID
90    private Context mContext;
91
92    /*
93     * Control Wifi States
94     */
95    public WifiManager mWifiManager;
96
97    /*
98     * Verify connectivity state
99     */
100    public static final int NUM_NETWORK_TYPES = ConnectivityManager.MAX_NETWORK_TYPE + 1;
101    NetworkState[] connectivityState = new NetworkState[NUM_NETWORK_TYPES];
102
103    // For wifi tethering tests
104    private String[] mWifiRegexs;
105    public int mWifiTetherResult = INIT;    // -1 is initialization state
106
107    /**
108     * A wrapper of a broadcast receiver which provides network connectivity information
109     * for all kinds of network: wifi, mobile, etc.
110     */
111    private class ConnectivityReceiver extends BroadcastReceiver {
112        @Override
113        public void onReceive(Context context, Intent intent) {
114            log("ConnectivityReceiver: onReceive() is called with " + intent);
115            String action = intent.getAction();
116            if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
117                Log.v("ConnectivityReceiver", "onReceive() called with " + intent);
118                return;
119            }
120
121            boolean noConnectivity =
122                intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
123
124            if (noConnectivity) {
125                mState = State.DISCONNECTED;
126            } else {
127                mState = State.CONNECTED;
128            }
129
130            mNetworkInfo = (NetworkInfo)
131                intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
132
133            mOtherNetworkInfo = (NetworkInfo)
134                intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
135
136            mReason = intent.getStringExtra(ConnectivityManager.EXTRA_REASON);
137            mIsFailOver = intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false);
138
139            log("mNetworkInfo: " + mNetworkInfo.toString());
140            if (mOtherNetworkInfo != null) {
141                log("mOtherNetworkInfo: " + mOtherNetworkInfo.toString());
142            }
143            recordNetworkState(mNetworkInfo.getType(), mNetworkInfo.getState());
144            if (mOtherNetworkInfo != null) {
145                recordNetworkState(mOtherNetworkInfo.getType(), mOtherNetworkInfo.getState());
146            }
147            notifyNetworkConnectivityChange();
148        }
149    }
150
151    private class WifiReceiver extends BroadcastReceiver {
152        @Override
153        public void onReceive(Context context, Intent intent) {
154            String action = intent.getAction();
155            Log.v("WifiReceiver", "onReceive() is calleld with " + intent);
156            if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
157                notifyScanResult();
158            } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
159                mWifiNetworkInfo =
160                    (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
161                log("mWifiNetworkInfo: " + mWifiNetworkInfo.toString());
162                if (mWifiNetworkInfo.getState() == State.CONNECTED) {
163                    mBssid = intent.getStringExtra(WifiManager.EXTRA_BSSID);
164                }
165                notifyWifiState();
166            } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
167                mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
168                                                WifiManager.WIFI_STATE_UNKNOWN);
169                log("mWifiState: " + mWifiState);
170                notifyWifiState();
171            } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
172                notifyWifiAPState();
173            } else if (action.equals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED)) {
174                ArrayList<String> available = intent.getStringArrayListExtra(
175                        ConnectivityManager.EXTRA_AVAILABLE_TETHER);
176                ArrayList<String> active = intent.getStringArrayListExtra(
177                        ConnectivityManager.EXTRA_ACTIVE_TETHER);
178                ArrayList<String> errored = intent.getStringArrayListExtra(
179                        ConnectivityManager.EXTRA_ERRORED_TETHER);
180                updateTetherState(available.toArray(), active.toArray(), errored.toArray());
181            }
182            else {
183                return;
184            }
185        }
186    }
187
188    public ConnectivityManagerTestActivity() {
189        mState = State.UNKNOWN;
190        scanResultAvailable = false;
191    }
192
193    @Override
194    protected void onCreate(Bundle savedInstanceState) {
195        super.onCreate(savedInstanceState);
196        log("onCreate, inst=" + Integer.toHexString(hashCode()));
197
198        // Create a simple layout
199        LinearLayout contentView = new LinearLayout(this);
200        contentView.setOrientation(LinearLayout.VERTICAL);
201        setContentView(contentView);
202        setTitle("ConnectivityManagerTestActivity");
203
204
205        // register a connectivity receiver for CONNECTIVITY_ACTION;
206        mConnectivityReceiver = new ConnectivityReceiver();
207        registerReceiver(mConnectivityReceiver,
208                new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
209
210        mWifiReceiver = new WifiReceiver();
211        IntentFilter mIntentFilter = new IntentFilter();
212        mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
213        mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
214        mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
215        mIntentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
216        mIntentFilter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
217        mIntentFilter.addAction(ConnectivityManager.ACTION_TETHER_STATE_CHANGED);
218        registerReceiver(mWifiReceiver, mIntentFilter);
219
220        // Get an instance of ConnectivityManager
221        mCM = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
222        // Get an instance of WifiManager
223        mWifiManager =(WifiManager)getSystemService(Context.WIFI_SERVICE);
224        initializeNetworkStates();
225
226        if (mWifiManager.isWifiEnabled()) {
227            log("Clear Wifi before we start the test.");
228            removeConfiguredNetworksAndDisableWifi();
229        }
230        mWifiRegexs = mCM.getTetherableWifiRegexs();
231     }
232
233    public List<WifiConfiguration> loadNetworkConfigurations() throws Exception {
234        InputStream in = getAssets().open(ACCESS_POINT_FILE);
235        mParseHelper = new AccessPointParserHelper(in);
236        return mParseHelper.getNetworkConfigurations();
237    }
238
239    public HashMap<String, DhcpInfo> getDhcpInfo() throws Exception{
240        if (mParseHelper == null) {
241            InputStream in = getAssets().open(ACCESS_POINT_FILE);
242            mParseHelper = new AccessPointParserHelper(in);
243        }
244        return mParseHelper.getSsidToDhcpInfoHashMap();
245    }
246
247
248    private void printNetConfig(String[] configuration) {
249        for (int i = 0; i < configuration.length; i++) {
250            if (i == 0) {
251                log("SSID: " + configuration[0]);
252            } else {
253                log("      " + configuration[i]);
254            }
255        }
256    }
257
258    // for each network type, initialize network states to UNKNOWN, and no verification flag is set
259    public void initializeNetworkStates() {
260        for (int networkType = NUM_NETWORK_TYPES - 1; networkType >=0; networkType--) {
261            connectivityState[networkType] =  new NetworkState();
262            log("Initialize network state for " + networkType + ": " +
263                    connectivityState[networkType].toString());
264        }
265    }
266
267    // deposit a network state
268    public void recordNetworkState(int networkType, State networkState) {
269        log("record network state for network " +  networkType +
270                ", state is " + networkState);
271        connectivityState[networkType].recordState(networkState);
272    }
273
274    // set the state transition criteria
275    public void setStateTransitionCriteria(int networkType, State initState,
276            int transitionDir, State targetState) {
277        connectivityState[networkType].setStateTransitionCriteria(
278                initState, transitionDir, targetState);
279    }
280
281    // Validate the states recorded
282    public boolean validateNetworkStates(int networkType) {
283        log("validate network state for " + networkType + ": ");
284        return connectivityState[networkType].validateStateTransition();
285    }
286
287    // return result from network state validation
288    public String getTransitionFailureReason(int networkType) {
289        log("get network state transition failure reason for " + networkType + ": " +
290                connectivityState[networkType].toString());
291        return connectivityState[networkType].getReason();
292    }
293
294    private void notifyNetworkConnectivityChange() {
295        synchronized(connectivityObject) {
296            log("notify network connectivity changed");
297            connectivityObject.notifyAll();
298        }
299    }
300    private void notifyScanResult() {
301        synchronized (this) {
302            log("notify that scan results are available");
303            scanResultAvailable = true;
304            this.notify();
305        }
306    }
307
308    private void notifyWifiState() {
309        synchronized (wifiObject) {
310            log("notify wifi state changed");
311            wifiObject.notify();
312        }
313    }
314
315    private void notifyWifiAPState() {
316        synchronized (this) {
317            log("notify wifi AP state changed");
318            this.notify();
319        }
320    }
321
322    // Update wifi tethering state
323    private void updateTetherState(Object[] available, Object[] tethered, Object[] errored) {
324        boolean wifiTethered = false;
325        boolean wifiErrored = false;
326
327        synchronized (this) {
328            for (Object obj: tethered) {
329                String str = (String)obj;
330                for (String tethRex: mWifiRegexs) {
331                    log("str: " + str +"tethRex: " + tethRex);
332                    if (str.matches(tethRex)) {
333                        wifiTethered = true;
334                    }
335                }
336            }
337
338            for (Object obj: errored) {
339                String str = (String)obj;
340                for (String tethRex: mWifiRegexs) {
341                    log("error: str: " + str +"tethRex: " + tethRex);
342                    if (str.matches(tethRex)) {
343                        wifiErrored = true;
344                    }
345                }
346            }
347
348            if (wifiTethered) {
349                mWifiTetherResult = SUCCESS;   // wifi tethering is successful
350            } else if (wifiErrored) {
351                mWifiTetherResult = FAILURE;   // wifi tethering failed
352            }
353            log("mWifiTetherResult: " + mWifiTetherResult);
354            this.notify();
355        }
356    }
357
358
359    // Wait for network connectivity state: CONNECTING, CONNECTED, SUSPENDED,
360    //                                      DISCONNECTING, DISCONNECTED, UNKNOWN
361    public boolean waitForNetworkState(int networkType, State expectedState, long timeout) {
362        long startTime = System.currentTimeMillis();
363        while (true) {
364            if ((System.currentTimeMillis() - startTime) > timeout) {
365                if (mCM.getNetworkInfo(networkType).getState() != expectedState) {
366                    return false;
367                } else {
368                    // the broadcast has been sent out. the state has been changed.
369                    log("networktype: " + networkType + " state: " +
370                            mCM.getNetworkInfo(networkType));
371                    return true;
372                }
373            }
374            log("Wait for the connectivity state for network: " + networkType +
375                    " to be " + expectedState.toString());
376            synchronized (connectivityObject) {
377                try {
378                    connectivityObject.wait(SHORT_TIMEOUT);
379                } catch (InterruptedException e) {
380                    e.printStackTrace();
381                }
382                if ((mNetworkInfo.getType() != networkType) ||
383                    (mNetworkInfo.getState() != expectedState)) {
384                    log("network state for " + mNetworkInfo.getType() +
385                            "is: " + mNetworkInfo.getState());
386                    continue;
387                }
388                return true;
389            }
390        }
391    }
392
393    // Wait for Wifi state: WIFI_STATE_DISABLED, WIFI_STATE_DISABLING, WIFI_STATE_ENABLED,
394    //                      WIFI_STATE_ENALBING, WIFI_STATE_UNKNOWN
395    public boolean waitForWifiState(int expectedState, long timeout) {
396        long startTime = System.currentTimeMillis();
397        while (true) {
398            if ((System.currentTimeMillis() - startTime) > timeout) {
399                if (mWifiState != expectedState) {
400                    return false;
401                } else {
402                    return true;
403                }
404            }
405            log("Wait for wifi state to be: " + expectedState);
406            synchronized (wifiObject) {
407                try {
408                    wifiObject.wait(SHORT_TIMEOUT);
409                } catch (InterruptedException e) {
410                    e.printStackTrace();
411                }
412                if (mWifiState != expectedState) {
413                    log("Wifi state is: " + mWifiState);
414                    continue;
415                }
416                return true;
417            }
418        }
419    }
420
421    // Wait for Wifi AP state: WIFI_AP_STATE_DISABLED, WIFI_AP_STATE_DISABLING,
422    //                         WIFI_AP_STATE_ENABLED, WIFI_STATE_ENALBING, WIFI_STATE_UNKNOWN
423    public boolean waitForWifiAPState(int expectedState, long timeout) {
424        long startTime = System.currentTimeMillis();
425        while (true) {
426            if ((System.currentTimeMillis() - startTime) > timeout) {
427                if (mWifiManager.getWifiApState() != expectedState) {
428                    return false;
429                } else {
430                    return true;
431                }
432            }
433            log("Wait for wifi AP state to be: " + expectedState);
434            synchronized (wifiObject) {
435                try {
436                    wifiObject.wait(SHORT_TIMEOUT);
437                } catch (InterruptedException e) {
438                    e.printStackTrace();
439                }
440                if (mWifiManager.getWifiApState() != expectedState) {
441                    log("Wifi state is: " + mWifiManager.getWifiApState());
442                    continue;
443                }
444                return true;
445            }
446        }
447    }
448
449    /**
450     * Wait for the wifi tethering result:
451     * @param timeout is the maximum waiting time
452     * @return SUCCESS if tethering result is successful
453     *         FAILURE if tethering result returns error.
454     */
455    public int waitForTetherStateChange(long timeout) {
456        long startTime = System.currentTimeMillis();
457        while (true) {
458            if ((System.currentTimeMillis() - startTime) > timeout) {
459                return mWifiTetherResult;
460            }
461            log("Wait for wifi tethering result.");
462            synchronized (this) {
463                try {
464                    this.wait(SHORT_TIMEOUT);
465                } catch (InterruptedException e) {
466                    e.printStackTrace();
467                }
468                if (mWifiTetherResult == INIT ) {
469                    continue;
470                } else {
471                    return mWifiTetherResult;
472                }
473            }
474        }
475    }
476
477    // Return true if device is currently connected to mobile network
478    public boolean isConnectedToMobile() {
479        return (mNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE);
480    }
481
482    // Return true if device is currently connected to Wifi
483    public boolean isConnectedToWifi() {
484        return (mNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI);
485    }
486
487    public boolean enableWifi() {
488        return mWifiManager.setWifiEnabled(true);
489    }
490
491    // Turn screen off
492    public void turnScreenOff() {
493        log("Turn screen off");
494        PowerManager pm =
495            (PowerManager) getSystemService(Context.POWER_SERVICE);
496        pm.goToSleep(SystemClock.uptimeMillis() + 100);
497    }
498
499    // Turn screen on
500    public void turnScreenOn() {
501        log("Turn screen on");
502        IPowerManager mPowerManagerService = IPowerManager.Stub.asInterface(
503                ServiceManager.getService("power"));;
504        try {
505            mPowerManagerService.userActivityWithForce(SystemClock.uptimeMillis(), false, true);
506        } catch (Exception e) {
507            log(e.toString());
508        }
509    }
510
511    /**
512     * @param pingServerList a list of servers that can be used for ping test, can be null
513     * @return true if the ping test is successful, false otherwise.
514     */
515    public boolean pingTest(String[] pingServerList) {
516        boolean result = false;
517        String[] hostList = {"www.google.com", "www.yahoo.com",
518                "www.bing.com", "www.facebook.com", "www.ask.com"};
519        if (pingServerList != null) {
520            hostList = pingServerList;
521        }
522        try {
523            // assume the chance that all servers are down is very small
524            for (int i = 0; i < hostList.length; i++ ) {
525                String host = hostList[i];
526                log("Start ping test, ping " + host);
527                Process p = Runtime.getRuntime().exec("ping -c 10 -w 100 " + host);
528                int status = p.waitFor();
529                if (status == 0) {
530                    // if any of the ping test is successful, return true
531                    result = true;
532                    break;
533                } else {
534                    result = false;
535                    log("ping " + host + " failed.");
536                }
537            }
538        } catch (UnknownHostException e) {
539            log("Ping test Fail: Unknown Host");
540        } catch (IOException e) {
541            log("Ping test Fail:  IOException");
542        } catch (InterruptedException e) {
543            log("Ping test Fail: InterruptedException");
544        }
545        log("return");
546        return result;
547    }
548
549    /**
550     * Associate the device to given SSID
551     * If the device is already associated with a WiFi, disconnect and forget it,
552     * We don't verify whether the connection is successful or not, leave this to the test
553     */
554    public boolean connectToWifi(String knownSSID) {
555        WifiConfiguration config = new WifiConfiguration();
556        config.SSID = knownSSID;
557        config.allowedKeyManagement.set(KeyMgmt.NONE);
558        return connectToWifiWithConfiguration(config);
559    }
560
561    /**
562     * Connect to Wi-Fi with the given configuration. Note the SSID in the configuration
563     * is pure string, we need to convert it to quoted string.
564     * @param config
565     * @return
566     */
567    public boolean connectToWifiWithConfiguration(WifiConfiguration config) {
568        String ssid = config.SSID;
569        config.SSID = convertToQuotedString(ssid);
570
571        //If Wifi is not enabled, enable it
572        if (!mWifiManager.isWifiEnabled()) {
573            log("Wifi is not enabled, enable it");
574            mWifiManager.setWifiEnabled(true);
575        }
576
577        List<ScanResult> netList = mWifiManager.getScanResults();
578        if (netList == null) {
579            log("scan results are null");
580            // if no scan results are available, start active scan
581            mWifiManager.startScanActive();
582            mScanResultIsAvailable = false;
583            long startTime = System.currentTimeMillis();
584            while (!mScanResultIsAvailable) {
585                if ((System.currentTimeMillis() - startTime) > WIFI_SCAN_TIMEOUT) {
586                    return false;
587                }
588                // wait for the scan results to be available
589                synchronized (this) {
590                    // wait for the scan result to be available
591                    try {
592                        this.wait(WAIT_FOR_SCAN_RESULT);
593                    } catch (InterruptedException e) {
594                        e.printStackTrace();
595                    }
596                    if ((mWifiManager.getScanResults() == null) ||
597                            (mWifiManager.getScanResults().size() <= 0)) {
598                        continue;
599                    }
600                    mScanResultIsAvailable = true;
601                }
602            }
603        }
604
605        netList = mWifiManager.getScanResults();
606
607        for (int i = 0; i < netList.size(); i++) {
608            ScanResult sr= netList.get(i);
609            if (sr.SSID.equals(ssid)) {
610                log("found " + ssid + " in the scan result list");
611                int networkId = mWifiManager.addNetwork(config);
612                // Connect to network by disabling others.
613                mWifiManager.enableNetwork(networkId, true);
614                mWifiManager.saveConfiguration();
615                mWifiManager.reconnect();
616                break;
617           }
618        }
619
620        List<WifiConfiguration> netConfList = mWifiManager.getConfiguredNetworks();
621        if (netConfList.size() <= 0) {
622            log(ssid + " is not available");
623            return false;
624        }
625        return true;
626    }
627
628    /*
629     * Disconnect from the current AP and remove configured networks.
630     */
631    public boolean disconnectAP() {
632        if (mWifiManager.isWifiEnabled()) {
633            //remove the current network Id
634            WifiInfo curWifi = mWifiManager.getConnectionInfo();
635            if (curWifi == null) {
636                return false;
637            }
638            int curNetworkId = curWifi.getNetworkId();
639            mWifiManager.removeNetwork(curNetworkId);
640            mWifiManager.saveConfiguration();
641
642            // remove other saved networks
643            List<WifiConfiguration> netConfList = mWifiManager.getConfiguredNetworks();
644            if (netConfList != null) {
645                log("remove configured network ids");
646                for (int i = 0; i < netConfList.size(); i++) {
647                    WifiConfiguration conf = new WifiConfiguration();
648                    conf = netConfList.get(i);
649                    mWifiManager.removeNetwork(conf.networkId);
650                }
651            }
652        }
653        mWifiManager.saveConfiguration();
654        return true;
655    }
656    /**
657     * Disable Wifi
658     * @return true if Wifi is disabled successfully
659     */
660    public boolean disableWifi() {
661        return mWifiManager.setWifiEnabled(false);
662    }
663
664    /**
665     * Remove configured networks and disable wifi
666     */
667    public boolean removeConfiguredNetworksAndDisableWifi() {
668            if (!disconnectAP()) {
669                return false;
670            }
671            // Disable Wifi
672            if (!mWifiManager.setWifiEnabled(false)) {
673                return false;
674            }
675            // Wait for the actions to be completed
676            try {
677                Thread.sleep(5*1000);
678            } catch (InterruptedException e) {}
679        return true;
680    }
681
682    /**
683     * Set airplane mode
684     */
685    public void setAirplaneMode(Context context, boolean enableAM) {
686        //set the airplane mode
687        Settings.System.putInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,
688                enableAM ? 1 : 0);
689        // Post the intent
690        Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
691        intent.putExtra("state", enableAM);
692        context.sendBroadcast(intent);
693    }
694
695    protected static String convertToQuotedString(String string) {
696        return "\"" + string + "\"";
697    }
698
699    @Override
700    protected void onDestroy() {
701        super.onDestroy();
702
703        //Unregister receiver
704        if (mConnectivityReceiver != null) {
705            unregisterReceiver(mConnectivityReceiver);
706        }
707        if (mWifiReceiver != null) {
708            unregisterReceiver(mWifiReceiver);
709        }
710        log("onDestroy, inst=" + Integer.toHexString(hashCode()));
711    }
712
713    @Override
714    public void onStart() {
715        super.onStart();
716        mContext = this;
717        Bundle bundle = this.getIntent().getExtras();
718        if (bundle != null){
719            mPowerSsid = bundle.getString("power_ssid");
720        }
721    }
722    //A thread to set the device into airplane mode then turn on wifi.
723    Thread setDeviceWifiAndAirplaneThread = new Thread(new Runnable() {
724        public void run() {
725            setAirplaneMode(mContext, true);
726            connectToWifi(mPowerSsid);
727        }
728    });
729
730    //A thread to set the device into wifi
731    Thread setDeviceInWifiOnlyThread = new Thread(new Runnable() {
732        public void run() {
733            connectToWifi(mPowerSsid);
734        }
735    });
736
737    @Override
738    public boolean onKeyDown(int keyCode, KeyEvent event) {
739        switch (keyCode) {
740            //This is a tricky way for the scripted monkey to
741            //set the device in wifi and wifi in airplane mode.
742            case KeyEvent.KEYCODE_1:
743                setDeviceWifiAndAirplaneThread.start();
744                break;
745
746            case KeyEvent.KEYCODE_2:
747                setDeviceInWifiOnlyThread.start();
748                break;
749        }
750        return super.onKeyDown(keyCode, event);
751    }
752
753    private void log(String message) {
754        Log.v(LOG_TAG, message);
755    }
756}
757