Merge commit 'goog/eclair-plus-aosp'
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index 78215b0..2981599 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -56,9 +56,6 @@
private static final boolean DBG = true;
private static final String TAG = "ConnectivityService";
- // Event log tags (must be in sync with event-log-tags)
- private static final int EVENTLOG_CONNECTIVITY_STATE_CHANGED = 50020;
-
// how long to wait before switching back to a radio's default network
private static final int RESTORE_DEFAULT_NETWORK_DELAY = 1 * 60 * 1000;
// system property that can override the above value
@@ -101,9 +98,9 @@
private List mFeatureUsers;
private boolean mSystemReady;
- private ArrayList<Intent> mDeferredBroadcasts;
+ private Intent mInitialBroadcast;
- private class NetworkAttributes {
+ private static class NetworkAttributes {
/**
* Class for holding settings read from resources.
*/
@@ -111,48 +108,29 @@
public int mType;
public int mRadio;
public int mPriority;
+ public NetworkInfo.State mLastState;
public NetworkAttributes(String init) {
String fragments[] = init.split(",");
mName = fragments[0].toLowerCase();
- if (fragments[1].toLowerCase().equals("wifi")) {
- mRadio = ConnectivityManager.TYPE_WIFI;
- } else {
- mRadio = ConnectivityManager.TYPE_MOBILE;
- }
- if (mName.equals("default")) {
- mType = mRadio;
- } else if (mName.equals("mms")) {
- mType = ConnectivityManager.TYPE_MOBILE_MMS;
- } else if (mName.equals("supl")) {
- mType = ConnectivityManager.TYPE_MOBILE_SUPL;
- } else if (mName.equals("dun")) {
- mType = ConnectivityManager.TYPE_MOBILE_DUN;
- } else if (mName.equals("hipri")) {
- mType = ConnectivityManager.TYPE_MOBILE_HIPRI;
- }
- mPriority = Integer.parseInt(fragments[2]);
+ mType = Integer.parseInt(fragments[1]);
+ mRadio = Integer.parseInt(fragments[2]);
+ mPriority = Integer.parseInt(fragments[3]);
+ mLastState = NetworkInfo.State.UNKNOWN;
}
public boolean isDefault() {
return (mType == mRadio);
}
}
NetworkAttributes[] mNetAttributes;
+ int mNetworksDefined;
- private class RadioAttributes {
- public String mName;
- public int mPriority;
+ private static class RadioAttributes {
public int mSimultaneity;
public int mType;
public RadioAttributes(String init) {
String fragments[] = init.split(",");
- mName = fragments[0].toLowerCase();
- mPriority = Integer.parseInt(fragments[1]);
- mSimultaneity = Integer.parseInt(fragments[2]);
- if (mName.equals("wifi")) {
- mType = ConnectivityManager.TYPE_WIFI;
- } else {
- mType = ConnectivityManager.TYPE_MOBILE;
- }
+ mType = Integer.parseInt(fragments[0]);
+ mSimultaneity = Integer.parseInt(fragments[1]);
}
}
RadioAttributes[] mRadioAttributes;
@@ -209,48 +187,87 @@
mNetworkPreference = getPersistedNetworkPreference();
+ mRadioAttributes = new RadioAttributes[ConnectivityManager.MAX_RADIO_TYPE+1];
+ mNetAttributes = new NetworkAttributes[ConnectivityManager.MAX_NETWORK_TYPE+1];
+
// Load device network attributes from resources
- mNetAttributes = new NetworkAttributes[
- ConnectivityManager.MAX_NETWORK_TYPE+1];
- mRadioAttributes = new RadioAttributes[
- ConnectivityManager.MAX_RADIO_TYPE+1];
- String[] naStrings = context.getResources().getStringArray(
- com.android.internal.R.array.networkAttributes);
- // TODO - what if the setting has gaps/unknown types?
- for (String a : naStrings) {
- NetworkAttributes n = new NetworkAttributes(a);
- mNetAttributes[n.mType] = n;
- }
String[] raStrings = context.getResources().getStringArray(
com.android.internal.R.array.radioAttributes);
- for (String a : raStrings) {
- RadioAttributes r = new RadioAttributes(a);
+ for (String raString : raStrings) {
+ RadioAttributes r = new RadioAttributes(raString);
+ if (r.mType > ConnectivityManager.MAX_RADIO_TYPE) {
+ Log.e(TAG, "Error in radioAttributes - ignoring attempt to define type " + r.mType);
+ continue;
+ }
+ if (mRadioAttributes[r.mType] != null) {
+ Log.e(TAG, "Error in radioAttributes - ignoring attempt to redefine type " +
+ r.mType);
+ continue;
+ }
mRadioAttributes[r.mType] = r;
}
- // high priority first
- mPriorityList = new int[naStrings.length];
- {
- int priority = 0; //lowest
- int nextPos = naStrings.length-1;
- while (nextPos>-1) {
- for (int i = 0; i < mNetAttributes.length; i++) {
- if(mNetAttributes[i].mPriority == priority) {
- mPriorityList[nextPos--] = i;
- }
+ String[] naStrings = context.getResources().getStringArray(
+ com.android.internal.R.array.networkAttributes);
+ for (String naString : naStrings) {
+ try {
+ NetworkAttributes n = new NetworkAttributes(naString);
+ if (n.mType > ConnectivityManager.MAX_NETWORK_TYPE) {
+ Log.e(TAG, "Error in networkAttributes - ignoring attempt to define type " +
+ n.mType);
+ continue;
}
- priority++;
+ if (mNetAttributes[n.mType] != null) {
+ Log.e(TAG, "Error in networkAttributes - ignoring attempt to redefine type " +
+ n.mType);
+ continue;
+ }
+ if (mRadioAttributes[n.mRadio] == null) {
+ Log.e(TAG, "Error in networkAttributes - ignoring attempt to use undefined " +
+ "radio " + n.mRadio + " in network type " + n.mType);
+ continue;
+ }
+ mNetAttributes[n.mType] = n;
+ mNetworksDefined++;
+ } catch(Exception e) {
+ // ignore it - leave the entry null
}
}
- mNetRequestersPids =
- new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
- for (int i=0; i<=ConnectivityManager.MAX_NETWORK_TYPE; i++) {
+ // high priority first
+ mPriorityList = new int[mNetworksDefined];
+ {
+ int insertionPoint = mNetworksDefined-1;
+ int currentLowest = 0;
+ int nextLowest = 0;
+ while (insertionPoint > -1) {
+ for (NetworkAttributes na : mNetAttributes) {
+ if (na == null) continue;
+ if (na.mPriority < currentLowest) continue;
+ if (na.mPriority > currentLowest) {
+ if (na.mPriority < nextLowest || nextLowest == 0) {
+ nextLowest = na.mPriority;
+ }
+ continue;
+ }
+ mPriorityList[insertionPoint--] = na.mType;
+ }
+ currentLowest = nextLowest;
+ nextLowest = 0;
+ }
+ }
+
+ mNetRequestersPids = new ArrayList[ConnectivityManager.MAX_NETWORK_TYPE+1];
+ for (int i : mPriorityList) {
mNetRequestersPids[i] = new ArrayList();
}
mFeatureUsers = new ArrayList();
+ mNumDnsEntries = 0;
+
+ mTestMode = SystemProperties.get("cm.test.mode").equals("true")
+ && SystemProperties.get("ro.build.type").equals("eng");
/*
* Create the network state trackers for Wi-Fi and mobile
* data. Maybe this could be done with a factory class,
@@ -258,49 +275,33 @@
* the number of different network types is not going
* to change very often.
*/
- if (DBG) Log.v(TAG, "Starting Wifi Service.");
- WifiStateTracker wst = new WifiStateTracker(context, mHandler);
- WifiService wifiService = new WifiService(context, wst);
- ServiceManager.addService(Context.WIFI_SERVICE, wifiService);
- mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
+ for (int netType : mPriorityList) {
+ switch (mNetAttributes[netType].mRadio) {
+ case ConnectivityManager.TYPE_WIFI:
+ if (DBG) Log.v(TAG, "Starting Wifi Service.");
+ WifiStateTracker wst = new WifiStateTracker(context, mHandler);
+ WifiService wifiService = new WifiService(context, wst);
+ ServiceManager.addService(Context.WIFI_SERVICE, wifiService);
+ mNetTrackers[ConnectivityManager.TYPE_WIFI] = wst;
+ wst.startMonitoring();
- mNetTrackers[ConnectivityManager.TYPE_MOBILE] =
- new MobileDataStateTracker(context, mHandler,
- ConnectivityManager.TYPE_MOBILE, Phone.APN_TYPE_DEFAULT,
- "MOBILE");
-
- mNetTrackers[ConnectivityManager.TYPE_MOBILE_MMS] =
- new MobileDataStateTracker(context, mHandler,
- ConnectivityManager.TYPE_MOBILE_MMS, Phone.APN_TYPE_MMS,
- "MOBILE_MMS");
-
- mNetTrackers[ConnectivityManager.TYPE_MOBILE_SUPL] =
- new MobileDataStateTracker(context, mHandler,
- ConnectivityManager.TYPE_MOBILE_SUPL, Phone.APN_TYPE_SUPL,
- "MOBILE_SUPL");
-
- mNetTrackers[ConnectivityManager.TYPE_MOBILE_DUN] =
- new MobileDataStateTracker(context, mHandler,
- ConnectivityManager.TYPE_MOBILE_DUN, Phone.APN_TYPE_DUN,
- "MOBILE_DUN");
-
- mNetTrackers[ConnectivityManager.TYPE_MOBILE_HIPRI] =
- new MobileDataStateTracker(context, mHandler,
- ConnectivityManager.TYPE_MOBILE_HIPRI, Phone.APN_TYPE_HIPRI,
- "MOBILE_HIPRI");
-
- mNumDnsEntries = 0;
-
- mTestMode = SystemProperties.get("cm.test.mode").equals("true")
- && SystemProperties.get("ro.build.type").equals("eng");
-
- for (NetworkStateTracker t : mNetTrackers)
- t.startMonitoring();
-
- // Constructing this starts it too
- mWifiWatchdogService = new WifiWatchdogService(context, wst);
+ // Constructing this starts it too
+ mWifiWatchdogService = new WifiWatchdogService(context, wst);
+ break;
+ case ConnectivityManager.TYPE_MOBILE:
+ mNetTrackers[netType] = new MobileDataStateTracker(context, mHandler,
+ netType, mNetAttributes[netType].mName);
+ mNetTrackers[netType].startMonitoring();
+ break;
+ default:
+ Log.e(TAG, "Trying to create a DataStateTracker for an unknown radio type " +
+ mNetAttributes[netType].mRadio);
+ continue;
+ }
+ }
}
+
/**
* Sets the preferred network.
* @param preference the new preference
@@ -308,6 +309,7 @@
public synchronized void setNetworkPreference(int preference) {
enforceChangePermission();
if (ConnectivityManager.isNetworkTypeValid(preference) &&
+ mNetAttributes[preference] != null &&
mNetAttributes[preference].isDefault()) {
if (mNetworkPreference != preference) {
persistNetworkPreference(preference);
@@ -355,7 +357,7 @@
return;
for (int t=0; t <= ConnectivityManager.MAX_RADIO_TYPE; t++) {
- if (t != mNetworkPreference &&
+ if (t != mNetworkPreference && mNetTrackers[t] != null &&
mNetTrackers[t].getNetworkInfo().isConnected()) {
if (DBG) {
Log.d(TAG, "tearing down " +
@@ -386,7 +388,7 @@
public NetworkInfo getActiveNetworkInfo() {
enforceAccessPermission();
for (int type=0; type <= ConnectivityManager.MAX_NETWORK_TYPE; type++) {
- if (!mNetAttributes[type].isDefault()) {
+ if (mNetAttributes[type] == null || !mNetAttributes[type].isDefault()) {
continue;
}
NetworkStateTracker t = mNetTrackers[type];
@@ -413,10 +415,10 @@
public NetworkInfo[] getAllNetworkInfo() {
enforceAccessPermission();
- NetworkInfo[] result = new NetworkInfo[mNetTrackers.length];
+ NetworkInfo[] result = new NetworkInfo[mNetworksDefined];
int i = 0;
for (NetworkStateTracker t : mNetTrackers) {
- result[i++] = t.getNetworkInfo();
+ if(t != null) result[i++] = t.getNetworkInfo();
}
return result;
}
@@ -425,7 +427,7 @@
boolean result = true;
enforceChangePermission();
for (NetworkStateTracker t : mNetTrackers) {
- result = t.setRadio(turnOn) && result;
+ if (t != null) result = t.setRadio(turnOn) && result;
}
return result;
}
@@ -493,7 +495,8 @@
": " + feature);
}
enforceChangePermission();
- if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
+ if (!ConnectivityManager.isNetworkTypeValid(networkType) ||
+ mNetAttributes[networkType] == null) {
return Phone.APN_REQUEST_FAILED;
}
@@ -572,6 +575,8 @@
// javadoc from interface
public int stopUsingNetworkFeature(int networkType, String feature) {
+ enforceChangePermission();
+
int pid = getCallingPid();
int uid = getCallingUid();
@@ -611,7 +616,7 @@
Log.d(TAG, "stopUsingNetworkFeature for net " + networkType +
": " + feature);
}
- enforceChangePermission();
+
if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
return -1;
}
@@ -657,7 +662,10 @@
}
}
tracker = mNetTrackers[usedNetworkType];
- if(usedNetworkType != networkType) {
+ if (tracker == null) {
+ return -1;
+ }
+ if (usedNetworkType != networkType) {
Integer currentPid = new Integer(pid);
reassessPidDns(pid, true);
mNetRequestersPids[usedNetworkType].remove(currentPid);
@@ -695,9 +703,10 @@
}
NetworkStateTracker tracker = mNetTrackers[networkType];
- if (!tracker.getNetworkInfo().isConnected() || tracker.isTeardownRequested()) {
+ if (tracker == null || !tracker.getNetworkInfo().isConnected() ||
+ tracker.isTeardownRequested()) {
if (DBG) {
- Log.d(TAG, "requestRouteToHost on down network (" + networkType + " - dropped");
+ Log.d(TAG, "requestRouteToHost on down network (" + networkType + ") - dropped");
}
return false;
}
@@ -735,7 +744,7 @@
int numConnectedNets = 0;
for (NetworkStateTracker nt : mNetTrackers) {
- if (nt.getNetworkInfo().isConnected() &&
+ if (nt != null && nt.getNetworkInfo().isConnected() &&
!nt.isTeardownRequested()) {
++numConnectedNets;
}
@@ -785,6 +794,7 @@
}
Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
if (info.isFailover()) {
intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
@@ -812,9 +822,8 @@
int newPriority = -1;
for (int checkType=0; checkType <=
ConnectivityManager.MAX_NETWORK_TYPE; checkType++) {
- if (checkType == prevNetType) {
- continue;
- }
+ if (checkType == prevNetType) continue;
+ if (mNetAttributes[checkType] == null) continue;
if (mNetAttributes[checkType].isDefault()) {
/* TODO - if we have multiple nets we could use
* we may want to put more thought into which we choose
@@ -823,11 +832,9 @@
newType = checkType;
break;
}
- if (mRadioAttributes[mNetAttributes[checkType].mRadio].
- mPriority > newPriority) {
+ if (mNetAttributes[checkType].mPriority > newPriority) {
newType = checkType;
- newPriority = mRadioAttributes[mNetAttributes[newType].
- mRadio].mPriority;
+ newPriority = mNetAttributes[newType].mPriority;
}
}
}
@@ -884,6 +891,7 @@
private void sendConnectedBroadcast(NetworkInfo info) {
Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
if (info.isFailover()) {
intent.putExtra(ConnectivityManager.EXTRA_IS_FAILOVER, true);
@@ -921,6 +929,7 @@
}
Intent intent = new Intent(ConnectivityManager.CONNECTIVITY_ACTION);
+ intent.addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING);
intent.putExtra(ConnectivityManager.EXTRA_NETWORK_INFO, info);
if (getActiveNetworkInfo() == null) {
intent.putExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, true);
@@ -940,26 +949,20 @@
private void sendStickyBroadcast(Intent intent) {
synchronized(this) {
- if (mSystemReady) {
- mContext.sendStickyBroadcast(intent);
- } else {
- if (mDeferredBroadcasts == null) {
- mDeferredBroadcasts = new ArrayList<Intent>();
- }
- mDeferredBroadcasts.add(intent);
+ if (!mSystemReady) {
+ mInitialBroadcast = new Intent(intent);
}
+ intent.addFlags(Intent.FLAG_RECEIVER_REGISTERED_ONLY_BEFORE_BOOT);
+ mContext.sendStickyBroadcast(intent);
}
}
void systemReady() {
synchronized(this) {
mSystemReady = true;
- if (mDeferredBroadcasts != null) {
- int count = mDeferredBroadcasts.size();
- for (int i = 0; i < count; i++) {
- mContext.sendStickyBroadcast(mDeferredBroadcasts.get(i));
- }
- mDeferredBroadcasts = null;
+ if (mInitialBroadcast != null) {
+ mContext.sendStickyBroadcast(mInitialBroadcast);
+ mInitialBroadcast = null;
}
}
}
@@ -1196,7 +1199,7 @@
}
pw.println();
for (NetworkStateTracker nst : mNetTrackers) {
- if (nst.getNetworkInfo().isConnected()) {
+ if (nst != null && nst.getNetworkInfo().isConnected()) {
pw.println("Active network: " + nst.getNetworkInfo().
getTypeName());
}
@@ -1214,9 +1217,22 @@
switch (msg.what) {
case NetworkStateTracker.EVENT_STATE_CHANGED:
info = (NetworkInfo) msg.obj;
+ int type = info.getType();
+ NetworkInfo.State state = info.getState();
+ if(mNetAttributes[type].mLastState == state) {
+ if (DBG) {
+ // TODO - remove this after we validate the dropping doesn't break anything
+ Log.d(TAG, "Dropping ConnectivityChange for " +
+ info.getTypeName() +": " +
+ state + "/" + info.getDetailedState());
+ }
+ return;
+ }
+ mNetAttributes[type].mLastState = state;
+
if (DBG) Log.d(TAG, "ConnectivityChange for " +
info.getTypeName() + ": " +
- info.getState() + "/" + info.getDetailedState());
+ state + "/" + info.getDetailedState());
// Connectivity state changed:
// [31-13] Reserved for future use
@@ -1228,16 +1244,15 @@
int eventLogParam = (info.getType() & 0x7) |
((info.getDetailedState().ordinal() & 0x3f) << 3) |
(info.getSubtype() << 9);
- EventLog.writeEvent(EVENTLOG_CONNECTIVITY_STATE_CHANGED,
+ EventLog.writeEvent(EventLogTags.CONNECTIVITY_STATE_CHANGED,
eventLogParam);
if (info.getDetailedState() ==
NetworkInfo.DetailedState.FAILED) {
handleConnectionFailure(info);
- } else if (info.getState() ==
- NetworkInfo.State.DISCONNECTED) {
+ } else if (state == NetworkInfo.State.DISCONNECTED) {
handleDisconnect(info);
- } else if (info.getState() == NetworkInfo.State.SUSPENDED) {
+ } else if (state == NetworkInfo.State.SUSPENDED) {
// TODO: need to think this over.
// the logic here is, handle SUSPENDED the same as
// DISCONNECTED. The only difference being we are
@@ -1246,7 +1261,7 @@
// opportunity to handle DISCONNECTED and SUSPENDED
// differently, or not.
handleDisconnect(info);
- } else if (info.getState() == NetworkInfo.State.CONNECTED) {
+ } else if (state == NetworkInfo.State.CONNECTED) {
handleConnect(info);
}
break;