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

Commit a9085a59 authored by Android (Google) Code Review's avatar Android (Google) Code Review
Browse files

Merge change 20853

* changes:
  Add net type to mobile for mobile-required traffic
parents bcda5e03 42acef37
Loading
Loading
Loading
Loading
+55 −4
Original line number Diff line number Diff line
@@ -18,6 +18,7 @@ package android.net;

import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
import android.os.Binder;
import android.os.RemoteException;

/**
@@ -114,15 +115,64 @@ public class ConnectivityManager
    public static final String ACTION_BACKGROUND_DATA_SETTING_CHANGED =
            "android.net.conn.BACKGROUND_DATA_SETTING_CHANGED";

    /**
     * The Default Mobile data connection.  When active, all data traffic
     * will use this connection by default.  Should not coexist with other
     * default connections.
     */
    public static final int TYPE_MOBILE      = 0;
    /**
     * The Default WIFI data connection.  When active, all data traffic
     * will use this connection by default.  Should not coexist with other
     * default connections.
     */
    public static final int TYPE_WIFI        = 1;
    /**
     * An MMS-specific Mobile data connection.  This connection may be the
     * same as {@link #TYPEMOBILE} but it may be different.  This is used
     * by applications needing to talk to the carrier's Multimedia Messaging
     * Service servers.  It may coexist with default data connections.
     * {@hide}
     */
    public static final int TYPE_MOBILE_MMS  = 2;
    /**
     * A SUPL-specific Mobile data connection.  This connection may be the
     * same as {@link #TYPEMOBILE} but it may be different.  This is used
     * by applications needing to talk to the carrier's Secure User Plane
     * Location servers for help locating the device.  It may coexist with
     * default data connections.
     * {@hide}
     */
    public static final int TYPE_MOBILE_SUPL = 3;
    /**
     * A DUN-specific Mobile data connection.  This connection may be the
     * same as {@link #TYPEMOBILE} but it may be different.  This is used
     * by applicaitons performing a Dial Up Networking bridge so that
     * the carrier is aware of DUN traffic.  It may coexist with default data
     * connections.
     * {@hide}
     */
    public static final int TYPE_MOBILE_DUN  = 4;
    /**
     * A High Priority Mobile data connection.  This connection is typically
     * the same as {@link #TYPEMOBILE} but the routing setup is different.
     * Only requesting processes will have access to the Mobile DNS servers
     * and only IP's explicitly requested via {@link #requestRouteToHost}
     * will route over this interface.
     *{@hide}
     */
    public static final int TYPE_MOBILE_HIPRI = 5;
    /** {@hide} */
    public static final int MAX_RADIO_TYPE   = TYPE_WIFI;
    /** {@hide} */
    public static final int MAX_NETWORK_TYPE = TYPE_MOBILE_HIPRI;

    public static final int DEFAULT_NETWORK_PREFERENCE = TYPE_WIFI;

    private IConnectivityManager mService;

    static public boolean isNetworkTypeValid(int networkType) {
        return networkType == TYPE_WIFI || networkType == TYPE_MOBILE;
        return networkType >= 0 && networkType <= MAX_NETWORK_TYPE;
    }

    public void setNetworkPreference(int preference) {
@@ -195,7 +245,8 @@ public class ConnectivityManager
     */
    public int startUsingNetworkFeature(int networkType, String feature) {
        try {
            return mService.startUsingNetworkFeature(networkType, feature);
            return mService.startUsingNetworkFeature(networkType, feature,
                    new Binder());
        } catch (RemoteException e) {
            return -1;
        }
+3 −1
Original line number Diff line number Diff line
@@ -17,6 +17,7 @@
package android.net;

import android.net.NetworkInfo;
import android.os.IBinder;

/**
 * Interface that answers queries about, and allows changing, the
@@ -39,7 +40,8 @@ interface IConnectivityManager

    boolean setRadio(int networkType, boolean turnOn);

    int startUsingNetworkFeature(int networkType, in String feature);
    int startUsingNetworkFeature(int networkType, in String feature,
            in IBinder binder);

    int stopUsingNetworkFeature(int networkType, in String feature);

+92 −173
Original line number Diff line number Diff line
@@ -32,9 +32,6 @@ import android.telephony.TelephonyManager;
import android.util.Log;
import android.text.TextUtils;

import java.util.List;
import java.util.ArrayList;

/**
 * Track the state of mobile data connectivity. This is done by
 * receiving broadcast intents from the Phone process whenever
@@ -45,36 +42,47 @@ import java.util.ArrayList;
public class MobileDataStateTracker extends NetworkStateTracker {

    private static final String TAG = "MobileDataStateTracker";
    private static final boolean DBG = false;
    private static final boolean DBG = true;

    private Phone.DataState mMobileDataState;
    private ITelephony mPhoneService;
    private static final String[] sDnsPropNames = {
          "net.rmnet0.dns1",
          "net.rmnet0.dns2",
          "net.eth0.dns1",
          "net.eth0.dns2",
          "net.eth0.dns3",
          "net.eth0.dns4",
          "net.gprs.dns1",
          "net.gprs.dns2"
    };
    private List<String> mDnsServers;
    private String mInterfaceName;
    private int mDefaultGatewayAddr;
    private int mLastCallingPid = -1;

    private String mApnType;
    private boolean mEnabled;
    private boolean mTeardownRequested;

    /**
     * Create a new MobileDataStateTracker
     * @param context the application context of the caller
     * @param target a message handler for getting callbacks about state changes
     * @param netType the ConnectivityManager network type
     * @param apnType the Phone apnType
     * @param tag the name of this network
     */
    public MobileDataStateTracker(Context context, Handler target) {
        super(context, target, ConnectivityManager.TYPE_MOBILE,
              TelephonyManager.getDefault().getNetworkType(), "MOBILE",
    public MobileDataStateTracker(Context context, Handler target,
            int netType, String apnType, String tag) {
        super(context, target, netType,
                TelephonyManager.getDefault().getNetworkType(), tag,
                TelephonyManager.getDefault().getNetworkTypeName());
        mApnType = apnType;
        mPhoneService = null;
        mDnsServers = new ArrayList<String>();
        mTeardownRequested = false;
        if(netType == ConnectivityManager.TYPE_MOBILE) {
            mEnabled = true;
        } else {
            mEnabled = false;
        }

        mDnsPropNames = new String[] {
                "net.rmnet0.dns1",
                "net.rmnet0.dns2",
                "net.eth0.dns1",
                "net.eth0.dns2",
                "net.eth0.dns3",
                "net.eth0.dns4",
                "net.gprs.dns1",
                "net.gprs.dns2"};

    }

    /**
@@ -93,31 +101,70 @@ public class MobileDataStateTracker extends NetworkStateTracker {
            mMobileDataState = Phone.DataState.DISCONNECTED;
    }

    private static Phone.DataState getMobileDataState(Intent intent) {
    private Phone.DataState getMobileDataState(Intent intent) {
        String str = intent.getStringExtra(Phone.STATE_KEY);
        if (str != null)
        if (str != null) {
            String apnTypeList =
                    intent.getStringExtra(Phone.DATA_APN_TYPES_KEY);
            if (isApnTypeIncluded(apnTypeList)) {
                return Enum.valueOf(Phone.DataState.class, str);
        else
            }
        }
        return Phone.DataState.DISCONNECTED;
    }

    private boolean isApnTypeIncluded(String typeList) {
        /* comma seperated list - split and check */
        if (typeList == null)
            return false;

        String[] list = typeList.split(",");
        for(int i=0; i< list.length; i++) {
            if (TextUtils.equals(list[i], mApnType) ||
                TextUtils.equals(list[i], Phone.APN_TYPE_ALL)) {
                return true;
            }
        }
        return false;
    }

    private class MobileDataStateReceiver extends BroadcastReceiver {
        public void onReceive(Context context, Intent intent) {
            if (intent.getAction().equals(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
            if (intent.getAction().equals(TelephonyIntents.
                    ACTION_ANY_DATA_CONNECTION_STATE_CHANGED)) {
                Phone.DataState state = getMobileDataState(intent);
                String reason = intent.getStringExtra(Phone.STATE_CHANGE_REASON_KEY);
                String reason =
                        intent.getStringExtra(Phone.STATE_CHANGE_REASON_KEY);
                String apnName = intent.getStringExtra(Phone.DATA_APN_KEY);
                boolean unavailable = intent.getBooleanExtra(Phone.NETWORK_UNAVAILABLE_KEY, false);
                if (DBG) Log.d(TAG, "Received " + intent.getAction() +
                    " broadcast - state = " + state
                    + ", unavailable = " + unavailable
                    + ", reason = " + (reason == null ? "(unspecified)" : reason));

                String apnTypeList =
                        intent.getStringExtra(Phone.DATA_APN_TYPES_KEY);

                boolean unavailable = intent.getBooleanExtra(
                        Phone.NETWORK_UNAVAILABLE_KEY, false);
                if (DBG) Log.d(TAG, mApnType + " Received "
                        + intent.getAction() + " broadcast - state = "
                        + state + ", unavailable = " + unavailable
                        + ", reason = "
                        + (reason == null ? "(unspecified)" : reason));

                if ((!isApnTypeIncluded(apnTypeList)) || mEnabled == false) {
                    if (DBG) Log.e(TAG, "  dropped - mEnabled = "+mEnabled);
                    return;
                }


                mNetworkInfo.setIsAvailable(!unavailable);
                if (mMobileDataState != state) {
                    mMobileDataState = state;

                    switch (state) {
                    case DISCONNECTED:
                        if(mTeardownRequested) {
                            mEnabled = false;
                            mTeardownRequested = false;
                        }

                        setDetailedState(DetailedState.DISCONNECTED, reason, apnName);
                        if (mInterfaceName != null) {
                            NetworkUtils.resetConnections(mInterfaceName);
@@ -136,12 +183,12 @@ public class MobileDataStateTracker extends NetworkStateTracker {
                        if (mInterfaceName == null) {
                            Log.d(TAG, "CONNECTED event did not supply interface name.");
                        }
                        setupDnsProperties();
                        setDetailedState(DetailedState.CONNECTED, reason, apnName);
                        break;
                    }
                }
            } else if (intent.getAction().equals(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED)) {
                mEnabled = false;
                String reason = intent.getStringExtra(Phone.FAILURE_REASON_KEY);
                String apnName = intent.getStringExtra(Phone.DATA_APN_KEY);
                if (DBG) Log.d(TAG, "Received " + intent.getAction() + " broadcast" +
@@ -154,40 +201,6 @@ public class MobileDataStateTracker extends NetworkStateTracker {
        }
    }

    /**
     * Make sure that route(s) exist to the carrier DNS server(s).
     */
    public void addPrivateRoutes() {
        if (mInterfaceName != null) {
            for (String addrString : mDnsServers) {
                int addr = NetworkUtils.lookupHost(addrString);
                if (addr != -1) {
                    NetworkUtils.addHostRoute(mInterfaceName, addr);
                }
            }
        }
    }

    public void removePrivateRoutes() {
        if(mInterfaceName != null) {
            NetworkUtils.removeHostRoutes(mInterfaceName);
        }
    }

    public void removeDefaultRoute() {
        if(mInterfaceName != null) {
            mDefaultGatewayAddr = NetworkUtils.getDefaultRoute(mInterfaceName);
            NetworkUtils.removeDefaultRoute(mInterfaceName);
        }
    }

    public void restoreDefaultRoute() {
        // 0 is not a valid address for a gateway
        if (mInterfaceName != null && mDefaultGatewayAddr != 0) {
            NetworkUtils.setDefaultRoute(mInterfaceName, mDefaultGatewayAddr);
        }
    }

    private void getPhoneService(boolean forceRefresh) {
        if ((mPhoneService == null) || forceRefresh) {
            mPhoneService = ITelephony.Stub.asInterface(ServiceManager.getService("phone"));
@@ -218,15 +231,6 @@ public class MobileDataStateTracker extends NetworkStateTracker {
        return false;
    }

    /**
     * Return the IP addresses of the DNS servers available for the mobile data
     * network interface.
     * @return a list of DNS addresses, with no holes.
     */
    public String[] getNameServers() {
        return getNameServerList(sDnsPropNames);
    }

    /**
     * {@inheritDoc}
     * The mobile data network subtype indicates what generation network technology is in effect,
@@ -273,54 +277,19 @@ public class MobileDataStateTracker extends NetworkStateTracker {
     */
    @Override
    public boolean teardown() {
        getPhoneService(false);
        /*
         * If the phone process has crashed in the past, we'll get a
         * RemoteException and need to re-reference the service.
         */
        for (int retry = 0; retry < 2; retry++) {
            if (mPhoneService == null) {
                Log.w(TAG,
                    "Ignoring mobile data teardown request because could not acquire PhoneService");
                break;
            }

            try {
                return mPhoneService.disableDataConnectivity();
            } catch (RemoteException e) {
                if (retry == 0) getPhoneService(true);
            }
        }

        Log.w(TAG, "Failed to tear down mobile data connectivity");
        return false;
        mTeardownRequested = true;
        return (setEnableApn(mApnType, false) != Phone.APN_REQUEST_FAILED);
    }

    /**
     * Re-enable mobile data connectivity after a {@link #teardown()}.
     */
    public boolean reconnect() {
        getPhoneService(false);
        /*
         * If the phone process has crashed in the past, we'll get a
         * RemoteException and need to re-reference the service.
         */
        for (int retry = 0; retry < 2; retry++) {
            if (mPhoneService == null) {
                Log.w(TAG,
                    "Ignoring mobile data connect request because could not acquire PhoneService");
                break;
            }

            try {
                return mPhoneService.enableDataConnectivity();
            } catch (RemoteException e) {
                if (retry == 0) getPhoneService(true);
            }
        }

        Log.w(TAG, "Failed to set up mobile data connectivity");
        return false;
        mEnabled = true;
        mTeardownRequested = false;
        mEnabled = (setEnableApn(mApnType, true) !=
                Phone.APN_REQUEST_FAILED);
        return mEnabled;
    }

    /**
@@ -374,15 +343,8 @@ public class MobileDataStateTracker extends NetworkStateTracker {
     * </ul>
     */
    public int startUsingNetworkFeature(String feature, int callingPid, int callingUid) {
        if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
            mLastCallingPid = callingPid;
            return setEnableApn(Phone.APN_TYPE_MMS, true);
        } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
            return setEnableApn(Phone.APN_TYPE_SUPL, true);
        } else {
        return -1;
    }
    }

    /**
     * Tells the phone sub-system that the caller is finished
@@ -397,14 +359,8 @@ public class MobileDataStateTracker extends NetworkStateTracker {
     * the value {@code -1} always indicates failure.
     */
    public int stopUsingNetworkFeature(String feature, int callingPid, int callingUid) {
        if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
            return setEnableApn(Phone.APN_TYPE_MMS, false);
        } else if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_SUPL)) {
            return setEnableApn(Phone.APN_TYPE_SUPL, false);
        } else {
        return -1;
    }
    }

    /**
     * Ensure that a network route exists to deliver traffic to the specified
@@ -433,43 +389,6 @@ public class MobileDataStateTracker extends NetworkStateTracker {
        return sb.toString();
    }

    private void setupDnsProperties() {
        mDnsServers.clear();
        // Set up per-process DNS server list on behalf of the MMS process
        int i = 1;
        if (mInterfaceName != null) {
            for (String propName : sDnsPropNames) {
                if (propName.indexOf(mInterfaceName) != -1) {
                    String propVal = SystemProperties.get(propName);
                    if (propVal != null && propVal.length() != 0 && !propVal.equals("0.0.0.0")) {
                        mDnsServers.add(propVal);
                        if (mLastCallingPid != -1) {
                            SystemProperties.set("net.dns"  + i + "." + mLastCallingPid, propVal);
                        }
                        ++i;
                    }
                }
            }
        }
        if (i == 1) {
            Log.d(TAG, "DNS server addresses are not known.");
        } else if (mLastCallingPid != -1) {
            /*
            * Bump the property that tells the name resolver library
            * to reread the DNS server list from the properties.
            */
            String propVal = SystemProperties.get("net.dnschange");
            if (propVal.length() != 0) {
                try {
                    int n = Integer.parseInt(propVal);
                    SystemProperties.set("net.dnschange", "" + (n+1));
                } catch (NumberFormatException e) {
                }
            }
        }
        mLastCallingPid = -1;
    }

   /**
     * Internal method supporting the ENABLE_MMS feature.
     * @param apnType the type of APN to be enabled or disabled (e.g., mms)
+64 −9
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import android.text.TextUtils;
import android.util.Config;
import android.util.Log;


/**
 * Each subclass of this class keeps track of the state of connectivity
 * of a network interface. All state information for a network should
@@ -40,6 +41,11 @@ public abstract class NetworkStateTracker extends Handler {
    protected NetworkInfo mNetworkInfo;
    protected Context mContext;
    protected Handler mTarget;
    protected String mInterfaceName;
    protected String[] mDnsPropNames;
    private boolean mPrivateDnsRouteSet;
    protected int mDefaultGatewayAddr;
    private boolean mDefaultRouteSet;
    private boolean mTeardownRequested;

    private static boolean DBG = Config.LOGV;
@@ -56,6 +62,7 @@ public abstract class NetworkStateTracker extends Handler {
    public static final int EVENT_CONFIGURATION_CHANGED = 4;
    public static final int EVENT_ROAMING_CHANGED = 5;
    public static final int EVENT_NETWORK_SUBTYPE_CHANGED = 6;
    public static final int EVENT_RESTORE_DEFAULT_NETWORK = 7;

    public NetworkStateTracker(Context context,
            Handler target,
@@ -67,6 +74,7 @@ public abstract class NetworkStateTracker extends Handler {
        mContext = context;
        mTarget = target;
        mTeardownRequested = false;

        this.mNetworkInfo = new NetworkInfo(networkType, subType, typeName, subtypeName);
    }

@@ -74,19 +82,21 @@ public abstract class NetworkStateTracker extends Handler {
        return mNetworkInfo;
    }

    /**
     * Return the list of DNS servers associated with this network.
     * @return a list of the IP addresses of the DNS servers available
     * for the network.
     */
    public abstract String[] getNameServers();

    /**
     * Return the system properties name associated with the tcp buffer sizes
     * for this network.
     */
    public abstract String getTcpBufferSizesPropName();

    /**
     * Return the IP addresses of the DNS servers available for the mobile data
     * network interface.
     * @return a list of DNS addresses, with no holes.
     */
    public String[] getNameServers() {
        return getNameServerList(mDnsPropNames);
    }

    /**
     * Return the IP addresses of the DNS servers available for this
     * network interface.
@@ -112,6 +122,50 @@ public abstract class NetworkStateTracker extends Handler {
        return dnsAddresses;
    }

    public void addPrivateDnsRoutes() {
        if (DBG) Log.d(TAG, "addPrivateDnsRoutes for " + this +
                "(" + mInterfaceName + ")");
        if (mInterfaceName != null && !mPrivateDnsRouteSet) {
            for (String addrString : getNameServers()) {
                int addr = NetworkUtils.lookupHost(addrString);
                if (addr != -1) {
                    NetworkUtils.addHostRoute(mInterfaceName, addr);
                }
            }
            mPrivateDnsRouteSet = true;
        }
    }

    public void removePrivateDnsRoutes() {
        if (DBG) Log.d(TAG, "removePrivateDnsRoutes for " + this +
                "(" + mInterfaceName + ")");
        // TODO - we should do this explicitly but the NetUtils api doesnt
        // support this yet - must remove all.  No worse than before
        if (mInterfaceName != null && mPrivateDnsRouteSet) {
            NetworkUtils.removeHostRoutes(mInterfaceName);
            mPrivateDnsRouteSet = false;
        }
    }

    public void addDefaultRoute() {
        if (DBG) Log.d(TAG, "addDefaultRoute for " + this + "(" +
                mInterfaceName + "), GatewayAddr=" + mDefaultGatewayAddr);
        if ((mInterfaceName != null) && (mDefaultGatewayAddr != 0) &&
                mDefaultRouteSet == false) {
            NetworkUtils.setDefaultRoute(mInterfaceName, mDefaultGatewayAddr);
            mDefaultRouteSet = true;
        }
    }

    public void removeDefaultRoute() {
        if (DBG) Log.d(TAG, "removeDefaultRoute for " + this + "(" +
                mInterfaceName + ")");
        if (mInterfaceName != null && mDefaultRouteSet == true) {
            NetworkUtils.removeDefaultRoute(mInterfaceName);
            mDefaultRouteSet = false;
        }
    }

    /**
     * Reads the network specific TCP buffer sizes from SystemProperties
     * net.tcp.buffersize.[default|wifi|umts|edge|gprs] and set them for system
@@ -209,6 +263,7 @@ public abstract class NetworkStateTracker extends Handler {
     * @param extraInfo optional {@code String} providing extra information about the state change
     */
    public void setDetailedState(NetworkInfo.DetailedState state, String reason, String extraInfo) {
        if (DBG) Log.d(TAG, "setDetailed state, old ="+mNetworkInfo.getDetailedState()+" and new state="+state);
        if (state != mNetworkInfo.getDetailedState()) {
            boolean wasConnecting = (mNetworkInfo.getState() == NetworkInfo.State.CONNECTING);
            String lastReason = mNetworkInfo.getReason();
+19 −0
Original line number Diff line number Diff line
@@ -38,4 +38,23 @@
    <!-- Flag indicating whether Last Name comes before First Name.
        This becomes true in Japan, for example.-->
    <bool name="config_lastname_comes_before_firstname">false</bool>

    <!-- 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 hardward -->
    <!-- An Array of "[type-name],[associated radio-name],[priority]  -->
    <string-array translatable="false" name="networkAttributes">
        <item>"default,wifi,0"</item>
        <item>"default,mobile,0"</item>
        <item>"mms,mobile,1"</item>
        <item>"supl,mobile,1"</item>
        <item>"dun,mobile,1"</item>
        <item>"hipri,mobile,2"</item>
    </string-array>

    <!-- This string array should be overridden by the device to present a list of radio attributes.  This is used by the connectivity manager to decide which networks can coexist based on the hardware -->
    <!-- An Array of "[radio-name],[priority]                        -->
    <!--              [# simultaneous connection types]"             -->
    <string-array translatable="false" name="radioAttributes">
        <item>"wifi,1,1"</item>
        <item>"mobile,0,1"</item>
    </string-array>
</resources>
Loading