ConnectionUtil.java revision 4b1afab106f3959ba56fba08fbdccee5d15068bc
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        mWifiManager.asyncConnect(mContext, new WifiServiceHandler());
11833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
11933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mDownloadManager = (DownloadManager)mContext.getSystemService(Context.DOWNLOAD_SERVICE);
12033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
12133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        initializeNetworkStates();
12233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
12333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
124a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang    }
125a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang
126a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang    /**
127a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang     * Additional initialization needed for wifi related tests.
128a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang     */
129a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang    public void wifiTestInit() {
130a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang        mWifiManager.setWifiEnabled(true);
13133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Log.v(LOG_TAG, "Clear Wifi before we start the test.");
13233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        sleep(SHORT_TIMEOUT);
13333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        removeConfiguredNetworksAndDisableWifi();
13433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
13533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
13633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
13733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
13833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * A wrapper of a broadcast receiver which provides network connectivity information
13933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * for all kinds of network: wifi, mobile, etc.
14033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
14133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private class ConnectivityReceiver extends BroadcastReceiver {
14233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        /**
14333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang         * {@inheritDoc}
14433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang         */
14533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        @Override
14633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        public void onReceive(Context context, Intent intent) {
14733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if (isInitialStickyBroadcast()) {
14833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.d(LOG_TAG, "This is a sticky broadcast don't do anything.");
14933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return;
15033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
15133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "ConnectivityReceiver: onReceive() is called with " + intent);
15233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            String action = intent.getAction();
15333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
15433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v("ConnectivityReceiver", "onReceive() called with " + intent);
15533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return;
15633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
157a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang
158a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang            final ConnectivityManager connManager = (ConnectivityManager) context
159a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang                    .getSystemService(Context.CONNECTIVITY_SERVICE);
160a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang            mNetworkInfo = connManager.getActiveNetworkInfo();
16133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
16233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if (intent.hasExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO)) {
16333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                mOtherNetworkInfo = (NetworkInfo)
16433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
16533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
16633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
16733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "mNetworkInfo: " + mNetworkInfo.toString());
16833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            recordNetworkState(mNetworkInfo.getType(), mNetworkInfo.getState());
16933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if (mOtherNetworkInfo != null) {
17033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v(LOG_TAG, "mOtherNetworkInfo: " + mOtherNetworkInfo.toString());
17133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                recordNetworkState(mOtherNetworkInfo.getType(), mOtherNetworkInfo.getState());
17233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
17333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            notifyNetworkConnectivityChange();
17433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
17533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
17633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
17733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
17833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * A wrapper of a broadcast receiver which provides wifi information.
17933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
18033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private class WifiReceiver extends BroadcastReceiver {
18133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        /**
18233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang         * {@inheritDoc}
18333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang         */
18433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        @Override
18533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        public void onReceive(Context context, Intent intent) {
18633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            String action = intent.getAction();
18733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v("WifiReceiver", "onReceive() is calleld with " + intent);
18833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
18933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v(LOG_TAG, "Scan results are available");
19033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                notifyScanResult();
19133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
19233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                mWifiNetworkInfo =
19333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
19433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v(LOG_TAG, "mWifiNetworkInfo: " + mWifiNetworkInfo.toString());
19533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                if (mWifiNetworkInfo.getState() == State.CONNECTED) {
19633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    intent.getStringExtra(WifiManager.EXTRA_BSSID);
19733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
19833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                notifyWifiState();
19933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
20033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
20133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        WifiManager.WIFI_STATE_UNKNOWN);
20233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                notifyWifiState();
20333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            } else if (action.equals(WifiManager.WIFI_AP_STATE_CHANGED_ACTION)) {
20433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                notifyWifiAPState();
20533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            } else {
20633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return;
20733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
20833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
20933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
21033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
21133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
21233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * A wrapper of a broadcast receiver which provides download manager information.
21333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
21433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private class DownloadReceiver extends BroadcastReceiver {
21533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        /**
21633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang         * {@inheritDoc}
21733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang         */
21833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        @Override
21933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        public void onReceive(Context context, Intent intent) {
22033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            String action = intent.getAction();
22133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v("DownloadReceiver", "onReceive() is called with " + intent);
22233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            // Download complete
22333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if (action.equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)) {
22433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                notifiyDownloadState();
22533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
22633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
22733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
22833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
22933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private class WifiServiceHandler extends Handler {
23033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        /**
23133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang         * {@inheritDoc}
23233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang         */
23333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        @Override
23433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        public void handleMessage(Message msg) {
23533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            switch (msg.what) {
23633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                case AsyncChannel.CMD_CHANNEL_HALF_CONNECTED:
23733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    if (msg.arg1 == AsyncChannel.STATUS_SUCCESSFUL) {
23833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        // AsyncChannel in msg.obj
23933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    } else {
24033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        Log.v(LOG_TAG, "Failed to establish AsyncChannel connection");
24133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    }
24233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    break;
24333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                default:
24433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    // Ignore
24533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    break;
24633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
24733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
24833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
24933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
25033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
25133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Initialize all the network states.
25233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
25333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public void initializeNetworkStates() {
25433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // For each network type, initialize network states to UNKNOWN, and no verification
25533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // flag is set.
25633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        for (int networkType = NUM_NETWORK_TYPES - 1; networkType >= 0; networkType--) {
25733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mConnectivityState[networkType] =  new NetworkState();
25833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "Initialize network state for " + networkType + ": " +
25933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    mConnectivityState[networkType].toString());
26033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
26133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
26233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
26333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public void recordNetworkState(int networkType, State networkState) {
26433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // deposit a network state
26533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Log.v(LOG_TAG, "record network state for network " +  networkType +
26633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                ", state is " + networkState);
26733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mConnectivityState[networkType].recordState(networkState);
26833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
26933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
270212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang    /**
271212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang     * Set the state transition criteria
272212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang     *
273212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang     * @param networkType
274212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang     * @param initState
275212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang     * @param transitionDir
276212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang     * @param targetState
277212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang     */
27833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public void setStateTransitionCriteria(int networkType, State initState,
27933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            StateTransitionDirection transitionDir, State targetState) {
28033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        mConnectivityState[networkType].setStateTransitionCriteria(
28133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                initState, transitionDir, targetState);
28233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
28333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
28433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
28533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Validate the states recorded.
28633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param networkType
28733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return
28833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
28933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean validateNetworkStates(int networkType) {
29033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Log.v(LOG_TAG, "validate network state for " + networkType + ": ");
29133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return mConnectivityState[networkType].validateStateTransition();
29233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
29333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
29433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
29533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Fetch the failure reason for the transition.
29633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param networkType
29733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return result from network state validation
29833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
29933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public String getTransitionFailureReason(int networkType) {
30033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Log.v(LOG_TAG, "get network state transition failure reason for " + networkType + ": " +
30133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                mConnectivityState[networkType].toString());
30233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return mConnectivityState[networkType].getFailureReason();
30333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
30433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
30533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
30633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Send a notification via the mConnectivityMonitor when the network connectivity changes.
30733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
30833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private void notifyNetworkConnectivityChange() {
30933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        synchronized(mConnectivityMonitor) {
31033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "notify network connectivity changed");
31133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mConnectivityMonitor.notifyAll();
31233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
31333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
31433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
31533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
31633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Send a notification when a scan for the wifi network is done.
31733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
31833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private void notifyScanResult() {
31933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        synchronized (this) {
32033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "notify that scan results are available");
32133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            this.notify();
32233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
32333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
32433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
32533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
32633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Send a notification via the mWifiMonitor when the wifi state changes.
32733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
32833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private void notifyWifiState() {
32933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        synchronized (mWifiMonitor) {
33033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "notify wifi state changed.");
33133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mWifiMonitor.notify();
33233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
33333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
33433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
33533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
33633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Send a notification via the mDownloadMonitor when a download is complete.
33733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
33833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private void notifiyDownloadState() {
33933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        synchronized (mDownloadMonitor) {
34033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "notifiy download manager state changed.");
34133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mDownloadMonitor.notify();
34233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
34333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
34433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
34533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
34633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Send a notification when the wifi ap state changes.
34733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
34833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private void notifyWifiAPState() {
34933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        synchronized (this) {
35033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "notify wifi AP state changed.");
35133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            this.notify();
35233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
35333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
35433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
35533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
35633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Start a download on a given url and wait for completion.
35733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     *
35833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param targetUrl the target to download.x
35933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param timeout to wait for download to finish
36033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return true if we successfully downloaded the requestedUrl, false otherwise.
36133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
36233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean startDownloadAndWait(String targetUrl, long timeout) {
36333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if (targetUrl.length() == 0 || targetUrl == null) {
36433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "Empty or Null target url requested to DownloadManager");
36533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            return true;
36633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
36733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Request request = new Request(Uri.parse(targetUrl));
36833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        long enqueue = mDownloadManager.enqueue(request);
36933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Log.v(LOG_TAG, "Sending download request of " + targetUrl + " to DownloadManager");
37033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        long startTime = System.currentTimeMillis();
37133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        while (true) {
37233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if ((System.currentTimeMillis() - startTime) > timeout) {
37333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v(LOG_TAG, "startDownloadAndWait timed out, failed to fetch " + targetUrl +
37433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        " within " + timeout);
37533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return downloadSuccessful(enqueue);
37633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
37733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "Waiting for the download to finish " + targetUrl);
37833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            synchronized (mDownloadMonitor) {
37933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                try {
38033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    mDownloadMonitor.wait(SHORT_TIMEOUT);
38133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                } catch (InterruptedException e) {
38233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    e.printStackTrace();
38333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
38433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                if (!downloadSuccessful(enqueue)) {
38533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    continue;
38633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
38733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return true;
38833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
38933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
39033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
39133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
39233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
39333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Fetch the Download Manager's UID.
39433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return the Download Manager's UID
39533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
39633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public int downloadManagerUid() {
39733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        try {
39833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            PackageManager pm = mContext.getPackageManager();
39933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            ApplicationInfo appInfo = pm.getApplicationInfo(DOWNLOAD_MANAGER_PKG_NAME,
40033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    PackageManager.GET_META_DATA);
40133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            return appInfo.uid;
40233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        } catch (NameNotFoundException e) {
40333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.d(LOG_TAG, "Did not find the package for the download service.");
40433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            return -1;
40533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
40633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
40733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
40833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
40933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Determines if a given download was successful by querying the DownloadManager.
41033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     *
41133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param enqueue the id used to identify/query the DownloadManager with.
41233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return true if download was successful, false otherwise.
41333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
41433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private boolean downloadSuccessful(long enqueue) {
41533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Query query = new Query();
41633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        query.setFilterById(enqueue);
41733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Cursor c = mDownloadManager.query(query);
41833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if (c.moveToFirst()) {
41933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            int columnIndex = c.getColumnIndex(DownloadManager.COLUMN_STATUS);
42033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if (DownloadManager.STATUS_SUCCESSFUL == c.getInt(columnIndex)) {
42133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v(LOG_TAG, "Successfully downloaded file!");
42233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return true;
42333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
42433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
42533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return false;
42633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
42733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
42833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
42933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Wait for network connectivity state.
43033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param networkType the network to check for
43133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param expectedState the desired state
43233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param timeout in milliseconds
43333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return true if the network connectivity state matched what was expected
43433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
43533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean waitForNetworkState(int networkType, State expectedState, long timeout) {
43633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        long startTime = System.currentTimeMillis();
43733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        while (true) {
43833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if ((System.currentTimeMillis() - startTime) > timeout) {
43933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v(LOG_TAG, "waitForNetworkState time out, the state of network type " + networkType +
44033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        " is: " + mCM.getNetworkInfo(networkType).getState());
44133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                if (mCM.getNetworkInfo(networkType).getState() != expectedState) {
44233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    return false;
44333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                } else {
44433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    // the broadcast has been sent out. the state has been changed.
44533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    Log.v(LOG_TAG, "networktype: " + networkType + " state: " +
44633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                            mCM.getNetworkInfo(networkType));
44733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    return true;
44833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
44933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
45033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "Wait for the connectivity state for network: " + networkType +
45133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    " to be " + expectedState.toString());
45233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            synchronized (mConnectivityMonitor) {
45333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                try {
45433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    mConnectivityMonitor.wait(SHORT_TIMEOUT);
45533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                } catch (InterruptedException e) {
45633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    e.printStackTrace();
45733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
4584fe25f693ad311556fb232c352ed0b84d59343a5Tsu Chiang Chuang                if (mNetworkInfo == null) {
4594fe25f693ad311556fb232c352ed0b84d59343a5Tsu Chiang Chuang                    Log.v(LOG_TAG, "Do not have networkInfo! Force fetch of network info.");
4604fe25f693ad311556fb232c352ed0b84d59343a5Tsu Chiang Chuang                    mNetworkInfo = mCM.getActiveNetworkInfo();
4614b1afab106f3959ba56fba08fbdccee5d15068bcTsu Chiang Chuang                }
4624b1afab106f3959ba56fba08fbdccee5d15068bcTsu Chiang Chuang                // Still null after force fetch? Maybe the network did not have time to be brought
4634b1afab106f3959ba56fba08fbdccee5d15068bcTsu Chiang Chuang                // up yet.
4644b1afab106f3959ba56fba08fbdccee5d15068bcTsu Chiang Chuang                if (mNetworkInfo == null) {
4654b1afab106f3959ba56fba08fbdccee5d15068bcTsu Chiang Chuang                    Log.v(LOG_TAG, "Failed to force fetch networkInfo. " +
4664b1afab106f3959ba56fba08fbdccee5d15068bcTsu Chiang Chuang                            "The network is still not ready. Wait for the next broadcast");
4674b1afab106f3959ba56fba08fbdccee5d15068bcTsu Chiang Chuang                    continue;
4684fe25f693ad311556fb232c352ed0b84d59343a5Tsu Chiang Chuang                }
46933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                if ((mNetworkInfo.getType() != networkType) ||
47033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        (mNetworkInfo.getState() != expectedState)) {
47133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    Log.v(LOG_TAG, "network state for " + mNetworkInfo.getType() +
47233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                            "is: " + mNetworkInfo.getState());
47333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    continue;
47433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
47533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return true;
47633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
47733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
47833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
47933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
48033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
48133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Wait for a given wifi state to occur within a given timeout.
48233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param expectedState the expected wifi state.
48333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param timeout for the state to be set in milliseconds.
48433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return true if the state was achieved within the timeout, false otherwise.
48533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
48633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean waitForWifiState(int expectedState, long timeout) {
48733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // Wait for Wifi state: WIFI_STATE_DISABLED, WIFI_STATE_DISABLING, WIFI_STATE_ENABLED,
48833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        //                      WIFI_STATE_ENALBING, WIFI_STATE_UNKNOWN
48933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        long startTime = System.currentTimeMillis();
49033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        while (true) {
49133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if ((System.currentTimeMillis() - startTime) > timeout) {
49233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                if (mWifiState != expectedState) {
49333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    return false;
49433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                } else {
49533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    return true;
49633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
49733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
49833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "Wait for wifi state to be: " + expectedState);
49933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            synchronized (mWifiMonitor) {
50033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                try {
50133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    mWifiMonitor.wait(SHORT_TIMEOUT);
50233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                } catch (InterruptedException e) {
50333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    e.printStackTrace();
50433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
50533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                if (mWifiState != expectedState) {
50633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    Log.v(LOG_TAG, "Wifi state is: " + mWifiState);
50733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    continue;
50833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
50933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return true;
51033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
51133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
51233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
51333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
51433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
51533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Convenience method to determine if we are connected to a mobile network.
51633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return true if connected to a mobile network, false otherwise.
51733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
51833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean isConnectedToMobile() {
519212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        NetworkInfo networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
520212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        return networkInfo.isConnected();
52133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
52233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
52333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
52433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Convenience method to determine if we are connected to wifi.
52533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return true if connected to wifi, false otherwise.
52633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
52733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean isConnectedToWifi() {
528212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        NetworkInfo networkInfo = mCM.getNetworkInfo(ConnectivityManager.TYPE_WIFI);
529212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        return networkInfo.isConnected();
53033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
53133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
53233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
53333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Associate the device to given SSID
53433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * If the device is already associated with a WiFi, disconnect and forget it,
53533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * We don't verify whether the connection is successful or not, leave this to the test
53633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
53733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean connectToWifi(String knownSSID) {
53833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        WifiConfiguration config = new WifiConfiguration();
53933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        config.SSID = knownSSID;
54033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        config.allowedKeyManagement.set(KeyMgmt.NONE);
54133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return connectToWifiWithConfiguration(config);
54233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
54333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
54433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
54533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Connect to Wi-Fi with the given configuration.
54633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param config
547a8c57bf6adf3bdd477ce4d6ed8cca031c66830cdTsu Chiang Chuang     * @return true if we are connected to a given AP.
54833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
54933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean connectToWifiWithConfiguration(WifiConfiguration config) {
55033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        //  The SSID in the configuration is a pure string, need to convert it to a quoted string.
55133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        String ssid = config.SSID;
55233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        config.SSID = convertToQuotedString(ssid);
55333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
55433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // If wifi is not enabled, enable it
55533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if (!mWifiManager.isWifiEnabled()) {
55633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "Wifi is not enabled, enable it");
55733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mWifiManager.setWifiEnabled(true);
55833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            // wait for the wifi state change before start scanning.
55933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if (!waitForWifiState(WifiManager.WIFI_STATE_ENABLED, 2 * SHORT_TIMEOUT)) {
56033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v(LOG_TAG, "Wait for WIFI_STATE_ENABLED failed");
56133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return false;
56233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
56333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
56433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
56533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        boolean foundApInScanResults = false;
56633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        for (int retry = 0; retry < 5; retry++) {
56733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            List<ScanResult> netList = mWifiManager.getScanResults();
56833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if (netList != null) {
56933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                Log.v(LOG_TAG, "size of scan result list: " + netList.size());
57033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                for (int i = 0; i < netList.size(); i++) {
57133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    ScanResult sr= netList.get(i);
57233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    if (sr.SSID.equals(ssid)) {
57333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        Log.v(LOG_TAG, "Found " + ssid + " in the scan result list.");
57433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        Log.v(LOG_TAG, "Retry: " + retry);
57533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        foundApInScanResults = true;
57633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        mWifiManager.connectNetwork(config);
57733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        break;
57833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    }
57933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
58033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
58133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            if (foundApInScanResults) {
58233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                return true;
58333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            } else {
58433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                // Start an active scan
58533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                mWifiManager.startScanActive();
58633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                mScanResultIsAvailable = false;
58733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                long startTime = System.currentTimeMillis();
58833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                while (!mScanResultIsAvailable) {
58933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    if ((System.currentTimeMillis() - startTime) > WIFI_SCAN_TIMEOUT) {
59033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        Log.v(LOG_TAG, "wait for scan results timeout");
59133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        return false;
59233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    }
59333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    // wait for the scan results to be available
59433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    synchronized (this) {
59533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        // wait for the scan result to be available
59633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        try {
59733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                            this.wait(WAIT_FOR_SCAN_RESULT);
59833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        } catch (InterruptedException e) {
59933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                            e.printStackTrace();
60033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        }
60133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        if ((mWifiManager.getScanResults() == null) ||
60233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                                (mWifiManager.getScanResults().size() <= 0)) {
60333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                            continue;
60433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        }
60533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                        mScanResultIsAvailable = true;
60633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                    }
60733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                }
60833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            }
60933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
61033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return false;
61133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
61233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
61333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /*
61433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Disconnect from the current AP and remove configured networks.
61533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
61633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean disconnectAP() {
61733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // remove saved networks
61833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        List<WifiConfiguration> wifiConfigList = mWifiManager.getConfiguredNetworks();
61933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Log.v(LOG_TAG, "size of wifiConfigList: " + wifiConfigList.size());
62033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        for (WifiConfiguration wifiConfig: wifiConfigList) {
62133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Log.v(LOG_TAG, "Remove wifi configuration: " + wifiConfig.networkId);
62233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            int netId = wifiConfig.networkId;
62333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mWifiManager.forgetNetwork(netId);
62433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
62533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return true;
62633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
62733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
62833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
62933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Enable Wifi
63033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return true if Wifi is enabled successfully
63133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
63233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean enableWifi() {
63333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return mWifiManager.setWifiEnabled(true);
63433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
63533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
63633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
63733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Disable Wifi
63833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return true if Wifi is disabled successfully
63933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
64033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean disableWifi() {
64133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return mWifiManager.setWifiEnabled(false);
64233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
64333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
64433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
64533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Remove configured networks and disable wifi
64633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
64733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public boolean removeConfiguredNetworksAndDisableWifi() {
64833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if (!disconnectAP()) {
64933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            return false;
65033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
65133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        sleep(SHORT_TIMEOUT);
65233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if (!mWifiManager.setWifiEnabled(false)) {
65333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            return false;
65433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
65533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        sleep(SHORT_TIMEOUT);
65633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return true;
65733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
65833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
65933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
66033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Make the current thread sleep.
66133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param sleeptime the time to sleep in milliseconds
66233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
66333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    private void sleep(long sleeptime) {
66433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        try {
66533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            Thread.sleep(sleeptime);
66633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        } catch (InterruptedException e) {}
66733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
66833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
66933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
67033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Set airplane mode on device, caller is responsible to ensuring correct state.
67133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param context {@link Context}
67233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param enableAM to enable or disable airplane mode.
67333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
67433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public void setAirplaneMode(Context context, boolean enableAM) {
67533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        //set the airplane mode
67633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Settings.System.putInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,
67733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang                enableAM ? 1 : 0);
67833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // Post the intent
67933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
68033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        intent.putExtra("state", enableAM);
68133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        context.sendBroadcast(intent);
68233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
68333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
68433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    /**
68533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * Add quotes around the string.
68633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @param string to convert
68733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     * @return string with quotes around it
68833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang     */
68933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    protected static String convertToQuotedString(String string) {
69033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        return "\"" + string + "\"";
69133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
69233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang
69333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    public void cleanUp() {
69433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        // Unregister receivers if defined.
69533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if (mConnectivityReceiver != null) {
69633f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mContext.unregisterReceiver(mConnectivityReceiver);
69733f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
69833f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if (mWifiReceiver != null) {
69933f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mContext.unregisterReceiver(mWifiReceiver);
70033f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
70133f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        if (mDownloadReceiver != null) {
70233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang            mContext.unregisterReceiver(mDownloadReceiver);
70333f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        }
70433f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang        Log.v(LOG_TAG, "onDestroy, inst=" + Integer.toHexString(hashCode()));
70533f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang    }
706212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang
707212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang    /**
708212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang     * Helper method used to test data connectivity by pinging a series of popular sites.
709212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang     * @return true if device has data connectivity, false otherwise.
710212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang     */
711212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang    public boolean hasData() {
712212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        String[] hostList = {"www.google.com", "www.yahoo.com",
713212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang                "www.bing.com", "www.facebook.com", "www.ask.com"};
714212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        try {
715212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang            for (int i = 0; i < hostList.length; ++i) {
716212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang                String host = hostList[i];
717212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang                Process p = Runtime.getRuntime().exec("ping -c 10 -w 100 " + host);
718212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang                int status = p.waitFor();
719212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang                if (status == 0) {
720212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang                    return true;
721212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang                }
722212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang            }
723212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        } catch (UnknownHostException e) {
724212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang            Log.e(LOG_TAG, "Ping test Failed: Unknown Host");
725212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        } catch (IOException e) {
726212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang            Log.e(LOG_TAG, "Ping test Failed: IOException");
727212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        } catch (InterruptedException e) {
728212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang            Log.e(LOG_TAG, "Ping test Failed: InterruptedException");
729212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        }
730212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang        return false;
731212efacb848f13b1565ef434e331a69e930d8935Tsu Chiang Chuang    }
73233f869951fde247927e66c3aa4ab86fc61f783adTsu Chiang Chuang}