Revert "Revert "add apn setting parameters, and set apn parameters to bp""

This reverts commit 01f27d2c616797e5ba821159f8aca7b75aa54ae1.

Change-Id: Id9e7cf180092f320f635084f805b97f6409d0f03
diff --git a/src/java/android/provider/Telephony.java b/src/java/android/provider/Telephony.java
index e3ec3e6..a145ddd 100644
--- a/src/java/android/provider/Telephony.java
+++ b/src/java/android/provider/Telephony.java
@@ -2713,6 +2713,41 @@
          */
         public static final String SUB_ID = "sub_id";
 
+        /**
+         * The profile_id to which the APN saved in modem
+         * <p>Type: INTEGER</p>
+         *@hide
+         */
+        public static final String PROFILE_ID = "profile_id";
+
+        /**
+         * Is the apn setting to be set in modem
+         * <P>Type: INTEGER (boolean)</P>
+         *@hide
+         */
+        public static final String MODEM_COGNITIVE = "modem_cognitive";
+
+        /**
+         * The max connections of this apn
+         * <p>Type: INTEGER</p>
+         *@hide
+         */
+        public static final String MAX_CONNS = "max_conns";
+
+        /**
+         * The wait time for retry of the apn
+         * <p>Type: INTEGER</p>
+         *@hide
+         */
+        public static final String WAIT_TIME = "wait_time";
+
+        /**
+         * The time to limit max connection for the apn
+         * <p>Type: INTEGER</p>
+         *@hide
+         */
+        public static final String MAX_CONNS_TIME = "max_conns_time";
+
     }
 
     /**
diff --git a/src/java/com/android/internal/telephony/CommandsInterface.java b/src/java/com/android/internal/telephony/CommandsInterface.java
index 3d14b86..f323cbc 100644
--- a/src/java/com/android/internal/telephony/CommandsInterface.java
+++ b/src/java/com/android/internal/telephony/CommandsInterface.java
@@ -17,6 +17,7 @@
 package com.android.internal.telephony;
 
 import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
+import com.android.internal.telephony.dataconnection.DataProfile;
 import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
 import com.android.internal.telephony.uicc.IccCardStatus;
 
@@ -1728,6 +1729,16 @@
             String password, Message result);
 
     /**
+     * Set data profiles in modem
+     *
+     * @param dps
+     *            Array of the data profiles set to modem
+     * @param result
+     *            callback message contains the information of SUCCESS/FAILURE
+     */
+    public void setDataProfile(DataProfile[] dps, Message result);
+
+    /**
      * Notifiy that we are testing an emergency call
      */
     public void testingEmergencyCall();
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 96148a6..8ea6fef 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -64,6 +64,7 @@
 import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
 import com.android.internal.telephony.dataconnection.DcFailCause;
 import com.android.internal.telephony.dataconnection.DataCallResponse;
+import com.android.internal.telephony.dataconnection.DataProfile;
 import com.android.internal.telephony.TelephonyDevController;
 import com.android.internal.telephony.HardwareConfig;
 
@@ -2483,6 +2484,7 @@
             case RIL_REQUEST_GET_CELL_INFO_LIST: ret = responseCellInfoList(p); break;
             case RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE: ret = responseVoid(p); break;
             case RIL_REQUEST_SET_INITIAL_ATTACH_APN: ret = responseVoid(p); break;
+            case RIL_REQUEST_SET_DATA_PROFILE: ret = responseVoid(p); break;
             case RIL_REQUEST_IMS_REGISTRATION_STATE: ret = responseInts(p); break;
             case RIL_REQUEST_IMS_SEND_SMS: ret =  responseSMS(p); break;
             case RIL_REQUEST_SIM_TRANSMIT_APDU_BASIC: ret =  responseICC_IO(p); break;
@@ -3887,6 +3889,7 @@
             case RIL_REQUEST_GET_CELL_INFO_LIST: return "RIL_REQUEST_GET_CELL_INFO_LIST";
             case RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE: return "RIL_REQUEST_SET_CELL_INFO_LIST_RATE";
             case RIL_REQUEST_SET_INITIAL_ATTACH_APN: return "RIL_REQUEST_SET_INITIAL_ATTACH_APN";
