1fc2dbd04005c32360eead803e29df3cc62209cd8Xia Wang/*
2fc2dbd04005c32360eead803e29df3cc62209cd8Xia Wang * Copyright (C) 2010, The Android Open Source Project
3fc2dbd04005c32360eead803e29df3cc62209cd8Xia Wang *
4fc2dbd04005c32360eead803e29df3cc62209cd8Xia Wang * Licensed under the Apache License, Version 2.0 (the "License");
5fc2dbd04005c32360eead803e29df3cc62209cd8Xia Wang * you may not use this file except in compliance with the License.
6fc2dbd04005c32360eead803e29df3cc62209cd8Xia Wang * You may obtain a copy of the License at
7fc2dbd04005c32360eead803e29df3cc62209cd8Xia Wang *
8fc2dbd04005c32360eead803e29df3cc62209cd8Xia Wang *      http://www.apache.org/licenses/LICENSE-2.0
9fc2dbd04005c32360eead803e29df3cc62209cd8Xia Wang *
10fc2dbd04005c32360eead803e29df3cc62209cd8Xia Wang * Unless required by applicable law or agreed to in writing, software
11fc2dbd04005c32360eead803e29df3cc62209cd8Xia Wang * distributed under the License is distributed on an "AS IS" BASIS,
12fc2dbd04005c32360eead803e29df3cc62209cd8Xia Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13fc2dbd04005c32360eead803e29df3cc62209cd8Xia Wang * See the License for the specific language governing permissions and
14fc2dbd04005c32360eead803e29df3cc62209cd8Xia Wang * limitations under the License.
15fc2dbd04005c32360eead803e29df3cc62209cd8Xia Wang */
16fc2dbd04005c32360eead803e29df3cc62209cd8Xia Wang
177fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wangpackage com.android.connectivitymanagertest;
187fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
197fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wangimport android.app.Activity;
207fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wangimport android.content.Context;
217fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wangimport android.content.BroadcastReceiver;
227fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wangimport android.content.Intent;
237fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wangimport android.content.IntentFilter;
247fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wangimport android.os.Bundle;
257fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wangimport android.provider.Settings;
267fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wangimport android.util.Log;
277fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wangimport java.util.List;
287fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wangimport android.widget.LinearLayout;
297fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wangimport android.net.ConnectivityManager;
307fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wangimport android.net.NetworkInfo;
317fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wangimport android.net.NetworkInfo.State;
327fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
337fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wangimport android.net.wifi.WifiConfiguration;
347fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wangimport android.net.wifi.WifiManager;
352c15966f8cf6160ad5dcbbde372508de89985829Xia Wangimport android.net.wifi.WifiInfo;
367fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wangimport android.net.wifi.ScanResult;
377fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wangimport android.net.wifi.WifiConfiguration.KeyMgmt;
387fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
397fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
407fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang/**
417fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang * An activity registered with connectivity manager broadcast
427fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang * provides network connectivity information and
437fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang * can be used to set device states: Cellular, Wifi, Airplane mode.
447fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang */
457fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wangpublic class ConnectivityManagerTestActivity extends Activity {
467fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
477fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public static final String LOG_TAG = "ConnectivityManagerTestActivity";
487fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public static final int WAIT_FOR_SCAN_RESULT = 5 * 1000; //5 seconds
497fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public static final int WIFI_SCAN_TIMEOUT = 20 * 1000;
507fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public ConnectivityReceiver mConnectivityReceiver = null;
517fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public WifiReceiver mWifiReceiver = null;
527fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    /*
537fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang     * Track network connectivity information
547fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang     */
557fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public State mState;
567fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public NetworkInfo mNetworkInfo;
577fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public NetworkInfo mOtherNetworkInfo;
587fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public boolean mIsFailOver;
597fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public String mReason;
607fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public boolean mScanResultIsAvailable = false;
617fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public ConnectivityManager mCM;
622c15966f8cf6160ad5dcbbde372508de89985829Xia Wang    public Object wifiObject = new Object();
632c15966f8cf6160ad5dcbbde372508de89985829Xia Wang    public Object connectivityObject = new Object();
642c15966f8cf6160ad5dcbbde372508de89985829Xia Wang    public int mWifiState;
652c15966f8cf6160ad5dcbbde372508de89985829Xia Wang    public NetworkInfo mWifiNetworkInfo;
662c15966f8cf6160ad5dcbbde372508de89985829Xia Wang    public String mBssid;
677fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
687fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    /*
697fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang     * Control Wifi States
707fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang     */
717fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public WifiManager mWifiManager;
727fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
737fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    /*
747fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang     * Verify connectivity state
757fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang     */
762c15966f8cf6160ad5dcbbde372508de89985829Xia Wang    public static final int NUM_NETWORK_TYPES = ConnectivityManager.MAX_NETWORK_TYPE + 1;
777fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    NetworkState[] connectivityState = new NetworkState[NUM_NETWORK_TYPES];
787fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
797fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    /**
807fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang     * A wrapper of a broadcast receiver which provides network connectivity information
817fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang     * for all kinds of network: wifi, mobile, etc.
827fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang     */
837fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    private class ConnectivityReceiver extends BroadcastReceiver {
847fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        @Override
857fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        public void onReceive(Context context, Intent intent) {
862c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            Log.v(LOG_TAG, "ConnectivityReceiver: onReceive() is called with " + intent);
877fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            String action = intent.getAction();
887fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
897fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                Log.v("ConnectivityReceiver", "onReceive() called with " + intent);
907fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                return;
917fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            }
927fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
937fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            boolean noConnectivity =
947fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
957fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
967fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            if (noConnectivity) {
977fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                mState = State.DISCONNECTED;
987fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            } else {
997fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                mState = State.CONNECTED;
1007fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            }
1017fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
1027fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            mNetworkInfo = (NetworkInfo)
1037fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                intent.getParcelableExtra(ConnectivityManager.EXTRA_NETWORK_INFO);
1047fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
1057fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            mOtherNetworkInfo = (NetworkInfo)
1067fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                intent.getParcelableExtra(ConnectivityManager.EXTRA_OTHER_NETWORK_INFO);
1077fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
1087fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            mReason = intent.getStringExtra(ConnectivityManager.EXTRA_REASON);
1097fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            mIsFailOver = intent.getBooleanExtra(ConnectivityManager.EXTRA_IS_FAILOVER, false);
1102c15966f8cf6160ad5dcbbde372508de89985829Xia Wang
1112c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            Log.v(LOG_TAG, "mNetworkInfo: " + mNetworkInfo.toString());
1122c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            if (mOtherNetworkInfo != null) {
1132c15966f8cf6160ad5dcbbde372508de89985829Xia Wang                Log.v(LOG_TAG, "mOtherNetworkInfo: " + mOtherNetworkInfo.toString());
1142c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            }
1157fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            recordNetworkState(mNetworkInfo.getType(), mNetworkInfo.getState());
1167fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            if (mOtherNetworkInfo != null) {
1177fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                recordNetworkState(mOtherNetworkInfo.getType(), mOtherNetworkInfo.getState());
1187fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            }
1192c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            notifyNetworkConnectivityChange();
1207fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        }
1217fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    }
1227fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
1237fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    private class WifiReceiver extends BroadcastReceiver {
1247fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        @Override
1257fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        public void onReceive(Context context, Intent intent) {
1267fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            String action = intent.getAction();
1272c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            Log.v("WifiReceiver", "onReceive() is calleld with " + intent);
1282c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            if (action.equals(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION)) {
1292c15966f8cf6160ad5dcbbde372508de89985829Xia Wang                notifyScanResult();
1302c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            } else if (action.equals(WifiManager.NETWORK_STATE_CHANGED_ACTION)) {
1312c15966f8cf6160ad5dcbbde372508de89985829Xia Wang                mWifiNetworkInfo =
1322c15966f8cf6160ad5dcbbde372508de89985829Xia Wang                    (NetworkInfo) intent.getParcelableExtra(WifiManager.EXTRA_NETWORK_INFO);
1332c15966f8cf6160ad5dcbbde372508de89985829Xia Wang                Log.v(LOG_TAG, "mWifiNetworkInfo: " + mWifiNetworkInfo.toString());
1342c15966f8cf6160ad5dcbbde372508de89985829Xia Wang                if (mWifiNetworkInfo.getState() == State.CONNECTED) {
1352c15966f8cf6160ad5dcbbde372508de89985829Xia Wang                    mBssid = intent.getStringExtra(WifiManager.EXTRA_BSSID);
1362c15966f8cf6160ad5dcbbde372508de89985829Xia Wang                }
1372c15966f8cf6160ad5dcbbde372508de89985829Xia Wang                notifyWifiState();
1382c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            } else if (action.equals(WifiManager.WIFI_STATE_CHANGED_ACTION)) {
1392c15966f8cf6160ad5dcbbde372508de89985829Xia Wang                mWifiState = intent.getIntExtra(WifiManager.EXTRA_WIFI_STATE,
1402c15966f8cf6160ad5dcbbde372508de89985829Xia Wang                                                WifiManager.WIFI_STATE_UNKNOWN);
1412c15966f8cf6160ad5dcbbde372508de89985829Xia Wang                notifyWifiState();
1422c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            }
1432c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            else {
1447fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                return;
1457fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            }
1467fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        }
1477fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    }
1487fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
1497fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public ConnectivityManagerTestActivity() {
1507fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        mState = State.UNKNOWN;
1517fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    }
1527fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
1537fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    @Override
1547fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    protected void onCreate(Bundle savedInstanceState) {
1557fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        super.onCreate(savedInstanceState);
1567fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        Log.v(LOG_TAG, "onCreate, inst=" + Integer.toHexString(hashCode()));
1577fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
1587fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        // Create a simple layout
1597fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        LinearLayout contentView = new LinearLayout(this);
1607fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        contentView.setOrientation(LinearLayout.VERTICAL);
1617fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        setContentView(contentView);
1627fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        setTitle("ConnectivityManagerTestActivity");
1637fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
1642c15966f8cf6160ad5dcbbde372508de89985829Xia Wang
1657fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        // register a connectivity receiver for CONNECTIVITY_ACTION;
1662c15966f8cf6160ad5dcbbde372508de89985829Xia Wang        mConnectivityReceiver = new ConnectivityReceiver();
1677fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        registerReceiver(mConnectivityReceiver,
1687fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                new IntentFilter(ConnectivityManager.CONNECTIVITY_ACTION));
1697fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
1707fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        mWifiReceiver = new WifiReceiver();
1712c15966f8cf6160ad5dcbbde372508de89985829Xia Wang        IntentFilter mIntentFilter = new IntentFilter();
1722c15966f8cf6160ad5dcbbde372508de89985829Xia Wang        mIntentFilter.addAction(WifiManager.SCAN_RESULTS_AVAILABLE_ACTION);
1732c15966f8cf6160ad5dcbbde372508de89985829Xia Wang        mIntentFilter.addAction(WifiManager.NETWORK_STATE_CHANGED_ACTION);
1742c15966f8cf6160ad5dcbbde372508de89985829Xia Wang        mIntentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
1752c15966f8cf6160ad5dcbbde372508de89985829Xia Wang        registerReceiver(mWifiReceiver, mIntentFilter);
1762c15966f8cf6160ad5dcbbde372508de89985829Xia Wang
1777fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        // Get an instance of ConnectivityManager
1787fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        mCM = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE);
1797fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        // Get an instance of WifiManager
1807fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        mWifiManager =(WifiManager)getSystemService(Context.WIFI_SERVICE);
1817fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        initializeNetworkStates();
1827fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
1837fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        if (mWifiManager.isWifiEnabled()) {
1847fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            Log.v(LOG_TAG, "Clear Wifi before we start the test.");
1857fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            clearWifi();
1867fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        }
1877fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang     }
1887fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
1897fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    // for each network type, initialize network states to UNKNOWN, and no verification flag is set
1907fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public void initializeNetworkStates() {
1917fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        for (int networkType = NUM_NETWORK_TYPES - 1; networkType >=0; networkType--) {
1927fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            connectivityState[networkType] =  new NetworkState();
1937fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            Log.v(LOG_TAG, "Initialize network state for " + networkType + ": " +
1947fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                    connectivityState[networkType].toString());
1957fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        }
1967fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    }
1977fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
1987fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    // deposit a network state
1997fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public void recordNetworkState(int networkType, State networkState) {
2007fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        Log.v(LOG_TAG, "record network state for network " +  networkType +
2012c15966f8cf6160ad5dcbbde372508de89985829Xia Wang                ", state is " + networkState);
2027fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        connectivityState[networkType].recordState(networkState);
2037fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    }
2047fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
2057fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    // set the state transition criteria
2067fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public void setStateTransitionCriteria(int networkType, State initState,
2077fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            int transitionDir, State targetState) {
2087fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        connectivityState[networkType].setStateTransitionCriteria(
2097fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                initState, transitionDir, targetState);
2107fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    }
2117fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
2127fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    // Validate the states recorded
2137fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public boolean validateNetworkStates(int networkType) {
2147fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        Log.v(LOG_TAG, "validate network state for " + networkType + ": ");
2157fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        return connectivityState[networkType].validateStateTransition();
2167fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    }
2177fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
2187fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    // return result from network state validation
2197fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public String getTransitionFailureReason(int networkType) {
2207fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        Log.v(LOG_TAG, "get network state transition failure reason for " + networkType + ": " +
2217fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                connectivityState[networkType].toString());
2227fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        return connectivityState[networkType].getReason();
2237fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    }
2247fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
2252c15966f8cf6160ad5dcbbde372508de89985829Xia Wang    private void notifyNetworkConnectivityChange() {
2262c15966f8cf6160ad5dcbbde372508de89985829Xia Wang        synchronized(connectivityObject) {
2272c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            Log.v(LOG_TAG, "notify network connectivity changed");
2282c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            connectivityObject.notifyAll();
2292c15966f8cf6160ad5dcbbde372508de89985829Xia Wang        }
2302c15966f8cf6160ad5dcbbde372508de89985829Xia Wang    }
2317fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    private void notifyScanResult() {
2327fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        synchronized (this) {
2337fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            Log.v(LOG_TAG, "notify that scan results are available");
2347fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            this.notify();
2357fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        }
2367fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    }
2377fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
2382c15966f8cf6160ad5dcbbde372508de89985829Xia Wang    public void notifyWifiState() {
2392c15966f8cf6160ad5dcbbde372508de89985829Xia Wang        synchronized (wifiObject) {
2402c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            Log.v(LOG_TAG, "notify wifi state changed");
2412c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            wifiObject.notify();
2422c15966f8cf6160ad5dcbbde372508de89985829Xia Wang        }
2432c15966f8cf6160ad5dcbbde372508de89985829Xia Wang    }
2442c15966f8cf6160ad5dcbbde372508de89985829Xia Wang
2457fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    // Return true if device is currently connected to mobile network
2467fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public boolean isConnectedToMobile() {
2477fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        return (mNetworkInfo.getType() == ConnectivityManager.TYPE_MOBILE);
2487fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    }
2497fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
2507fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    // Return true if device is currently connected to Wifi
2517fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public boolean isConnectedToWifi() {
2527fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        return (mNetworkInfo.getType() == ConnectivityManager.TYPE_WIFI);
2537fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    }
2547fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
2557fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public boolean enableWifi() {
2567fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        return mWifiManager.setWifiEnabled(true);
2577fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    }
2587fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
2597fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    /**
2607fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang     * Associate the device to given SSID
2617fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang     * If the device is already associated with a WiFi, disconnect and forget it,
2627fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang     * We don't verify whether the connection is successful or not, leave this to the test
2637fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang     */
2647fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public boolean connectToWifi(String knownSSID) {
2657fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        //If Wifi is not enabled, enable it
2667fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        if (!mWifiManager.isWifiEnabled()) {
2677fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            Log.v(LOG_TAG, "Wifi is not enabled, enable it");
2687fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            mWifiManager.setWifiEnabled(true);
2697fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        }
2707fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
2717fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        List<ScanResult> netList = mWifiManager.getScanResults();
2727fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        if (netList == null) {
2737fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            // if no scan results are available, start active scan
2747fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            mWifiManager.startScanActive();
2757fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            mScanResultIsAvailable = false;
2767fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            long startTime = System.currentTimeMillis();
2777fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            while (!mScanResultIsAvailable) {
2787fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                if ((System.currentTimeMillis() - startTime) > WIFI_SCAN_TIMEOUT) {
2797fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                    return false;
2807fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                }
2817fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                // wait for the scan results to be available
2827fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                synchronized (this) {
2837fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                    // wait for the scan result to be available
2847fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                    try {
2857fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                        this.wait(WAIT_FOR_SCAN_RESULT);
2867fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                    } catch (InterruptedException e) {
2877fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                        e.printStackTrace();
2887fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                    }
2897fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                    if ((mWifiManager.getScanResults() == null) ||
2907fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                            (mWifiManager.getScanResults().size() <= 0)) {
2917fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                        continue;
2927fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                    }
2937fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                    mScanResultIsAvailable = true;
2947fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                }
2957fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            }
2967fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        }
2977fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
2987fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        netList = mWifiManager.getScanResults();
2997fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        for (int i = 0; i < netList.size(); i++) {
3007fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            ScanResult sr= netList.get(i);
3017fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            if (sr.SSID.equals(knownSSID)) {
3027fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                Log.v(LOG_TAG, "found " + knownSSID + " in the scan result list");
3037fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                WifiConfiguration config = new WifiConfiguration();
304069067963cf0117cfb4a1aef99b550b126d9ca92Xia Wang                config.SSID = convertToQuotedString(sr.SSID);
3057fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                config.allowedKeyManagement.set(KeyMgmt.NONE);
3067fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                int networkId = mWifiManager.addNetwork(config);
3077fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                // Connect to network by disabling others.
3087fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                mWifiManager.enableNetwork(networkId, true);
3092c15966f8cf6160ad5dcbbde372508de89985829Xia Wang                mWifiManager.saveConfiguration();
3107fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                mWifiManager.reconnect();
3117fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                break;
3127fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang           }
3137fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        }
3147fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
3157fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        List<WifiConfiguration> netConfList = mWifiManager.getConfiguredNetworks();
3167fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        if (netConfList.size() <= 0) {
3177fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            Log.v(LOG_TAG, knownSSID + " is not available");
3187fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            return false;
3197fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        }
3207fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        return true;
3217fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    }
3227fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
3232c15966f8cf6160ad5dcbbde372508de89985829Xia Wang    /*
3242c15966f8cf6160ad5dcbbde372508de89985829Xia Wang     * Disconnect from the current AP
3257fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang     */
3262c15966f8cf6160ad5dcbbde372508de89985829Xia Wang    public boolean disconnectAP() {
3272c15966f8cf6160ad5dcbbde372508de89985829Xia Wang        if (mWifiManager.isWifiEnabled()) {
3287fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            //remove the current network Id
3292c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            WifiInfo curWifi = mWifiManager.getConnectionInfo();
3302c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            if (curWifi == null) {
3312c15966f8cf6160ad5dcbbde372508de89985829Xia Wang                return false;
3322c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            }
3332c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            int curNetworkId = curWifi.getNetworkId();
3347fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            mWifiManager.removeNetwork(curNetworkId);
3357fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            mWifiManager.saveConfiguration();
3367fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
3377fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            // remove other saved networks
3387fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            List<WifiConfiguration> netConfList = mWifiManager.getConfiguredNetworks();
3397fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            if (netConfList != null) {
3407fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                Log.v(LOG_TAG, "remove configured network ids");
3417fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                for (int i = 0; i < netConfList.size(); i++) {
3427fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                    WifiConfiguration conf = new WifiConfiguration();
3437fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                    conf = netConfList.get(i);
3447fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                    mWifiManager.removeNetwork(conf.networkId);
3457fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                }
3467fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            }
3472c15966f8cf6160ad5dcbbde372508de89985829Xia Wang        }
3482c15966f8cf6160ad5dcbbde372508de89985829Xia Wang        mWifiManager.saveConfiguration();
3492c15966f8cf6160ad5dcbbde372508de89985829Xia Wang        return true;
3502c15966f8cf6160ad5dcbbde372508de89985829Xia Wang    }
3512c15966f8cf6160ad5dcbbde372508de89985829Xia Wang    /**
3522c15966f8cf6160ad5dcbbde372508de89985829Xia Wang     * Disable Wifi
3532c15966f8cf6160ad5dcbbde372508de89985829Xia Wang     * @return true if Wifi is disabled successfully
3542c15966f8cf6160ad5dcbbde372508de89985829Xia Wang     */
3552c15966f8cf6160ad5dcbbde372508de89985829Xia Wang    public boolean disableWifi() {
3562c15966f8cf6160ad5dcbbde372508de89985829Xia Wang        return mWifiManager.setWifiEnabled(false);
3572c15966f8cf6160ad5dcbbde372508de89985829Xia Wang    }
3582c15966f8cf6160ad5dcbbde372508de89985829Xia Wang
3592c15966f8cf6160ad5dcbbde372508de89985829Xia Wang    /**
3602c15966f8cf6160ad5dcbbde372508de89985829Xia Wang     * Disconnect from the current Wifi and clear the configuration list
3612c15966f8cf6160ad5dcbbde372508de89985829Xia Wang     */
3622c15966f8cf6160ad5dcbbde372508de89985829Xia Wang    public boolean clearWifi() {
3632c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            if (!disconnectAP()) {
3642c15966f8cf6160ad5dcbbde372508de89985829Xia Wang                return false;
3652c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            }
3662c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            // Disable Wifi
3677fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            if (!mWifiManager.setWifiEnabled(false)) {
3687fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                return false;
3697fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            }
3702c15966f8cf6160ad5dcbbde372508de89985829Xia Wang            // Wait for the actions to be completed
3717fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            try {
3727fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                Thread.sleep(5*1000);
3737fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            } catch (InterruptedException e) {}
3747fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        return true;
3757fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    }
3767fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
3777fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    /**
3787fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang     * Set airplane mode
3797fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang     */
3807fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    public void setAirplaneMode(Context context, boolean enableAM) {
3817fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        //set the airplane mode
3827fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        Settings.System.putInt(context.getContentResolver(), Settings.System.AIRPLANE_MODE_ON,
3837fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang                enableAM ? 1 : 0);
3847fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        // Post the intent
3857fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        Intent intent = new Intent(Intent.ACTION_AIRPLANE_MODE_CHANGED);
3867fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        intent.putExtra("state", enableAM);
3877fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        context.sendBroadcast(intent);
3887fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    }
3897fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
390069067963cf0117cfb4a1aef99b550b126d9ca92Xia Wang    protected static String convertToQuotedString(String string) {
391069067963cf0117cfb4a1aef99b550b126d9ca92Xia Wang        return "\"" + string + "\"";
392069067963cf0117cfb4a1aef99b550b126d9ca92Xia Wang    }
393069067963cf0117cfb4a1aef99b550b126d9ca92Xia Wang
3947fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    @Override
3957fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    protected void onDestroy() {
3967fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        super.onDestroy();
3977fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang
3987fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        //Unregister receiver
3997fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        if (mConnectivityReceiver != null) {
4007fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            unregisterReceiver(mConnectivityReceiver);
4017fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        }
4027fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        if (mWifiReceiver != null) {
4037fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang            unregisterReceiver(mWifiReceiver);
4047fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        }
4057fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang        Log.v(LOG_TAG, "onDestroy, inst=" + Integer.toHexString(hashCode()));
4067fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang    }
4077fb1f674c90eb8f85f1d1ad7dab29ac65c15cb6eXia Wang}
408