OSDN Git Service

Encode the Number of MNC Digits in CellIdentity
authorNathan Harold <nharold@google.com>
Mon, 20 Aug 2018 18:38:27 +0000 (11:38 -0700)
committerNathan Harold <nharold@google.com>
Fri, 21 Sep 2018 04:34:22 +0000 (04:34 +0000)
Legacy RIL uses an integer to encode the number of
MNC digits. Because the size is not fixed, leading
zeroes result in ambiguity in the length of the mnc.

This change adds support for passing the number of
encoded digits in the most-significant nibble of the
mnc integer (which is only 10 bits). Thus, on any
implementation that is 16-bits or wider, the mnc info
will be properly encoded and decoded with the
correctly-sized string.

Bug: 111971808
Test: ril::util::mnc::test
Change-Id: I24aeba5328a63f80b0d6b25b068bd19160191dff
Merged-In: I24aeba5328a63f80b0d6b25b068bd19160191dff
(cherry picked from commit 98cfceefdf06d5e4ec3bfff3d1cd425baefb155e)

include/telephony/ril.h
include/telephony/ril_mnc.h [new file with mode: 0644]
libril/ril_service.cpp

index c4add62..e189777 100644 (file)
@@ -1360,14 +1360,18 @@ typedef struct {
 
 typedef struct {
     int mcc;    /* 3-digit Mobile Country Code, 0..999, INT_MAX if unknown */
-    int mnc;    /* 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown */
+    int mnc;    /* 2 or 3-digit Mobile Network Code, 0..999;
+                   the most significant nibble encodes the number of digits - {2, 3, 0 (unset)};
+                   INT_MAX if unknown */
     int lac;    /* 16-bit Location Area Code, 0..65535, INT_MAX if unknown  */
     int cid;    /* 16-bit GSM Cell Identity described in TS 27.007, 0..65535, INT_MAX if unknown  */
 } RIL_CellIdentityGsm;
 
 typedef struct {
     int mcc;    /* 3-digit Mobile Country Code, 0..999, INT_MAX if unknown */
-    int mnc;    /* 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown */
+    int mnc;    /* 2 or 3-digit Mobile Network Code, 0..999;
+                   the most significant nibble encodes the number of digits - {2, 3, 0 (unset)};
+                   INT_MAX if unknown */
     int lac;    /* 16-bit Location Area Code, 0..65535, INT_MAX if unknown  */
     int cid;    /* 16-bit GSM Cell Identity described in TS 27.007, 0..65535, INT_MAX if unknown  */
     int arfcn;  /* 16-bit GSM Absolute RF channel number; this value must be reported */
@@ -1376,7 +1380,9 @@ typedef struct {
 
 typedef struct {
     int mcc;    /* 3-digit Mobile Country Code, 0..999, INT_MAX if unknown  */
-    int mnc;    /* 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown  */
+    int mnc;    /* 2 or 3-digit Mobile Network Code, 0..999;
+                   the most significant nibble encodes the number of digits - {2, 3, 0 (unset)};
+                   INT_MAX if unknown */
     int lac;    /* 16-bit Location Area Code, 0..65535, INT_MAX if unknown  */
     int cid;    /* 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown  */
     int psc;    /* 9-bit UMTS Primary Scrambling Code described in TS 25.331, 0..511, INT_MAX if unknown */
@@ -1384,7 +1390,9 @@ typedef struct {
 
 typedef struct {
     int mcc;    /* 3-digit Mobile Country Code, 0..999, INT_MAX if unknown  */
-    int mnc;    /* 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown  */
+    int mnc;    /* 2 or 3-digit Mobile Network Code, 0..999;
+                   the most significant nibble encodes the number of digits - {2, 3, 0 (unset)};
+                   INT_MAX if unknown */
     int lac;    /* 16-bit Location Area Code, 0..65535, INT_MAX if unknown  */
     int cid;    /* 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown  */
     int psc;    /* 9-bit UMTS Primary Scrambling Code described in TS 25.331, 0..511; this value must be reported */
@@ -1408,7 +1416,9 @@ typedef struct {
 
 typedef struct {
     int mcc;    /* 3-digit Mobile Country Code, 0..999, INT_MAX if unknown  */
-    int mnc;    /* 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown  */
+    int mnc;    /* 2 or 3-digit Mobile Network Code, 0..999;
+                   the most significant nibble encodes the number of digits - {2, 3, 0 (unset)};
+                   INT_MAX if unknown */
     int ci;     /* 28-bit Cell Identity described in TS ???, INT_MAX if unknown */
     int pci;    /* physical cell id 0..503, INT_MAX if unknown  */
     int tac;    /* 16-bit tracking area code, INT_MAX if unknown  */
@@ -1416,7 +1426,9 @@ typedef struct {
 
 typedef struct {
     int mcc;    /* 3-digit Mobile Country Code, 0..999, INT_MAX if unknown  */
-    int mnc;    /* 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown  */
+    int mnc;    /* 2 or 3-digit Mobile Network Code, 0..999;
+                   the most significant nibble encodes the number of digits - {2, 3, 0 (unset)};
+                   INT_MAX if unknown */
     int ci;     /* 28-bit Cell Identity described in TS ???, INT_MAX if unknown */
     int pci;    /* physical cell id 0..503; this value must be reported */
     int tac;    /* 16-bit tracking area code, INT_MAX if unknown  */
@@ -1425,7 +1437,9 @@ typedef struct {
 
 typedef struct {
     int mcc;    /* 3-digit Mobile Country Code, 0..999, INT_MAX if unknown  */
-    int mnc;    /* 2 or 3-digit Mobile Network Code, 0..999, INT_MAX if unknown  */
+    int mnc;    /* 2 or 3-digit Mobile Network Code, 0..999;
+                   the most significant nibble encodes the number of digits - {2, 3, 0 (unset)};
+                   INT_MAX if unknown */
     int lac;    /* 16-bit Location Area Code, 0..65535, INT_MAX if unknown  */
     int cid;    /* 28-bit UMTS Cell Identity described in TS 25.331, 0..268435455, INT_MAX if unknown  */
     int cpid;    /* 8-bit Cell Parameters ID described in TS 25.331, 0..127, INT_MAX if unknown */
diff --git a/include/telephony/ril_mnc.h b/include/telephony/ril_mnc.h
new file mode 100644 (file)
index 0000000..fcbae99
--- /dev/null
@@ -0,0 +1,149 @@
+/*
+ * Copyright (C) 2018 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.
+ */
+
+#ifndef RIL_MNC_H
+#define RIL_MNC_H
+
+#include <climits>
+#include <cstdio>
+#include <string>
+
+namespace ril {
+namespace util {
+namespace mnc {
+
+/**
+ * Decode an MNC with an optional length indicator provided in the most-significant nibble.
+ *
+ * @param mnc an encoded MNC value; if no encoding is provided, then the string is returned
+ *     as a minimum length string representing the provided integer.
+ *
+ * @return string representation of an encoded MNC or an empty string if the MNC is not a valid
+ *     MNC value.
+ */
+static inline std::string decode(int mnc) {
+    if (mnc == INT_MAX || mnc < 0) return "";
+    unsigned umnc = mnc;
+    char mncNumDigits = (umnc >> (sizeof(int) * 8 - 4)) & 0xF;
+
+    umnc = (umnc << 4) >> 4;
+    if (umnc > 999) return "";
+
+    char mncStr[4] = {0};
+    switch (mncNumDigits) {
+        case 0:
+            // Legacy MNC report hasn't set the number of digits; preserve current
+            // behavior and make a string of the minimum number of required digits.
+            return std::to_string(umnc);
+
+        case 2:
+            snprintf(mncStr, sizeof(mncStr), "%03.3u", umnc);
+            return mncStr + 1;
+
+        case 3:
+            snprintf(mncStr, sizeof(mncStr), "%03.3u", umnc);
+            return mncStr;
+
+        default:
+            // Error case
+            return "";
+    }
+
+}
+
+/**
+ * Encode an MNC of the given value and a given number of digits
+ *
+ * @param mnc an MNC value 0-999 or INT_MAX if unknown
+ * @param numDigits the number of MNC digits {2, 3} or 0 if unknown
+ *
+ * @return an encoded MNC with embedded length information
+ */
+static inline int encode(int mnc, int numDigits) {
+    if (mnc > 999 || mnc < 0) return INT_MAX;
+    switch (numDigits) {
+        case 0: // fall through
+        case 2: // fall through
+        case 3:
+            break;
+
+        default:
+            return INT_MAX;
+    };
+
+    return (numDigits << (sizeof(int) * 8 - 4)) | mnc;
+}
+
+/**
+ * Encode an MNC of the given value
+ *
+ * @param mnc the string representation of the MNC, with the length equal to the length of the
+ *     provided string.
+ *
+ * @return an encoded MNC with embedded length information
+ */
+static inline int encode(const std::string & mnc) {
+    return encode(std::stoi(mnc), mnc.length());
+}
+
+// echo -e "#include \"hardware/ril/include/telephony/ril_mnc.h\"\nint main()"\
+// "{ return ril::util::mnc::test(); }" > ril_test.cpp \
+// && g++ -o /tmp/ril_test -DTEST_RIL_MNC ril_test.cpp; \
+// rm ril_test.cpp; /tmp/ril_test && [ $? ] && echo "passed"
+#ifdef TEST_RIL_MNC
+static int test() {
+    const struct mnc_strings { const char * in; const char * out; } mncs[] = {
+        {"0001",""},
+        {"9999",""},
+        {"0",""},
+        {"9",""},
+        {"123","123"},
+        {"000","000"},
+        {"001","001"},
+        {"011","011"},
+        {"111","111"},
+        {"00","00"},
+        {"01","01"},
+        {"11","11"},
+        {"09","09"},
+        {"099","099"},
+        {"999", "999"}};
+
+    for (int i=0; i< sizeof(mncs) / sizeof(struct mnc_strings); i++) {
+        if (decode(encode(mncs[i].in)).compare(mncs[i].out)) return 1;
+    }
+
+    const struct mnc_ints { const int in; const char * out; } legacy_mncs[] = {
+        {INT_MAX, ""},
+        {1, "1"},
+        {11, "11"},
+        {111, "111"},
+        {0, "0"},
+        {9999, ""},
+    };
+
+    for (int i=0; i < sizeof(legacy_mncs) / sizeof(struct mnc_ints); i++) {
+        if (decode(legacy_mncs[i].in).compare(legacy_mncs[i].out)) return 1;
+    }
+
+    return 0;
+}
+#endif
+
+}
+}
+}
+#endif /* !defined(RIL_MNC_H) */
index 07fd49f..7400f30 100644 (file)
@@ -25,6 +25,8 @@
 
 #include <hwbinder/IPCThreadState.h>
 #include <hwbinder/ProcessState.h>
+#include <telephony/ril.h>
+#include <telephony/ril_mnc.h>
 #include <ril_service.h>
 #include <hidl/HidlTransportSupport.h>
 #include <utils/SystemClock.h>
@@ -3549,7 +3551,7 @@ void fillCellIdentityResponse(CellIdentity &cellIdentity, RIL_CellIdentity_v16 &
             cellIdentity.cellIdentityGsm[0].mcc =
                     std::to_string(rilCellIdentity.cellIdentityGsm.mcc);
             cellIdentity.cellIdentityGsm[0].mnc =
-                    std::to_string(rilCellIdentity.cellIdentityGsm.mnc);
+                    ril::util::mnc::decode(rilCellIdentity.cellIdentityGsm.mnc);
             cellIdentity.cellIdentityGsm[0].lac = rilCellIdentity.cellIdentityGsm.lac;
             cellIdentity.cellIdentityGsm[0].cid = rilCellIdentity.cellIdentityGsm.cid;
             cellIdentity.cellIdentityGsm[0].arfcn = rilCellIdentity.cellIdentityGsm.arfcn;
@@ -3562,7 +3564,7 @@ void fillCellIdentityResponse(CellIdentity &cellIdentity, RIL_CellIdentity_v16 &
             cellIdentity.cellIdentityWcdma[0].mcc =
                     std::to_string(rilCellIdentity.cellIdentityWcdma.mcc);
             cellIdentity.cellIdentityWcdma[0].mnc =
-                    std::to_string(rilCellIdentity.cellIdentityWcdma.mnc);
+                    ril::util::mnc::decode(rilCellIdentity.cellIdentityWcdma.mnc);
             cellIdentity.cellIdentityWcdma[0].lac = rilCellIdentity.cellIdentityWcdma.lac;
             cellIdentity.cellIdentityWcdma[0].cid = rilCellIdentity.cellIdentityWcdma.cid;
             cellIdentity.cellIdentityWcdma[0].psc = rilCellIdentity.cellIdentityWcdma.psc;
@@ -3586,7 +3588,7 @@ void fillCellIdentityResponse(CellIdentity &cellIdentity, RIL_CellIdentity_v16 &
             cellIdentity.cellIdentityLte[0].mcc =
                     std::to_string(rilCellIdentity.cellIdentityLte.mcc);
             cellIdentity.cellIdentityLte[0].mnc =
-                    std::to_string(rilCellIdentity.cellIdentityLte.mnc);
+                    ril::util::mnc::decode(rilCellIdentity.cellIdentityLte.mnc);
             cellIdentity.cellIdentityLte[0].ci = rilCellIdentity.cellIdentityLte.ci;
             cellIdentity.cellIdentityLte[0].pci = rilCellIdentity.cellIdentityLte.pci;
             cellIdentity.cellIdentityLte[0].tac = rilCellIdentity.cellIdentityLte.tac;
@@ -3599,7 +3601,7 @@ void fillCellIdentityResponse(CellIdentity &cellIdentity, RIL_CellIdentity_v16 &
             cellIdentity.cellIdentityTdscdma[0].mcc =
                     std::to_string(rilCellIdentity.cellIdentityTdscdma.mcc);
             cellIdentity.cellIdentityTdscdma[0].mnc =
-                    std::to_string(rilCellIdentity.cellIdentityTdscdma.mnc);
+                    ril::util::mnc::decode(rilCellIdentity.cellIdentityTdscdma.mnc);
             cellIdentity.cellIdentityTdscdma[0].lac = rilCellIdentity.cellIdentityTdscdma.lac;
             cellIdentity.cellIdentityTdscdma[0].cid = rilCellIdentity.cellIdentityTdscdma.cid;
             cellIdentity.cellIdentityTdscdma[0].cpid = rilCellIdentity.cellIdentityTdscdma.cpid;
@@ -7863,7 +7865,7 @@ void convertRilCellInfoListToHal(void *response, size_t responseLen, hidl_vec<Ce
                 cellInfoGsm->cellIdentityGsm.mcc =
                         std::to_string(rillCellInfo->CellInfo.gsm.cellIdentityGsm.mcc);
                 cellInfoGsm->cellIdentityGsm.mnc =
-                        std::to_string(rillCellInfo->CellInfo.gsm.cellIdentityGsm.mnc);
+                        ril::util::mnc::decode(rillCellInfo->CellInfo.gsm.cellIdentityGsm.mnc);
                 cellInfoGsm->cellIdentityGsm.lac =
                         rillCellInfo->CellInfo.gsm.cellIdentityGsm.lac;
                 cellInfoGsm->cellIdentityGsm.cid =
@@ -7887,7 +7889,7 @@ void convertRilCellInfoListToHal(void *response, size_t responseLen, hidl_vec<Ce
                 cellInfoWcdma->cellIdentityWcdma.mcc =
                         std::to_string(rillCellInfo->CellInfo.wcdma.cellIdentityWcdma.mcc);
                 cellInfoWcdma->cellIdentityWcdma.mnc =
-                        std::to_string(rillCellInfo->CellInfo.wcdma.cellIdentityWcdma.mnc);
+                        ril::util::mnc::decode(rillCellInfo->CellInfo.wcdma.cellIdentityWcdma.mnc);
                 cellInfoWcdma->cellIdentityWcdma.lac =
                         rillCellInfo->CellInfo.wcdma.cellIdentityWcdma.lac;
                 cellInfoWcdma->cellIdentityWcdma.cid =
@@ -7935,7 +7937,7 @@ void convertRilCellInfoListToHal(void *response, size_t responseLen, hidl_vec<Ce
                 cellInfoLte->cellIdentityLte.mcc =
                         std::to_string(rillCellInfo->CellInfo.lte.cellIdentityLte.mcc);
                 cellInfoLte->cellIdentityLte.mnc =
-                        std::to_string(rillCellInfo->CellInfo.lte.cellIdentityLte.mnc);
+                        ril::util::mnc::decode(rillCellInfo->CellInfo.lte.cellIdentityLte.mnc);
                 cellInfoLte->cellIdentityLte.ci =
                         rillCellInfo->CellInfo.lte.cellIdentityLte.ci;
                 cellInfoLte->cellIdentityLte.pci =
@@ -7965,7 +7967,8 @@ void convertRilCellInfoListToHal(void *response, size_t responseLen, hidl_vec<Ce
                 cellInfoTdscdma->cellIdentityTdscdma.mcc =
                         std::to_string(rillCellInfo->CellInfo.tdscdma.cellIdentityTdscdma.mcc);
                 cellInfoTdscdma->cellIdentityTdscdma.mnc =
-                        std::to_string(rillCellInfo->CellInfo.tdscdma.cellIdentityTdscdma.mnc);
+                        ril::util::mnc::decode(
+                                rillCellInfo->CellInfo.tdscdma.cellIdentityTdscdma.mnc);
                 cellInfoTdscdma->cellIdentityTdscdma.lac =
                         rillCellInfo->CellInfo.tdscdma.cellIdentityTdscdma.lac;
                 cellInfoTdscdma->cellIdentityTdscdma.cid =