+            case RIL_REQUEST_SET_DATA_PROFILE: return "RIL_REQUEST_SET_DATA_PROFILE";
             case RIL_REQUEST_IMS_REGISTRATION_STATE: return "RIL_REQUEST_IMS_REGISTRATION_STATE";
             case RIL_REQUEST_IMS_SEND_SMS: return "RIL_REQUEST_IMS_SEND_SMS";
             case RIL_REQUEST_SIM_TRANSMIT_APDU_BASIC: return "RIL_REQUEST_SIM_TRANSMIT_APDU_BASIC";
@@ -4260,6 +4263,23 @@
         send(rr);
     }
 
+    public void setDataProfile(DataProfile[] dps, Message result) {
+        if (RILJ_LOGD) riljLog("Set RIL_REQUEST_SET_DATA_PROFILE");
+
+        RILRequest rr = RILRequest.obtain(RIL_REQUEST_SET_DATA_PROFILE, null);
+        DataProfile.toParcel(rr.mParcel, dps);
+
+        if (RILJ_LOGD) {
+            riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+                    + " with " + dps + " Data Profiles : ");
+            for (int i = 0; i < dps.length; i++) {
+                riljLog(dps[i].toString());
+            }
+        }
+
+        send(rr);
+    }
+
     /* (non-Javadoc)
      * @see com.android.internal.telephony.BaseCommands#testingEmergencyCall()
      */
diff --git a/src/java/com/android/internal/telephony/dataconnection/ApnSetting.java b/src/java/com/android/internal/telephony/dataconnection/ApnSetting.java
index 784bfd1..891b717 100755
--- a/src/java/com/android/internal/telephony/dataconnection/ApnSetting.java
+++ b/src/java/com/android/internal/telephony/dataconnection/ApnSetting.java
@@ -27,6 +27,7 @@
 public class ApnSetting {
 
     static final String V2_FORMAT_REGEX = "^\\[ApnSettingV2\\]\\s*";
+    static final String V3_FORMAT_REGEX = "^\\[ApnSettingV3\\]\\s*";
 
     public final String carrier;
     public final String apn;
@@ -56,11 +57,19 @@
       */
     public final int bearer;
 
+    /* ID of the profile in the modem */
+    public final int profileId;
+    public final boolean modemCognitive;
+    public final int maxConns;
+    public final int waitTime;
+    public final int maxConnsTime;
+
     public ApnSetting(int id, String numeric, String carrier, String apn,
             String proxy, String port,
             String mmsc, String mmsProxy, String mmsPort,
             String user, String password, int authType, String[] types,
-            String protocol, String roamingProtocol, boolean carrierEnabled, int bearer) {
+            String protocol, String roamingProtocol, boolean carrierEnabled, int bearer,
+            int profileId, boolean modemCognitive, int maxConns, int waitTime, int maxConnsTime) {
         this.id = id;
         this.numeric = numeric;
         this.carrier = carrier;
@@ -81,6 +90,11 @@
         this.roamingProtocol = roamingProtocol;
         this.carrierEnabled = carrierEnabled;
         this.bearer = bearer;
+        this.profileId = profileId;
+        this.modemCognitive = modemCognitive;
+        this.maxConns = maxConns;
+        this.waitTime = waitTime;
+        this.maxConnsTime = maxConnsTime;
     }
 
     /**
@@ -101,6 +115,12 @@
      *   <mmsport>, <user>, <password>, <authtype>, <mcc>, <mnc>,
      *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearer>
      *
+     * v3 format:
+     *   [ApnSettingV2] <carrier>, <apn>, <proxy>, <port>, <mmsc>, <mmsproxy>,
+     *   <mmsport>, <user>, <password>, <authtype>, <mcc>, <mnc>,
+     *   <type>[| <type>...], <protocol>, <roaming_protocol>, <carrierEnabled>, <bearer>,
+     *   <profileId>, <modemCognitive>, <maxConns>, <waitTime>, <maxConnsTime>
+     *
      * Note that the strings generated by toString() do not contain the username
      * and password and thus cannot be read by this method.
      */
@@ -109,7 +129,10 @@
 
         int version;
         // matches() operates on the whole string, so append .* to the regex.
-        if (data.matches(V2_FORMAT_REGEX + ".*")) {
+        if (data.matches(V3_FORMAT_REGEX + ".*")) {
+            version = 3;
+            data = data.replaceFirst(V3_FORMAT_REGEX, "");
+        } else if (data.matches(V2_FORMAT_REGEX + ".*")) {
             version = 2;
             data = data.replaceFirst(V2_FORMAT_REGEX, "");
         } else {
@@ -132,6 +155,11 @@
         String protocol, roamingProtocol;
         boolean carrierEnabled;
         int bearer;
+        int profileId = 0;
+        boolean modemCognitive = false;
+        int maxConns = 0;
+        int waitTime = 0;
+        int maxConnsTime = 0;
         if (version == 1) {
             typeArray = new String[a.length - 13];
             System.arraycopy(a, 13, typeArray, 0, a.length - 13);
@@ -152,10 +180,21 @@
                 carrierEnabled = true;
             }
             bearer = Integer.parseInt(a[17]);
+            if(a.length > 22) {
+                try {
+                    profileId = Integer.parseInt(a[18]);
+                    modemCognitive = Boolean.parseBoolean(a[19]);
+                    maxConns = Integer.parseInt(a[20]);
+                    waitTime = Integer.parseInt(a[21]);
+                    maxConnsTime = Integer.parseInt(a[22]);
+                } catch (Exception e) {
+                }
+            }
         }
 
         return new ApnSetting(-1,a[10]+a[11],a[0],a[1],a[2],a[3],a[7],a[8],
-                a[9],a[4],a[5],authType,typeArray,protocol,roamingProtocol,carrierEnabled,bearer);
+                a[9],a[4],a[5],authType,typeArray,protocol,roamingProtocol,carrierEnabled,bearer,
+                profileId, modemCognitive, maxConns, waitTime, maxConnsTime);
     }
 
     @Override
