Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 68954464 authored by Jeremy Klein's avatar Jeremy Klein Committed by Android (Google) Code Review
Browse files

Merge "Make TetherSettings use the new tether api."

parents 57fae3b3 e3e7b953
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -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" />
+10 −0
Original line number Diff line number Diff line
@@ -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>
+10 −3
Original line number Diff line number Diff line
@@ -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;
@@ -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(
@@ -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);
    }

+25 −8
Original line number Diff line number Diff line
@@ -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;
@@ -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 {
@@ -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;
@@ -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;
        }
+82 −168
Original line number Diff line number Diff line
@@ -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;
@@ -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;
@@ -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";
@@ -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;

@@ -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;
@@ -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);
@@ -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;
@@ -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() {
@@ -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) {
@@ -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:
@@ -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);
@@ -331,6 +308,7 @@ public class TetherSettings extends SettingsPreferenceFragment
        }
        getActivity().unregisterReceiver(mTetherChangeReceiver);
        mTetherChangeReceiver = null;
        mStartTetheringCallback = null;
        if (mWifiApEnabler != null) {
            mEnableWifiAp.setOnPreferenceChangeListener(null);
            mWifiApEnabler.pause();
@@ -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);
    }

@@ -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);
                    }
                }
            }
@@ -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;
    }
@@ -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);
@@ -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();
@@ -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();
            }
        }
    }
}