Merge "Allow GSM RSSI levels to be customized by CarrierConfig"
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 0dd6614..c2b8661 100755
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2598,6 +2598,19 @@
     public static final String KEY_IS_OPPORTUNISTIC_SUBSCRIPTION_BOOL =
             "key_is_opportunistic_subscription_bool";
 
+    /**
+     * A list of 4 GSM RSSI thresholds above which a signal level is considered POOR,
+     * MODERATE, GOOD, or EXCELLENT, to be used in SignalStrength reporting.
+     *
+     * Note that the min and max thresholds are fixed at -113 and -51, as set in 3GPP TS 27.007
+     * section 8.5.
+     * <p>
+     * See CellSignalStrengthGsm#GSM_RSSI_MAX and CellSignalStrengthGsm#GSM_RSSI_MIN. Any signal
+     * level outside these boundaries is considered invalid.
+     * @hide
+     */
+    public static final String KEY_GSM_RSSI_THRESHOLDS_INT_ARRAY =
+            "gsm_rssi_thresholds_int_array";
 
     /** The default value for every variable. */
     private final static PersistableBundle sDefaults;
@@ -2992,6 +3005,13 @@
                 false);
         sDefaults.putString(KEY_SUBSCRIPTION_GROUP_UUID_STRING, "");
         sDefaults.putBoolean(KEY_IS_OPPORTUNISTIC_SUBSCRIPTION_BOOL, false);
+        sDefaults.putIntArray(KEY_GSM_RSSI_THRESHOLDS_INT_ARRAY,
+                new int[] {
+                        -107, /* SIGNAL_STRENGTH_POOR */
+                        -103, /* SIGNAL_STRENGTH_MODERATE */
+                        -97, /* SIGNAL_STRENGTH_GOOD */
+                        -89,  /* SIGNAL_STRENGTH_GREAT */
+                });
     }
 
     /**
diff --git a/telephony/java/android/telephony/CellSignalStrengthGsm.java b/telephony/java/android/telephony/CellSignalStrengthGsm.java
index c304db2..591f972 100644
--- a/telephony/java/android/telephony/CellSignalStrengthGsm.java
+++ b/telephony/java/android/telephony/CellSignalStrengthGsm.java
@@ -38,6 +38,10 @@
     private static final int GSM_RSSI_GOOD = -97;
     private static final int GSM_RSSI_MODERATE = -103;
     private static final int GSM_RSSI_POOR = -107;
+    private static final int GSM_RSSI_MIN = -113;
+
+    private static final int[] sRssiThresholds = new int[] {
+            GSM_RSSI_POOR, GSM_RSSI_MODERATE, GSM_RSSI_GOOD, GSM_RSSI_GREAT};
 
     private int mRssi; // in dBm [-113, -51] or UNAVAILABLE
     @UnsupportedAppUsage
@@ -54,7 +58,7 @@
 
     /** @hide */
     public CellSignalStrengthGsm(int rssi, int ber, int ta) {
-        mRssi = inRangeOrUnavailable(rssi, -113, -51);
+        mRssi = inRangeOrUnavailable(rssi, GSM_RSSI_MIN, GSM_RSSI_MAX);
         mBitErrorRate = inRangeOrUnavailable(ber, 0, 7, 99);
         mTimingAdvance = inRangeOrUnavailable(ta, 0, 219);
         updateLevel(null, null);
@@ -108,12 +112,22 @@
     /** @hide */
     @Override
     public void updateLevel(PersistableBundle cc, ServiceState ss) {
-        if (mRssi > GSM_RSSI_MAX) mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
-        else if (mRssi >= GSM_RSSI_GREAT) mLevel = SIGNAL_STRENGTH_GREAT;
-        else if (mRssi >= GSM_RSSI_GOOD)  mLevel = SIGNAL_STRENGTH_GOOD;
-        else if (mRssi >= GSM_RSSI_MODERATE)  mLevel = SIGNAL_STRENGTH_MODERATE;
-        else if (mRssi >= GSM_RSSI_POOR) mLevel = SIGNAL_STRENGTH_POOR;
-        else mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+        int[] rssiThresholds;
+        if (cc == null) {
+            rssiThresholds = sRssiThresholds;
+        } else {
+            rssiThresholds = cc.getIntArray(CarrierConfigManager.KEY_GSM_RSSI_THRESHOLDS_INT_ARRAY);
+            if (rssiThresholds == null || rssiThresholds.length != NUM_SIGNAL_STRENGTH_THRESHOLDS) {
+                rssiThresholds = sRssiThresholds;
+            }
+        }
+        int level = NUM_SIGNAL_STRENGTH_THRESHOLDS;
+        if (mRssi < GSM_RSSI_MIN || mRssi > GSM_RSSI_MAX) {
+            mLevel = SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
+            return;
+        }
+        while (level > 0 && mRssi < rssiThresholds[level - 1]) level--;
+        mLevel = level;
     }
 
     /**