@@ -182,10 +221,16 @@
         sb.append(", ").append(roamingProtocol);
         sb.append(", ").append(carrierEnabled);
         sb.append(", ").append(bearer);
+        sb.append(", ").append(profileId);
+        sb.append(", ").append(modemCognitive);
+        sb.append(", ").append(maxConns);
+        sb.append(", ").append(waitTime);
+        sb.append(", ").append(maxConnsTime);
         return sb.toString();
     }
 
     public boolean canHandleType(String type) {
+        if (!carrierEnabled) return false;
         for (String t : types) {
             // DEFAULT handles all, and HIPRI is handled by DEFAULT
             if (t.equalsIgnoreCase(type) ||
diff --git a/src/java/com/android/internal/telephony/dataconnection/DataProfile.java b/src/java/com/android/internal/telephony/dataconnection/DataProfile.java
new file mode 100644
index 0000000..3672e5d
--- /dev/null
+++ b/src/java/com/android/internal/telephony/dataconnection/DataProfile.java
@@ -0,0 +1,110 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.internal.telephony.dataconnection;
+
+import android.os.Parcel;
+import android.telephony.ServiceState;
+
+public class DataProfile {
+
+    static final int TYPE_COMMON = 0;
+    static final int TYPE_3GPP = 1;
+    static final int TYPE_3GPP2 = 2;
+
+    //id of the data profile
+    public final int profileId;
+    //the APN to connect to
+    public final String apn;
+    //one of the PDP_type values in TS 27.007 section 10.1.1.
+    //For example, "IP", "IPV6", "IPV4V6", or "PPP".
+    public final String protocol;
+    //authentication protocol used for this PDP context
+    //(None: 0, PAP: 1, CHAP: 2, PAP&CHAP: 3)
+    public final int authType;
+    //the username for APN, or NULL
+    public final String user;
+    //the password for APN, or NULL
+    public final String password;
+    //the profile type, TYPE_COMMON, TYPE_3GPP, TYPE_3GPP2
+    public final int type;
+    //the period in seconds to limit the maximum connections
+    public final int maxConnsTime;
+    //the maximum connections during maxConnsTime
+    public final int maxConns;
+    //the required wait time in seconds after a successful UE initiated
+    //disconnect of a given PDN connection before the device can send
+    //a new PDN connection request for that given PDN
+    public final int waitTime;
+    //true to enable the profile, false to disable
+    public final boolean enabled;
+
+
+    DataProfile(int profileId, String apn, String protocol, int authType,
+            String user, String password, int type, int maxConnsTime, int maxConns,
+            int waitTime, boolean enabled) {
+
+        this.profileId = profileId;
+        this.apn = apn;
+        this.protocol = protocol;
+        this.authType = authType;
+        this.user = user;
+        this.password = password;
+        this.type = type;
+        this.maxConnsTime = maxConnsTime;
+        this.maxConns = maxConns;
+        this.waitTime = waitTime;
+        this.enabled = enabled;
+    }
+
+    DataProfile(ApnSetting apn, boolean isRoaming) {
+        this(apn.profileId, apn.apn, isRoaming? apn.protocol : apn.roamingProtocol,
+                apn.authType, apn.user, apn.password, apn.bearer == 0 ? TYPE_COMMON :
+                (ServiceState.isCdma(apn.bearer) ? TYPE_3GPP2 : TYPE_3GPP), apn.maxConnsTime,
+                apn.maxConns, apn.waitTime, apn.carrierEnabled);
+    }
+
+    public static Parcel toParcel(Parcel pc, DataProfile[] dps) {
+
+        if(pc == null) {
+            return null;
+        }
+
+        pc.writeInt(dps.length);
+        for(int i = 0; i < dps.length; i++) {
+            pc.writeInt(dps[i].profileId);
+            pc.writeString(dps[i].apn);
+            pc.writeString(dps[i].protocol);
+            pc.writeInt(dps[i].authType);
+            pc.writeString(dps[i].user);
+            pc.writeString(dps[i].password);
+            pc.writeInt(dps[i].type);
+            pc.writeInt(dps[i].maxConnsTime);
+            pc.writeInt(dps[i].maxConns);
+            pc.writeInt(dps[i].waitTime);
+            pc.writeInt(dps[i].enabled ? 1 : 0);
+        }
+        return pc;
+    }
+
+    @Override
+    public String toString() {
+        return "DataProfile " + profileId + "/" + apn + "/" + protocol + "/" + authType
+                + "/" + user + "/" + password + "/" + type + "/" + maxConnsTime
+                + "/" + maxConns + "/" + waitTime + "/" + enabled;
+    }
+
+}
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
index 663451d..af59420 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
@@ -1123,7 +1123,14 @@
                         Telephony.Carriers.ROAMING_PROTOCOL)),
                 cursor.getInt(cursor.getColumnIndexOrThrow(
                         Telephony.Carriers.CARRIER_ENABLED)) == 1,
-                cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.BEARER)));
+                cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.BEARER)),
+                cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.PROFILE_ID)),
+                cursor.getInt(cursor.getColumnIndexOrThrow(
+                        Telephony.Carriers.MODEM_COGNITIVE)) == 1,
+                cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MAX_CONNS)),
+                cursor.getInt(cursor.getColumnIndexOrThrow(
+                        Telephony.Carriers.WAIT_TIME)),
+                cursor.getInt(cursor.getColumnIndexOrThrow(Telephony.Carriers.MAX_CONNS_TIME)));
         return apn;
     }
 
