Loading AndroidManifest.xml +1 −1 Original line number Diff line number Diff line Loading @@ -455,7 +455,7 @@ <activity android:name="TetherProvisioningActivity" android:exported="true" android:permission="android.permission.TETHER_PRIVILEGED" android:theme="@android:style/Theme.Translucent.NoTitleBar"> android:theme="@style/Theme.ProvisioningActivity"> <intent-filter android:priority="1"> <action android:name="android.settings.TETHER_PROVISIONING_UI" /> <category android:name="android.intent.category.DEFAULT" /> Loading res/values/themes.xml +10 −0 Original line number Diff line number Diff line Loading @@ -173,6 +173,16 @@ <item name="switchBarTheme">@style/ThemeOverlay.SwitchBar.SubSettings</item> </style> <style name="Theme.ProvisioningActivity" parent="@android:style/Theme.Translucent.NoTitleBar"> <item name="android:windowAnimationStyle">@null</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowContentOverlay">@null</item> <item name="android:windowNoTitle">true</item> <item name="android:windowIsFloating">true</item> <item name="android:backgroundDimEnabled">false</item> </style> <style name="Theme.ActionBar" parent="@android:style/Widget.Material.ActionBar.Solid"> <item name="android:contentInsetStart">@dimen/actionbar_contentInsetStart</item> </style> Loading src/com/android/settings/TetherProvisioningActivity.java +10 −3 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.settings; import android.app.Activity; import android.content.Intent; import android.content.pm.PackageManager; import android.net.ConnectivityManager; import android.os.Bundle; import android.os.ResultReceiver; Loading @@ -44,9 +45,6 @@ public class TetherProvisioningActivity extends Activity { mResultReceiver = (ResultReceiver)getIntent().getParcelableExtra( ConnectivityManager.EXTRA_PROVISION_CALLBACK); // TODO: Move isProvisioningNeededButUnavailable into ConnectivityManager and check // it here to short-circuit and fail. int tetherType = getIntent().getIntExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, ConnectivityManager.TETHERING_INVALID); String[] provisionApp = getResources().getStringArray( Loading @@ -58,6 +56,15 @@ public class TetherProvisioningActivity extends Activity { if (DEBUG) { Log.d(TAG, "Starting provisioning app: " + provisionApp[0] + "." + provisionApp[1]); } if (getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) { Log.e(TAG, "Provisioning app is configured, but not available."); mResultReceiver.send(ConnectivityManager.TETHER_ERROR_PROVISION_FAILED, null); finish(); return; } startActivityForResultAsUser(intent, PROVISION_REQUEST, UserHandle.CURRENT); } Loading src/com/android/settings/TetherService.java +25 −8 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.net.ConnectivityManager; import android.os.IBinder; import android.os.ResultReceiver; Loading Loading @@ -121,13 +122,7 @@ public class TetherService extends Service { int index = mCurrentTethers.indexOf(type); if (DEBUG) Log.d(TAG, "Removing tether " + type + ", index " + index); if (index >= 0) { mCurrentTethers.remove(index); // If we are currently in the middle of a check, we may need to adjust the // index accordingly. if (DEBUG) Log.d(TAG, "mCurrentTypeIndex: " + mCurrentTypeIndex); if (index <= mCurrentTypeIndex && mCurrentTypeIndex > 0) { mCurrentTypeIndex--; } removeTypeAtIndex(index); } cancelAlarmIfNecessary(); } else { Loading Loading @@ -170,6 +165,16 @@ public class TetherService extends Service { super.onDestroy(); } private void removeTypeAtIndex(int index) { mCurrentTethers.remove(index); // If we are currently in the middle of a check, we may need to adjust the // index accordingly. if (DEBUG) Log.d(TAG, "mCurrentTypeIndex: " + mCurrentTypeIndex); if (index <= mCurrentTypeIndex && mCurrentTypeIndex > 0) { mCurrentTypeIndex--; } } private ArrayList<Integer> stringToTethers(String tethersStr) { ArrayList<Integer> ret = new ArrayList<Integer>(); if (TextUtils.isEmpty(tethersStr)) return ret; Loading Loading @@ -227,8 +232,20 @@ public class TetherService extends Service { if (DEBUG) Log.d(TAG, "Sending provisioning broadcast: " + provisionAction + " type: " + mCurrentTethers.get(index)); Intent intent = new Intent(provisionAction); intent.putExtra(TETHER_CHOICE, mCurrentTethers.get(index)); int type = mCurrentTethers.get(index); intent.putExtra(TETHER_CHOICE, type); intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); // Ensure that the provisioning app will actually handle the intent. final PackageManager packageManager = getPackageManager(); if (packageManager.queryBroadcastReceivers( intent, PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) { Log.e(TAG, "Provisioning app is configured, but not available."); fireCallbacksForType(type, ConnectivityManager.TETHER_ERROR_PROVISION_FAILED); removeTypeAtIndex(index); return; } sendBroadcast(intent); mInProvisionCheck = true; } Loading src/com/android/settings/TetherSettings.java +82 −168 Original line number Diff line number Diff line Loading @@ -16,6 +16,10 @@ package com.android.settings; import static android.net.ConnectivityManager.TETHERING_BLUETOOTH; import static android.net.ConnectivityManager.TETHERING_USB; import static android.net.ConnectivityManager.TETHERING_WIFI; import android.app.Activity; import android.app.Dialog; import android.bluetooth.BluetoothAdapter; Loading @@ -33,6 +37,7 @@ import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.UserManager; import android.support.v14.preference.SwitchPreference; import android.support.v7.preference.Preference; Loading @@ -44,20 +49,15 @@ import com.android.settings.wifi.WifiApDialog; import com.android.settings.wifi.WifiApEnabler; import com.android.settingslib.TetherUtil; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicReference; import static android.net.ConnectivityManager.TETHERING_BLUETOOTH; import static android.net.ConnectivityManager.TETHERING_INVALID; import static android.net.ConnectivityManager.TETHERING_USB; import static android.net.ConnectivityManager.TETHERING_WIFI; /* * Displays preferences for Tethering. */ public class TetherSettings extends SettingsPreferenceFragment implements DialogInterface.OnClickListener, Preference.OnPreferenceChangeListener { private static final String TAG = "TetherSettings"; private static final String USB_TETHER_SETTINGS = "usb_tether_settings"; private static final String ENABLE_WIFI_AP = "enable_wifi_ap"; Loading @@ -82,6 +82,9 @@ public class TetherSettings extends SettingsPreferenceFragment private String[] mBluetoothRegexs; private AtomicReference<BluetoothPan> mBluetoothPan = new AtomicReference<BluetoothPan>(); private Handler mHandler = new Handler(); private OnStartTetheringCallback mStartTetheringCallback; private static final String WIFI_AP_SSID_AND_SECURITY = "wifi_ap_ssid_and_security"; private static final int CONFIG_SUBTEXT = R.string.wifi_tether_configure_subtext; Loading @@ -92,15 +95,13 @@ public class TetherSettings extends SettingsPreferenceFragment private WifiManager mWifiManager; private WifiConfiguration mWifiConfig = null; private UserManager mUm; private ConnectivityManager mCm; private boolean mUsbConnected; private boolean mMassStorageActive; private boolean mBluetoothEnableForTether; /* One of INVALID, WIFI_TETHERING, USB_TETHERING or BLUETOOTH_TETHERING */ private int mTetherChoice = TETHERING_INVALID; /* Stores the package name and the class name of the provisioning app */ private String[] mProvisionApp; private static final int PROVISION_REQUEST = 0; Loading @@ -116,9 +117,6 @@ public class TetherSettings extends SettingsPreferenceFragment public void onCreate(Bundle icicle) { super.onCreate(icicle); if(icicle != null) { mTetherChoice = icicle.getInt(TETHER_CHOICE); } addPreferencesFromResource(R.xml.tether_prefs); mUm = (UserManager) getSystemService(Context.USER_SERVICE); Loading @@ -143,12 +141,11 @@ public class TetherSettings extends SettingsPreferenceFragment mUsbTether = (SwitchPreference) findPreference(USB_TETHER_SETTINGS); mBluetoothTether = (SwitchPreference) findPreference(ENABLE_BLUETOOTH_TETHERING); ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); mCm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); mUsbRegexs = cm.getTetherableUsbRegexs(); mWifiRegexs = cm.getTetherableWifiRegexs(); mBluetoothRegexs = cm.getTetherableBluetoothRegexs(); mUsbRegexs = mCm.getTetherableUsbRegexs(); mWifiRegexs = mCm.getTetherableWifiRegexs(); mBluetoothRegexs = mCm.getTetherableBluetoothRegexs(); final boolean usbAvailable = mUsbRegexs.length != 0; final boolean wifiAvailable = mWifiRegexs.length != 0; Loading Loading @@ -176,15 +173,6 @@ public class TetherSettings extends SettingsPreferenceFragment mBluetoothTether.setChecked(false); } } mProvisionApp = getResources().getStringArray( com.android.internal.R.array.config_mobile_hotspot_provision_app); } @Override public void onSaveInstanceState(Bundle savedInstanceState) { savedInstanceState.putInt(TETHER_CHOICE, mTetherChoice); super.onSaveInstanceState(savedInstanceState); } private void initWifiTethering() { Loading @@ -208,16 +196,6 @@ public class TetherSettings extends SettingsPreferenceFragment } } private BluetoothProfile.ServiceListener mProfileServiceListener = new BluetoothProfile.ServiceListener() { public void onServiceConnected(int profile, BluetoothProfile proxy) { mBluetoothPan.set((BluetoothPan) proxy); } public void onServiceDisconnected(int profile) { mBluetoothPan.set(null); } }; @Override public Dialog onCreateDialog(int id) { if (id == DIALOG_AP_SETTINGS) { Loading Loading @@ -258,11 +236,8 @@ public class TetherSettings extends SettingsPreferenceFragment switch (intent .getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) { case BluetoothAdapter.STATE_ON: BluetoothPan bluetoothPan = mBluetoothPan.get(); if (bluetoothPan != null) { bluetoothPan.setBluetoothTethering(true); startTethering(TETHERING_BLUETOOTH); mBluetoothEnableForTether = false; } break; case BluetoothAdapter.STATE_OFF: Loading Loading @@ -294,6 +269,8 @@ public class TetherSettings extends SettingsPreferenceFragment final Activity activity = getActivity(); mStartTetheringCallback = new OnStartTetheringCallback(this); mMassStorageActive = Environment.MEDIA_SHARED.equals(Environment.getExternalStorageState()); mTetherChangeReceiver = new TetherChangeReceiver(); IntentFilter filter = new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED); Loading Loading @@ -331,6 +308,7 @@ public class TetherSettings extends SettingsPreferenceFragment } getActivity().unregisterReceiver(mTetherChangeReceiver); mTetherChangeReceiver = null; mStartTetheringCallback = null; if (mWifiApEnabler != null) { mEnableWifiAp.setOnPreferenceChangeListener(null); mWifiApEnabler.pause(); Loading @@ -338,12 +316,9 @@ public class TetherSettings extends SettingsPreferenceFragment } private void updateState() { ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); String[] available = cm.getTetherableIfaces(); String[] tethered = cm.getTetheredIfaces(); String[] errored = cm.getTetheringErroredIfaces(); String[] available = mCm.getTetherableIfaces(); String[] tethered = mCm.getTetheredIfaces(); String[] errored = mCm.getTetheringErroredIfaces(); updateState(available, tethered, errored); } Loading @@ -356,15 +331,13 @@ public class TetherSettings extends SettingsPreferenceFragment private void updateUsbState(String[] available, String[] tethered, String[] errored) { ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); boolean usbAvailable = mUsbConnected && !mMassStorageActive; int usbError = ConnectivityManager.TETHER_ERROR_NO_ERROR; for (String s : available) { for (String regex : mUsbRegexs) { if (s.matches(regex)) { if (usbError == ConnectivityManager.TETHER_ERROR_NO_ERROR) { usbError = cm.getLastTetherError(s); usbError = mCm.getLastTetherError(s); } } } Loading Loading @@ -456,16 +429,14 @@ public class TetherSettings extends SettingsPreferenceFragment } } @Override public boolean onPreferenceChange(Preference preference, Object value) { boolean enable = (Boolean) value; if (enable) { startProvisioningIfNecessary(TETHERING_WIFI); startTethering(TETHERING_WIFI); } else { if (TetherUtil.isProvisioningNeeded(getActivity())) { TetherService.cancelRecheckAlarmIfNecessary(getActivity(), TETHERING_WIFI); } mWifiApEnabler.setSoftapEnabled(false); mCm.stopTethering(TETHERING_WIFI); } return false; } Loading @@ -486,120 +457,38 @@ public class TetherSettings extends SettingsPreferenceFragment PackageManager.MATCH_DEFAULT_ONLY).size() > 0); } private void startProvisioningIfNecessary(int choice) { mTetherChoice = choice; if (TetherUtil.isProvisioningNeeded(getActivity())) { Intent intent = new Intent(Intent.ACTION_MAIN); intent.setClassName(mProvisionApp[0], mProvisionApp[1]); intent.putExtra(TETHER_CHOICE, mTetherChoice); startActivityForResult(intent, PROVISION_REQUEST); } else { startTethering(); } } public void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); if (requestCode == PROVISION_REQUEST) { if (resultCode == Activity.RESULT_OK) { TetherService.scheduleRecheckAlarm(getActivity(), mTetherChoice); startTethering(); } else { //BT and USB need switch turned off on failure //Wifi tethering is never turned on until afterwards switch (mTetherChoice) { case TETHERING_BLUETOOTH: mBluetoothTether.setChecked(false); break; case TETHERING_USB: mUsbTether.setChecked(false); break; } mTetherChoice = TETHERING_INVALID; } } } private void startTethering() { switch (mTetherChoice) { case TETHERING_WIFI: mWifiApEnabler.setSoftapEnabled(true); break; case TETHERING_BLUETOOTH: // turn on Bluetooth first private void startTethering(int choice) { if (choice == TETHERING_BLUETOOTH) { // Turn on Bluetooth first. BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if (adapter.getState() == BluetoothAdapter.STATE_OFF) { mBluetoothEnableForTether = true; adapter.enable(); mBluetoothTether.setSummary(R.string.bluetooth_turning_on); mBluetoothTether.setEnabled(false); } else { BluetoothPan bluetoothPan = mBluetoothPan.get(); if (bluetoothPan != null) bluetoothPan.setBluetoothTethering(true); mBluetoothTether.setSummary(R.string.bluetooth_tethering_available_subtext); } break; case TETHERING_USB: setUsbTethering(true); break; default: //should not happen break; return; } } private void setUsbTethering(boolean enabled) { ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); mUsbTether.setChecked(false); if (cm.setUsbTethering(enabled) != ConnectivityManager.TETHER_ERROR_NO_ERROR) { mUsbTether.setSummary(R.string.usb_tethering_errored_subtext); return; } mUsbTether.setSummary(""); mCm.startTethering(choice, true, mStartTetheringCallback, mHandler); } @Override public boolean onPreferenceTreeClick(Preference preference) { ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); if (preference == mUsbTether) { boolean newState = mUsbTether.isChecked(); if (newState) { startProvisioningIfNecessary(TETHERING_USB); if (mUsbTether.isChecked()) { startTethering(TETHERING_USB); } else { if (TetherUtil.isProvisioningNeeded(getActivity())) { TetherService.cancelRecheckAlarmIfNecessary(getActivity(), TETHERING_USB); } setUsbTethering(newState); mCm.stopTethering(TETHERING_USB); } } else if (preference == mBluetoothTether) { boolean bluetoothTetherState = mBluetoothTether.isChecked(); if (bluetoothTetherState) { startProvisioningIfNecessary(TETHERING_BLUETOOTH); if (mBluetoothTether.isChecked()) { startTethering(TETHERING_BLUETOOTH); } else { if (TetherUtil.isProvisioningNeeded(getActivity())) { TetherService.cancelRecheckAlarmIfNecessary(getActivity(), TETHERING_BLUETOOTH); } boolean errored = false; String [] tethered = cm.getTetheredIfaces(); String bluetoothIface = findIface(tethered, mBluetoothRegexs); if (bluetoothIface != null && cm.untether(bluetoothIface) != ConnectivityManager.TETHER_ERROR_NO_ERROR) { errored = true; } BluetoothPan bluetoothPan = mBluetoothPan.get(); if (bluetoothPan != null) bluetoothPan.setBluetoothTethering(false); if (errored) { mBluetoothTether.setSummary(R.string.bluetooth_tethering_errored_subtext); } else { mBluetoothTether.setSummary(R.string.bluetooth_tethering_off_subtext); } mCm.stopTethering(TETHERING_BLUETOOTH); // No ACTION_TETHER_STATE_CHANGED is fired or bluetooth unless a device is // connected. Need to update state manually. updateState(); } } else if (preference == mCreateNetwork) { showDialog(DIALOG_AP_SETTINGS); Loading @@ -608,17 +497,6 @@ public class TetherSettings extends SettingsPreferenceFragment return super.onPreferenceTreeClick(preference); } private static String findIface(String[] ifaces, String[] regexes) { for (String iface : ifaces) { for (String regex : regexes) { if (iface.matches(regex)) { return iface; } } } return null; } public void onClick(DialogInterface dialogInterface, int button) { if (button == DialogInterface.BUTTON_POSITIVE) { mWifiConfig = mDialog.getConfig(); Loading Loading @@ -646,4 +524,40 @@ public class TetherSettings extends SettingsPreferenceFragment public int getHelpResource() { return R.string.help_url_tether; } private BluetoothProfile.ServiceListener mProfileServiceListener = new BluetoothProfile.ServiceListener() { public void onServiceConnected(int profile, BluetoothProfile proxy) { mBluetoothPan.set((BluetoothPan) proxy); } public void onServiceDisconnected(int profile) { mBluetoothPan.set(null); } }; private static final class OnStartTetheringCallback extends ConnectivityManager.OnStartTetheringCallback { final WeakReference<TetherSettings> mTetherSettings; OnStartTetheringCallback(TetherSettings settings) { mTetherSettings = new WeakReference<TetherSettings>(settings); } @Override public void onTetheringStarted() { update(); } @Override public void onTetheringFailed() { update(); } private void update() { TetherSettings settings = mTetherSettings.get(); if (settings != null) { settings.updateState(); } } } } Loading
AndroidManifest.xml +1 −1 Original line number Diff line number Diff line Loading @@ -455,7 +455,7 @@ <activity android:name="TetherProvisioningActivity" android:exported="true" android:permission="android.permission.TETHER_PRIVILEGED" android:theme="@android:style/Theme.Translucent.NoTitleBar"> android:theme="@style/Theme.ProvisioningActivity"> <intent-filter android:priority="1"> <action android:name="android.settings.TETHER_PROVISIONING_UI" /> <category android:name="android.intent.category.DEFAULT" /> Loading
res/values/themes.xml +10 −0 Original line number Diff line number Diff line Loading @@ -173,6 +173,16 @@ <item name="switchBarTheme">@style/ThemeOverlay.SwitchBar.SubSettings</item> </style> <style name="Theme.ProvisioningActivity" parent="@android:style/Theme.Translucent.NoTitleBar"> <item name="android:windowAnimationStyle">@null</item> <item name="android:windowIsTranslucent">true</item> <item name="android:windowBackground">@android:color/transparent</item> <item name="android:windowContentOverlay">@null</item> <item name="android:windowNoTitle">true</item> <item name="android:windowIsFloating">true</item> <item name="android:backgroundDimEnabled">false</item> </style> <style name="Theme.ActionBar" parent="@android:style/Widget.Material.ActionBar.Solid"> <item name="android:contentInsetStart">@dimen/actionbar_contentInsetStart</item> </style> Loading
src/com/android/settings/TetherProvisioningActivity.java +10 −3 Original line number Diff line number Diff line Loading @@ -18,6 +18,7 @@ package com.android.settings; import android.app.Activity; import android.content.Intent; import android.content.pm.PackageManager; import android.net.ConnectivityManager; import android.os.Bundle; import android.os.ResultReceiver; Loading @@ -44,9 +45,6 @@ public class TetherProvisioningActivity extends Activity { mResultReceiver = (ResultReceiver)getIntent().getParcelableExtra( ConnectivityManager.EXTRA_PROVISION_CALLBACK); // TODO: Move isProvisioningNeededButUnavailable into ConnectivityManager and check // it here to short-circuit and fail. int tetherType = getIntent().getIntExtra(ConnectivityManager.EXTRA_ADD_TETHER_TYPE, ConnectivityManager.TETHERING_INVALID); String[] provisionApp = getResources().getStringArray( Loading @@ -58,6 +56,15 @@ public class TetherProvisioningActivity extends Activity { if (DEBUG) { Log.d(TAG, "Starting provisioning app: " + provisionApp[0] + "." + provisionApp[1]); } if (getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) { Log.e(TAG, "Provisioning app is configured, but not available."); mResultReceiver.send(ConnectivityManager.TETHER_ERROR_PROVISION_FAILED, null); finish(); return; } startActivityForResultAsUser(intent, PROVISION_REQUEST, UserHandle.CURRENT); } Loading
src/com/android/settings/TetherService.java +25 −8 Original line number Diff line number Diff line Loading @@ -29,6 +29,7 @@ import android.content.Context; import android.content.Intent; import android.content.IntentFilter; import android.content.SharedPreferences; import android.content.pm.PackageManager; import android.net.ConnectivityManager; import android.os.IBinder; import android.os.ResultReceiver; Loading Loading @@ -121,13 +122,7 @@ public class TetherService extends Service { int index = mCurrentTethers.indexOf(type); if (DEBUG) Log.d(TAG, "Removing tether " + type + ", index " + index); if (index >= 0) { mCurrentTethers.remove(index); // If we are currently in the middle of a check, we may need to adjust the // index accordingly. if (DEBUG) Log.d(TAG, "mCurrentTypeIndex: " + mCurrentTypeIndex); if (index <= mCurrentTypeIndex && mCurrentTypeIndex > 0) { mCurrentTypeIndex--; } removeTypeAtIndex(index); } cancelAlarmIfNecessary(); } else { Loading Loading @@ -170,6 +165,16 @@ public class TetherService extends Service { super.onDestroy(); } private void removeTypeAtIndex(int index) { mCurrentTethers.remove(index); // If we are currently in the middle of a check, we may need to adjust the // index accordingly. if (DEBUG) Log.d(TAG, "mCurrentTypeIndex: " + mCurrentTypeIndex); if (index <= mCurrentTypeIndex && mCurrentTypeIndex > 0) { mCurrentTypeIndex--; } } private ArrayList<Integer> stringToTethers(String tethersStr) { ArrayList<Integer> ret = new ArrayList<Integer>(); if (TextUtils.isEmpty(tethersStr)) return ret; Loading Loading @@ -227,8 +232,20 @@ public class TetherService extends Service { if (DEBUG) Log.d(TAG, "Sending provisioning broadcast: " + provisionAction + " type: " + mCurrentTethers.get(index)); Intent intent = new Intent(provisionAction); intent.putExtra(TETHER_CHOICE, mCurrentTethers.get(index)); int type = mCurrentTethers.get(index); intent.putExtra(TETHER_CHOICE, type); intent.setFlags(Intent.FLAG_RECEIVER_FOREGROUND); // Ensure that the provisioning app will actually handle the intent. final PackageManager packageManager = getPackageManager(); if (packageManager.queryBroadcastReceivers( intent, PackageManager.MATCH_DEFAULT_ONLY).isEmpty()) { Log.e(TAG, "Provisioning app is configured, but not available."); fireCallbacksForType(type, ConnectivityManager.TETHER_ERROR_PROVISION_FAILED); removeTypeAtIndex(index); return; } sendBroadcast(intent); mInProvisionCheck = true; } Loading
src/com/android/settings/TetherSettings.java +82 −168 Original line number Diff line number Diff line Loading @@ -16,6 +16,10 @@ package com.android.settings; import static android.net.ConnectivityManager.TETHERING_BLUETOOTH; import static android.net.ConnectivityManager.TETHERING_USB; import static android.net.ConnectivityManager.TETHERING_WIFI; import android.app.Activity; import android.app.Dialog; import android.bluetooth.BluetoothAdapter; Loading @@ -33,6 +37,7 @@ import android.net.wifi.WifiConfiguration; import android.net.wifi.WifiManager; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.os.UserManager; import android.support.v14.preference.SwitchPreference; import android.support.v7.preference.Preference; Loading @@ -44,20 +49,15 @@ import com.android.settings.wifi.WifiApDialog; import com.android.settings.wifi.WifiApEnabler; import com.android.settingslib.TetherUtil; import java.lang.ref.WeakReference; import java.util.ArrayList; import java.util.concurrent.atomic.AtomicReference; import static android.net.ConnectivityManager.TETHERING_BLUETOOTH; import static android.net.ConnectivityManager.TETHERING_INVALID; import static android.net.ConnectivityManager.TETHERING_USB; import static android.net.ConnectivityManager.TETHERING_WIFI; /* * Displays preferences for Tethering. */ public class TetherSettings extends SettingsPreferenceFragment implements DialogInterface.OnClickListener, Preference.OnPreferenceChangeListener { private static final String TAG = "TetherSettings"; private static final String USB_TETHER_SETTINGS = "usb_tether_settings"; private static final String ENABLE_WIFI_AP = "enable_wifi_ap"; Loading @@ -82,6 +82,9 @@ public class TetherSettings extends SettingsPreferenceFragment private String[] mBluetoothRegexs; private AtomicReference<BluetoothPan> mBluetoothPan = new AtomicReference<BluetoothPan>(); private Handler mHandler = new Handler(); private OnStartTetheringCallback mStartTetheringCallback; private static final String WIFI_AP_SSID_AND_SECURITY = "wifi_ap_ssid_and_security"; private static final int CONFIG_SUBTEXT = R.string.wifi_tether_configure_subtext; Loading @@ -92,15 +95,13 @@ public class TetherSettings extends SettingsPreferenceFragment private WifiManager mWifiManager; private WifiConfiguration mWifiConfig = null; private UserManager mUm; private ConnectivityManager mCm; private boolean mUsbConnected; private boolean mMassStorageActive; private boolean mBluetoothEnableForTether; /* One of INVALID, WIFI_TETHERING, USB_TETHERING or BLUETOOTH_TETHERING */ private int mTetherChoice = TETHERING_INVALID; /* Stores the package name and the class name of the provisioning app */ private String[] mProvisionApp; private static final int PROVISION_REQUEST = 0; Loading @@ -116,9 +117,6 @@ public class TetherSettings extends SettingsPreferenceFragment public void onCreate(Bundle icicle) { super.onCreate(icicle); if(icicle != null) { mTetherChoice = icicle.getInt(TETHER_CHOICE); } addPreferencesFromResource(R.xml.tether_prefs); mUm = (UserManager) getSystemService(Context.USER_SERVICE); Loading @@ -143,12 +141,11 @@ public class TetherSettings extends SettingsPreferenceFragment mUsbTether = (SwitchPreference) findPreference(USB_TETHER_SETTINGS); mBluetoothTether = (SwitchPreference) findPreference(ENABLE_BLUETOOTH_TETHERING); ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); mCm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); mUsbRegexs = cm.getTetherableUsbRegexs(); mWifiRegexs = cm.getTetherableWifiRegexs(); mBluetoothRegexs = cm.getTetherableBluetoothRegexs(); mUsbRegexs = mCm.getTetherableUsbRegexs(); mWifiRegexs = mCm.getTetherableWifiRegexs(); mBluetoothRegexs = mCm.getTetherableBluetoothRegexs(); final boolean usbAvailable = mUsbRegexs.length != 0; final boolean wifiAvailable = mWifiRegexs.length != 0; Loading Loading @@ -176,15 +173,6 @@ public class TetherSettings extends SettingsPreferenceFragment mBluetoothTether.setChecked(false); } } mProvisionApp = getResources().getStringArray( com.android.internal.R.array.config_mobile_hotspot_provision_app); } @Override public void onSaveInstanceState(Bundle savedInstanceState) { savedInstanceState.putInt(TETHER_CHOICE, mTetherChoice); super.onSaveInstanceState(savedInstanceState); } private void initWifiTethering() { Loading @@ -208,16 +196,6 @@ public class TetherSettings extends SettingsPreferenceFragment } } private BluetoothProfile.ServiceListener mProfileServiceListener = new BluetoothProfile.ServiceListener() { public void onServiceConnected(int profile, BluetoothProfile proxy) { mBluetoothPan.set((BluetoothPan) proxy); } public void onServiceDisconnected(int profile) { mBluetoothPan.set(null); } }; @Override public Dialog onCreateDialog(int id) { if (id == DIALOG_AP_SETTINGS) { Loading Loading @@ -258,11 +236,8 @@ public class TetherSettings extends SettingsPreferenceFragment switch (intent .getIntExtra(BluetoothAdapter.EXTRA_STATE, BluetoothAdapter.ERROR)) { case BluetoothAdapter.STATE_ON: BluetoothPan bluetoothPan = mBluetoothPan.get(); if (bluetoothPan != null) { bluetoothPan.setBluetoothTethering(true); startTethering(TETHERING_BLUETOOTH); mBluetoothEnableForTether = false; } break; case BluetoothAdapter.STATE_OFF: Loading Loading @@ -294,6 +269,8 @@ public class TetherSettings extends SettingsPreferenceFragment final Activity activity = getActivity(); mStartTetheringCallback = new OnStartTetheringCallback(this); mMassStorageActive = Environment.MEDIA_SHARED.equals(Environment.getExternalStorageState()); mTetherChangeReceiver = new TetherChangeReceiver(); IntentFilter filter = new IntentFilter(ConnectivityManager.ACTION_TETHER_STATE_CHANGED); Loading Loading @@ -331,6 +308,7 @@ public class TetherSettings extends SettingsPreferenceFragment } getActivity().unregisterReceiver(mTetherChangeReceiver); mTetherChangeReceiver = null; mStartTetheringCallback = null; if (mWifiApEnabler != null) { mEnableWifiAp.setOnPreferenceChangeListener(null); mWifiApEnabler.pause(); Loading @@ -338,12 +316,9 @@ public class TetherSettings extends SettingsPreferenceFragment } private void updateState() { ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); String[] available = cm.getTetherableIfaces(); String[] tethered = cm.getTetheredIfaces(); String[] errored = cm.getTetheringErroredIfaces(); String[] available = mCm.getTetherableIfaces(); String[] tethered = mCm.getTetheredIfaces(); String[] errored = mCm.getTetheringErroredIfaces(); updateState(available, tethered, errored); } Loading @@ -356,15 +331,13 @@ public class TetherSettings extends SettingsPreferenceFragment private void updateUsbState(String[] available, String[] tethered, String[] errored) { ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); boolean usbAvailable = mUsbConnected && !mMassStorageActive; int usbError = ConnectivityManager.TETHER_ERROR_NO_ERROR; for (String s : available) { for (String regex : mUsbRegexs) { if (s.matches(regex)) { if (usbError == ConnectivityManager.TETHER_ERROR_NO_ERROR) { usbError = cm.getLastTetherError(s); usbError = mCm.getLastTetherError(s); } } } Loading Loading @@ -456,16 +429,14 @@ public class TetherSettings extends SettingsPreferenceFragment } } @Override public boolean onPreferenceChange(Preference preference, Object value) { boolean enable = (Boolean) value; if (enable) { startProvisioningIfNecessary(TETHERING_WIFI); startTethering(TETHERING_WIFI); } else { if (TetherUtil.isProvisioningNeeded(getActivity())) { TetherService.cancelRecheckAlarmIfNecessary(getActivity(), TETHERING_WIFI); } mWifiApEnabler.setSoftapEnabled(false); mCm.stopTethering(TETHERING_WIFI); } return false; } Loading @@ -486,120 +457,38 @@ public class TetherSettings extends SettingsPreferenceFragment PackageManager.MATCH_DEFAULT_ONLY).size() > 0); } private void startProvisioningIfNecessary(int choice) { mTetherChoice = choice; if (TetherUtil.isProvisioningNeeded(getActivity())) { Intent intent = new Intent(Intent.ACTION_MAIN); intent.setClassName(mProvisionApp[0], mProvisionApp[1]); intent.putExtra(TETHER_CHOICE, mTetherChoice); startActivityForResult(intent, PROVISION_REQUEST); } else { startTethering(); } } public void onActivityResult(int requestCode, int resultCode, Intent intent) { super.onActivityResult(requestCode, resultCode, intent); if (requestCode == PROVISION_REQUEST) { if (resultCode == Activity.RESULT_OK) { TetherService.scheduleRecheckAlarm(getActivity(), mTetherChoice); startTethering(); } else { //BT and USB need switch turned off on failure //Wifi tethering is never turned on until afterwards switch (mTetherChoice) { case TETHERING_BLUETOOTH: mBluetoothTether.setChecked(false); break; case TETHERING_USB: mUsbTether.setChecked(false); break; } mTetherChoice = TETHERING_INVALID; } } } private void startTethering() { switch (mTetherChoice) { case TETHERING_WIFI: mWifiApEnabler.setSoftapEnabled(true); break; case TETHERING_BLUETOOTH: // turn on Bluetooth first private void startTethering(int choice) { if (choice == TETHERING_BLUETOOTH) { // Turn on Bluetooth first. BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter(); if (adapter.getState() == BluetoothAdapter.STATE_OFF) { mBluetoothEnableForTether = true; adapter.enable(); mBluetoothTether.setSummary(R.string.bluetooth_turning_on); mBluetoothTether.setEnabled(false); } else { BluetoothPan bluetoothPan = mBluetoothPan.get(); if (bluetoothPan != null) bluetoothPan.setBluetoothTethering(true); mBluetoothTether.setSummary(R.string.bluetooth_tethering_available_subtext); } break; case TETHERING_USB: setUsbTethering(true); break; default: //should not happen break; return; } } private void setUsbTethering(boolean enabled) { ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); mUsbTether.setChecked(false); if (cm.setUsbTethering(enabled) != ConnectivityManager.TETHER_ERROR_NO_ERROR) { mUsbTether.setSummary(R.string.usb_tethering_errored_subtext); return; } mUsbTether.setSummary(""); mCm.startTethering(choice, true, mStartTetheringCallback, mHandler); } @Override public boolean onPreferenceTreeClick(Preference preference) { ConnectivityManager cm = (ConnectivityManager)getSystemService(Context.CONNECTIVITY_SERVICE); if (preference == mUsbTether) { boolean newState = mUsbTether.isChecked(); if (newState) { startProvisioningIfNecessary(TETHERING_USB); if (mUsbTether.isChecked()) { startTethering(TETHERING_USB); } else { if (TetherUtil.isProvisioningNeeded(getActivity())) { TetherService.cancelRecheckAlarmIfNecessary(getActivity(), TETHERING_USB); } setUsbTethering(newState); mCm.stopTethering(TETHERING_USB); } } else if (preference == mBluetoothTether) { boolean bluetoothTetherState = mBluetoothTether.isChecked(); if (bluetoothTetherState) { startProvisioningIfNecessary(TETHERING_BLUETOOTH); if (mBluetoothTether.isChecked()) { startTethering(TETHERING_BLUETOOTH); } else { if (TetherUtil.isProvisioningNeeded(getActivity())) { TetherService.cancelRecheckAlarmIfNecessary(getActivity(), TETHERING_BLUETOOTH); } boolean errored = false; String [] tethered = cm.getTetheredIfaces(); String bluetoothIface = findIface(tethered, mBluetoothRegexs); if (bluetoothIface != null && cm.untether(bluetoothIface) != ConnectivityManager.TETHER_ERROR_NO_ERROR) { errored = true; } BluetoothPan bluetoothPan = mBluetoothPan.get(); if (bluetoothPan != null) bluetoothPan.setBluetoothTethering(false); if (errored) { mBluetoothTether.setSummary(R.string.bluetooth_tethering_errored_subtext); } else { mBluetoothTether.setSummary(R.string.bluetooth_tethering_off_subtext); } mCm.stopTethering(TETHERING_BLUETOOTH); // No ACTION_TETHER_STATE_CHANGED is fired or bluetooth unless a device is // connected. Need to update state manually. updateState(); } } else if (preference == mCreateNetwork) { showDialog(DIALOG_AP_SETTINGS); Loading @@ -608,17 +497,6 @@ public class TetherSettings extends SettingsPreferenceFragment return super.onPreferenceTreeClick(preference); } private static String findIface(String[] ifaces, String[] regexes) { for (String iface : ifaces) { for (String regex : regexes) { if (iface.matches(regex)) { return iface; } } } return null; } public void onClick(DialogInterface dialogInterface, int button) { if (button == DialogInterface.BUTTON_POSITIVE) { mWifiConfig = mDialog.getConfig(); Loading Loading @@ -646,4 +524,40 @@ public class TetherSettings extends SettingsPreferenceFragment public int getHelpResource() { return R.string.help_url_tether; } private BluetoothProfile.ServiceListener mProfileServiceListener = new BluetoothProfile.ServiceListener() { public void onServiceConnected(int profile, BluetoothProfile proxy) { mBluetoothPan.set((BluetoothPan) proxy); } public void onServiceDisconnected(int profile) { mBluetoothPan.set(null); } }; private static final class OnStartTetheringCallback extends ConnectivityManager.OnStartTetheringCallback { final WeakReference<TetherSettings> mTetherSettings; OnStartTetheringCallback(TetherSettings settings) { mTetherSettings = new WeakReference<TetherSettings>(settings); } @Override public void onTetheringStarted() { update(); } @Override public void onTetheringFailed() { update(); } private void update() { TetherSettings settings = mTetherSettings.get(); if (settings != null) { settings.updateState(); } } } }