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