@@ -1201,8 +1208,12 @@
         ApnSetting apnSetting;
         DcAsyncChannel dcac;
 
-        int profileId = getApnProfileID(apnContext.getApnType());
         apnSetting = apnContext.getNextWaitingApn();
+        int profileId = apnSetting.profileId;
+        if (profileId == 0) {
+            profileId = getApnProfileID(apnContext.getApnType());
+        }
+
         if (apnSetting == null) {
             if (DBG) log("setupData: return for no apn found!");
             return false;
@@ -2132,7 +2143,7 @@
             String selection = "numeric = '" + operator + "'";
             // query only enabled apn.
             // carrier_enabled : 1 means enabled apn, 0 disabled apn.
-            selection += " and carrier_enabled = 1";
+            // selection += " and carrier_enabled = 1";
             if (DBG) log("createAllApnList: selection=" + selection);
 
             Cursor cursor = mPhone.getContext().getContentResolver().query(
@@ -2162,6 +2173,8 @@
             if (DBG) log("createAllApnList: mPreferredApn=" + mPreferredApn);
         }
         if (DBG) log("createAllApnList: X mAllApnSettings=" + mAllApnSettings);
+
+        setDataProfilesAsNeeded();
     }
 
     /** Return the DC AsyncChannel for the new data connection */
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTrackerBase.java b/src/java/com/android/internal/telephony/dataconnection/DcTrackerBase.java
index 2eedec1..3d5984c 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTrackerBase.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTrackerBase.java
@@ -23,6 +23,7 @@
 import android.content.Context;
 import android.content.Intent;
 import android.content.IntentFilter;
