IMS: Adding Support for Emergency APN in Telephony Framework (opt/telephony)

(NOTE: No SIM case will be covered in next patch)

Change-Id: I87e653e29674f0e4821484908f799d6b84659c72

Signed-off-by: Ram <ram.pl@samsung.com>
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index be8b018..fb4a40c 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -76,6 +76,7 @@
     static final String FEATURE_ENABLE_FOTA = "enableFOTA";
     static final String FEATURE_ENABLE_IMS = "enableIMS";
     static final String FEATURE_ENABLE_CBS = "enableCBS";
+    static final String FEATURE_ENABLE_EMERGENCY = "enableEmergency";
 
     /**
      * Optional reasons for disconnect and connect
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
index 7508219..ae8986d 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTracker.java
@@ -379,7 +379,10 @@
         DctConstants.State apnContextState = apnContext.getState();
         boolean apnTypePossible = !(apnContextIsEnabled &&
                 (apnContextState == DctConstants.State.FAILED));
-        boolean dataAllowed = isDataAllowed();
+        boolean isEmergencyApn = apnContext.getApnType().equals(PhoneConstants.APN_TYPE_EMERGENCY);
+        // Set the emergency APN availability status as TRUE irrespective of conditions checked in
+        // isDataAllowed() like IN_SERVICE, MOBILE DATA status etc.
+        boolean dataAllowed = isEmergencyApn || isDataAllowed();
         boolean possible = dataAllowed && apnTypePossible;
 
         if (VDBG) {
@@ -413,6 +416,7 @@
         cm.supplyMessenger(ConnectivityManager.TYPE_MOBILE_FOTA, new Messenger(this));
         cm.supplyMessenger(ConnectivityManager.TYPE_MOBILE_IMS, new Messenger(this));
         cm.supplyMessenger(ConnectivityManager.TYPE_MOBILE_CBS, new Messenger(this));
+        cm.supplyMessenger(ConnectivityManager.TYPE_MOBILE_EMERGENCY, new Messenger(this));
     }
 
     private ApnContext addApnContext(String type, NetworkConfig networkConfig) {
@@ -460,6 +464,9 @@
             case ConnectivityManager.TYPE_MOBILE_IA:
                 apnContext = addApnContext(PhoneConstants.APN_TYPE_IA, networkConfig);
                 break;
+            case ConnectivityManager.TYPE_MOBILE_EMERGENCY:
+                apnContext = addApnContext(PhoneConstants.APN_TYPE_EMERGENCY, networkConfig);
+                break;
             default:
                 log("initApnContexts: skipping unknown type=" + networkConfig.type);
                 continue;
@@ -785,13 +792,16 @@
             return true;
         }
 
+        // Allow SETUP_DATA request for E-APN to be completed during emergency call
+        // and MOBILE DATA On/Off cases as well.
+        boolean isEmergencyApn = apnContext.getApnType().equals(PhoneConstants.APN_TYPE_EMERGENCY);
         boolean desiredPowerState = mPhone.getServiceStateTracker().getDesiredPowerState();
         boolean checkUserDataEnabled =
                     !(apnContext.getApnType().equals(PhoneConstants.APN_TYPE_IMS));
 
-        if (apnContext.isConnectable() &&
-                isDataAllowed(apnContext) &&
-                getAnyDataEnabled(checkUserDataEnabled) && !isEmergency()) {
+        if (apnContext.isConnectable() && (isEmergencyApn ||
+                (isDataAllowed(apnContext) &&
+                getAnyDataEnabled(checkUserDataEnabled) && !isEmergency()))) {
             if (apnContext.getState() == DctConstants.State.FAILED) {
                 if (DBG) log("trySetupData: make a FAILED ApnContext IDLE so its reusable");
                 apnContext.setState(DctConstants.State.IDLE);
diff --git a/src/java/com/android/internal/telephony/dataconnection/DcTrackerBase.java b/src/java/com/android/internal/telephony/dataconnection/DcTrackerBase.java
index a23bd6a..5be989d 100644
--- a/src/java/com/android/internal/telephony/dataconnection/DcTrackerBase.java
+++ b/src/java/com/android/internal/telephony/dataconnection/DcTrackerBase.java
@@ -1025,6 +1025,8 @@
             return DctConstants.APN_CBS_ID;
         } else if (TextUtils.equals(type, PhoneConstants.APN_TYPE_IA)) {
             return DctConstants.APN_IA_ID;
+        } else if (TextUtils.equals(type, PhoneConstants.APN_TYPE_EMERGENCY)) {
+            return DctConstants.APN_EMERGENCY_ID;
         } else {
             return DctConstants.APN_INVALID_ID;
         }
@@ -1050,6 +1052,8 @@
             return PhoneConstants.APN_TYPE_CBS;
         case DctConstants.APN_IA_ID:
             return PhoneConstants.APN_TYPE_IA;
+        case DctConstants.APN_EMERGENCY_ID:
+            return PhoneConstants.APN_TYPE_EMERGENCY;
         default:
             log("Unknown id (" + id + ") in apnIdToType");
             return PhoneConstants.APN_TYPE_DEFAULT;
diff --git a/src/java/com/android/internal/telephony/gsm/GSMPhone.java b/src/java/com/android/internal/telephony/gsm/GSMPhone.java
index 3dfbceb..b68a790 100644
--- a/src/java/com/android/internal/telephony/gsm/GSMPhone.java
+++ b/src/java/com/android/internal/telephony/gsm/GSMPhone.java
@@ -341,10 +341,14 @@
             // already been called
 
             ret = PhoneConstants.DataState.DISCONNECTED;
-        } else if (mSST.getCurrentDataConnectionState()
-                != ServiceState.STATE_IN_SERVICE) {
+        } else if (!apnType.equals(PhoneConstants.APN_TYPE_EMERGENCY) &&
+                mSST.getCurrentDataConnectionState() != ServiceState.STATE_IN_SERVICE) {
             // If we're out of service, open TCP sockets may still work
             // but no data will flow
+
+            // Emergency APN is available even in Out Of Service
+            // Pass the actual State of EPDN
+
             ret = PhoneConstants.DataState.DISCONNECTED;
         } else if (mDcTracker.isApnTypeEnabled(apnType) == false ||
                 mDcTracker.isApnTypeActive(apnType) == false) {