Merge change 20853

* changes:
  Add net type to mobile for mobile-required traffic
This commit is contained in:
Android (Google) Code Review
2009-08-13 14:02:08 -07:00
12 changed files with 976 additions and 526 deletions

View File

@@ -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";
public static final int TYPE_MOBILE = 0;
public static final int TYPE_WIFI = 1;
/**
* 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;
}

View File

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

View File

@@ -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",
TelephonyManager.getDefault().getNetworkTypeName());
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)
return Enum.valueOf(Phone.DataState.class, str);
else
return Phone.DataState.DISCONNECTED;
if (str != null) {
String apnTypeList =
intent.getStringExtra(Phone.DATA_APN_TYPES_KEY);
if (isApnTypeIncluded(apnTypeList)) {
return Enum.valueOf(Phone.DataState.class, str);
}
}
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,14 +343,7 @@ 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;
}
return -1;
}
/**
@@ -397,13 +359,7 @@ 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;
}
return -1;
}
/**
@@ -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)

View File

@@ -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,11 +41,16 @@ 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;
private static boolean DBG = Config.LOGV;
private static final String TAG = "NetworkStateTracker";
public static final int EVENT_STATE_CHANGED = 1;
public static final int EVENT_SCAN_RESULTS_AVAILABLE = 2;
/**
@@ -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();

View File

@@ -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>

File diff suppressed because it is too large Load Diff

View File

@@ -88,6 +88,8 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
private String mDataConnectionApn = "";
private String[] mDataConnectionApnTypes = null;
private String mDataConnectionInterfaceName = "";
private Bundle mCellLocation = new Bundle();
@@ -337,7 +339,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
public void notifyDataConnection(int state, boolean isDataConnectivityPossible,
String reason, String apn, String interfaceName) {
String reason, String apn, String[] apnTypes, String interfaceName) {
if (!checkNotifyPermission("notifyDataConnection()" )) {
return;
}
@@ -346,6 +348,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
mDataConnectionPossible = isDataConnectivityPossible;
mDataConnectionReason = reason;
mDataConnectionApn = apn;
mDataConnectionApnTypes = apnTypes;
mDataConnectionInterfaceName = interfaceName;
for (int i = mRecords.size() - 1; i >= 0; i--) {
Record r = mRecords.get(i);
@@ -359,7 +362,7 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
}
}
broadcastDataConnectionStateChanged(state, isDataConnectivityPossible, reason, apn,
interfaceName);
apnTypes, interfaceName);
}
public void notifyDataConnectionFailed(String reason) {
@@ -517,8 +520,9 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
mContext.sendBroadcast(intent, android.Manifest.permission.READ_PHONE_STATE);
}
private void broadcastDataConnectionStateChanged(int state, boolean isDataConnectivityPossible,
String reason, String apn, String interfaceName) {
private void broadcastDataConnectionStateChanged(int state,
boolean isDataConnectivityPossible,
String reason, String apn, String[] apnTypes, String interfaceName) {
// Note: not reporting to the battery stats service here, because the
// status bar takes care of that after taking into account all of the
// required info.
@@ -531,6 +535,11 @@ class TelephonyRegistry extends ITelephonyRegistry.Stub {
intent.putExtra(Phone.STATE_CHANGE_REASON_KEY, reason);
}
intent.putExtra(Phone.DATA_APN_KEY, apn);
String types = apnTypes[0];
for (int i = 1; i < apnTypes.length; i++) {
types = types+","+apnTypes[i];
}
intent.putExtra(Phone.DATA_APN_TYPES_KEY, types);
intent.putExtra(Phone.DATA_IFACE_NAME_KEY, interfaceName);
mContext.sendStickyBroadcast(intent);
}

View File

@@ -94,8 +94,11 @@ public class DefaultPhoneNotifier implements PhoneNotifier {
public void notifyDataConnection(Phone sender, String reason) {
try {
mRegistry.notifyDataConnection(convertDataState(sender.getDataConnectionState()),
sender.isDataConnectivityPossible(), reason, sender.getActiveApn(),
mRegistry.notifyDataConnection(
convertDataState(sender.getDataConnectionState()),
sender.isDataConnectivityPossible(), reason,
sender.getActiveApn(),
sender.getActiveApnTypes(),
sender.getInterfaceName(null));
} catch (RemoteException ex) {
// system process is dead

View File

@@ -32,7 +32,7 @@ interface ITelephonyRegistry {
void notifyCallForwardingChanged(boolean cfi);
void notifyDataActivity(int state);
void notifyDataConnection(int state, boolean isDataConnectivityPossible,
String reason, String apn, String interfaceName);
String reason, String apn, in String[] apnTypes, String interfaceName);
void notifyDataConnectionFailed(String reason);
void notifyCellLocation(in Bundle cellLocation);
}

View File

@@ -99,8 +99,9 @@ public interface Phone {
static final String PHONE_NAME_KEY = "phoneName";
static final String FAILURE_REASON_KEY = "reason";
static final String STATE_CHANGE_REASON_KEY = "reason";
static final String DATA_APN_TYPE_KEY = "apnType";
static final String DATA_APN_TYPES_KEY = "apnType";
static final String DATA_APN_KEY = "apn";
static final String DATA_IFACE_NAME_KEY = "iface";
static final String NETWORK_UNAVAILABLE_KEY = "networkUnvailable";
static final String PHONE_IN_ECM_STATE = "phoneinECMState";
@@ -120,10 +121,16 @@ public interface Phone {
static final String APN_TYPE_MMS = "mms";
/** APN type for SUPL assisted GPS */
static final String APN_TYPE_SUPL = "supl";
/** APN type for DUN traffic */
static final String APN_TYPE_DUN = "dun";
/** APN type for HiPri traffic */
static final String APN_TYPE_HIPRI = "hipri";
// "Features" accessible through the connectivity manager
static final String FEATURE_ENABLE_MMS = "enableMMS";
static final String FEATURE_ENABLE_SUPL = "enableSUPL";
static final String FEATURE_ENABLE_DUN = "enableDUN";
static final String FEATURE_ENABLE_HIPRI = "enableHIPRI";
/**
* Return codes for <code>enableApnType()</code>

View File

@@ -72,7 +72,10 @@ public class ApnSetting {
boolean canHandleType(String type) {
for (String t : types) {
if (t.equals(type) || t.equals(Phone.APN_TYPE_ALL)) {
// DEFAULT handles all, and HIPRI is handled by DEFAULT
if (t.equals(type) || t.equals(Phone.APN_TYPE_ALL) ||
(t.equals(Phone.APN_TYPE_DEFAULT) &&
type.equals(Phone.APN_TYPE_HIPRI))) {
return true;
}
}

View File

@@ -135,12 +135,16 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
/** Currently active PdpConnection */
private PdpConnection mActivePdp;
private static int APN_INVALID_ID = -1;
private static int APN_DEFAULT_ID = 0;
private static int APN_MMS_ID = 1;
private static int APN_SUPL_ID = 2;
private static int APN_NUM_TYPES = 3;
private static int APN_DUN_ID = 3;
private static int APN_HIPRI_ID = 4;
private static int APN_NUM_TYPES = 5;
private boolean[] dataEnabled = new boolean[APN_NUM_TYPES];
private int enabledCount = 0;
/** Is packet service restricted by network */
private boolean mIsPsRestricted = false;
@@ -213,7 +217,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
GsmDataConnectionTracker(GSMPhone p) {
super(p);
mGsmPhone = p;
p.mCM.registerForAvailable (this, EVENT_RADIO_AVAILABLE, null);
p.mCM.registerForOffOrNotAvailable(this, EVENT_RADIO_OFF_OR_NOT_AVAILABLE, null);
p.mSIMRecords.registerForRecordsLoaded(this, EVENT_RECORDS_LOADED, null);
@@ -252,6 +255,9 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
// and 2) whether the RIL will setup the baseband to auto-PS attach.
SharedPreferences sp = PreferenceManager.getDefaultSharedPreferences(phone.getContext());
dataEnabled[APN_DEFAULT_ID] = !sp.getBoolean(GSMPhone.DATA_DISABLED_ON_BOOT_KEY, false);
if (dataEnabled[APN_DEFAULT_ID]) {
enabledCount++;
}
noAutoAttach = !dataEnabled[APN_DEFAULT_ID];
if (!mRetryMgr.configure(SystemProperties.get("ro.gsm.data_retry_config"))) {
@@ -332,6 +338,22 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
return result;
}
protected int apnTypeToId(String type) {
if (TextUtils.equals(type, Phone.APN_TYPE_DEFAULT)) {
return APN_DEFAULT_ID;
} else if (TextUtils.equals(type, Phone.APN_TYPE_MMS)) {
return APN_MMS_ID;
} else if (TextUtils.equals(type, Phone.APN_TYPE_SUPL)) {
return APN_SUPL_ID;
} else if (TextUtils.equals(type, Phone.APN_TYPE_DUN)) {
return APN_DUN_ID;
} else if (TextUtils.equals(type, Phone.APN_TYPE_HIPRI)) {
return APN_HIPRI_ID;
} else {
return APN_INVALID_ID;
}
}
/**
* Ensure that we are connected to an APN of the specified type.
* @param type the APN type (currently the only valid values
@@ -343,25 +365,15 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
* the APN has been established.
*/
protected int enableApnType(String type) {
if (!TextUtils.equals(type, Phone.APN_TYPE_MMS) &&
!TextUtils.equals(type, Phone.APN_TYPE_SUPL)) {
int id = apnTypeToId(type);
if (id == APN_INVALID_ID) {
return Phone.APN_REQUEST_FAILED;
}
// If already active, return
Log.d(LOG_TAG, "enableApnType("+type+")");
if(DBG) Log.d(LOG_TAG, "enableApnType("+type+"), isApnTypeActive = "
+ isApnTypeActive(type) + " and state = " + state);
if (isApnTypeActive(type)) {
setEnabled(type, true);
removeMessages(EVENT_RESTORE_DEFAULT_APN);
/**
* We're being asked to enable a non-default APN that's already in use.
* This means we should restart the timer that will automatically
* switch back to the default APN and disable the non-default APN
* when it expires.
*/
sendMessageDelayed(
obtainMessage(EVENT_RESTORE_DEFAULT_APN),
getRestoreDefaultApnDelay());
if (state == State.INITING) return Phone.APN_REQUEST_STARTED;
else if (state == State.CONNECTED) return Phone.APN_ALREADY_ACTIVE;
}
@@ -370,7 +382,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
return Phone.APN_TYPE_NOT_AVAILABLE;
}
setEnabled(type, true);
setEnabled(id, true);
mRequestedApnType = type;
sendMessage(obtainMessage(EVENT_ENABLE_NEW_APN));
return Phone.APN_REQUEST_STARTED;
@@ -385,31 +397,21 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
* @return
*/
protected int disableApnType(String type) {
Log.d(LOG_TAG, "disableApnType("+type+")");
if ((TextUtils.equals(type, Phone.APN_TYPE_MMS) ||
TextUtils.equals(type, Phone.APN_TYPE_SUPL))
&& isEnabled(type)) {
removeMessages(EVENT_RESTORE_DEFAULT_APN);
setEnabled(type, false);
if (DBG) Log.d(LOG_TAG, "disableApnType("+type+")");
int id = apnTypeToId(type);
if (id == APN_INVALID_ID) {
return Phone.APN_REQUEST_FAILED;
}
if (isEnabled(id)) {
setEnabled(id, false);
if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
mRequestedApnType = Phone.APN_TYPE_DEFAULT;
if (dataEnabled[APN_DEFAULT_ID]) {
return Phone.APN_ALREADY_ACTIVE;
} else {
Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
msg.arg1 = 1; // tearDown is true;
msg.obj = Phone.REASON_DATA_DISABLED;
sendMessage(msg);
return Phone.APN_REQUEST_STARTED;
}
} else {
/*
* Note that if default data is disabled, the following
* has the effect of disabling the MMS APN, and then
* ignoring the request to enable the default APN.
* The net result is that data is completely disabled.
*/
sendMessage(obtainMessage(EVENT_RESTORE_DEFAULT_APN));
return Phone.APN_REQUEST_STARTED;
}
} else {
@@ -455,30 +457,30 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
return false;
}
private boolean isEnabled(String apnType) {
if (TextUtils.equals(apnType, Phone.APN_TYPE_DEFAULT)) {
return dataEnabled[APN_DEFAULT_ID];
} else if (TextUtils.equals(apnType, Phone.APN_TYPE_MMS)) {
return dataEnabled[APN_MMS_ID];
} else if (TextUtils.equals(apnType, Phone.APN_TYPE_SUPL)) {
return dataEnabled[APN_SUPL_ID];
} else {
return false;
private boolean isEnabled(int id) {
if (id != APN_INVALID_ID) {
return dataEnabled[id];
}
return false;
}
private void setEnabled(String apnType, boolean enable) {
Log.d(LOG_TAG, "setEnabled(" + apnType + ", " + enable + ')');
if (TextUtils.equals(apnType, Phone.APN_TYPE_DEFAULT)) {
dataEnabled[APN_DEFAULT_ID] = enable;
} else if (TextUtils.equals(apnType, Phone.APN_TYPE_MMS)) {
dataEnabled[APN_MMS_ID] = enable;
} else if (TextUtils.equals(apnType, Phone.APN_TYPE_SUPL)) {
dataEnabled[APN_SUPL_ID] = enable;
private void setEnabled(int id, boolean enable) {
if (DBG) Log.d(LOG_TAG, "setEnabled(" + id + ", " + enable + ')');
if (dataEnabled[id] != enable) {
dataEnabled[id] = enable;
if (enable) {
enabledCount++;
} else {
enabledCount--;
}
if (enabledCount == 0) {
setPrivateDataEnabled(false);
} else if (enabledCount == 1) {
setPrivateDataEnabled(true);
}
}
Log.d(LOG_TAG, "dataEnabled[DEFAULT_APN]=" + dataEnabled[APN_DEFAULT_ID] +
" dataEnabled[MMS_APN]=" + dataEnabled[APN_MMS_ID] +
" dataEnabled[SUPL_APN]=" + dataEnabled[APN_SUPL_ID]);
}
/**
@@ -493,30 +495,20 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
* @return {@code true} if the operation succeeded
*/
public boolean setDataEnabled(boolean enable) {
boolean isEnabled = isEnabled(Phone.APN_TYPE_DEFAULT);
Log.d(LOG_TAG, "setDataEnabled("+enable+") isEnabled=" + isEnabled);
if (!isEnabled && enable) {
setEnabled(Phone.APN_TYPE_DEFAULT, true);
// trySetupData() will be a no-op if we are currently
// connected to the MMS APN
if (DBG) Log.d(LOG_TAG, "setDataEnabled("+enable+")");
setEnabled(APN_DEFAULT_ID, enable);
return true;
}
private void setPrivateDataEnabled(boolean enable) {
if (DBG) Log.d(LOG_TAG, "setPrivateDataEnabled("+enable+")");
if (enable) {
sendMessage(obtainMessage(EVENT_TRY_SETUP_DATA));
return true;
} else if (!enable) {
setEnabled(Phone.APN_TYPE_DEFAULT, false);
// Don't tear down if there is an active APN and it handles MMS or SUPL.
// TODO: This isn't very general.
if ((isApnTypeActive(Phone.APN_TYPE_MMS) && isEnabled(Phone.APN_TYPE_MMS)) ||
(isApnTypeActive(Phone.APN_TYPE_SUPL) && isEnabled(Phone.APN_TYPE_SUPL))) {
return false;
}
} else {
Message msg = obtainMessage(EVENT_CLEAN_UP_CONNECTION);
msg.arg1 = 1; // tearDown is true
msg.obj = Phone.REASON_DATA_DISABLED;
sendMessage(msg);
return true;
} else {
// isEnabled && enable
return true;
}
}
@@ -536,7 +528,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
* {@code true} otherwise.
*/
public boolean getAnyDataEnabled() {
return dataEnabled[APN_DEFAULT_ID] || dataEnabled[APN_MMS_ID] || dataEnabled[APN_SUPL_ID];
return (enabledCount != 0);
}
/**
@@ -618,7 +610,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
if (DBG) {
log ("Setup watingApns : " + apnListToString(waitingApns));
log ("Setup waitngApns : " + apnListToString(waitingApns));
}
return setupData(reason);
} else {
@@ -629,6 +621,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
" sim=" + mGsmPhone.mSIMRecords.getRecordsLoaded() +
" UMTS=" + mGsmPhone.mSST.isConcurrentVoiceAndData() +
" phoneState=" + phone.getState() +
" isDataAllowed=" + isDataAllowed() +
" dataEnabled=" + getAnyDataEnabled() +
" roaming=" + roaming +
" dataOnRoamingEnable=" + getDataOnRoamingEnabled() +
@@ -1251,15 +1244,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
trySetupData(reason);
}
protected void onRestoreDefaultApn() {
if (DBG) Log.d(LOG_TAG, "Restore default APN");
setEnabled(Phone.APN_TYPE_MMS, false);
mRequestedApnType = Phone.APN_TYPE_DEFAULT;
if (!isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
cleanUpConnection(true, Phone.REASON_RESTORE_DEFAULT_APN);
}
}
protected void onRoamingOff() {
trySetupData(Phone.REASON_ROAMING_OFF);
}
@@ -1313,22 +1297,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
if (ar.exception == null) {
// everything is setup
/*
* We may have switched away from the default PDP context
* in order to enable a "special" APN (e.g., for MMS
* traffic). Set a timer to switch back and/or disable the
* special APN, so that a negligient application doesn't
* permanently prevent data connectivity. What we are
* protecting against here is not malicious apps, but
* rather an app that inadvertantly fails to reset to the
* default APN, or that dies before doing so.
*/
if (dataEnabled[APN_MMS_ID] || dataEnabled[APN_SUPL_ID]) {
removeMessages(EVENT_RESTORE_DEFAULT_APN);
sendMessageDelayed(obtainMessage(EVENT_RESTORE_DEFAULT_APN),
getRestoreDefaultApnDelay());
}
if (isApnTypeActive(Phone.APN_TYPE_DEFAULT)) {
SystemProperties.set("gsm.defaultpdpcontext.active", "true");
if (canSetPreferApn && preferredApn == null) {
@@ -1432,18 +1400,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
cleanUpConnection(tearDown, reason);
}
private int getRestoreDefaultApnDelay() {
String restoreApnDelayStr = SystemProperties.get(APN_RESTORE_DELAY_PROP_NAME);
if (restoreApnDelayStr != null && restoreApnDelayStr.length() != 0) {
try {
return Integer.valueOf(restoreApnDelayStr);
} catch (NumberFormatException e) {
}
}
return RESTORE_DEFAULT_APN_DELAY;
}
/**
* Based on the sim operator numeric, create a list for all possible pdps
* with all apns associated with that pdp
@@ -1568,10 +1524,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
private void startDelayedRetry(PdpConnection.FailCause cause, String reason) {
notifyNoData(cause);
if (mRequestedApnType != Phone.APN_TYPE_DEFAULT) {
sendMessage(obtainMessage(EVENT_RESTORE_DEFAULT_APN));
}
else {
if (mRequestedApnType == Phone.APN_TYPE_DEFAULT) {
reconnectAfterFail(cause, reason);
}
}
@@ -1626,7 +1579,7 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
}
public void handleMessage (Message msg) {
if (DBG) Log.d(LOG_TAG,"GSMDataConnTrack handleMessage "+msg);
switch (msg.what) {
case EVENT_RECORDS_LOADED:
onRecordsLoaded();
@@ -1636,10 +1589,6 @@ public final class GsmDataConnectionTracker extends DataConnectionTracker {
onEnableNewApn();
break;
case EVENT_RESTORE_DEFAULT_APN:
onRestoreDefaultApn();
break;
case EVENT_GPRS_DETACHED:
onGprsDetached();
break;