Cleanup ConnectivityServices network configuration

Don't instantiate objects not needed for the device.

bug: 2226064
diff --git a/core/java/android/net/MobileDataStateTracker.java b/core/java/android/net/MobileDataStateTracker.java
index 538e51a..b254961 100644
--- a/core/java/android/net/MobileDataStateTracker.java
+++ b/core/java/android/net/MobileDataStateTracker.java
@@ -60,12 +60,11 @@
      * @param apnType the Phone apnType
      * @param tag the name of this network
      */
-    public MobileDataStateTracker(Context context, Handler target,
-            int netType, String apnType, String tag) {
+    public MobileDataStateTracker(Context context, Handler target, int netType, String tag) {
         super(context, target, netType,
                 TelephonyManager.getDefault().getNetworkType(), tag,
                 TelephonyManager.getDefault().getNetworkTypeName());
-        mApnType = apnType;
+        mApnType = networkTypeToApnType(netType);
         mPhoneService = null;
         if(netType == ConnectivityManager.TYPE_MOBILE) {
             mEnabled = true;
@@ -501,4 +500,22 @@
                 + " APN type \"" + apnType + "\"");
         return Phone.APN_REQUEST_FAILED;
     }
+
+    public static String networkTypeToApnType(int netType) {
+        switch(netType) {
+            case ConnectivityManager.TYPE_MOBILE:
+                return Phone.APN_TYPE_DEFAULT;  // TODO - use just one of these
+            case ConnectivityManager.TYPE_MOBILE_MMS:
+                return Phone.APN_TYPE_MMS;
+            case ConnectivityManager.TYPE_MOBILE_SUPL:
+                return Phone.APN_TYPE_SUPL;
+            case ConnectivityManager.TYPE_MOBILE_DUN:
+                return Phone.APN_TYPE_DUN;
+            case ConnectivityManager.TYPE_MOBILE_HIPRI:
+                return Phone.APN_TYPE_HIPRI;
+            default:
+                Log.e(TAG, "Error mapping networkType " + netType + " to apnType.");
+                return null;
+        }
+    }
 }
diff --git a/core/res/res/values/config.xml b/core/res/res/values/config.xml
index 0b6f97e..cc54ba3 100644
--- a/core/res/res/values/config.xml
+++ b/core/res/res/values/config.xml
@@ -46,26 +46,30 @@
 
     <!-- XXXXX NOTE THE FOLLOWING RESOURCES USE THE WRONG NAMING CONVENTION.
          Please don't copy them, copy anything else. -->
-         
-    <!-- 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]  -->
+
+    <!-- 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],
+         [associated radio-type],[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>
+        <item>"wifi,1,1,1"</item>
+        <item>"mobile,0,0,0"</item>
+        <item>"mobile_mms,2,0,2"</item>
+        <item>"mobile_supl,3,0,2"</item>
+        <item>"mobile_hipri,5,0,3"</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]"             -->
+    <!-- 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 "[ConnectivityManager connectionType],
+                      [# simultaneous connection types]"  -->
     <string-array translatable="false" name="radioAttributes">
-        <item>"wifi,1,1"</item>
-        <item>"mobile,0,1"</item>
+        <item>"1,1"</item>
+        <item>"0,1"</item>
     </string-array>
-    
+
     <!-- Flag indicating whether the keyguard should be bypassed when
          the slider is open.  This can be set or unset depending how easily
          the slider can be opened (for example, in a pocket or purse). -->
diff --git a/services/java/com/android/server/ConnectivityService.java b/services/java/com/android/server/ConnectivityService.java
index a91635e..16d8b7f 100644
--- a/services/java/com/android/server/ConnectivityService.java
+++ b/services/java/com/android/server/ConnectivityService.java
@@ -114,45 +114,24 @@
         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]);
         }
         public boolean isDefault() {
             return (mType == mRadio);
         }
     }
     NetworkAttributes[] mNetAttributes;
+    int mNetworksDefined;
 
     private class RadioAttributes {
-        public String mName;
-        public int mPriority;
         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 +188,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 +276,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 +310,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 +358,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 +389,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 +416,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 +428,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 +496,8 @@
                     ": " + feature);
         }
         enforceChangePermission();
-        if (!ConnectivityManager.isNetworkTypeValid(networkType)) {
+        if (!ConnectivityManager.isNetworkTypeValid(networkType) ||
+                mNetAttributes[networkType] == null) {
             return Phone.APN_REQUEST_FAILED;
         }
 
@@ -659,7 +663,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);
@@ -697,9 +704,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;
         }
@@ -737,7 +745,7 @@
         int numConnectedNets = 0;
 
         for (NetworkStateTracker nt : mNetTrackers) {
-            if (nt.getNetworkInfo().isConnected() &&
+            if (nt != null && nt.getNetworkInfo().isConnected() &&
                     !nt.isTeardownRequested()) {
                 ++numConnectedNets;
             }
@@ -814,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
@@ -825,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;
                     }
                 }
             }
@@ -1198,7 +1203,7 @@
         }
         pw.println();
         for (NetworkStateTracker nst : mNetTrackers) {
-            if (nst.getNetworkInfo().isConnected()) {
+            if (nst != null && nst.getNetworkInfo().isConnected()) {
                 pw.println("Active network: " + nst.getNetworkInfo().
                         getTypeName());
             }