FileDocCategorySizeDatePackage
MobileDataStateTracker.javaAPI DocAndroid 1.5 API18815Wed May 06 22:41:54 BST 2009android.net

MobileDataStateTracker

public class MobileDataStateTracker extends NetworkStateTracker
Track the state of mobile data connectivity. This is done by receiving broadcast intents from the Phone process whenever the state of data connectivity changes. {@hide}

Fields Summary
private static final String
TAG
private static final boolean
DBG
private Phone.DataState
mMobileDataState
private com.android.internal.telephony.ITelephony
mPhoneService
private static final String[]
sDnsPropNames
private List
mDnsServers
private String
mInterfaceName
private int
mDefaultGatewayAddr
private int
mLastCallingPid
Constructors Summary
public MobileDataStateTracker(android.content.Context context, android.os.Handler target)
Create a new MobileDataStateTracker

param
context the application context of the caller
param
target a message handler for getting callbacks about state changes


                                
         
        super(context, target, ConnectivityManager.TYPE_MOBILE,
              TelephonyManager.getDefault().getNetworkType(), "MOBILE",
              TelephonyManager.getDefault().getNetworkTypeName());
        mPhoneService = null;
        mDnsServers = new ArrayList<String>();
    
Methods Summary
public voidaddPrivateRoutes()
Make sure that route(s) exist to the carrier DNS server(s).

        if (mInterfaceName != null) {
            for (String addrString : mDnsServers) {
                int addr = NetworkUtils.lookupHost(addrString);
                if (addr != -1) {
                    NetworkUtils.addHostRoute(mInterfaceName, addr);
                }
            }
        }
    
private static Phone.DataStategetMobileDataState(android.content.Intent intent)

        String str = intent.getStringExtra(Phone.STATE_KEY);
        if (str != null)
            return Enum.valueOf(Phone.DataState.class, str);
        else
            return Phone.DataState.DISCONNECTED;
    
public java.lang.String[]getNameServers()
Return the IP addresses of the DNS servers available for the mobile data network interface.

return
a list of DNS addresses, with no holes.

        return getNameServerList(sDnsPropNames);
    
public intgetNetworkSubtype()
{@inheritDoc} The mobile data network subtype indicates what generation network technology is in effect, e.g., GPRS, EDGE, UMTS, etc.

        return TelephonyManager.getDefault().getNetworkType();
    
private voidgetPhoneService(boolean forceRefresh)

        if ((mPhoneService == null) || forceRefresh) {
            mPhoneService = ITelephony.Stub.asInterface(ServiceManager.getService("phone"));
        }
    
public java.lang.StringgetTcpBufferSizesPropName()
Return the system properties name associated with the tcp buffer sizes for this network.

      String networkTypeStr = "unknown";
        TelephonyManager tm = new TelephonyManager(mContext);
        switch(tm.getNetworkType()) {
          case TelephonyManager.NETWORK_TYPE_GPRS:
            networkTypeStr = "gprs";
            break;
          case TelephonyManager.NETWORK_TYPE_EDGE:
            networkTypeStr = "edge";
            break;
          case TelephonyManager.NETWORK_TYPE_UMTS:
            networkTypeStr = "umts";
            break;
        }
        return "net.tcp.buffersize." + networkTypeStr;
    
public booleanisAvailable()
Report whether data connectivity is possible.

        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) break;

            try {
                return mPhoneService.isDataConnectivityPossible();
            } catch (RemoteException e) {
                // First-time failed, get the phone service again
                if (retry == 0) getPhoneService(true);
            }
        }
        
        return false;
    