+import android.content.res.Resources;
 import android.content.SharedPreferences;
 import android.database.ContentObserver;
 import android.net.ConnectivityManager;
@@ -48,6 +49,7 @@
 import android.text.TextUtils;
 import android.util.EventLog;
 import android.telephony.Rlog;
+import android.telephony.ServiceState;
 
 import com.android.internal.R;
 import com.android.internal.telephony.DctConstants;
@@ -1723,6 +1725,23 @@
         }
     }
 
+    protected void setDataProfilesAsNeeded() {
+        if (DBG) log("setDataProfilesAsNeeded");
+        if (mAllApnSettings != null && !mAllApnSettings.isEmpty()) {
+            ArrayList<DataProfile> dps = new ArrayList<DataProfile>();
+            for (ApnSetting apn : mAllApnSettings) {
+                if (apn.modemCognitive) {
+                    DataProfile dp = new DataProfile(apn,
+                            mPhone.getServiceState().getRoaming());
+                    dps.add(dp);
+                }
+            }
+            if(dps.size() > 0) {
+                mPhone.mCi.setDataProfile(dps.toArray(new DataProfile[0]), null);
+            }
+        }
+    }
+
     protected void onActionIntentProvisioningApnAlarm(Intent intent) {
         if (DBG) log("onActionIntentProvisioningApnAlarm: action=" + intent.getAction());
         Message msg = obtainMessage(DctConstants.EVENT_PROVISIONING_APN_ALARM,
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java
index b804075..28bcf6a 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCommandInterface.java
@@ -24,6 +24,7 @@
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.UUSInfo;
 import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
+import com.android.internal.telephony.dataconnection.DataProfile;
 import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
 
 /**
@@ -559,6 +560,10 @@
     }
 
     @Override
+    public void setDataProfile(DataProfile[] dps, Message result) {
+    }
+
+    @Override
     public void iccOpenLogicalChannel(String AID, Message response) {}
 
     @Override
diff --git a/src/java/com/android/internal/telephony/sip/SipCommandInterface.java b/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
index 83f95fb..433e9f2 100644
--- a/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
+++ b/src/java/com/android/internal/telephony/sip/SipCommandInterface.java
@@ -24,6 +24,7 @@
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.UUSInfo;
 import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
+import com.android.internal.telephony.dataconnection.DataProfile;
 import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
 
 /**
@@ -561,6 +562,10 @@
     }
 
     @Override
+    public void setDataProfile(DataProfile[] dps, Message result) {
+    }
+
+    @Override
     public void iccOpenLogicalChannel(String AID, Message response) {
     }
 
diff --git a/src/java/com/android/internal/telephony/test/SimulatedCommands.java b/src/java/com/android/internal/telephony/test/SimulatedCommands.java
index 0aef631..11bc6ad 100644
--- a/src/java/com/android/internal/telephony/test/SimulatedCommands.java
+++ b/src/java/com/android/internal/telephony/test/SimulatedCommands.java
@@ -27,6 +27,7 @@
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo;
 import com.android.internal.telephony.dataconnection.DataCallResponse;
+import com.android.internal.telephony.dataconnection.DataProfile;
 import com.android.internal.telephony.Phone;
 import com.android.internal.telephony.UUSInfo;
 import com.android.internal.telephony.gsm.CallFailCause;
@@ -1668,6 +1669,10 @@
     }
 
     @Override
+    public void setDataProfile(DataProfile[] dps, Message result) {
+    }
+
+    @Override
     public void getImsRegistrationState(Message response) {
         unimplemented(response);
     }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java b/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java
index e64b597..5ce74d1 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/gsm/UsimDataDownloadCommands.java
@@ -646,6 +646,10 @@
     }
 
     @Override
+    public void setDataProfile(DataProfile[] dps, Message result) {
+    }
+
+    @Override
     public void getIMSIForApp(String aid, Message result) {
     }