13901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt/* 23901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt * Copyright (C) 2008 The Android Open Source Project 33901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt * 43901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt * Licensed under the Apache License, Version 2.0 (the "License"); 53901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt * you may not use this file except in compliance with the License. 63901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt * You may obtain a copy of the License at 73901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt * 83901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt * http://www.apache.org/licenses/LICENSE-2.0 93901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt * 103901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt * Unless required by applicable law or agreed to in writing, software 113901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt * distributed under the License is distributed on an "AS IS" BASIS, 123901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 133901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt * See the License for the specific language governing permissions and 143901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt * limitations under the License. 153901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt */ 163901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt 173901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwaltpackage com.android.settings; 183901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt 1965cff177222560f43b7da367c45ec425e86e9eecIrfan Sheriffimport com.android.settings.wifi.WifiApEnabler; 2084a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasaniimport com.android.settings.wifi.WifiApDialog; 2165cff177222560f43b7da367c45ec425e86e9eecIrfan Sheriff 229c602c47892e7fbe322a449162badeb9def2c4faDaisuke Miyakawaimport android.app.Activity; 23c3c93e5c6226863d09748160a0bfab00aebf0b9dRobert Greenwaltimport android.app.AlertDialog; 240b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriffimport android.app.Dialog; 2532711b6752eb73324e1b10db975ac956888eda96Danica Changimport android.bluetooth.BluetoothAdapter; 2632711b6752eb73324e1b10db975ac956888eda96Danica Changimport android.bluetooth.BluetoothPan; 279ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganeshimport android.bluetooth.BluetoothProfile; 283901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwaltimport android.content.BroadcastReceiver; 293901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwaltimport android.content.Context; 3084a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasaniimport android.content.DialogInterface; 313901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwaltimport android.content.Intent; 323901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwaltimport android.content.IntentFilter; 334c3b2f0cf062b38a6e380cc15ff8dc9abdca518bRobert Greenwaltimport android.content.res.AssetManager; 3469a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwoodimport android.hardware.usb.UsbManager; 353901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwaltimport android.net.ConnectivityManager; 3684a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasaniimport android.net.wifi.WifiConfiguration; 3784a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasaniimport android.net.wifi.WifiManager; 389c602c47892e7fbe322a449162badeb9def2c4faDaisuke Miyakawaimport android.os.Bundle; 3926dad3ecef45ffb75178fc2fe184307089815510Mike Lockwoodimport android.os.Environment; 40209177aac6761db097c53152f6e9543f60748f15Robert Greenwaltimport android.preference.CheckBoxPreference; 413901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwaltimport android.preference.Preference; 423901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwaltimport android.preference.PreferenceScreen; 43aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriffimport android.text.TextUtils; 44476d79566752bfc128a7b3ae200c735d683370f7Amith Yamasaniimport android.view.ViewGroup; 45476d79566752bfc128a7b3ae200c735d683370f7Amith Yamasaniimport android.view.ViewParent; 46c3c93e5c6226863d09748160a0bfab00aebf0b9dRobert Greenwaltimport android.webkit.WebView; 473901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt 484c3b2f0cf062b38a6e380cc15ff8dc9abdca518bRobert Greenwaltimport java.io.InputStream; 49c4764d24837cf297440f0ee97fe8adb943c56fe0Robert Greenwaltimport java.util.ArrayList; 50c3c93e5c6226863d09748160a0bfab00aebf0b9dRobert Greenwaltimport java.util.Locale; 5165cff177222560f43b7da367c45ec425e86e9eecIrfan Sheriff 523901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt/* 533901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt * Displays preferences for Tethering. 543901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt */ 5584a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasanipublic class TetherSettings extends SettingsPreferenceFragment 56aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff implements DialogInterface.OnClickListener, Preference.OnPreferenceChangeListener { 5732711b6752eb73324e1b10db975ac956888eda96Danica Chang 583901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt private static final String USB_TETHER_SETTINGS = "usb_tether_settings"; 5965cff177222560f43b7da367c45ec425e86e9eecIrfan Sheriff private static final String ENABLE_WIFI_AP = "enable_wifi_ap"; 6032711b6752eb73324e1b10db975ac956888eda96Danica Chang private static final String ENABLE_BLUETOOTH_TETHERING = "enable_bluetooth_tethering"; 61c3c93e5c6226863d09748160a0bfab00aebf0b9dRobert Greenwalt private static final String TETHERING_HELP = "tethering_help"; 6238925c0b964b7aef23c8a03af4d1a9499474f1b2Robert Greenwalt private static final String USB_HELP_MODIFIER = "usb_"; 6338925c0b964b7aef23c8a03af4d1a9499474f1b2Robert Greenwalt private static final String WIFI_HELP_MODIFIER = "wifi_"; 644c3b2f0cf062b38a6e380cc15ff8dc9abdca518bRobert Greenwalt private static final String HELP_URL = "file:///android_asset/html/%y%z/tethering_%xhelp.html"; 654c3b2f0cf062b38a6e380cc15ff8dc9abdca518bRobert Greenwalt private static final String HELP_PATH = "html/%y%z/tethering_help.html"; 663901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt 670b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff private static final int DIALOG_TETHER_HELP = 1; 6884a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani private static final int DIALOG_AP_SETTINGS = 2; 690b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff 700b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff private WebView mView; 71209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt private CheckBoxPreference mUsbTether; 723901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt 7365cff177222560f43b7da367c45ec425e86e9eecIrfan Sheriff private WifiApEnabler mWifiApEnabler; 74aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff private CheckBoxPreference mEnableWifiAp; 7532711b6752eb73324e1b10db975ac956888eda96Danica Chang 7632711b6752eb73324e1b10db975ac956888eda96Danica Chang private CheckBoxPreference mBluetoothTether; 7732711b6752eb73324e1b10db975ac956888eda96Danica Chang 78c3c93e5c6226863d09748160a0bfab00aebf0b9dRobert Greenwalt private PreferenceScreen mTetherHelp; 7965cff177222560f43b7da367c45ec425e86e9eecIrfan Sheriff 803901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt private BroadcastReceiver mTetherChangeReceiver; 813901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt 82c4764d24837cf297440f0ee97fe8adb943c56fe0Robert Greenwalt private String[] mUsbRegexs; 83c4764d24837cf297440f0ee97fe8adb943c56fe0Robert Greenwalt 84c4764d24837cf297440f0ee97fe8adb943c56fe0Robert Greenwalt private String[] mWifiRegexs; 85c4764d24837cf297440f0ee97fe8adb943c56fe0Robert Greenwalt 8632711b6752eb73324e1b10db975ac956888eda96Danica Chang private String[] mBluetoothRegexs; 8732711b6752eb73324e1b10db975ac956888eda96Danica Chang private BluetoothPan mBluetoothPan; 8832711b6752eb73324e1b10db975ac956888eda96Danica Chang 8984a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani private static final String WIFI_AP_SSID_AND_SECURITY = "wifi_ap_ssid_and_security"; 9084a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani private static final int CONFIG_SUBTEXT = R.string.wifi_tether_configure_subtext; 9184a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani 9284a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani private String[] mSecurityType; 9384a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani private Preference mCreateNetwork; 9484a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani 9584a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani private WifiApDialog mDialog; 9684a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani private WifiManager mWifiManager; 9784a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani private WifiConfiguration mWifiConfig = null; 9884a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani 9969a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood private boolean mUsbConnected; 10069a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood private boolean mMassStorageActive; 10169a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood 102c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby private boolean mBluetoothEnableForTether; 103c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby 10401b32368fffd944a0265f22db764b689179be94cIrfan Sheriff private static final int INVALID = -1; 10501b32368fffd944a0265f22db764b689179be94cIrfan Sheriff private static final int WIFI_TETHERING = 0; 10601b32368fffd944a0265f22db764b689179be94cIrfan Sheriff private static final int USB_TETHERING = 1; 10701b32368fffd944a0265f22db764b689179be94cIrfan Sheriff private static final int BLUETOOTH_TETHERING = 2; 10801b32368fffd944a0265f22db764b689179be94cIrfan Sheriff 10901b32368fffd944a0265f22db764b689179be94cIrfan Sheriff /* One of INVALID, WIFI_TETHERING, USB_TETHERING or BLUETOOTH_TETHERING */ 11001b32368fffd944a0265f22db764b689179be94cIrfan Sheriff private int mTetherChoice = INVALID; 11101b32368fffd944a0265f22db764b689179be94cIrfan Sheriff 11201b32368fffd944a0265f22db764b689179be94cIrfan Sheriff /* Stores the package name and the class name of the provisioning app */ 11301b32368fffd944a0265f22db764b689179be94cIrfan Sheriff private String[] mProvisionApp; 11401b32368fffd944a0265f22db764b689179be94cIrfan Sheriff private static final int PROVISION_REQUEST = 0; 11501b32368fffd944a0265f22db764b689179be94cIrfan Sheriff 1163901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt @Override 1179c602c47892e7fbe322a449162badeb9def2c4faDaisuke Miyakawa public void onCreate(Bundle icicle) { 1183901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt super.onCreate(icicle); 1193901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt addPreferencesFromResource(R.xml.tether_prefs); 120476d79566752bfc128a7b3ae200c735d683370f7Amith Yamasani 1219c602c47892e7fbe322a449162badeb9def2c4faDaisuke Miyakawa final Activity activity = getActivity(); 1229ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganesh BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 1239ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganesh if (adapter != null) { 1249ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganesh adapter.getProfileProxy(activity.getApplicationContext(), mProfileServiceListener, 1259ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganesh BluetoothProfile.PAN); 1269ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganesh } 1279ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganesh 128aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff mEnableWifiAp = 129436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby (CheckBoxPreference) findPreference(ENABLE_WIFI_AP); 1300f47465a3f73a4f013ec7958efec95ecbb848ba8Amith Yamasani Preference wifiApSettings = findPreference(WIFI_AP_SSID_AND_SECURITY); 131209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt mUsbTether = (CheckBoxPreference) findPreference(USB_TETHER_SETTINGS); 13232711b6752eb73324e1b10db975ac956888eda96Danica Chang mBluetoothTether = (CheckBoxPreference) findPreference(ENABLE_BLUETOOTH_TETHERING); 133c3c93e5c6226863d09748160a0bfab00aebf0b9dRobert Greenwalt mTetherHelp = (PreferenceScreen) findPreference(TETHERING_HELP); 134c4764d24837cf297440f0ee97fe8adb943c56fe0Robert Greenwalt 135c4764d24837cf297440f0ee97fe8adb943c56fe0Robert Greenwalt ConnectivityManager cm = 136c4764d24837cf297440f0ee97fe8adb943c56fe0Robert Greenwalt (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); 13747ebb7895457160c88592248a2e9049c14e2b625Irfan Sheriff 138c4764d24837cf297440f0ee97fe8adb943c56fe0Robert Greenwalt mUsbRegexs = cm.getTetherableUsbRegexs(); 13932711b6752eb73324e1b10db975ac956888eda96Danica Chang mWifiRegexs = cm.getTetherableWifiRegexs(); 14032711b6752eb73324e1b10db975ac956888eda96Danica Chang mBluetoothRegexs = cm.getTetherableBluetoothRegexs(); 141e434bfb216682a6ca331fa54ce58a2bff7adf8d7Robert Greenwalt 142e419bc1bed37d0584b32f0c0d54ecd9b9e1ea212Amith Yamasani final boolean usbAvailable = mUsbRegexs.length != 0; 143e419bc1bed37d0584b32f0c0d54ecd9b9e1ea212Amith Yamasani final boolean wifiAvailable = mWifiRegexs.length != 0; 144e419bc1bed37d0584b32f0c0d54ecd9b9e1ea212Amith Yamasani final boolean bluetoothAvailable = mBluetoothRegexs.length != 0; 14565cff177222560f43b7da367c45ec425e86e9eecIrfan Sheriff 14632711b6752eb73324e1b10db975ac956888eda96Danica Chang if (!usbAvailable || Utils.isMonkeyRunning()) { 14732711b6752eb73324e1b10db975ac956888eda96Danica Chang getPreferenceScreen().removePreference(mUsbTether); 14832711b6752eb73324e1b10db975ac956888eda96Danica Chang } 149e419bc1bed37d0584b32f0c0d54ecd9b9e1ea212Amith Yamasani 1500f47465a3f73a4f013ec7958efec95ecbb848ba8Amith Yamasani if (wifiAvailable) { 151aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff mWifiApEnabler = new WifiApEnabler(activity, mEnableWifiAp); 1520f47465a3f73a4f013ec7958efec95ecbb848ba8Amith Yamasani initWifiTethering(); 1530f47465a3f73a4f013ec7958efec95ecbb848ba8Amith Yamasani } else { 154aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff getPreferenceScreen().removePreference(mEnableWifiAp); 155436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby getPreferenceScreen().removePreference(wifiApSettings); 15632711b6752eb73324e1b10db975ac956888eda96Danica Chang } 157e419bc1bed37d0584b32f0c0d54ecd9b9e1ea212Amith Yamasani 15832711b6752eb73324e1b10db975ac956888eda96Danica Chang if (!bluetoothAvailable) { 15932711b6752eb73324e1b10db975ac956888eda96Danica Chang getPreferenceScreen().removePreference(mBluetoothTether); 16032711b6752eb73324e1b10db975ac956888eda96Danica Chang } else { 1619ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganesh if (mBluetoothPan != null && mBluetoothPan.isTetheringOn()) { 16232711b6752eb73324e1b10db975ac956888eda96Danica Chang mBluetoothTether.setChecked(true); 16332711b6752eb73324e1b10db975ac956888eda96Danica Chang } else { 16432711b6752eb73324e1b10db975ac956888eda96Danica Chang mBluetoothTether.setChecked(false); 16532711b6752eb73324e1b10db975ac956888eda96Danica Chang } 16632711b6752eb73324e1b10db975ac956888eda96Danica Chang } 167e419bc1bed37d0584b32f0c0d54ecd9b9e1ea212Amith Yamasani 16801b32368fffd944a0265f22db764b689179be94cIrfan Sheriff mProvisionApp = getResources().getStringArray( 16901b32368fffd944a0265f22db764b689179be94cIrfan Sheriff com.android.internal.R.array.config_mobile_hotspot_provision_app); 17001b32368fffd944a0265f22db764b689179be94cIrfan Sheriff 1719c602c47892e7fbe322a449162badeb9def2c4faDaisuke Miyakawa mView = new WebView(activity); 17284a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani } 17384a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani 17484a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani private void initWifiTethering() { 17584a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani final Activity activity = getActivity(); 17684a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); 17784a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani mWifiConfig = mWifiManager.getWifiApConfiguration(); 17884a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani mSecurityType = getResources().getStringArray(R.array.wifi_ap_security); 17984a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani 18084a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani mCreateNetwork = findPreference(WIFI_AP_SSID_AND_SECURITY); 18184a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani 18284a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani if (mWifiConfig == null) { 18384a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani final String s = activity.getString( 18484a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani com.android.internal.R.string.wifi_tether_configure_ssid_default); 18584a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani mCreateNetwork.setSummary(String.format(activity.getString(CONFIG_SUBTEXT), 18684a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani s, mSecurityType[WifiApDialog.OPEN_INDEX])); 18784a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani } else { 18884a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani int index = WifiApDialog.getSecurityTypeIndex(mWifiConfig); 18984a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani mCreateNetwork.setSummary(String.format(activity.getString(CONFIG_SUBTEXT), 19084a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani mWifiConfig.SSID, 19184a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani mSecurityType[index])); 19284a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani } 1933901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt } 1943901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt 1959ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganesh private BluetoothProfile.ServiceListener mProfileServiceListener = 1969ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganesh new BluetoothProfile.ServiceListener() { 1979ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganesh public void onServiceConnected(int profile, BluetoothProfile proxy) { 1989ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganesh mBluetoothPan = (BluetoothPan) proxy; 1999ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganesh } 2009ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganesh public void onServiceDisconnected(int profile) { 2019ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganesh mBluetoothPan = null; 2029ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganesh } 2039ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganesh }; 2049ad703cdb9a8d0972c123b041d18aa7bbeb391a4Jaikumar Ganesh 2050b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff @Override 2069c602c47892e7fbe322a449162badeb9def2c4faDaisuke Miyakawa public Dialog onCreateDialog(int id) { 2070b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff if (id == DIALOG_TETHER_HELP) { 2080b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff Locale locale = Locale.getDefault(); 2090b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff 2104c3b2f0cf062b38a6e380cc15ff8dc9abdca518bRobert Greenwalt // check for the full language + country resource, if not there, try just language 2119c602c47892e7fbe322a449162badeb9def2c4faDaisuke Miyakawa final AssetManager am = getActivity().getAssets(); 2124c3b2f0cf062b38a6e380cc15ff8dc9abdca518bRobert Greenwalt String path = HELP_PATH.replace("%y", locale.getLanguage().toLowerCase()); 213436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby path = path.replace("%z", '_'+locale.getCountry().toLowerCase()); 2144c3b2f0cf062b38a6e380cc15ff8dc9abdca518bRobert Greenwalt boolean useCountry = true; 2154c3b2f0cf062b38a6e380cc15ff8dc9abdca518bRobert Greenwalt InputStream is = null; 2164c3b2f0cf062b38a6e380cc15ff8dc9abdca518bRobert Greenwalt try { 2174c3b2f0cf062b38a6e380cc15ff8dc9abdca518bRobert Greenwalt is = am.open(path); 218436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } catch (Exception ignored) { 2194c3b2f0cf062b38a6e380cc15ff8dc9abdca518bRobert Greenwalt useCountry = false; 2204c3b2f0cf062b38a6e380cc15ff8dc9abdca518bRobert Greenwalt } finally { 2214c3b2f0cf062b38a6e380cc15ff8dc9abdca518bRobert Greenwalt if (is != null) { 2224c3b2f0cf062b38a6e380cc15ff8dc9abdca518bRobert Greenwalt try { 2234c3b2f0cf062b38a6e380cc15ff8dc9abdca518bRobert Greenwalt is.close(); 224436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby } catch (Exception ignored) {} 2254c3b2f0cf062b38a6e380cc15ff8dc9abdca518bRobert Greenwalt } 2264c3b2f0cf062b38a6e380cc15ff8dc9abdca518bRobert Greenwalt } 2274c3b2f0cf062b38a6e380cc15ff8dc9abdca518bRobert Greenwalt String url = HELP_URL.replace("%y", locale.getLanguage().toLowerCase()); 228436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby url = url.replace("%z", useCountry ? '_'+locale.getCountry().toLowerCase() : ""); 2290b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff if ((mUsbRegexs.length != 0) && (mWifiRegexs.length == 0)) { 2300b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff url = url.replace("%x", USB_HELP_MODIFIER); 2310b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff } else if ((mWifiRegexs.length != 0) && (mUsbRegexs.length == 0)) { 2320b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff url = url.replace("%x", WIFI_HELP_MODIFIER); 2330b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff } else { 2340b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff // could assert that both wifi and usb have regexs, but the default 2350b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff // is to use this anyway so no check is needed 2360b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff url = url.replace("%x", ""); 2370b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff } 2384c3b2f0cf062b38a6e380cc15ff8dc9abdca518bRobert Greenwalt 2390b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff mView.loadUrl(url); 240476d79566752bfc128a7b3ae200c735d683370f7Amith Yamasani // Detach from old parent first 241476d79566752bfc128a7b3ae200c735d683370f7Amith Yamasani ViewParent parent = mView.getParent(); 242476d79566752bfc128a7b3ae200c735d683370f7Amith Yamasani if (parent != null && parent instanceof ViewGroup) { 243476d79566752bfc128a7b3ae200c735d683370f7Amith Yamasani ((ViewGroup) parent).removeView(mView); 244476d79566752bfc128a7b3ae200c735d683370f7Amith Yamasani } 2459c602c47892e7fbe322a449162badeb9def2c4faDaisuke Miyakawa return new AlertDialog.Builder(getActivity()) 2460b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff .setCancelable(true) 2470b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff .setTitle(R.string.tethering_help_button_text) 2480b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff .setView(mView) 2490b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff .create(); 25084a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani } else if (id == DIALOG_AP_SETTINGS) { 25184a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani final Activity activity = getActivity(); 25284a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani mDialog = new WifiApDialog(activity, this, mWifiConfig); 25384a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani return mDialog; 2540b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff } 25584a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani 2560b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff return null; 2570b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff } 258c4764d24837cf297440f0ee97fe8adb943c56fe0Robert Greenwalt 2593901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt private class TetherChangeReceiver extends BroadcastReceiver { 26032711b6752eb73324e1b10db975ac956888eda96Danica Chang @Override 2613901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt public void onReceive(Context content, Intent intent) { 262c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby String action = intent.getAction(); 263c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby if (action.equals(ConnectivityManager.ACTION_TETHER_STATE_CHANGED)) { 264a2488762a7c80eb4a22a4dd018c916784526bba4Robert Greenwalt // TODO - this should understand the interface types 265a2488762a7c80eb4a22a4dd018c916784526bba4Robert Greenwalt ArrayList<String> available = intent.getStringArrayListExtra( 266a2488762a7c80eb4a22a4dd018c916784526bba4Robert Greenwalt ConnectivityManager.EXTRA_AVAILABLE_TETHER); 267a2488762a7c80eb4a22a4dd018c916784526bba4Robert Greenwalt ArrayList<String> active = intent.getStringArrayListExtra( 268a2488762a7c80eb4a22a4dd018c916784526bba4Robert Greenwalt ConnectivityManager.EXTRA_ACTIVE_TETHER); 269a2488762a7c80eb4a22a4dd018c916784526bba4Robert Greenwalt ArrayList<String> errored = intent.getStringArrayListExtra( 270a2488762a7c80eb4a22a4dd018c916784526bba4Robert Greenwalt ConnectivityManager.EXTRA_ERRORED_TETHER); 27132711b6752eb73324e1b10db975ac956888eda96Danica Chang updateState(available.toArray(new String[available.size()]), 27232711b6752eb73324e1b10db975ac956888eda96Danica Chang active.toArray(new String[active.size()]), 27332711b6752eb73324e1b10db975ac956888eda96Danica Chang errored.toArray(new String[errored.size()])); 27469a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood } else if (action.equals(Intent.ACTION_MEDIA_SHARED)) { 27569a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood mMassStorageActive = true; 27669a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood updateState(); 27769a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood } else if (action.equals(Intent.ACTION_MEDIA_UNSHARED)) { 27869a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood mMassStorageActive = false; 27969a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood updateState(); 28069a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood } else if (action.equals(UsbManager.ACTION_USB_STATE)) { 28169a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood mUsbConnected = intent.getBooleanExtra(UsbManager.USB_CONNECTED, false); 282a2488762a7c80eb4a22a4dd018c916784526bba4Robert Greenwalt updateState(); 283c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } else if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) { 284c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby if (mBluetoothEnableForTether) { 285c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby switch (intent 286c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby .getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) { 287c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby case BluetoothAdapter.STATE_ON: 288c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mBluetoothPan.setBluetoothTethering(true); 289c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mBluetoothEnableForTether = false; 290c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby break; 291c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby 292c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby case BluetoothAdapter.STATE_OFF: 293c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby case BluetoothAdapter.ERROR: 294c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mBluetoothEnableForTether = false; 295c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby break; 296c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby 297c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby default: 298c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby // ignore transition states 299c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } 300c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } 30132711b6752eb73324e1b10db975ac956888eda96Danica Chang updateState(); 302a2488762a7c80eb4a22a4dd018c916784526bba4Robert Greenwalt } 3033901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt } 3043901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt } 3053901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt 3063901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt @Override 30702cf71a5916d1b0155e8fff3f62987cdc5c2b7c3Amith Yamasani public void onStart() { 30802cf71a5916d1b0155e8fff3f62987cdc5c2b7c3Amith Yamasani super.onStart(); 3093901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt 3109c602c47892e7fbe322a449162badeb9def2c4faDaisuke Miyakawa final Activity activity = getActivity(); 3119c602c47892e7fbe322a449162badeb9def2c4faDaisuke Miyakawa 31269a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood mMassStorageActive = Environment.MEDIA_SHARED.equals(Environment.getExternalStorageState()); 3133901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt mTetherChangeReceiver = new TetherChangeReceiver(); 31432711b6752eb73324e1b10db975ac956888eda96Danica Chang IntentFilter filter = new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED); 3159c602c47892e7fbe322a449162badeb9def2c4faDaisuke Miyakawa Intent intent = activity.registerReceiver(mTetherChangeReceiver, filter); 3163901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt 317f0ed2f3f3175457825a0b49cab72f9cb78c3b997Robert Greenwalt filter = new IntentFilter(); 31869a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood filter.addAction(UsbManager.ACTION_USB_STATE); 31969a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood activity.registerReceiver(mTetherChangeReceiver, filter); 32069a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood 32169a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood filter = new IntentFilter(); 322f0ed2f3f3175457825a0b49cab72f9cb78c3b997Robert Greenwalt filter.addAction(Intent.ACTION_MEDIA_SHARED); 323f0ed2f3f3175457825a0b49cab72f9cb78c3b997Robert Greenwalt filter.addAction(Intent.ACTION_MEDIA_UNSHARED); 324f0ed2f3f3175457825a0b49cab72f9cb78c3b997Robert Greenwalt filter.addDataScheme("file"); 3259c602c47892e7fbe322a449162badeb9def2c4faDaisuke Miyakawa activity.registerReceiver(mTetherChangeReceiver, filter); 326f0ed2f3f3175457825a0b49cab72f9cb78c3b997Robert Greenwalt 32732711b6752eb73324e1b10db975ac956888eda96Danica Chang filter = new IntentFilter(); 32832711b6752eb73324e1b10db975ac956888eda96Danica Chang filter.addAction(BluetoothAdapter.ACTION_STATE_CHANGED); 3299c602c47892e7fbe322a449162badeb9def2c4faDaisuke Miyakawa activity.registerReceiver(mTetherChangeReceiver, filter); 33032711b6752eb73324e1b10db975ac956888eda96Danica Chang 3319c602c47892e7fbe322a449162badeb9def2c4faDaisuke Miyakawa if (intent != null) mTetherChangeReceiver.onReceive(activity, intent); 3320f47465a3f73a4f013ec7958efec95ecbb848ba8Amith Yamasani if (mWifiApEnabler != null) { 333aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff mEnableWifiAp.setOnPreferenceChangeListener(this); 3340f47465a3f73a4f013ec7958efec95ecbb848ba8Amith Yamasani mWifiApEnabler.resume(); 3350f47465a3f73a4f013ec7958efec95ecbb848ba8Amith Yamasani } 336c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby 337c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby updateState(); 3383901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt } 3393901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt 3403901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt @Override 34102cf71a5916d1b0155e8fff3f62987cdc5c2b7c3Amith Yamasani public void onStop() { 34202cf71a5916d1b0155e8fff3f62987cdc5c2b7c3Amith Yamasani super.onStop(); 3439c602c47892e7fbe322a449162badeb9def2c4faDaisuke Miyakawa getActivity().unregisterReceiver(mTetherChangeReceiver); 3443901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt mTetherChangeReceiver = null; 3450f47465a3f73a4f013ec7958efec95ecbb848ba8Amith Yamasani if (mWifiApEnabler != null) { 346aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff mEnableWifiAp.setOnPreferenceChangeListener(null); 3470f47465a3f73a4f013ec7958efec95ecbb848ba8Amith Yamasani mWifiApEnabler.pause(); 3480f47465a3f73a4f013ec7958efec95ecbb848ba8Amith Yamasani } 3493901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt } 3503901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt 351209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt private void updateState() { 352209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt ConnectivityManager cm = 353209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); 354209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt 355209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt String[] available = cm.getTetherableIfaces(); 356209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt String[] tethered = cm.getTetheredIfaces(); 357209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt String[] errored = cm.getTetheringErroredIfaces(); 358209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt updateState(available, tethered, errored); 359209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt } 360209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt 3610008d219a2964218477d5bd5f28a848844063c44Ben Clark private void updateState(String[] available, String[] tethered, 3620008d219a2964218477d5bd5f28a848844063c44Ben Clark String[] errored) { 36332711b6752eb73324e1b10db975ac956888eda96Danica Chang updateUsbState(available, tethered, errored); 36432711b6752eb73324e1b10db975ac956888eda96Danica Chang updateBluetoothState(available, tethered, errored); 36532711b6752eb73324e1b10db975ac956888eda96Danica Chang } 36632711b6752eb73324e1b10db975ac956888eda96Danica Chang 36732711b6752eb73324e1b10db975ac956888eda96Danica Chang 36832711b6752eb73324e1b10db975ac956888eda96Danica Chang private void updateUsbState(String[] available, String[] tethered, 36932711b6752eb73324e1b10db975ac956888eda96Danica Chang String[] errored) { 370209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt ConnectivityManager cm = 371209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); 37269a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood boolean usbAvailable = mUsbConnected && !mMassStorageActive; 373209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt int usbError = ConnectivityManager.TETHER_ERROR_NO_ERROR; 3740008d219a2964218477d5bd5f28a848844063c44Ben Clark for (String s : available) { 375c4764d24837cf297440f0ee97fe8adb943c56fe0Robert Greenwalt for (String regex : mUsbRegexs) { 376209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt if (s.matches(regex)) { 377209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt if (usbError == ConnectivityManager.TETHER_ERROR_NO_ERROR) { 378209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt usbError = cm.getLastTetherError(s); 379209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt } 380209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt } 381c4764d24837cf297440f0ee97fe8adb943c56fe0Robert Greenwalt } 382c4764d24837cf297440f0ee97fe8adb943c56fe0Robert Greenwalt } 383436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean usbTethered = false; 3840008d219a2964218477d5bd5f28a848844063c44Ben Clark for (String s : tethered) { 385c4764d24837cf297440f0ee97fe8adb943c56fe0Robert Greenwalt for (String regex : mUsbRegexs) { 386c4764d24837cf297440f0ee97fe8adb943c56fe0Robert Greenwalt if (s.matches(regex)) usbTethered = true; 387c4764d24837cf297440f0ee97fe8adb943c56fe0Robert Greenwalt } 388c4764d24837cf297440f0ee97fe8adb943c56fe0Robert Greenwalt } 389436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean usbErrored = false; 3900008d219a2964218477d5bd5f28a848844063c44Ben Clark for (String s: errored) { 391d5f121c66ab83f5304fca37c14ac519fcd530fb8Robert Greenwalt for (String regex : mUsbRegexs) { 392d5f121c66ab83f5304fca37c14ac519fcd530fb8Robert Greenwalt if (s.matches(regex)) usbErrored = true; 393d5f121c66ab83f5304fca37c14ac519fcd530fb8Robert Greenwalt } 394d5f121c66ab83f5304fca37c14ac519fcd530fb8Robert Greenwalt } 395c4764d24837cf297440f0ee97fe8adb943c56fe0Robert Greenwalt 396c4764d24837cf297440f0ee97fe8adb943c56fe0Robert Greenwalt if (usbTethered) { 3973901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt mUsbTether.setSummary(R.string.usb_tethering_active_subtext); 3983901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt mUsbTether.setEnabled(true); 399204e7c1a6ed3ad9c89e6e10fc59fc8551817c2beRobert Greenwalt mUsbTether.setChecked(true); 400c4764d24837cf297440f0ee97fe8adb943c56fe0Robert Greenwalt } else if (usbAvailable) { 401209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt if (usbError == ConnectivityManager.TETHER_ERROR_NO_ERROR) { 402209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt mUsbTether.setSummary(R.string.usb_tethering_available_subtext); 403209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt } else { 404209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt mUsbTether.setSummary(R.string.usb_tethering_errored_subtext); 405209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt } 4063901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt mUsbTether.setEnabled(true); 407204e7c1a6ed3ad9c89e6e10fc59fc8551817c2beRobert Greenwalt mUsbTether.setChecked(false); 408d5f121c66ab83f5304fca37c14ac519fcd530fb8Robert Greenwalt } else if (usbErrored) { 409d5f121c66ab83f5304fca37c14ac519fcd530fb8Robert Greenwalt mUsbTether.setSummary(R.string.usb_tethering_errored_subtext); 410d5f121c66ab83f5304fca37c14ac519fcd530fb8Robert Greenwalt mUsbTether.setEnabled(false); 411204e7c1a6ed3ad9c89e6e10fc59fc8551817c2beRobert Greenwalt mUsbTether.setChecked(false); 41269a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood } else if (mMassStorageActive) { 413a2488762a7c80eb4a22a4dd018c916784526bba4Robert Greenwalt mUsbTether.setSummary(R.string.usb_tethering_storage_active_subtext); 414a2488762a7c80eb4a22a4dd018c916784526bba4Robert Greenwalt mUsbTether.setEnabled(false); 415a2488762a7c80eb4a22a4dd018c916784526bba4Robert Greenwalt mUsbTether.setChecked(false); 4163901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt } else { 4173901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt mUsbTether.setSummary(R.string.usb_tethering_unavailable_subtext); 4183901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt mUsbTether.setEnabled(false); 419204e7c1a6ed3ad9c89e6e10fc59fc8551817c2beRobert Greenwalt mUsbTether.setChecked(false); 4203901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt } 4213901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt } 422209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt 42332711b6752eb73324e1b10db975ac956888eda96Danica Chang private void updateBluetoothState(String[] available, String[] tethered, 42432711b6752eb73324e1b10db975ac956888eda96Danica Chang String[] errored) { 425c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby int bluetoothTethered = 0; 42632711b6752eb73324e1b10db975ac956888eda96Danica Chang for (String s : tethered) { 42732711b6752eb73324e1b10db975ac956888eda96Danica Chang for (String regex : mBluetoothRegexs) { 428c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby if (s.matches(regex)) bluetoothTethered++; 42932711b6752eb73324e1b10db975ac956888eda96Danica Chang } 43032711b6752eb73324e1b10db975ac956888eda96Danica Chang } 431436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby boolean bluetoothErrored = false; 43232711b6752eb73324e1b10db975ac956888eda96Danica Chang for (String s: errored) { 43332711b6752eb73324e1b10db975ac956888eda96Danica Chang for (String regex : mBluetoothRegexs) { 43432711b6752eb73324e1b10db975ac956888eda96Danica Chang if (s.matches(regex)) bluetoothErrored = true; 43532711b6752eb73324e1b10db975ac956888eda96Danica Chang } 43632711b6752eb73324e1b10db975ac956888eda96Danica Chang } 43732711b6752eb73324e1b10db975ac956888eda96Danica Chang 43832711b6752eb73324e1b10db975ac956888eda96Danica Chang BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 43932711b6752eb73324e1b10db975ac956888eda96Danica Chang int btState = adapter.getState(); 44032711b6752eb73324e1b10db975ac956888eda96Danica Chang if (btState == BluetoothAdapter.STATE_TURNING_OFF) { 44132711b6752eb73324e1b10db975ac956888eda96Danica Chang mBluetoothTether.setEnabled(false); 44232711b6752eb73324e1b10db975ac956888eda96Danica Chang mBluetoothTether.setSummary(R.string.wifi_stopping); 44332711b6752eb73324e1b10db975ac956888eda96Danica Chang } else if (btState == BluetoothAdapter.STATE_TURNING_ON) { 44432711b6752eb73324e1b10db975ac956888eda96Danica Chang mBluetoothTether.setEnabled(false); 44532711b6752eb73324e1b10db975ac956888eda96Danica Chang mBluetoothTether.setSummary(R.string.bluetooth_turning_on); 446c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } else if (btState == BluetoothAdapter.STATE_ON && mBluetoothPan.isTetheringOn()) { 44732711b6752eb73324e1b10db975ac956888eda96Danica Chang mBluetoothTether.setChecked(true); 448c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mBluetoothTether.setEnabled(true); 449c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby if (bluetoothTethered > 1) { 450c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby String summary = getString( 451c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby R.string.bluetooth_tethering_devices_connected_subtext, bluetoothTethered); 452c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mBluetoothTether.setSummary(summary); 453c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } else if (bluetoothTethered == 1) { 454c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mBluetoothTether.setSummary(R.string.bluetooth_tethering_device_connected_subtext); 455c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } else if (bluetoothErrored) { 456c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mBluetoothTether.setSummary(R.string.bluetooth_tethering_errored_subtext); 457c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } else { 458c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby mBluetoothTether.setSummary(R.string.bluetooth_tethering_available_subtext); 45932711b6752eb73324e1b10db975ac956888eda96Danica Chang } 46032711b6752eb73324e1b10db975ac956888eda96Danica Chang } else { 46132711b6752eb73324e1b10db975ac956888eda96Danica Chang mBluetoothTether.setEnabled(true); 46232711b6752eb73324e1b10db975ac956888eda96Danica Chang mBluetoothTether.setChecked(false); 46332711b6752eb73324e1b10db975ac956888eda96Danica Chang mBluetoothTether.setSummary(R.string.bluetooth_tethering_off_subtext); 46432711b6752eb73324e1b10db975ac956888eda96Danica Chang } 46532711b6752eb73324e1b10db975ac956888eda96Danica Chang } 46632711b6752eb73324e1b10db975ac956888eda96Danica Chang 467aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff public boolean onPreferenceChange(Preference preference, Object value) { 468aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff boolean enable = (Boolean) value; 469aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff 470aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff if (enable) { 47101b32368fffd944a0265f22db764b689179be94cIrfan Sheriff startProvisioningIfNecessary(WIFI_TETHERING); 472aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff } else { 473aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff mWifiApEnabler.setSoftapEnabled(false); 474aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff } 475aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff return false; 476aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff } 477aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff 47801b32368fffd944a0265f22db764b689179be94cIrfan Sheriff boolean isProvisioningNeeded() { 47901b32368fffd944a0265f22db764b689179be94cIrfan Sheriff return mProvisionApp.length == 2; 48001b32368fffd944a0265f22db764b689179be94cIrfan Sheriff } 48101b32368fffd944a0265f22db764b689179be94cIrfan Sheriff 48201b32368fffd944a0265f22db764b689179be94cIrfan Sheriff private void startProvisioningIfNecessary(int choice) { 48301b32368fffd944a0265f22db764b689179be94cIrfan Sheriff mTetherChoice = choice; 48401b32368fffd944a0265f22db764b689179be94cIrfan Sheriff if (isProvisioningNeeded()) { 48501b32368fffd944a0265f22db764b689179be94cIrfan Sheriff Intent intent = new Intent(Intent.ACTION_MAIN); 48601b32368fffd944a0265f22db764b689179be94cIrfan Sheriff intent.setClassName(mProvisionApp[0], mProvisionApp[1]); 48701b32368fffd944a0265f22db764b689179be94cIrfan Sheriff startActivityForResult(intent, PROVISION_REQUEST); 48801b32368fffd944a0265f22db764b689179be94cIrfan Sheriff } else { 48901b32368fffd944a0265f22db764b689179be94cIrfan Sheriff startTethering(); 49001b32368fffd944a0265f22db764b689179be94cIrfan Sheriff } 49101b32368fffd944a0265f22db764b689179be94cIrfan Sheriff } 49201b32368fffd944a0265f22db764b689179be94cIrfan Sheriff 493aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff public void onActivityResult(int requestCode, int resultCode, Intent intent) { 494aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff super.onActivityResult(requestCode, resultCode, intent); 49501b32368fffd944a0265f22db764b689179be94cIrfan Sheriff if (requestCode == PROVISION_REQUEST) { 496aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff if (resultCode == Activity.RESULT_OK) { 49701b32368fffd944a0265f22db764b689179be94cIrfan Sheriff startTethering(); 49801b32368fffd944a0265f22db764b689179be94cIrfan Sheriff } else { 49901b32368fffd944a0265f22db764b689179be94cIrfan Sheriff //BT and USB need checkbox turned off on failure 50001b32368fffd944a0265f22db764b689179be94cIrfan Sheriff //Wifi tethering is never turned on until afterwards 50101b32368fffd944a0265f22db764b689179be94cIrfan Sheriff switch (mTetherChoice) { 50201b32368fffd944a0265f22db764b689179be94cIrfan Sheriff case BLUETOOTH_TETHERING: 50301b32368fffd944a0265f22db764b689179be94cIrfan Sheriff mBluetoothTether.setChecked(false); 50401b32368fffd944a0265f22db764b689179be94cIrfan Sheriff break; 50501b32368fffd944a0265f22db764b689179be94cIrfan Sheriff case USB_TETHERING: 50601b32368fffd944a0265f22db764b689179be94cIrfan Sheriff mUsbTether.setChecked(false); 50701b32368fffd944a0265f22db764b689179be94cIrfan Sheriff break; 50801b32368fffd944a0265f22db764b689179be94cIrfan Sheriff } 50901b32368fffd944a0265f22db764b689179be94cIrfan Sheriff mTetherChoice = INVALID; 510aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff } 511aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff } 512aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff } 513aa3d2c406ed0af9bf6890e9984e6b2c1be8cbd99Irfan Sheriff 51401b32368fffd944a0265f22db764b689179be94cIrfan Sheriff private void startTethering() { 51501b32368fffd944a0265f22db764b689179be94cIrfan Sheriff switch (mTetherChoice) { 51601b32368fffd944a0265f22db764b689179be94cIrfan Sheriff case WIFI_TETHERING: 51701b32368fffd944a0265f22db764b689179be94cIrfan Sheriff mWifiApEnabler.setSoftapEnabled(true); 51801b32368fffd944a0265f22db764b689179be94cIrfan Sheriff break; 51901b32368fffd944a0265f22db764b689179be94cIrfan Sheriff case BLUETOOTH_TETHERING: 52001b32368fffd944a0265f22db764b689179be94cIrfan Sheriff // turn on Bluetooth first 52101b32368fffd944a0265f22db764b689179be94cIrfan Sheriff BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); 52201b32368fffd944a0265f22db764b689179be94cIrfan Sheriff if (adapter.getState() == BluetoothAdapter.STATE_OFF) { 52301b32368fffd944a0265f22db764b689179be94cIrfan Sheriff mBluetoothEnableForTether = true; 52401b32368fffd944a0265f22db764b689179be94cIrfan Sheriff adapter.enable(); 52501b32368fffd944a0265f22db764b689179be94cIrfan Sheriff mBluetoothTether.setSummary(R.string.bluetooth_turning_on); 52601b32368fffd944a0265f22db764b689179be94cIrfan Sheriff mBluetoothTether.setEnabled(false); 52701b32368fffd944a0265f22db764b689179be94cIrfan Sheriff } else { 52801b32368fffd944a0265f22db764b689179be94cIrfan Sheriff mBluetoothPan.setBluetoothTethering(true); 52901b32368fffd944a0265f22db764b689179be94cIrfan Sheriff mBluetoothTether.setSummary(R.string.bluetooth_tethering_available_subtext); 53001b32368fffd944a0265f22db764b689179be94cIrfan Sheriff } 53101b32368fffd944a0265f22db764b689179be94cIrfan Sheriff break; 53201b32368fffd944a0265f22db764b689179be94cIrfan Sheriff case USB_TETHERING: 53301b32368fffd944a0265f22db764b689179be94cIrfan Sheriff setUsbTethering(true); 53401b32368fffd944a0265f22db764b689179be94cIrfan Sheriff break; 53501b32368fffd944a0265f22db764b689179be94cIrfan Sheriff default: 53601b32368fffd944a0265f22db764b689179be94cIrfan Sheriff //should not happen 53701b32368fffd944a0265f22db764b689179be94cIrfan Sheriff break; 53801b32368fffd944a0265f22db764b689179be94cIrfan Sheriff } 53901b32368fffd944a0265f22db764b689179be94cIrfan Sheriff } 54001b32368fffd944a0265f22db764b689179be94cIrfan Sheriff 54101b32368fffd944a0265f22db764b689179be94cIrfan Sheriff private void setUsbTethering(boolean enabled) { 54201b32368fffd944a0265f22db764b689179be94cIrfan Sheriff ConnectivityManager cm = 54301b32368fffd944a0265f22db764b689179be94cIrfan Sheriff (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); 54401b32368fffd944a0265f22db764b689179be94cIrfan Sheriff if (cm.setUsbTethering(enabled) != ConnectivityManager.TETHER_ERROR_NO_ERROR) { 54501b32368fffd944a0265f22db764b689179be94cIrfan Sheriff mUsbTether.setChecked(false); 54601b32368fffd944a0265f22db764b689179be94cIrfan Sheriff mUsbTether.setSummary(R.string.usb_tethering_errored_subtext); 54701b32368fffd944a0265f22db764b689179be94cIrfan Sheriff return; 54801b32368fffd944a0265f22db764b689179be94cIrfan Sheriff } 54901b32368fffd944a0265f22db764b689179be94cIrfan Sheriff mUsbTether.setSummary(""); 55001b32368fffd944a0265f22db764b689179be94cIrfan Sheriff } 55101b32368fffd944a0265f22db764b689179be94cIrfan Sheriff 552209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt @Override 5536ebf8619d7f09e9642aed84310b56d9847eead94Daisuke Miyakawa public boolean onPreferenceTreeClick(PreferenceScreen screen, Preference preference) { 55469a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood ConnectivityManager cm = 55569a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); 55669a09577179cc96cd90f724ad330ddde13f9eed6Mike Lockwood 557209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt if (preference == mUsbTether) { 558209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt boolean newState = mUsbTether.isChecked(); 559209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt 56001b32368fffd944a0265f22db764b689179be94cIrfan Sheriff if (newState) { 56101b32368fffd944a0265f22db764b689179be94cIrfan Sheriff startProvisioningIfNecessary(USB_TETHERING); 56201b32368fffd944a0265f22db764b689179be94cIrfan Sheriff } else { 56301b32368fffd944a0265f22db764b689179be94cIrfan Sheriff setUsbTethering(newState); 564209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt } 565c777ee29c856e1d1a2a61ccd799b6e18b50febdcJake Hamby } else if (preference == mBluetoothTether) { 56632711b6752eb73324e1b10db975ac956888eda96Danica Chang boolean bluetoothTetherState = mBluetoothTether.isChecked(); 56732711b6752eb73324e1b10db975ac956888eda96Danica Chang 56832711b6752eb73324e1b10db975ac956888eda96Danica Chang if (bluetoothTetherState) { 56901b32368fffd944a0265f22db764b689179be94cIrfan Sheriff startProvisioningIfNecessary(BLUETOOTH_TETHERING); 57032711b6752eb73324e1b10db975ac956888eda96Danica Chang } else { 57132711b6752eb73324e1b10db975ac956888eda96Danica Chang boolean errored = false; 57238925c0b964b7aef23c8a03af4d1a9499474f1b2Robert Greenwalt 57332711b6752eb73324e1b10db975ac956888eda96Danica Chang String [] tethered = cm.getTetheredIfaces(); 57432711b6752eb73324e1b10db975ac956888eda96Danica Chang String bluetoothIface = findIface(tethered, mBluetoothRegexs); 57532711b6752eb73324e1b10db975ac956888eda96Danica Chang if (bluetoothIface != null && 57632711b6752eb73324e1b10db975ac956888eda96Danica Chang cm.untether(bluetoothIface) != ConnectivityManager.TETHER_ERROR_NO_ERROR) { 57732711b6752eb73324e1b10db975ac956888eda96Danica Chang errored = true; 57832711b6752eb73324e1b10db975ac956888eda96Danica Chang } 57932711b6752eb73324e1b10db975ac956888eda96Danica Chang 580d2bed6935fd702afe2958499fc4e410ee3bca51eJaikumar Ganesh mBluetoothPan.setBluetoothTethering(false); 58132711b6752eb73324e1b10db975ac956888eda96Danica Chang if (errored) { 58232711b6752eb73324e1b10db975ac956888eda96Danica Chang mBluetoothTether.setSummary(R.string.bluetooth_tethering_errored_subtext); 58332711b6752eb73324e1b10db975ac956888eda96Danica Chang } else { 58432711b6752eb73324e1b10db975ac956888eda96Danica Chang mBluetoothTether.setSummary(R.string.bluetooth_tethering_off_subtext); 58532711b6752eb73324e1b10db975ac956888eda96Danica Chang } 58632711b6752eb73324e1b10db975ac956888eda96Danica Chang } 58732711b6752eb73324e1b10db975ac956888eda96Danica Chang } else if (preference == mTetherHelp) { 5880b2669647f1328d2df79fd2d259bc9d15433ba0aIrfan Sheriff showDialog(DIALOG_TETHER_HELP); 5896ebf8619d7f09e9642aed84310b56d9847eead94Daisuke Miyakawa return true; 59084a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani } else if (preference == mCreateNetwork) { 59184a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani showDialog(DIALOG_AP_SETTINGS); 592209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt } 5939c602c47892e7fbe322a449162badeb9def2c4faDaisuke Miyakawa 5946ebf8619d7f09e9642aed84310b56d9847eead94Daisuke Miyakawa return super.onPreferenceTreeClick(screen, preference); 595209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt } 596209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt 597436b29e68e6608bed9e8e7d54385b8f62d89208eJake Hamby private static String findIface(String[] ifaces, String[] regexes) { 598209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt for (String iface : ifaces) { 599209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt for (String regex : regexes) { 600209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt if (iface.matches(regex)) { 601209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt return iface; 602209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt } 603209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt } 604209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt } 605209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt return null; 606209177aac6761db097c53152f6e9543f60748f15Robert Greenwalt } 60784a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani 60884a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani public void onClick(DialogInterface dialogInterface, int button) { 60984a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani if (button == DialogInterface.BUTTON_POSITIVE) { 61084a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani mWifiConfig = mDialog.getConfig(); 61184a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani if (mWifiConfig != null) { 61284a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani /** 613233577cc255561443114d6726792b9df06c2a2a1Irfan Sheriff * if soft AP is stopped, bring up 614233577cc255561443114d6726792b9df06c2a2a1Irfan Sheriff * else restart with new config 615233577cc255561443114d6726792b9df06c2a2a1Irfan Sheriff * TODO: update config on a running access point when framework support is added 61684a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani */ 61784a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani if (mWifiManager.getWifiApState() == WifiManager.WIFI_AP_STATE_ENABLED) { 618233577cc255561443114d6726792b9df06c2a2a1Irfan Sheriff mWifiManager.setWifiApEnabled(null, false); 61984a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani mWifiManager.setWifiApEnabled(mWifiConfig, true); 62084a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani } else { 62184a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani mWifiManager.setWifiApConfiguration(mWifiConfig); 62284a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani } 62384a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani int index = WifiApDialog.getSecurityTypeIndex(mWifiConfig); 62484a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani mCreateNetwork.setSummary(String.format(getActivity().getString(CONFIG_SUBTEXT), 62584a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani mWifiConfig.SSID, 62684a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani mSecurityType[index])); 62784a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani } 62884a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani } 62984a042c6e9ff80d9ddb7b446b0507f6f576bc128Amith Yamasani } 6303901edbdf5cb7b14d4773b3fc7adb3181519855cRobert Greenwalt} 631