public booleanreconnect()
Re-enable mobile data connectivity after a {@link #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 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;
    
public voidremoveDefaultRoute()

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

        if(mInterfaceName != null) {
            NetworkUtils.removeHostRoutes(mInterfaceName);
        }
    
public booleanrequestRouteToHost(int hostAddress)
Ensure that a network route exists to deliver traffic to the specified host via the mobile data network.

param
hostAddress the IP address of the host to which the route is desired, in network byte order.
return
{@code true} on success, {@code false} on failure

        if (mInterfaceName != null && hostAddress != -1) {
            if (DBG) {
                Log.d(TAG, "Requested host route to " + Integer.toHexString(hostAddress));
            }
            return NetworkUtils.addHostRoute(mInterfaceName, hostAddress) == 0;
        } else {
            return false;
        }
    
public voidrestoreDefaultRoute()

        // 0 is not a valid address for a gateway
        if (mInterfaceName != null && mDefaultGatewayAddr != 0) {
            NetworkUtils.setDefaultRoute(mInterfaceName, mDefaultGatewayAddr);
        }
    
private intsetEnableApn(java.lang.String apnType, boolean enable)
Internal method supporting the ENABLE_MMS feature.

param
apnType the type of APN to be enabled or disabled (e.g., mms)
param
enable {@code true} to enable the specified APN type, {@code false} to disable it.
return
an integer value representing the outcome of the request.

        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 feature request because could not acquire PhoneService");
                break;
            }

            try {
                if (enable) {
                    return mPhoneService.enableApnType(apnType);
                } else {
                    return mPhoneService.disableApnType(apnType);
                }
            } catch (RemoteException e) {
                if (retry == 0) getPhoneService(true);
            }
        }

        Log.w(TAG, "Could not " + (enable ? "enable" : "disable")
                + " APN type \"" + apnType + "\"");
        return Phone.APN_REQUEST_FAILED;
    
public booleansetRadio(boolean turnOn)
Turn on or off the mobile radio. No connectivity will be possible while the radio is off. The operation is a no-op if the radio is already in the desired state.

param
turnOn {@code true} if the radio should be turned on, {@code false} if

        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 radio request because could not acquire PhoneService");
                break;
            }
            
            try {
                return mPhoneService.setRadio(turnOn);
            } catch (RemoteException e) {
                if (retry == 0) getPhoneService(true);
            }
        }

        Log.w(TAG, "Could not set radio power to " + (turnOn ? "on" : "off"));
        return false;
    
private voidsetupDnsProperties()

        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;
    
public voidstartMonitoring()
Begin monitoring mobile data connectivity.

        IntentFilter filter =
                new IntentFilter(TelephonyIntents.ACTION_ANY_DATA_CONNECTION_STATE_CHANGED);
        filter.addAction(TelephonyIntents.ACTION_DATA_CONNECTION_FAILED);
        filter.addAction(TelephonyIntents.ACTION_SERVICE_STATE_CHANGED);

        Intent intent = mContext.registerReceiver(new MobileDataStateReceiver(), filter);
        if (intent != null)
            mMobileDataState = getMobileDataState(intent);
        else
            mMobileDataState = Phone.DataState.DISCONNECTED;
    
public intstartUsingNetworkFeature(java.lang.String feature, int callingPid, int callingUid)
Tells the phone sub-system that the caller wants to begin using the named feature. The only supported feature at this time is {@code Phone.FEATURE_ENABLE_MMS}, which allows an application to specify that it wants to send and/or receive MMS data.

param
feature the name of the feature to be used
param
callingPid the process ID of the process that is issuing this request
param
callingUid the user ID of the process that is issuing this request
return
an integer value representing the outcome of the request. The interpretation of this value is feature-specific. specific, except that the value {@code -1} always indicates failure. For {@code Phone.FEATURE_ENABLE_MMS}, the other possible return values are
  • {@code Phone.APN_ALREADY_ACTIVE}
  • {@code Phone.APN_REQUEST_STARTED}
  • {@code Phone.APN_TYPE_NOT_AVAILABLE}
  • {@code Phone.APN_REQUEST_FAILED}

        if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
            mLastCallingPid = callingPid;
            return setEnableApn(Phone.APN_TYPE_MMS, true);
        } else {
            return -1;
        }
    
public intstopUsingNetworkFeature(java.lang.String feature, int callingPid, int callingUid)
Tells the phone sub-system that the caller is finished using the named feature. The only supported feature at this time is {@code Phone.FEATURE_ENABLE_MMS}, which allows an application to specify that it wants to send and/or receive MMS data.

param
feature the name of the feature that is no longer needed
param
callingPid the process ID of the process that is issuing this request
param
callingUid the user ID of the process that is issuing this request
return
an integer value representing the outcome of the request. The interpretation of this value is feature-specific, except that the value {@code -1} always indicates failure.

        if (TextUtils.equals(feature, Phone.FEATURE_ENABLE_MMS)) {
            return setEnableApn(Phone.APN_TYPE_MMS, false);
        } else {
            return -1;
        }
    
public booleanteardown()
Tear down mobile data connectivity, i.e., disable the ability to create mobile data connections.

        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;
    
public java.lang.StringtoString()

        StringBuffer sb = new StringBuffer("Mobile data state: ");

        sb.append(mMobileDataState);
        return sb.toString();