133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang/*
233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang * Copyright (C) 2011, The Android Open Source Project
333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang *
433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang * Licensed under the Apache License, Version 2.0 (the "License");
533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang * you may not use this file except in compliance with the License.
633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang * You may obtain a copy of the License at
733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang *
833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang *      http://www.apache.org/licenses/LICENSE-2.0
933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang *
1033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang * Unless required by applicable law or agreed to in writing, software
1133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang * distributed under the License is distributed on an "AS IS" BASIS,
1233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang * See the License for the specific language governing permissions and
1433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang * limitations under the License.
1533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang */
1633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
1733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangpackage com.android.bandwidthtest.util;
1833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
1933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.app.DownloadManager;
2033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.app.DownloadManager.Query;
2133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.app.DownloadManager.Request;
2233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.content.BroadcastReceiver;
2333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.content.Context;
2433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.content.Intent;
2533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.content.IntentFilter;
2633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.content.pm.ApplicationInfo;
2733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.content.pm.PackageManager;
2833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.content.pm.PackageManager.NameNotFoundException;
2933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.database.Cursor;
3033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.net.ConnectivityManager;
3133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.net.NetworkInfo;
3233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.net.NetworkInfo.State;
3333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.net.Uri;
3433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.net.wifi.ScanResult;
3533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.net.wifi.WifiConfiguration;
3633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.net.wifi.WifiConfiguration.KeyMgmt;
3733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.net.wifi.WifiManager;
3833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.os.Handler;
3933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.os.Message;
4033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.provider.Settings;
4133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport android.util.Log;
4233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
4333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport com.android.bandwidthtest.NetworkState;
4433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport com.android.bandwidthtest.NetworkState.StateTransitionDirection;
4533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport com.android.internal.util.AsyncChannel;
4633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
474fe25f693ad311556fb232c352ed0b84d59343a5Tsu Chiang Chuangimport junit.framework.Assert;
484fe25f693ad311556fb232c352ed0b84d59343a5Tsu Chiang Chuang
49212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuangimport java.io.IOException;
50212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuangimport java.net.UnknownHostException;
5133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangimport java.util.List;
5233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
5333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang/*
5433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang * Utility class used to set the connectivity of the device and to download files.
5533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang */
5633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuangpublic class ConnectionUtil {
5733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private static final String LOG_TAG = "ConnectionUtil";
5833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private static final String DOWNLOAD_MANAGER_PKG_NAME = "com.android.providers.downloads";
5933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private static final int WAIT_FOR_SCAN_RESULT = 10 * 1000; // 10 seconds
6033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private static final int WIFI_SCAN_TIMEOUT = 50 * 1000;
6133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public static final int SHORT_TIMEOUT = 5 * 1000;
624b1afab106f3959ba56fba08fbdccee5d15068bcTsu Chiang Chuang    public static final int LONG_TIMEOUT = 5 * 60 * 1000; // 5 minutes
6333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private ConnectivityReceiver mConnectivityReceiver = null;
6433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private WifiReceiver mWifiReceiver = null;
6533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private DownloadReceiver mDownloadReceiver = null;
6633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private DownloadManager mDownloadManager;
6733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private NetworkInfo mNetworkInfo;
6833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private NetworkInfo mOtherNetworkInfo;
6933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private boolean mScanResultIsAvailable = false;
7033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private ConnectivityManager mCM;
7133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private Object mWifiMonitor = new Object();
7233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private Object mConnectivityMonitor = new Object();
7333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private Object mDownloadMonitor = new Object();
7433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private int mWifiState;
7533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private NetworkInfo mWifiNetworkInfo;
7633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private WifiManager mWifiManager;
7733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private Context mContext;
7833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    // Verify connectivity state
7933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private static final int NUM_NETWORK_TYPES = ConnectivityManager.MAX_NETWORK_TYPE + 1;
8033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private NetworkState[] mConnectivityState = new NetworkState[NUM_NETWORK_TYPES];
8133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
8233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public ConnectionUtil(Context context) {
8333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mContext = context;
8433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
8533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
8633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
8733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Initialize the class. Needs to be called before any other methods in {@link ConnectionUtil}
8833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     *
8933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @throws Exception
9033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
9133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public void initialize() throws Exception {
9233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // Register a connectivity receiver for CONNECTIVITY_ACTION
9333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mConnectivityReceiver = new ConnectivityReceiver();
9433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mContext.registerReceiver(mConnectivityReceiver,
9533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
9633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
9733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // Register a download receiver for ACTION_DOWNLOAD_COMPLETE
9833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mDownloadReceiver = new DownloadReceiver();
9933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mContext.registerReceiver(mDownloadReceiver,
10033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
10133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
10233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // Register a wifi receiver
10333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mWifiReceiver = new WifiReceiver();
10433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        IntentFilter mIntentFilter = new IntentFilter();
10533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
10633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
10733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
10833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mIntentFilter.addAction(WifiManager.SUPPLICANT_CONNECTION_CHANGE_ACTION);
10933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mIntentFilter.addAction(WifiManager.WIFI_AP_STATE_CHANGED_ACTION);
11033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mContext.registerReceiver(mWifiReceiver, mIntentFilter);
11133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
11233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // Get an instance of ConnectivityManager
11333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mCM = (ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
11433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
11533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // Get an instance of WifiManager
11633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mWifiManager =(WifiManager)mContext.getSystemService(Context.WIFI_SERVICE);
11733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
11833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mDownloadManager = (DownloadManager)mContext.getSystemService(Context.DOWNLOAD_SERVICE);
11933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
12033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        initializeNetworkStates();
12133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
12233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
123a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang    }
124a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang
125a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang    /**
126a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang     * Additional initialization needed for wifi related tests.
127a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang     */
128a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang    public void wifiTestInit() {
129a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang        mWifiManager.setWifiEnabled(true);
13033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Log.v(LOG_TAG, "Clear Wifi before we start the test.");
13133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        sleep(SHORT_TIMEOUT);
13233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        removeConfiguredNetworksAndDisableWifi();
13333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
13433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
13533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
13633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
13733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * A wrapper of a broadcast receiver which provides network connectivity information
13833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * for all kinds of network: wifi, mobile, etc.
13933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
14033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private class ConnectivityReceiver extends BroadcastReceiver {
14133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        /**
14233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang         * {@inheritDoc}
14333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang         */
14433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        @Override
14533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        public void onReceive(Context context, Intent intent) {
14633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if (isInitialStickyBroadcast()) {
14733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.d(LOG_TAG, "This is a sticky broadcast don't do anything.");
14833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return;
14933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
15033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "ConnectivityReceiver: onReceive() is called with " + intent);
15133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            String action = intent.getAction();
15233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
15333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v("ConnectivityReceiver", "onReceive() called with " + intent);
15433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return;
15533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
156a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang
157a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang            final ConnectivityManager connManager = (ConnectivityManager) context
158a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang                    .getSystemService(Context.CONNECTIVITY_SERVICE);
159a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang            mNetworkInfo = connManager.getActiveNetworkInfo();
16033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
16133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if (intent.hasExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO)) {
16233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                mOtherNetworkInfo = (NetworkInfo)
16333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
16433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
16533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
16633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "mNetworkInfo: " + mNetworkInfo.toString());
16733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            recordNetworkState(mNetworkInfo.getType(), mNetworkInfo.getState());
16833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if (mOtherNetworkInfo != null) {
16933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v(LOG_TAG, "mOtherNetworkInfo: " + mOtherNetworkInfo.toString());
17033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                recordNetworkState(mOtherNetworkInfo.getType(), mOtherNetworkInfo.getState());
17133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
17233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            notifyNetworkConnectivityChange();
17333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
17433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
17533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
17633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
17733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * A wrapper of a broadcast receiver which provides wifi information.
17833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
17933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private class WifiReceiver extends BroadcastReceiver {
18033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        /**
18133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang         * {@inheritDoc}
18233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang         */
18333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        @Override
18433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        public void onReceive(Context context, Intent intent) {
18533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            String action = intent.getAction();
18633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v("WifiReceiver", "onReceive() is calleld with " + intent);
18733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
18833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v(LOG_TAG, "Scan results are available");
18933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                notifyScanResult();
19033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
19133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                mWifiNetworkInfo =
19233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
19333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v(LOG_TAG, "mWifiNetworkInfo: " + mWifiNetworkInfo.toString());
19433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                if (mWifiNetworkInfo.getState() == State.CONNECTED) {
19533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    intent.getStringExtra(WifiManager.EXTRA_BSSID);
19633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
19733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                notifyWifiState();
19833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
19933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
20033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        WifiManager.WIFI_STATE_UNKNOWN);
20133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                notifyWifiState();
20233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
20333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                notifyWifiAPState();
20433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            } else {
20533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return;
20633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
20733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
20833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
20933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
21033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
21133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * A wrapper of a broadcast receiver which provides download manager information.
21233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
21333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private class DownloadReceiver extends BroadcastReceiver {
21433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        /**
21533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang         * {@inheritDoc}
21633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang         */
21733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        @Override
21833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        public void onReceive(Context context, Intent intent) {
21933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            String action = intent.getAction();
22033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v("DownloadReceiver", "onReceive() is called with " + intent);
22133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            // Download complete
22233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if (action.equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
22333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                notifiyDownloadState();
22433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
22533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
22633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
22733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
22833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private class WifiServiceHandler extends Handler {
22933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        /**
23033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang         * {@inheritDoc}
23133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang         */
23233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        @Override
23333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        public void handleMessage(Message msg) {
23433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            switch (msg.what) {
23533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
23633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
23733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        // AsyncChannel in msg.obj
23833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    } else {
23933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        Log.v(LOG_TAG, "Failed to establish AsyncChannel connection");
24033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    }
24133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    break;
24233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                default:
24333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    // Ignore
24433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    break;
24533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
24633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
24733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
24833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
24933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
25033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Initialize all the network states.
25133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
25233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public void initializeNetworkStates() {
25333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // For each network type, initialize network states to UNKNOWN, and no verification
25433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // flag is set.
25533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        for (int networkType = NUM_NETWORK_TYPES - 1; networkType >= 0; networkType--) {
25633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mConnectivityState[networkType] =  new NetworkState();
25733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "Initialize network state for " + networkType + ": " +
25833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    mConnectivityState[networkType].toString());
25933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
26033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
26133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
26233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public void recordNetworkState(int networkType, State networkState) {
26333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // deposit a network state
26433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Log.v(LOG_TAG, "record network state for network " +  networkType +
26533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                ", state is " + networkState);
26633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mConnectivityState[networkType].recordState(networkState);
26733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
26833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
269212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang    /**
270212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang     * Set the state transition criteria
271212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang     *
272212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang     * @param networkType
273212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang     * @param initState
274212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang     * @param transitionDir
275212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang     * @param targetState
276212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang     */
27733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public void setStateTransitionCriteria(int networkType, State initState,
27833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            StateTransitionDirection transitionDir, State targetState) {
27933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mConnectivityState[networkType].setStateTransitionCriteria(
28033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                initState, transitionDir, targetState);
28133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
28233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
28333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
28433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Validate the states recorded.
28533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param networkType
28633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return
28733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
28833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean validateNetworkStates(int networkType) {
28933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Log.v(LOG_TAG, "validate network state for " + networkType + ": ");
29033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return mConnectivityState[networkType].validateStateTransition();
29133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
29233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
29333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
29433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Fetch the failure reason for the transition.
29533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param networkType
29633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return result from network state validation
29733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
29833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public String getTransitionFailureReason(int networkType) {
29933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Log.v(LOG_TAG, "get network state transition failure reason for " + networkType + ": " +
30033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                mConnectivityState[networkType].toString());
30133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return mConnectivityState[networkType].getFailureReason();
30233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
30333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
30433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
30533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Send a notification via the mConnectivityMonitor when the network connectivity changes.
30633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
30733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private void notifyNetworkConnectivityChange() {
30833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        synchronized(mConnectivityMonitor) {
30933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "notify network connectivity changed");
31033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mConnectivityMonitor.notifyAll();
31133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
31233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
31333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
31433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
31533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Send a notification when a scan for the wifi network is done.
31633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
31733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private void notifyScanResult() {
31833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        synchronized (this) {
31933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "notify that scan results are available");
32033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            this.notify();
32133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
32233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
32333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
32433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
32533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Send a notification via the mWifiMonitor when the wifi state changes.
32633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
32733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private void notifyWifiState() {
32833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        synchronized (mWifiMonitor) {
32933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "notify wifi state changed.");
33033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mWifiMonitor.notify();
33133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
33233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
33333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
33433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
33533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Send a notification via the mDownloadMonitor when a download is complete.
33633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
33733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private void notifiyDownloadState() {
33833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        synchronized (mDownloadMonitor) {
33933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "notifiy download manager state changed.");
34033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mDownloadMonitor.notify();
34133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
34233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
34333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
34433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
34533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Send a notification when the wifi ap state changes.
34633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
34733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private void notifyWifiAPState() {
34833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        synchronized (this) {
34933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "notify wifi AP state changed.");
35033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            this.notify();
35133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
35233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
35333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
35433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
35533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Start a download on a given url and wait for completion.
35633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     *
35733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param targetUrl the target to download.x
35833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param timeout to wait for download to finish
35933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return true if we successfully downloaded the requestedUrl, false otherwise.
36033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
36133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean startDownloadAndWait(String targetUrl, long timeout) {
36233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if (targetUrl.length() == 0 || targetUrl == null) {
36333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "Empty or Null target url requested to DownloadManager");
36433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            return true;
36533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
36633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Request request = new Request(Uri.parse(targetUrl));
36733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        long enqueue = mDownloadManager.enqueue(request);
36833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Log.v(LOG_TAG, "Sending download request of " + targetUrl + " to DownloadManager");
36933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        long startTime = System.currentTimeMillis();
37033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        while (true) {
37133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if ((System.currentTimeMillis() - startTime) > timeout) {
37233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v(LOG_TAG, "startDownloadAndWait timed out, failed to fetch " + targetUrl +
37333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        " within " + timeout);
37433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return downloadSuccessful(enqueue);
37533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
37633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "Waiting for the download to finish " + targetUrl);
37733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            synchronized (mDownloadMonitor) {
37833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                try {
37933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    mDownloadMonitor.wait(SHORT_TIMEOUT);
38033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                } catch (InterruptedException e) {
38133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    e.printStackTrace();
38233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
38333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                if (!downloadSuccessful(enqueue)) {
38433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    continue;
38533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
38633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return true;
38733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
38833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
38933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
39033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
39133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
39233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Fetch the Download Manager's UID.
39333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return the Download Manager's UID
39433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
39533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public int downloadManagerUid() {
39633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        try {
39733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            PackageManager pm = mContext.getPackageManager();
39833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            ApplicationInfo appInfo = pm.getApplicationInfo(DOWNLOAD_MANAGER_PKG_NAME,
39933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    PackageManager.GET_META_DATA);
40033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            return appInfo.uid;
40133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        } catch (NameNotFoundException e) {
40233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.d(LOG_TAG, "Did not find the package for the download service.");
40333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            return -1;
40433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
40533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
40633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
40733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
40833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Determines if a given download was successful by querying the DownloadManager.
40933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     *
41033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param enqueue the id used to identify/query the DownloadManager with.
41133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return true if download was successful, false otherwise.
41233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
41333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private boolean downloadSuccessful(long enqueue) {
41433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Query query = new Query();
41533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        query.setFilterById(enqueue);
41633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Cursor c = mDownloadManager.query(query);
41733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if (c.moveToFirst()) {
41833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
41933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
42033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v(LOG_TAG, "Successfully downloaded file!");
42133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return true;
42233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
42333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
42433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return false;
42533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
42633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
42733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
42833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Wait for network connectivity state.
42933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param networkType the network to check for
43033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param expectedState the desired state
43133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param timeout in milliseconds
43233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return true if the network connectivity state matched what was expected
43333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
43433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean waitForNetworkState(int networkType, State expectedState, long timeout) {
43533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        long startTime = System.currentTimeMillis();
43633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        while (true) {
43733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if ((System.currentTimeMillis() - startTime) > timeout) {
43833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v(LOG_TAG, "waitForNetworkState time out, the state of network type " + networkType +
43933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        " is: " + mCM.getNetworkInfo(networkType).getState());
44033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                if (mCM.getNetworkInfo(networkType).getState() != expectedState) {
44133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    return false;
44233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                } else {
44333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    // the broadcast has been sent out. the state has been changed.
44433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    Log.v(LOG_TAG, "networktype: " + networkType + " state: " +
44533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                            mCM.getNetworkInfo(networkType));
44633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    return true;
44733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
44833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
44933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "Wait for the connectivity state for network: " + networkType +
45033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    " to be " + expectedState.toString());
45133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            synchronized (mConnectivityMonitor) {
45233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                try {
45333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    mConnectivityMonitor.wait(SHORT_TIMEOUT);
45433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                } catch (InterruptedException e) {
45533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    e.printStackTrace();
45633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
4574fe25f693ad311556fb232c352ed0b84d59343a5Tsu Chiang Chuang                if (mNetworkInfo == null) {
4584fe25f693ad311556fb232c352ed0b84d59343a5Tsu Chiang Chuang                    Log.v(LOG_TAG, "Do not have networkInfo! Force fetch of network info.");
4594fe25f693ad311556fb232c352ed0b84d59343a5Tsu Chiang Chuang                    mNetworkInfo = mCM.getActiveNetworkInfo();
4604b1afab106f3959ba56fba08fbdccee5d15068bcTsu Chiang Chuang                }
4614b1afab106f3959ba56fba08fbdccee5d15068bcTsu Chiang Chuang                // Still null after force fetch? Maybe the network did not have time to be brought
4624b1afab106f3959ba56fba08fbdccee5d15068bcTsu Chiang Chuang                // up yet.
4634b1afab106f3959ba56fba08fbdccee5d15068bcTsu Chiang Chuang                if (mNetworkInfo == null) {
4644b1afab106f3959ba56fba08fbdccee5d15068bcTsu Chiang Chuang                    Log.v(LOG_TAG, "Failed to force fetch networkInfo. " +
4654b1afab106f3959ba56fba08fbdccee5d15068bcTsu Chiang Chuang                            "The network is still not ready. Wait for the next broadcast");
4664b1afab106f3959ba56fba08fbdccee5d15068bcTsu Chiang Chuang                    continue;
4674fe25f693ad311556fb232c352ed0b84d59343a5Tsu Chiang Chuang                }
46833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                if ((mNetworkInfo.getType() != networkType) ||
46933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        (mNetworkInfo.getState() != expectedState)) {
47033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    Log.v(LOG_TAG, "network state for " + mNetworkInfo.getType() +
47133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                            "is: " + mNetworkInfo.getState());
47233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    continue;
47333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
47433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return true;
47533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
47633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
47733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
47833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
47933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
48033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Wait for a given wifi state to occur within a given timeout.
48133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param expectedState the expected wifi state.
48233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param timeout for the state to be set in milliseconds.
48333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return true if the state was achieved within the timeout, false otherwise.
48433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
48533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean waitForWifiState(int expectedState, long timeout) {
48633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // Wait for Wifi state: WIFI_STATE_DISABLED, WIFI_STATE_DISABLING, WIFI_STATE_ENABLED,
48733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        //                      WIFI_STATE_ENALBING, WIFI_STATE_UNKNOWN
48833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        long startTime = System.currentTimeMillis();
48933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        while (true) {
49033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if ((System.currentTimeMillis() - startTime) > timeout) {
49133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                if (mWifiState != expectedState) {
49233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    return false;
49333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                } else {
49433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    return true;
49533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
49633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
49733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "Wait for wifi state to be: " + expectedState);
49833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            synchronized (mWifiMonitor) {
49933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                try {
50033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    mWifiMonitor.wait(SHORT_TIMEOUT);
50133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                } catch (InterruptedException e) {
50233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    e.printStackTrace();
50333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
50433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                if (mWifiState != expectedState) {
50533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    Log.v(LOG_TAG, "Wifi state is: " + mWifiState);
50633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    continue;
50733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
50833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return true;
50933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
51033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
51133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
51233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
51333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
51433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Convenience method to determine if we are connected to a mobile network.
51533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return true if connected to a mobile network, false otherwise.
51633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
51733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean isConnectedToMobile() {
518212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        NetworkInfo networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
519212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        return networkInfo.isConnected();
52033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
52133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
52233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
52333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Convenience method to determine if we are connected to wifi.
52433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return true if connected to wifi, false otherwise.
52533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
52633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean isConnectedToWifi() {
527212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        NetworkInfo networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
528212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        return networkInfo.isConnected();
52933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
53033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
53133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
53233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Associate the device to given SSID
53333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * If the device is already associated with a WiFi, disconnect and forget it,
53433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * We don't verify whether the connection is successful or not, leave this to the test
53533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
53633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean connectToWifi(String knownSSID) {
53733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        WifiConfiguration config = new WifiConfiguration();
53833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        config.SSID = knownSSID;
53933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        config.allowedKeyManagement.set(KeyMgmt.NONE);
54033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return connectToWifiWithConfiguration(config);
54133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
54233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
54333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
54433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Connect to Wi-Fi with the given configuration.
54533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param config
546a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang     * @return true if we are connected to a given AP.
54733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
54833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean connectToWifiWithConfiguration(WifiConfiguration config) {
54933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        //  The SSID in the configuration is a pure string, need to convert it to a quoted string.
55033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        String ssid = config.SSID;
55133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        config.SSID = convertToQuotedString(ssid);
55233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
55333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // If wifi is not enabled, enable it
55433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if (!mWifiManager.isWifiEnabled()) {
55533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "Wifi is not enabled, enable it");
55633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mWifiManager.setWifiEnabled(true);
55733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            // wait for the wifi state change before start scanning.
55833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if (!waitForWifiState(WifiManager.WIFI_STATE_ENABLED, 2 * SHORT_TIMEOUT)) {
55933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v(LOG_TAG, "Wait for WIFI_STATE_ENABLED failed");
56033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return false;
56133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
56233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
56333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
56433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        boolean foundApInScanResults = false;
56533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        for (int retry = 0; retry < 5; retry++) {
56633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            List<ScanResult> netList = mWifiManager.getScanResults();
56733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if (netList != null) {
56833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v(LOG_TAG, "size of scan result list: " + netList.size());
56933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                for (int i = 0; i < netList.size(); i++) {
57033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    ScanResult sr= netList.get(i);
57133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    if (sr.SSID.equals(ssid)) {
57233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        Log.v(LOG_TAG, "Found " + ssid + " in the scan result list.");
57333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        Log.v(LOG_TAG, "Retry: " + retry);
57433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        foundApInScanResults = true;
57588759bbd31e05a4163e1f8e72804ca83000afd53Irfan Sheriff                        mWifiManager.connect(config, new WifiManager.ActionListener() {
576d3975a917799b85cacaf382b65c5832813066b51Irfan Sheriff                                public void onSuccess() {
577d3975a917799b85cacaf382b65c5832813066b51Irfan Sheriff                                }
578d3975a917799b85cacaf382b65c5832813066b51Irfan Sheriff                                public void onFailure(int reason) {
579d3975a917799b85cacaf382b65c5832813066b51Irfan Sheriff                                    Log.e(LOG_TAG, "connect failed " + reason);
580d3975a917799b85cacaf382b65c5832813066b51Irfan Sheriff                                }
581d3975a917799b85cacaf382b65c5832813066b51Irfan Sheriff                            });
582d3975a917799b85cacaf382b65c5832813066b51Irfan Sheriff
58333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        break;
58433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    }
58533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
58633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
58733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if (foundApInScanResults) {
58833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return true;
58933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            } else {
59033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                // Start an active scan
591bcc97ca43a339c3356b5c8d9eaf1cbdfb0de3165Irfan Sheriff                mWifiManager.startScan();
59233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                mScanResultIsAvailable = false;
59333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                long startTime = System.currentTimeMillis();
59433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                while (!mScanResultIsAvailable) {
59533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    if ((System.currentTimeMillis() - startTime) > WIFI_SCAN_TIMEOUT) {
59633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        Log.v(LOG_TAG, "wait for scan results timeout");
59733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        return false;
59833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    }
59933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    // wait for the scan results to be available
60033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    synchronized (this) {
60133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        // wait for the scan result to be available
60233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        try {
60333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                            this.wait(WAIT_FOR_SCAN_RESULT);
60433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        } catch (InterruptedException e) {
60533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                            e.printStackTrace();
60633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        }
60733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        if ((mWifiManager.getScanResults() == null) ||
60833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                                (mWifiManager.getScanResults().size() <= 0)) {
60933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                            continue;
61033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        }
61133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        mScanResultIsAvailable = true;
61233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    }
61333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
61433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
61533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
61633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return false;
61733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
61833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
61933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /*
62033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Disconnect from the current AP and remove configured networks.
62133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
62233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean disconnectAP() {
62333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // remove saved networks
62433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        List<WifiConfiguration> wifiConfigList = mWifiManager.getConfiguredNetworks();
62533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Log.v(LOG_TAG, "size of wifiConfigList: " + wifiConfigList.size());
62633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        for (WifiConfiguration wifiConfig: wifiConfigList) {
62733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "Remove wifi configuration: " + wifiConfig.networkId);
62833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            int netId = wifiConfig.networkId;
62988759bbd31e05a4163e1f8e72804ca83000afd53Irfan Sheriff            mWifiManager.forget(netId, new WifiManager.ActionListener() {
630d3975a917799b85cacaf382b65c5832813066b51Irfan Sheriff                    public void onSuccess() {
631d3975a917799b85cacaf382b65c5832813066b51Irfan Sheriff                    }
632d3975a917799b85cacaf382b65c5832813066b51Irfan Sheriff                    public void onFailure(int reason) {
633d3975a917799b85cacaf382b65c5832813066b51Irfan Sheriff                        Log.e(LOG_TAG, "forget failed " + reason);
634d3975a917799b85cacaf382b65c5832813066b51Irfan Sheriff                    }
635d3975a917799b85cacaf382b65c5832813066b51Irfan Sheriff                });
63633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
63733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return true;
63833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
63933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
64033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
64133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Enable Wifi
64233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return true if Wifi is enabled successfully
64333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
64433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean enableWifi() {
64533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return mWifiManager.setWifiEnabled(true);
64633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
64733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
64833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
64933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Disable Wifi
65033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return true if Wifi is disabled successfully
65133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
65233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean disableWifi() {
65333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return mWifiManager.setWifiEnabled(false);
65433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
65533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
65633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
65733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Remove configured networks and disable wifi
65833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
65933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean removeConfiguredNetworksAndDisableWifi() {
66033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if (!disconnectAP()) {
66133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            return false;
66233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
66333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        sleep(SHORT_TIMEOUT);
66433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if (!mWifiManager.setWifiEnabled(false)) {
66533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            return false;
66633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
66733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        sleep(SHORT_TIMEOUT);
66833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return true;
66933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
67033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
67133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
67233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Make the current thread sleep.
67333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param sleeptime the time to sleep in milliseconds
67433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
67533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private void sleep(long sleeptime) {
67633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        try {
67733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Thread.sleep(sleeptime);
67833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        } catch (InterruptedException e) {}
67933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
68033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
68133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
68233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Set airplane mode on device, caller is responsible to ensuring correct state.
68333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param context {@link Context}
68433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param enableAM to enable or disable airplane mode.
68533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
68633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public void setAirplaneMode(Context context, boolean enableAM) {
68733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        //set the airplane mode
68833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Settings.System.putInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,
68933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                enableAM ? 1 : 0);
69033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // Post the intent
69133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
69233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        intent.putExtra("state", enableAM);
69333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        context.sendBroadcast(intent);
69433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
69533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
69633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
69733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Add quotes around the string.
69833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param string to convert
69933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return string with quotes around it
70033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
70133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    protected static String convertToQuotedString(String string) {
70233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return "\"" + string + "\"";
70333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
70433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
70533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public void cleanUp() {
70633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // Unregister receivers if defined.
70733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if (mConnectivityReceiver != null) {
70833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mContext.unregisterReceiver(mConnectivityReceiver);
70933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
71033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if (mWifiReceiver != null) {
71133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mContext.unregisterReceiver(mWifiReceiver);
71233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
71333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if (mDownloadReceiver != null) {
71433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mContext.unregisterReceiver(mDownloadReceiver);
71533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
71633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Log.v(LOG_TAG, "onDestroy, inst=" + Integer.toHexString(hashCode()));
71733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
718212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang
719212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang    /**
720212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang     * Helper method used to test data connectivity by pinging a series of popular sites.
721212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang     * @return true if device has data connectivity, false otherwise.
722212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang     */
723212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang    public boolean hasData() {
724212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        String[] hostList = {"www.google.com", "www.yahoo.com",
725212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang                "www.bing.com", "www.facebook.com", "www.ask.com"};
726212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        try {
727212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang            for (int i = 0; i < hostList.length; ++i) {
728212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang                String host = hostList[i];
729212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang                Process p = Runtime.getRuntime().exec("ping -c 10 -w 100 " + host);
730212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang                int status = p.waitFor();
731212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang                if (status == 0) {
732212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang                    return true;
733212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang                }
734212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang            }
735212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        } catch (UnknownHostException e) {
736212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang            Log.e(LOG_TAG, "Ping test Failed: Unknown Host");
737212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        } catch (IOException e) {
738212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang            Log.e(LOG_TAG, "Ping test Failed: IOException");
739212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        } catch (InterruptedException e) {
740212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang            Log.e(LOG_TAG, "Ping test Failed: InterruptedException");
741212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        }
742212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        return false;
743212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang    }
744d3975a917799b85cacaf382b65c5832813066b51Irfan Sheriff}
745