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