telephony/cdma: Fix Erroneous Roaming Indicators and Latitude-Longitude parsing

When Android Telephony receives response to GET_REGISTRATION_STATE
message from RIL it may contain few fields set to NULL. Due to a parsing
exception encountered while parsing that field, the remaining fields will
not be parsed even if they are valid data. Ignore all fields that are NULL
while letting it parse non-NULL data.

For Latitude and Longitude, the values should not be hexadecimal. They
shall be parsed as decimal values as specified in the 3GPP2 C.S0005-A
specification. Invalid value is changed from -1 to Integer.MAX_VALUE.

Bug: 2201613
Change-Id: I13dd02fcfa2ae7fcb6f21c4b94b830786bd7270c
diff --git a/telephony/java/android/telephony/cdma/CdmaCellLocation.java b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
index 676fba7..7ef7747 100644
--- a/telephony/java/android/telephony/cdma/CdmaCellLocation.java
+++ b/telephony/java/android/telephony/cdma/CdmaCellLocation.java
@@ -24,19 +24,35 @@
  */
 public class CdmaCellLocation extends CellLocation {
     private int mBaseStationId = -1;
-    private int mBaseStationLatitude = -1;
-    private int mBaseStationLongitude = -1;
+
+    /**
+     * Latitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
+     * It is represented in units of 0.25 seconds and ranges from -1296000
+     * to 1296000, both values inclusive (corresponding to a range of -90
+     * to +90 degrees). Integer.MAX_VALUE is considered invalid value.
+     */
+    private int mBaseStationLatitude = Integer.MAX_VALUE;
+
+    /**
+     * Longitude is a decimal number as specified in 3GPP2 C.S0005-A v6.0.
+     * It is represented in units of 0.25 seconds and ranges from -2592000
+     * to 2592000, both values inclusive (corresponding to a range of -180
+     * to +180 degrees). Integer.MAX_VALUE is considered invalid value.
+     */
+    private int mBaseStationLongitude = Integer.MAX_VALUE;
+
     private int mSystemId = -1;
     private int mNetworkId = -1;
 
     /**
      * Empty constructor.
-     * Initializes the BID, SID, NID and base station latitude and longitude to -1.
+     * Initializes the BID, SID, NID and base station latitude and longitude
+     * to invalid values.
      */
     public CdmaCellLocation() {
         this.mBaseStationId = -1;
-        this.mBaseStationLatitude = -1;
-        this.mBaseStationLongitude = -1;
+        this.mBaseStationLatitude = Integer.MAX_VALUE;
+        this.mBaseStationLongitude = Integer.MAX_VALUE;
         this.mSystemId = -1;
         this.mNetworkId = -1;
     }
@@ -60,14 +76,14 @@
     }
 
     /**
-     * @return cdma base station latitude, -1 if unknown
+     * @return cdma base station latitude, Integer.MAX_VALUE if unknown
      */
     public int getBaseStationLatitude() {
         return this.mBaseStationLatitude;
     }
 
     /**
-     * @return cdma base station longitude, -1 if unknown
+     * @return cdma base station longitude, Integer.MAX_VALUE if unknown
      */
     public int getBaseStationLongitude() {
         return this.mBaseStationLongitude;
@@ -88,12 +104,12 @@
     }
 
     /**
-     * Invalidate this object.  The cell location data is set to -1.
+     * Invalidate this object.  The cell location data is set to invalid values.
      */
     public void setStateInvalid() {
         this.mBaseStationId = -1;
-        this.mBaseStationLatitude = -1;
-        this.mBaseStationLongitude = -1;
+        this.mBaseStationLatitude = Integer.MAX_VALUE;
+        this.mBaseStationLongitude = Integer.MAX_VALUE;
         this.mSystemId = -1;
         this.mNetworkId = -1;
     }
