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

Commit 5ff886e5 authored by Robert Greenwalt's avatar Robert Greenwalt
Browse files

resolved conflicts for merge of 7a652bc8 to master

Change-Id: Id0a41cae36f5a3b30f2fe8a202c934153b9cd03f
parents 8969d992 7a652bc8
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -163,6 +163,12 @@ public class ConnectivityManager {
     */
    public static final String EXTRA_ERRORED_TETHER = "erroredArray";

    /**
     * The absence of APN..
     * @hide
     */
    public static final int TYPE_NONE        = -1;

    /**
     * The Default Mobile data connection.  When active, all data traffic
     * will use this connection by default.
+8 −12
Original line number Diff line number Diff line
@@ -98,7 +98,7 @@
    <!-- This string array should be overridden by the device to present a list of network
         attributes.  This is used by the connectivity manager to decide which networks can coexist
         based on the hardware -->
    <!-- An Array of "[Connection name],[ConnectivityManager connection type],
    <!-- An Array of "[Connection name],[ConnectivityManager.TYPE_xxxx],
         [associated radio-type],[priority],[restoral-timer(ms)],[dependencyMet]  -->
    <!-- the 5th element "resore-time" indicates the number of milliseconds to delay
         before automatically restore the default connection.  Set -1 if the connection
@@ -154,20 +154,16 @@
    <string-array translatable="false" name="config_tether_dhcp_range">
    </string-array>

    <!-- Regex array of allowable upstream ifaces for tethering - for example if you want
         tethering on a new interface called "foo2" add <item>"foo\\d"</item> to the array -->
    <!-- Interfaces will be prioritized according to the order listed -->
    <string-array translatable="false" name="config_tether_upstream_regexs">
    </string-array>

    <!-- Regex of wired ethernet ifaces -->
    <string translatable="false" name="config_ethernet_iface_regex">eth\\d</string>

    <!-- Boolean indicating if we require the use of DUN on mobile for tethering.
         Note that this defaults to false so that if you move to a carrier that
         hasn't configured anything tethering will still work.  If you'd rather
         make the device untetherable on unconfigured devices, set to true -->
    <bool translatable="false" name="config_tether_dun_required">false</bool>
    <!-- Array of ConnectivityManager.TYPE_xxxx values allowable for tethering -->
    <!-- Common options are [1, 4] for TYPE_WIFI and TYPE_MOBILE_DUN or
    <!== [0,1,5,7] for TYPE_MOBILE, TYPE_WIFI, TYPE_MOBILE_HIPRI and TYPE_BLUETOOTH -->
    <integer-array translatable="false" name="config_tether_upstream_types">
        <item>1</item>
        <item>4</item>
    </integer-array>

    <!-- String containing the apn value for tethering.  May be overriden by secure settings
         TETHER_DUN_APN.  Value is a comma separated series of strings:
+2 −18
Original line number Diff line number Diff line
@@ -466,12 +466,10 @@ public class ConnectivityService extends IConnectivityManager.Stub {
        INetworkManagementService nmService = INetworkManagementService.Stub.asInterface(b);

        mTethering = new Tethering(mContext, nmService, mHandler.getLooper());
        mTetheringConfigValid = (((mNetTrackers[ConnectivityManager.TYPE_MOBILE_DUN] != null) ||
                                  !mTethering.isDunRequired()) &&
                                 (mTethering.getTetherableUsbRegexs().length != 0 ||
        mTetheringConfigValid = ((mTethering.getTetherableUsbRegexs().length != 0 ||
                                  mTethering.getTetherableWifiRegexs().length != 0 ||
                                  mTethering.getTetherableBluetoothRegexs().length != 0) &&
                                 mTethering.getUpstreamIfaceRegexs().length != 0);
                                 mTethering.getUpstreamIfaceTypes().length != 0);

        mVpn = new Vpn(mContext, new VpnCallback());

@@ -1576,12 +1574,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
                }
                addPrivateDnsRoutes(mNetTrackers[netType]);
            }

            /** Notify TetheringService if interface name has been changed. */
            if (TextUtils.equals(mNetTrackers[netType].getNetworkInfo().getReason(),
                                 Phone.REASON_LINK_PROPERTIES_CHANGED)) {
                handleTetherIfaceChange(netType);
            }
        } else {
            if (mNetConfigs[netType].isDefault()) {
                removeDefaultRoute(mNetTrackers[netType]);
@@ -2412,14 +2404,6 @@ public class ConnectivityService extends IConnectivityManager.Stub {
        }
    }

    private void handleTetherIfaceChange(int type) {
        String iface = mNetTrackers[type].getLinkProperties().getInterfaceName();

        if (isTetheringSupported()) {
            mTethering.handleTetherIfaceChange(iface);
        }
    }

    private void log(String s) {
        Slog.d(TAG, s);
    }
+115 −136
Original line number Diff line number Diff line
@@ -57,7 +57,9 @@ import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.Set;
/**
@@ -82,7 +84,15 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
    private String[] mTetherableUsbRegexs;
    private String[] mTetherableWifiRegexs;
    private String[] mTetherableBluetoothRegexs;
    private String[] mUpstreamIfaceRegexs;
    private Collection<Integer> mUpstreamIfaceTypes;

    private static final Integer MOBILE_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE);
    private static final Integer HIPRI_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_HIPRI);
    private static final Integer DUN_TYPE = new Integer(ConnectivityManager.TYPE_MOBILE_DUN);

    // if we have to connect to mobile, what APN type should we use?  Calculated by examining the
    // upstream type list and the DUN_REQUIRED secure-setting
    private int mPreferredUpstreamMobileApn = ConnectivityManager.TYPE_NONE;

    private INetworkManagementService mNMService;
    private Looper mLooper;
@@ -112,9 +122,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
    private static final String DNS_DEFAULT_SERVER1 = "8.8.8.8";
    private static final String DNS_DEFAULT_SERVER2 = "8.8.4.4";

    // resampled each time we turn on tethering - used as cache for settings/config-val
    private boolean mDunRequired;  // configuration info - must use DUN apn on 3g

    private StateMachine mTetherMasterSM;

    private Notification mTetheredNotification;
@@ -159,7 +166,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
        if ((mDhcpRange.length == 0) || (mDhcpRange.length % 2 ==1)) {
            mDhcpRange = DHCP_DEFAULT_RANGE;
        }
        mDunRequired = false; // resample when we turn on

        mTetherableUsbRegexs = context.getResources().getStringArray(
                com.android.internal.R.array.config_tether_usb_regexs);
@@ -167,8 +173,15 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
                com.android.internal.R.array.config_tether_wifi_regexs);
        mTetherableBluetoothRegexs = context.getResources().getStringArray(
                com.android.internal.R.array.config_tether_bluetooth_regexs);
        mUpstreamIfaceRegexs = context.getResources().getStringArray(
                com.android.internal.R.array.config_tether_upstream_regexs);
        int ifaceTypes[] = context.getResources().getIntArray(
                com.android.internal.R.array.config_tether_upstream_types);
        mUpstreamIfaceTypes = new ArrayList();
        for (int i : ifaceTypes) {
            mUpstreamIfaceTypes.add(new Integer(i));
        }

        // check if the upstream type list needs to be modified due to secure-settings
        checkDunRequired();

        // TODO - remove and rely on real notifications of the current iface
        mDnsServers = new String[2];
@@ -582,16 +595,44 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
        return mTetherableBluetoothRegexs;
    }

    public String[] getUpstreamIfaceRegexs() {
        return mUpstreamIfaceRegexs;
    public int[] getUpstreamIfaceTypes() {
        int values[] = new int[mUpstreamIfaceTypes.size()];
        Iterator<Integer> iterator = mUpstreamIfaceTypes.iterator();
        for (int i=0; i < mUpstreamIfaceTypes.size(); i++) {
            values[i] = iterator.next();
        }
        return values;
    }

    public boolean isDunRequired() {
        boolean defaultVal = mContext.getResources().getBoolean(
                com.android.internal.R.bool.config_tether_dun_required);
        boolean result = (Settings.Secure.getInt(mContext.getContentResolver(),
                Settings.Secure.TETHER_DUN_REQUIRED, (defaultVal ? 1 : 0)) == 1);
        return result;
    public void checkDunRequired() {
        int requiredApn = ((Settings.Secure.getInt(mContext.getContentResolver(),
                Settings.Secure.TETHER_DUN_REQUIRED, 0) == 1) ?
                ConnectivityManager.TYPE_MOBILE_DUN :
                ConnectivityManager.TYPE_MOBILE_HIPRI);
        if (mPreferredUpstreamMobileApn != requiredApn) {
            if (requiredApn == ConnectivityManager.TYPE_MOBILE_DUN) {
                while (mUpstreamIfaceTypes.contains(MOBILE_TYPE)) {
                    mUpstreamIfaceTypes.remove(MOBILE_TYPE);
                }
                while (mUpstreamIfaceTypes.contains(HIPRI_TYPE)) {
                    mUpstreamIfaceTypes.remove(HIPRI_TYPE);
                }
                if (mUpstreamIfaceTypes.contains(DUN_TYPE) == false) {
                    mUpstreamIfaceTypes.add(DUN_TYPE);
                }
            } else {
                while (mUpstreamIfaceTypes.contains(DUN_TYPE)) {
                    mUpstreamIfaceTypes.remove(DUN_TYPE);
                }
                if (mUpstreamIfaceTypes.contains(MOBILE_TYPE) == false) {
                    mUpstreamIfaceTypes.add(MOBILE_TYPE);
                }
                if (mUpstreamIfaceTypes.contains(HIPRI_TYPE) == false) {
                    mUpstreamIfaceTypes.add(HIPRI_TYPE);
                }
            }
            mPreferredUpstreamMobileApn = requiredApn;
        }
    }

    public String[] getTetheredIfaces() {
@@ -648,17 +689,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
        return retVal;
    }

    public void handleTetherIfaceChange(String iface) {
        // check if iface is white listed
        for (String regex : mUpstreamIfaceRegexs) {
            if (iface.matches(regex)) {
                if (DEBUG) Log.d(TAG, "Tethering got Interface Change");
                mTetherMasterSM.sendMessage(TetherMasterSM.CMD_IFACE_CHANGED, iface);
                break;
            }
        }
    }

    class TetherInterfaceSM extends StateMachine {
        // notification from the master SM that it's not in tether mode
        static final int CMD_TETHER_MODE_DEAD            =  1;
@@ -1051,8 +1081,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
        static final int CMD_CELL_CONNECTION_RENEW   = 4;
        // we don't have a valid upstream conn, check again after a delay
        static final int CMD_RETRY_UPSTREAM          = 5;
        // received an indication that upstream interface has changed
        static final int CMD_IFACE_CHANGED           = 6;

        // This indicates what a timeout event relates to.  A state that
        // sends itself a delayed timeout event and handles incoming timeout events
@@ -1072,7 +1100,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
        private ArrayList mNotifyList;

        private int mCurrentConnectionSequence;
        private boolean mMobileReserved = false;
        private int mMobileApnReserved = ConnectivityManager.TYPE_NONE;

        private String mUpstreamIfaceName = null;

@@ -1111,22 +1139,34 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
            public boolean processMessage(Message m) {
                return false;
            }
            protected boolean turnOnMobileConnection() {
            protected String enableString(int apnType) {
                switch (apnType) {
                case ConnectivityManager.TYPE_MOBILE_DUN:
                    return Phone.FEATURE_ENABLE_DUN_ALWAYS;
                case ConnectivityManager.TYPE_MOBILE:
                case ConnectivityManager.TYPE_MOBILE_HIPRI:
                    return Phone.FEATURE_ENABLE_HIPRI;
                }
                return null;
            }
            protected boolean turnOnUpstreamMobileConnection(int apnType) {
                boolean retValue = true;
                if (mMobileReserved) return retValue;
                if (apnType == ConnectivityManager.TYPE_NONE) return false;
                if (apnType != mMobileApnReserved) turnOffUpstreamMobileConnection();
                IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
                IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
                int result = Phone.APN_REQUEST_FAILED;
                String enableString = enableString(apnType);
                if (enableString == null) return false;
                try {
                    result = cm.startUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
                            (mDunRequired ? Phone.FEATURE_ENABLE_DUN_ALWAYS :
                            Phone.FEATURE_ENABLE_HIPRI), new Binder());
                            enableString, new Binder());
                } catch (Exception e) {
                }
                switch (result) {
                case Phone.APN_ALREADY_ACTIVE:
                case Phone.APN_REQUEST_STARTED:
                    mMobileReserved = true;
                    mMobileApnReserved = apnType;
                    Message m = obtainMessage(CMD_CELL_CONNECTION_RENEW);
                    m.arg1 = ++mCurrentConnectionSequence;
                    sendMessageDelayed(m, CELL_CONNECTION_RENEW_MS);
@@ -1139,18 +1179,17 @@ public class Tethering extends INetworkManagementEventObserver.Stub {

                return retValue;
            }
            protected boolean turnOffMobileConnection() {
                if (mMobileReserved) {
            protected boolean turnOffUpstreamMobileConnection() {
                if (mMobileApnReserved != ConnectivityManager.TYPE_NONE) {
                    IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
                    IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
                    try {
                        cm.stopUsingNetworkFeature(ConnectivityManager.TYPE_MOBILE,
                                (mDunRequired? Phone.FEATURE_ENABLE_DUN_ALWAYS :
                                             Phone.FEATURE_ENABLE_HIPRI));
                                enableString(mMobileApnReserved));
                    } catch (Exception e) {
                        return false;
                    }
                    mMobileReserved = false;
                    mMobileApnReserved = ConnectivityManager.TYPE_NONE;
                }
                return true;
            }
@@ -1196,108 +1235,55 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
                transitionTo(mInitialState);
                return true;
            }
            protected String findActiveUpstreamIface() {
                // check for what iface we can use - if none found switch to error.

            protected void chooseUpstreamType(boolean tryCell) {
                IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
                IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
                int upType = ConnectivityManager.TYPE_NONE;
                String iface = null;

                for (Integer netType : mUpstreamIfaceTypes) {
                    NetworkInfo info = null;
                    try {
                    LinkProperties defaultProp = cm.getActiveLinkProperties();
                    if (defaultProp != null) {
                        String iface = defaultProp.getInterfaceName();
                        for(String regex : mUpstreamIfaceRegexs) {
                            if (iface.matches(regex)) return iface;
                        }
                    }
                        info = cm.getNetworkInfo(netType.intValue());
                    } catch (RemoteException e) { }

                String[] ifaces = new String[0];
                try {
                    ifaces = mNMService.listInterfaces();
                } catch (Exception e) {
                    Log.e(TAG, "Error listing Interfaces", e);
                    return null;
                }

                for (String regex : mUpstreamIfaceRegexs) {
                    for (String iface : ifaces) {
                        if (iface.matches(regex)) {
                            // verify it is active
                            InterfaceConfiguration ifcg = null;
                            try {
                                ifcg = mNMService.getInterfaceConfig(iface);
                                if (ifcg.isActive()) {
                                    return iface;
                                }
                            } catch (Exception e) {
                                Log.e(TAG, "Error getting iface config", e);
                                // ignore - try next
                                continue;
                            }
                        }
                    }
                    if ((info != null) && info.isConnected()) {
                        upType = netType.intValue();
                        break;
                    }
                return null;
                }

            protected void chooseUpstreamType(boolean tryCell) {
                // decide if the current upstream is good or not and if not
                // do something about it (start up DUN if required or HiPri if not)
                String iface = findActiveUpstreamIface();
                IBinder b = ServiceManager.getService(Context.CONNECTIVITY_SERVICE);
                IConnectivityManager cm = IConnectivityManager.Stub.asInterface(b);
                mMobileReserved = false;
                if (DEBUG) {
                    Log.d(TAG, "chooseUpstreamType(" + tryCell + "),  dunRequired ="
                            + mDunRequired + ", iface=" + iface);
                }
                if (iface != null) {
                    try {
                        if (mDunRequired) {
                            // check if Dun is on - we can use that
                            NetworkInfo info = cm.getNetworkInfo(
                                    ConnectivityManager.TYPE_MOBILE_DUN);
                            if (info.isConnected()) {
                                if (DEBUG) Log.d(TAG, "setting dun ifacename =" + iface);
                                // even if we're already connected - it may be somebody else's
                                // refcount, so add our own
                                turnOnMobileConnection();
                            } else {
                                // verify the iface is not the default mobile - can't use that!
                                info = cm.getNetworkInfo(ConnectivityManager.TYPE_MOBILE);
                                if (info.isConnected()) {
                                    iface = null; // can't accept this one
                                }
                            }
                        } else {
                            if (DEBUG) Log.d(TAG, "checking if hipri brought us this connection");
                            NetworkInfo info = cm.getNetworkInfo(
                                    ConnectivityManager.TYPE_MOBILE_HIPRI);
                            if (info.isConnected()) {
                                if (DEBUG) Log.d(TAG, "yes - hipri in use");
                                // even if we're already connected - it may be sombody else's
                                // refcount, so add our own
                                turnOnMobileConnection();
                            }
                        }
                    } catch (RemoteException e) {
                        Log.e(TAG, "RemoteException calling ConnectivityManager", e);
                        iface = null;
                    Log.d(TAG, "chooseUpstreamType(" + tryCell + "), preferredApn ="
                            + mPreferredUpstreamMobileApn + ", got type=" + upType);
                }

                // if we're on DUN, put our own grab on it
                if (upType == ConnectivityManager.TYPE_MOBILE_DUN ||
                        upType == ConnectivityManager.TYPE_MOBILE_HIPRI) {
                    turnOnUpstreamMobileConnection(upType);
                }
                // may have been set to null in the if above
                if (iface == null ) {
                    boolean success = false;
                    if (tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) {
                        success = turnOnMobileConnection();

                if (upType == ConnectivityManager.TYPE_NONE) {
                    boolean tryAgainLater = true;
                    if ((tryCell == TRY_TO_SETUP_MOBILE_CONNECTION) &&
                            (turnOnUpstreamMobileConnection(mPreferredUpstreamMobileApn) == true)) {
                        // we think mobile should be coming up - don't set a retry
                        tryAgainLater = false;
                    }
                    if (!success) {
                        // wait for things to settle and retry
                    if (tryAgainLater) {
                        sendMessageDelayed(CMD_RETRY_UPSTREAM, UPSTREAM_SETTLE_TIME_MS);
                    }
                } else {
                    LinkProperties linkProperties = null;
                    try {
                        linkProperties = cm.getLinkProperties(upType);
                    } catch (RemoteException e) { }
                    if (linkProperties != null) iface = linkProperties.getInterfaceName();
                }
                notifyTetheredOfNewUpstreamIface(iface);
            }

            protected void notifyTetheredOfNewUpstreamIface(String ifaceName) {
                if (DEBUG) Log.d(TAG, "notifying tethered with iface =" + ifaceName);
                mUpstreamIfaceName = ifaceName;
@@ -1312,7 +1298,6 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
        class InitialState extends TetherMasterUtilState {
            @Override
            public void enter() {
                mMobileReserved = false;
            }
            @Override
            public boolean processMessage(Message message) {
@@ -1320,7 +1305,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
                boolean retValue = true;
                switch (message.what) {
                    case CMD_TETHER_MODE_REQUESTED:
                        mDunRequired = isDunRequired();
                        checkDunRequired();
                        TetherInterfaceSM who = (TetherInterfaceSM)message.obj;
                        if (DEBUG) Log.d(TAG, "Tether Mode requested by " + who.toString());
                        mNotifyList.add(who);
@@ -1354,7 +1339,7 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
            }
            @Override
            public void exit() {
                turnOffMobileConnection();
                turnOffUpstreamMobileConnection();
                notifyTetheredOfNewUpstreamIface(null);
            }
            @Override
@@ -1392,19 +1377,13 @@ public class Tethering extends INetworkManagementEventObserver.Stub {
                                Log.d(TAG, "renewing mobile connection - requeuing for another " +
                                        CELL_CONNECTION_RENEW_MS + "ms");
                            }
                            mMobileReserved = false; // need to renew it
                            turnOnMobileConnection();
                            turnOnUpstreamMobileConnection(mMobileApnReserved);
                        }
                        break;
                    case CMD_RETRY_UPSTREAM:
                        chooseUpstreamType(mTryCell);
                        mTryCell = !mTryCell;
                        break;
                    case CMD_IFACE_CHANGED:
                        String iface = (String)message.obj;
                        if (DEBUG) Log.d(TAG, "Activie upstream interface changed: " + iface);
                        notifyTetheredOfNewUpstreamIface(iface);
                        break;
                    default:
                        retValue = false;
                        break;