diff --git a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
index a410f0e..3051e2f 100644
--- a/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
+++ b/telephony/java/com/android/internal/telephony/cdma/CdmaServiceStateTracker.java
@@ -350,29 +350,35 @@
             if (ar.exception == null) {
                 String states[] = (String[])ar.result;
                 int baseStationId = -1;
-                int baseStationLongitude = -1;
-                int baseStationLatitude = -1;
+                int baseStationLatitude = Integer.MAX_VALUE;
+                int baseStationLongitude = Integer.MAX_VALUE;
+                int systemId = -1;
+                int networkId = -1;
 
-                int baseStationData[] = {
-                        -1, // baseStationId
-                        -1, // baseStationLatitude
-                        -1  // baseStationLongitude
-                };
-
-                if (states.length == 3) {
-                    for(int i = 0; i < states.length; i++) {
-                        try {
-                            if (states[i] != null && states[i].length() > 0) {
-                                baseStationData[i] = Integer.parseInt(states[i], 16);
-                            }
-                        } catch (NumberFormatException ex) {
-                            Log.w(LOG_TAG, "error parsing cell location data: " + ex);
+                if (states.length > 9) {
+                    try {
+                        if (states[4] != null) {
+                            baseStationId = Integer.parseInt(states[4]);
                         }
+                        if (states[5] != null) {
+                            baseStationLatitude = Integer.parseInt(states[5]);
+                        }
+                        if (states[6] != null) {
+                            baseStationLongitude = Integer.parseInt(states[6]);
+                        }
+                        if (states[8] != null) {
+                            systemId = Integer.parseInt(states[8]);
+                        }
+                        if (states[9] != null) {
+                            networkId = Integer.parseInt(states[9]);
+                        }
+                    } catch (NumberFormatException ex) {
+                        Log.w(LOG_TAG, "error parsing cell location data: " + ex);
                     }
                 }
 
-                cellLoc.setCellLocationData(baseStationData[0],
-                        baseStationData[1], baseStationData[2]);
+                cellLoc.setCellLocationData(baseStationId, baseStationLatitude,
+                        baseStationLongitude, systemId, networkId);
                 phone.notifyLocationChanged();
             }
 
@@ -640,8 +646,8 @@
                 int registrationState = 4;     //[0] registrationState
                 int radioTechnology = -1;      //[3] radioTechnology
                 int baseStationId = -1;        //[4] baseStationId
-                int baseStationLatitude = -1;  //[5] baseStationLatitude
-                int baseStationLongitude = -1; //[6] baseStationLongitude
+                int baseStationLatitude = Integer.MAX_VALUE;  //[5] baseStationLatitude
+                int baseStationLongitude = Integer.MAX_VALUE; //[6] baseStationLongitude
                 int cssIndicator = 0;          //[7] init with 0, because it is treated as a boolean
                 int systemId = 0;              //[8] systemId
                 int networkId = 0;             //[9] networkId
@@ -652,20 +658,43 @@
 
                 if (states.length == 14) {
                     try {
-                        registrationState = Integer.parseInt(states[0]);
-                        radioTechnology = Integer.parseInt(states[3]);
-                        baseStationId = Integer.parseInt(states[4]);
-                        baseStationLatitude = Integer.parseInt(states[5], 16);
-                        baseStationLongitude = Integer.parseInt(states[6], 16);
-                        cssIndicator = Integer.parseInt(states[7]);
-                        systemId = Integer.parseInt(states[8]);
-                        networkId = Integer.parseInt(states[9]);
-                        roamingIndicator = Integer.parseInt(states[10]);
-                        systemIsInPrl = Integer.parseInt(states[11]);
-                        defaultRoamingIndicator = Integer.parseInt(states[12]);
-                        reasonForDenial = Integer.parseInt(states[13]);
-                    }
-                    catch(NumberFormatException ex) {
+                        if (states[0] != null) {
+                            registrationState = Integer.parseInt(states[0]);
+                        }
+                        if (states[3] != null) {
+                            radioTechnology = Integer.parseInt(states[3]);
+                        }
+                        if (states[4] != null) {
+                            baseStationId = Integer.parseInt(states[4]);
+                        }
+                        if (states[5] != null) {
+                            baseStationLatitude = Integer.parseInt(states[5]);
+                        }
+                        if (states[6] != null) {
+                            baseStationLongitude = Integer.parseInt(states[6]);
+                        }
+                        if (states[7] != null) {
+                            cssIndicator = Integer.parseInt(states[7]);
+                        }
+                        if (states[8] != null) {
+                            systemId = Integer.parseInt(states[8]);
+                        }
+                        if (states[9] != null) {
+                            networkId = Integer.parseInt(states[9]);
+                        }
+                        if (states[10] != null) {
+                            roamingIndicator = Integer.parseInt(states[10]);
+                        }
+                        if (states[11] != null) {
+                            systemIsInPrl = Integer.parseInt(states[11]);
+                        }
+                        if (states[12] != null) {
+                            defaultRoamingIndicator = Integer.parseInt(states[12]);
+                        }
+                        if (states[13] != null) {
+                            reasonForDenial = Integer.parseInt(states[13]);
+                        }
+                    } catch (NumberFormatException ex) {
                         Log.w(LOG_TAG, "error parsing RegistrationState: " + ex);
                     }
                 } else {