[Feature]add MT2731_MP2_MR2_SVN388 baseline version

Change-Id: Ief04314834b31e27effab435d3ca8ba33b499059
diff --git a/src/lynq/lib/liblynq-tele-ril/lynq-riltel/sms/cdma/BearerData.cpp b/src/lynq/lib/liblynq-tele-ril/lynq-riltel/sms/cdma/BearerData.cpp
new file mode 100644
index 0000000..fccbfbf
--- /dev/null
+++ b/src/lynq/lib/liblynq-tele-ril/lynq-riltel/sms/cdma/BearerData.cpp
@@ -0,0 +1,1624 @@
+/*
+ * Copyright (C) 2008 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.
+ */
+#include <string>
+#include <memory>
+#include <iostream>
+#include <list>
+#include <algorithm>
+using namespace std;
+
+#include "BearerData.h"
+#include "UserData.h"
+#include "SmsConstants.h"
+#include "HexDump.h"
+#include "IccUtils.h"
+#include "BitwiseInputStream.h"
+#include "CdmaSmsCbProgramData.h";
+#include "SmsHeader.h"
+#include "GsmAlphabet.h"
+#include "SmsEnvelope.h"
+
+extern "C" {
+    #include <glib.h>
+}
+
+BearerData::BearerData() {
+  // TODO Auto-generated constructor stub
+
+}
+
+BearerData::~BearerData() {
+  // TODO Auto-generated destructor stub
+}
+
+/**
+ * Decodes a CDMA style BCD byte like {@link #gsmBcdByteToInt}, but
+ * opposite nibble format. The least significant BCD digit
+ * is in the least significant nibble and the most significant
+ * is in the most significant nibble.
+ */
+int BearerData::cdmaBcdByteToInt(uint8_t b) {
+  int ret = 0;
+
+  // treat out-of-range BCD values as 0
+  if ((b & 0xf0) <= 0x90) {
+    ret = ((b >> 4) & 0xf) * 10;
+  }
+
+  if ((b & 0x0f) <= 0x09) {
+    ret += (b & 0xf);
+  }
+
+  return ret;
+}
+
+void BearerData::fromByteArray(std::vector<uint8_t> data, struct tm& ts) {
+  // C.S0015-B v2.0, 4.5.4: range is 1996-2095
+  int year = cdmaBcdByteToInt(data[0]);
+  if (year > 99 || year < 0) {
+    ts = {0};
+    return;
+  }
+  ts.tm_year = year /*>= 96 ? year + 1900 : year + 2000*/; //TBD
+  int month = cdmaBcdByteToInt(data[1]);
+  if (month < 1 || month > 12) {
+    ts = {0};
+    return;
+  }
+  ts.tm_mon = month - 1;
+  int day = cdmaBcdByteToInt(data[2]);
+  if (day < 1 || day > 31) {
+    ts = {0};
+    return;
+  }
+  ts.tm_mday = day;
+  int hour = cdmaBcdByteToInt(data[3]);
+  if (hour < 0 || hour > 23) {
+    ts = {0};
+    return;
+  }
+  ts.tm_hour = hour;
+  int minute = cdmaBcdByteToInt(data[4]);
+  if (minute < 0 || minute > 59) {
+    ts = {0};
+    return;
+  }
+  ts.tm_min = minute;
+  int second = cdmaBcdByteToInt(data[5]);
+  if (second < 0 || second > 59) {
+    ts = {0};
+    return;
+  }
+  ts.tm_sec = second;
+}
+
+void BearerData::encodeMessageId(BearerData* bData,
+    shared_ptr<BitwiseOutputStream> outStream) {
+  outStream->write(8, 3);
+  outStream->write(4, bData->messageType);
+  outStream->write(8, bData->messageId >> 8);
+  outStream->write(8, bData->messageId);
+  outStream->write(1, bData->hasUserDataHeader ? 1 : 0);
+  outStream->skip(3);
+}
+
+uint32_t BearerData::countAsciiSeptets(char* msg, bool force) {
+  string strmsg(msg);
+  int msgLen = strmsg.length();
+  if (force)
+    return msgLen;
+  for (int i = 0; i < msgLen; i++) {
+    if (UserData::charToAscii.find(msg[i]) == UserData::charToAscii.end()) {
+      return -1;
+    }
+  }
+  return msgLen;
+}
+
+std::vector<uint8_t> BearerData::encodeUtf16(std::string msg) {
+    GError *error = NULL;
+    gsize bytes_written = 0;
+    std::vector<uint8_t> data;
+    char *ret = g_convert (msg.c_str(), -1, "UCS-2BE", "UTF-8", NULL, &bytes_written, &error);
+    if (!ret) {
+        if (error) {
+            cout << "failed to convert UTF-8 to UCS-2BE character set: " << (error->code) << error->message << endl;
+            g_error_free (error);
+        }
+        return data;
+    }
+    for (int i = 0; i < bytes_written; i++) {
+        data.push_back(ret[i]);
+    }
+    g_free (ret);
+    return data;
+}
+
+//release byte[]
+std::vector<uint8_t> BearerData::encode7bitAscii(std::string msgs, bool force) {
+  string msg(msgs);
+  shared_ptr<BitwiseOutputStream> outStream = make_shared<BitwiseOutputStream>(
+      msg.length());
+  int msgLen = msg.length();
+  for (int i = 0; i < msgLen; i++) {
+    uint8_t charCode;
+    try {
+      charCode = UserData::charToAscii.at(msg[i]);
+      outStream->write(7, charCode);
+    } catch (const out_of_range &e) {
+      if (force) {
+        outStream->write(7, UserData::UNENCODABLE_7_BIT_CHAR);
+      }
+      //TBD log
+    }
+  }
+  return outStream->toByteVector();
+}
+
+BearerData::Gsm7bitCodingResult BearerData::encode7bitGsm(std::string msg, int septetOffset, bool force) {
+    std::vector<uint8_t> fullData = GsmAlphabet::stringToGsm7BitPacked(msg, septetOffset, !force, 0, 0);
+    Gsm7bitCodingResult result;
+    result.data.insert(result.data.begin(), fullData.begin() + 1, fullData.end());
+    result.septets = fullData[0] & 0x00FF;
+    return result;
+}
+
+void BearerData::encode7bitEms(std::shared_ptr<UserData> uData, std::vector<uint8_t> udhData, bool force) {
+    int udhBytes = udhData.size() + 1;  // Add length octet.
+    int udhSeptets = ((udhBytes * 8) + 6) / 7;
+    BearerData::Gsm7bitCodingResult gcr = encode7bitGsm(uData->payloadStr, udhSeptets, force);
+    uData->msgEncoding = UserData::ENCODING_GSM_7BIT_ALPHABET;
+    uData->msgEncodingSet = true;
+    uData->numFields = gcr.septets;
+    uData->payload = gcr.data;
+    uData->payload.insert(uData->payload.begin()+1, udhData.begin(), udhData.end());
+    uData->payload[0] = (uint8_t)udhData.size();
+}
+
+void BearerData::encode16bitEms(std::shared_ptr<UserData> uData, std::vector<uint8_t> udhData) {
+    std::vector<uint8_t>  payload = encodeUtf16(uData->payloadStr);
+    int udhBytes = udhData.size() + 1;  // Add length octet.
+    int udhCodeUnits = (udhBytes + 1) / 2;
+    int payloadCodeUnits = payload.size() / 2;
+    uData->msgEncoding = UserData::ENCODING_UNICODE_16;
+    uData->msgEncodingSet = true;
+    uData->numFields = udhCodeUnits + payloadCodeUnits;
+    uData->payload.push_back(udhData.size());
+    (uData->payload).insert((uData->payload).begin() + 1, udhData.begin(), udhData.end());
+    (uData->payload).insert((uData->payload).begin() + udhBytes, payload.begin(), payload.end());
+}
+
+void BearerData::encodeOctetEms(std::shared_ptr<UserData> uData, std::vector<uint8_t> udhData) {
+    int udhBytes = udhData.size() + 1;
+    uData->msgEncoding = UserData::ENCODING_OCTET;
+    uData->msgEncodingSet = true;
+    uData->numFields = udhBytes + uData->payload.size();
+    //byte[] payload = new byte[uData.numFields];
+    std::vector<uint8_t> payload;
+    uData->payload.push_back(udhData.size());
+    (uData->payload).insert((uData->payload).begin() + 1, udhData.begin(), udhData.end());
+    (uData->payload).insert((uData->payload).begin() + udhBytes, payload.begin(), payload.end());
+}
+
+void BearerData::encodeEmsUserDataPayload(std::shared_ptr<UserData> uData) {
+    std::vector<uint8_t> headerData = SmsHeader::toByteArray(uData->userDataHeader);
+    if (uData->msgEncodingSet) {
+        if (uData->msgEncoding == UserData::ENCODING_GSM_7BIT_ALPHABET) {
+            encode7bitEms(uData, headerData, true);
+        } else if (uData->msgEncoding == UserData::ENCODING_OCTET) {
+            encodeOctetEms(uData, headerData);
+        } else if (uData->msgEncoding == UserData::ENCODING_UNICODE_16) {
+            encode16bitEms(uData, headerData);
+        } else {
+            cout << "unsupported EMS user data encoding (" << uData->msgEncoding << ")" <<endl;
+        }
+    } else {
+        encode7bitEms(uData, headerData, false);
+    }
+}
+//maybe free memory
+void BearerData::encodeUserDataPayload(std::shared_ptr<UserData> uData) {
+  if ((uData->payloadStr.empty())
+      && (uData->msgEncoding != UserData::ENCODING_OCTET)) {
+    //Rlog.e(LOG_TAG, "user data with null payloadStr");
+    uData->payloadStr = string("");
+  }
+
+   if (uData->userDataHeader != nullptr) {
+      encodeEmsUserDataPayload(uData);
+   return;
+  }
+
+  if (uData->msgEncodingSet) {
+    if (uData->msgEncoding == UserData::ENCODING_OCTET) {
+      if (uData->payload.empty()) {
+        //Rlog.e(LOG_TAG, "user data with octet encoding but null payload");
+        uData->payload.clear();
+        uData->numFields = 0;
+      } else {
+        uData->numFields = uData->payload.size(); //maybe wrong?
+      }
+    } else {
+      if (uData->payloadStr.empty()) {
+        //Rlog.e(LOG_TAG, "non-octet user data with null payloadStr");
+        uData->payloadStr = string("");
+      }
+//                  if (uData.msgEncoding == UserData::ENCODING_GSM_7BIT_ALPHABET) {
+//                      Gsm7bitCodingResult gcr = encode7bitGsm(uData.payloadStr, 0, true);
+//                      uData.payload = gcr.data;
+//                      uData.numFields = gcr.septets;
+//                  } else
+
+      if (uData->msgEncoding == UserData::ENCODING_7BIT_ASCII) {
+        uData->payload = encode7bitAscii(uData->payloadStr, true);
+        uData->numFields = uData->payloadStr.size();
+      } else if (uData->msgEncoding == UserData::ENCODING_UNICODE_16) {
+        uData->payload = encodeUtf16(uData->payloadStr);
+        uData->numFields = string(uData->payloadStr).length();
+//                  } else if (uData->msgEncoding == UserData::ENCODING_SHIFT_JIS) {
+//                      uData->payload = encodeShiftJis(uData->payloadStr);
+//                      uData->numFields = string(uData->payloadStr).length();
+      } else {
+        cout << "unsupported user data encoding (" << uData->msgEncoding << ")"
+            << endl;
+      }
+    }
+  } else {
+    uData->payload = encode7bitAscii(uData->payloadStr, false);
+    string str1 = HexDump::toHexString(uData->payload);
+    //std::cout << "uData->payload: " << str1 << endl;
+    uData->msgEncoding = UserData::ENCODING_7BIT_ASCII;
+//              try {
+//              } catch (CodingException ex) {
+//                  uData.payload = encodeUtf16(uData.payloadStr);
+//                  uData.msgEncoding = UserData.ENCODING_UNICODE_16;
+//              }
+    uData->numFields = uData->payloadStr.size();
+    uData->msgEncodingSet = true;
+  }
+}
+
+void BearerData::encodeUserData(BearerData* bData,
+    shared_ptr<BitwiseOutputStream> outStream) {
+  /*
+   * TODO(cleanup): Do we really need to set userData.payload as
+   * a side effect of encoding?  If not, we could avoid data
+   * copies by passing outStream directly.
+   */
+  encodeUserDataPayload(bData->userData);
+  bData->hasUserDataHeader = false; //bData->userData->userDataHeader != null;
+
+  int length = bData->userData->payload.size();
+  if (length > SmsConstants::MAX_USER_DATA_BYTES) {
+    cout << "encoded user data too large (" << bData->userData->payload.size()
+        << " > " << SmsConstants::MAX_USER_DATA_BYTES << " bytes)" << endl;
+    return;
+  }
+
+  /*
+   * TODO(cleanup): figure out what the right answer is WRT paddingBits field
+   *
+   *   userData->pad->ingBits = (userData->payload.length * 8) - (userData.numFields * 7);
+   *   userData.paddingBits = 0; // XXX this seems better, but why?
+   *
+   */
+  int dataBits = (length * 8) - (bData->userData->paddingBits);
+  int paramBits = dataBits + 13;
+  if (((bData->userData->msgEncoding)
+      == UserData::ENCODING_IS91_EXTENDED_PROTOCOL)
+      || ((bData->userData->msgEncoding) == UserData::ENCODING_GSM_DCS)) {
+    paramBits += 8;
+  }
+  int paramBytes = (paramBits / 8) + ((paramBits % 8) > 0 ? 1 : 0);
+  int paddingBits = (paramBytes * 8) - paramBits;
+  outStream->write(8, paramBytes);
+  outStream->write(5, bData->userData->msgEncoding);
+  if ((bData->userData->msgEncoding == UserData::ENCODING_IS91_EXTENDED_PROTOCOL)
+      || (bData->userData->msgEncoding == UserData::ENCODING_GSM_DCS)) {
+    outStream->write(8, bData->userData->msgType);
+  }
+  outStream->write(8, (bData->userData)->numFields);
+  outStream->writeByteVector(dataBits, (bData->userData)->payload);
+  if (paddingBits > 0)
+    outStream->write(paddingBits, 0);
+}
+
+void BearerData::encodeReplyOption(BearerData* bData,
+    shared_ptr<BitwiseOutputStream> outStream) {
+  outStream->write(8, 1);
+  outStream->write(1, bData->userAckReq ? 1 : 0);
+  outStream->write(1, bData->deliveryAckReq ? 1 : 0);
+  outStream->write(1, bData->readAckReq ? 1 : 0);
+  outStream->write(1, bData->reportReq ? 1 : 0);
+  outStream->write(4, 0);
+}
+
+//free memory
+std::vector<uint8_t> BearerData::encodeDtmfSmsAddress(std::string address) {
+  int digits = address.length();
+  int dataBits = digits * 4;
+  int dataBytes = (dataBits / 8);
+  dataBytes += (dataBits % 8) > 0 ? 1 : 0;
+  //uint8_t* rawData = new uint8_t[dataBytes];
+  std::vector<uint8_t> rawData;
+  for (int i = 0; i < digits; i++) {
+    char c = address[i];
+    int val = 0;
+    if ((c >= '1') && (c <= '9'))
+      val = c - '0';
+    else if (c == '0')
+      val = 10;
+    else if (c == '*')
+      val = 11;
+    else if (c == '#')
+      val = 12;
+    else
+      return rawData;
+    int size = rawData.size();
+    if ((i / 2) < size) {
+      rawData[i / 2] |= val << (4 - ((i % 2) * 4));
+    } else {
+      rawData.push_back(val << (4 - ((i % 2) * 4)));
+    }
+  }
+  return rawData;
+}
+
+void BearerData::encodeCdmaSmsAddress(std::shared_ptr<CdmaSmsAddress> addr) {
+  if (addr->digitMode == CdmaSmsAddress::DIGIT_MODE_8BIT_CHAR) {
+    //TBD
+//              try {
+//                  addr.origBytes = addr.address.getBytes("US-ASCII");
+//              } catch (java.io.UnsupportedEncodingException ex) {
+//                  throw new CodingException("invalid SMS address, cannot convert to ASCII");
+//              }
+  } else {
+    addr->origBytes = encodeDtmfSmsAddress(addr->address);
+  }
+}
+
+void BearerData::encodeCallbackNumber(BearerData* bData,
+    shared_ptr<BitwiseOutputStream> outStream) {
+  auto addr = bData->callbackNumber;
+  encodeCdmaSmsAddress(addr);
+  int paramBits = 9;
+  int dataBits = 0;
+  if (addr->digitMode == CdmaSmsAddress::DIGIT_MODE_8BIT_CHAR) {
+    paramBits += 7;
+    dataBits = addr->numberOfDigits * 8;
+  } else {
+    dataBits = addr->numberOfDigits * 4;
+  }
+  paramBits += dataBits;
+  int paramBytes = (paramBits / 8) + ((paramBits % 8) > 0 ? 1 : 0);
+  int paddingBits = (paramBytes * 8) - paramBits;
+  outStream->write(8, paramBytes);
+  outStream->write(1, addr->digitMode);
+  if (addr->digitMode == CdmaSmsAddress::DIGIT_MODE_8BIT_CHAR) {
+    outStream->write(3, addr->ton);
+    outStream->write(4, addr->numberPlan);
+  }
+  outStream->write(8, addr->numberOfDigits);
+  outStream->writeByteVector(dataBits, addr->origBytes);
+  if (paddingBits > 0)
+    outStream->write(paddingBits, 0);
+}
+
+void BearerData::encodeMsgStatus(BearerData* bData,
+    shared_ptr<BitwiseOutputStream> outStream) {
+  outStream->write(8, 1);
+  outStream->write(2, bData->errorClass);
+  outStream->write(6, bData->messageStatus);
+}
+void BearerData::encodeMsgCount(BearerData* bData,
+    shared_ptr<BitwiseOutputStream> outStream) {
+  outStream->write(8, 1);
+  outStream->write(8, bData->numberOfMessages);
+}
+void BearerData::encodeValidityPeriodRel(BearerData* bData,
+    shared_ptr<BitwiseOutputStream> outStream) {
+  outStream->write(8, 1);
+  outStream->write(8, bData->validityPeriodRelative);
+}
+void BearerData::encodePrivacyIndicator(BearerData* bData,
+    shared_ptr<BitwiseOutputStream> outStream) {
+  outStream->write(8, 1);
+  outStream->write(2, bData->privacy);
+  outStream->skip(6);
+}
+void BearerData::encodeLanguageIndicator(BearerData* bData,
+    shared_ptr<BitwiseOutputStream> outStream) {
+  outStream->write(8, 1);
+  outStream->write(8, bData->language);
+}
+void BearerData::encodeDisplayMode(BearerData* bData,
+    shared_ptr<BitwiseOutputStream> outStream) {
+  outStream->write(8, 1);
+  outStream->write(2, bData->displayMode);
+  outStream->skip(6);
+}
+void BearerData::encodePriorityIndicator(BearerData* bData,
+    shared_ptr<BitwiseOutputStream> outStream) {
+  outStream->write(8, 1);
+  outStream->write(2, bData->priority);
+  outStream->skip(6);
+}
+void BearerData::encodeMsgDeliveryAlert(BearerData* bData,
+    shared_ptr<BitwiseOutputStream> outStream) {
+  outStream->write(8, 1);
+  outStream->write(2, bData->alert);
+  outStream->skip(6);
+}
+std::vector<uint8_t> BearerData::encode(BearerData* bData) {
+  bData->hasUserDataHeader = false; //((bData->userData != nullptr) && (bData->userData->userDataHeader != null));
+  shared_ptr<BitwiseOutputStream> outStream = make_shared<BitwiseOutputStream>(
+      200);
+  outStream->write(8, SUBPARAM_MESSAGE_IDENTIFIER);
+  encodeMessageId(bData, outStream);
+  if (bData->userData != nullptr) {
+    outStream->write(8, SUBPARAM_USER_DATA);
+    encodeUserData(bData, outStream);
+    //cout << "userData" << endl;
+  }
+  if (bData->callbackNumber != nullptr) {
+    //cout << "callbackNumber" << endl;
+    outStream->write(8, SUBPARAM_CALLBACK_NUMBER);
+    encodeCallbackNumber(bData, outStream);
+  }
+  if (bData->userAckReq || bData->deliveryAckReq || bData->readAckReq
+      || bData->reportReq) {
+    //cout << "userAckReq" << endl;
+    outStream->write(8, SUBPARAM_REPLY_OPTION);
+    encodeReplyOption(bData, outStream);
+  }
+  if (bData->numberOfMessages != 0) {
+    //cout << "numberOfMessages" << endl;
+    outStream->write(8, SUBPARAM_NUMBER_OF_MESSAGES);
+    encodeMsgCount(bData, outStream);
+  }
+  if (bData->validityPeriodRelativeSet) {
+    //cout << "validityPeriodRelativeSet" << endl;
+    outStream->write(8, SUBPARAM_VALIDITY_PERIOD_RELATIVE);
+    encodeValidityPeriodRel(bData, outStream);
+  }
+  if (bData->privacyIndicatorSet) {
+    //cout << "privacyIndicatorSet" << endl;
+    outStream->write(8, SUBPARAM_PRIVACY_INDICATOR);
+    encodePrivacyIndicator(bData, outStream);
+  }
+  if (bData->languageIndicatorSet) {
+    //cout << "languageIndicatorSet" << endl;
+    outStream->write(8, SUBPARAM_LANGUAGE_INDICATOR);
+    encodeLanguageIndicator(bData, outStream);
+  }
+  if (bData->displayModeSet) {
+    //cout << "displayModeSet" << endl;
+    outStream->write(8, SUBPARAM_MESSAGE_DISPLAY_MODE);
+    encodeDisplayMode(bData, outStream);
+  }
+  if (bData->priorityIndicatorSet) {
+    //cout << "priorityIndicatorSet" << endl;
+    outStream->write(8, SUBPARAM_PRIORITY_INDICATOR);
+    encodePriorityIndicator(bData, outStream);
+  }
+  if (bData->alertIndicatorSet) {
+    //cout << "alertIndicatorSet" << endl;
+    outStream->write(8, SUBPARAM_ALERT_ON_MESSAGE_DELIVERY);
+    encodeMsgDeliveryAlert(bData, outStream);
+  }
+  if (bData->messageStatusSet) {
+    //cout << "messageStatusSet" << endl;
+    outStream->write(8, SUBPARAM_MESSAGE_STATUS);
+    encodeMsgStatus(bData, outStream);
+  }
+//      if (bData->serviceCategoryProgramResults != null) {
+//          outStream->write(8, SUBPARAM_SERVICE_CATEGORY_PROGRAM_RESULTS);
+//          encodeScpResults(bData, outStream);
+//      }
+  return outStream->toByteVector();
+}
+
+std::shared_ptr<BearerData> BearerData::decode(std::vector<uint8_t> smsData) {
+  return decode(smsData, 0);
+}
+
+bool BearerData::decodeMessageId(std::shared_ptr<BearerData> bData,
+    std::shared_ptr<BitwiseInputStream> inStream) {
+  const int EXPECTED_PARAM_SIZE = 3 * 8;
+  bool decodeSuccess = false;
+  int paramBits = inStream->read(8) * 8;
+  if (paramBits >= EXPECTED_PARAM_SIZE) {
+    paramBits -= EXPECTED_PARAM_SIZE;
+    decodeSuccess = true;
+    bData->messageType = inStream->read(4);
+    bData->messageId = inStream->read(8) << 8;
+    bData->messageId |= inStream->read(8);
+    bData->hasUserDataHeader = (inStream->read(1) == 1);
+    inStream->skip(3);
+  }
+  if ((!decodeSuccess) || (paramBits > 0)) {
+//              Rlog.d(LOG_TAG, "MESSAGE_IDENTIFIER decode " +
+//                        (decodeSuccess ? "succeeded" : "failed") +
+//                        " (extra bits = " + paramBits + ")");
+  }
+  inStream->skip(paramBits);
+  return decodeSuccess;
+}
+
+bool BearerData::decodeUserData(std::shared_ptr<BearerData> bData,
+    std::shared_ptr<BitwiseInputStream> inStream) {
+  uint32_t paramBits = inStream->read((uint32_t) 8) * 8;
+  bData->userData = std::make_shared<UserData>();
+  bData->userData->msgEncoding = inStream->read(5);
+  bData->userData->msgEncodingSet = true;
+  bData->userData->msgType = 0;
+  int consumedBits = 5;
+  if ((bData->userData->msgEncoding == UserData::ENCODING_IS91_EXTENDED_PROTOCOL)
+      || (bData->userData->msgEncoding == UserData::ENCODING_GSM_DCS)) {
+    bData->userData->msgType = inStream->read(8);
+    consumedBits += 8;
+  }
+  bData->userData->numFields = inStream->read(8);
+  consumedBits += 8;
+  int dataBits = paramBits - consumedBits;
+  bData->userData->payload = inStream->readByteVector(dataBits);
+  return true;
+}
+
+bool BearerData::decodeUserResponseCode(std::shared_ptr<BearerData> bData,
+    std::shared_ptr<BitwiseInputStream> inStream) {
+  const uint32_t EXPECTED_PARAM_SIZE = 1 * 8;
+  bool decodeSuccess = false;
+  uint32_t paramBits = inStream->read(8) * 8;
+  if (paramBits >= EXPECTED_PARAM_SIZE) {
+    paramBits -= EXPECTED_PARAM_SIZE;
+    decodeSuccess = true;
+    bData->userResponseCode = inStream->read(8);
+  }
+  if ((!decodeSuccess) || (paramBits > 0)) {
+//      Rlog.d(LOG_TAG, "USER_RESPONSE_CODE decode " +
+//                (decodeSuccess ? "succeeded" : "failed") +
+//                " (extra bits = " + paramBits + ")");
+  }
+  inStream->skip(paramBits);
+  bData->userResponseCodeSet = decodeSuccess;
+  return decodeSuccess;
+}
+
+bool BearerData::decodeReplyOption(std::shared_ptr<BearerData> bData,
+    std::shared_ptr<BitwiseInputStream> inStream) {
+  const int EXPECTED_PARAM_SIZE = 1 * 8;
+  bool decodeSuccess = false;
+  int paramBits = inStream->read(8) * 8;
+  if (paramBits >= EXPECTED_PARAM_SIZE) {
+    paramBits -= EXPECTED_PARAM_SIZE;
+    decodeSuccess = true;
+    bData->userAckReq = (inStream->read(1) == 1);
+    bData->deliveryAckReq = (inStream->read(1) == 1);
+    bData->readAckReq = (inStream->read(1) == 1);
+    bData->reportReq = (inStream->read(1) == 1);
+    inStream->skip(4);
+  }
+  if ((!decodeSuccess) || (paramBits > 0)) {
+//      Rlog->d(LOG_TAG, "REPLY_OPTION decode " +
+//                (decodeSuccess ? "succeeded" : "failed") +
+//                " (extra bits = " + paramBits + ")");
+  }
+  inStream->skip(paramBits);
+  return decodeSuccess;
+}
+
+bool BearerData::decodeMsgCount(std::shared_ptr<BearerData> bData,
+    std::shared_ptr<BitwiseInputStream> inStream) {
+  const int EXPECTED_PARAM_SIZE = 1 * 8;
+  bool decodeSuccess = false;
+  int paramBits = inStream->read(8) * 8;
+  if (paramBits >= EXPECTED_PARAM_SIZE) {
+    paramBits -= EXPECTED_PARAM_SIZE;
+    decodeSuccess = true;
+    bData->numberOfMessages = IccUtils::cdmaBcdByteToInt(
+        (uint8_t) inStream->read(8));
+  }
+  if ((!decodeSuccess) || (paramBits > 0)) {
+//              Rlog.d(LOG_TAG, "NUMBER_OF_MESSAGES decode " +
+//                        (decodeSuccess ? "succeeded" : "failed") +
+//                        " (extra bits = " + paramBits + ")");
+  }
+  inStream->skip(paramBits);
+  return decodeSuccess;
+}
+
+std::string BearerData::decodeDtmfSmsAddress(std::vector<uint8_t> rawData,
+    int numFields) {
+  /* DTMF 4-bit digit encoding, defined in at
+   * 3GPP2 C.S005-D, v2.0, table 2.7.1.3.2.4-4 */
+  string strBuf;
+  for (int i = 0; i < numFields; i++) {
+    int val = 0x0F & (rawData[i / 2] >> (4 - ((i % 2) * 4)));
+    if ((val >= 1) && (val <= 9))
+      strBuf.append(to_string(val));
+    else if (val == 10)
+      strBuf.push_back('0');
+    else if (val == 11)
+      strBuf.push_back('*');
+    else if (val == 12)
+      strBuf.push_back('#');
+    else
+      throw runtime_error(
+          "invalid SMS address DTMF code (" + std::to_string(val) + ")");
+  }
+  return strBuf;
+}
+
+void BearerData::decodeSmsAddress(std::shared_ptr<CdmaSmsAddress> addr) {
+  if (addr->digitMode == CdmaSmsAddress::DIGIT_MODE_8BIT_CHAR) {
+    //android not support
+//              try {
+//                  /* As specified in 3GPP2 C.S0015-B, v2, 4.5.15 -- actually
+//                   * just 7-bit ASCII encoding, with the MSB being zero. */
+//                  addr->address = new string(addr->origBytes, addr->origBytes_length);
+//              } catch (exception& ex) {
+//                  throw runtime_error("invalid SMS address ASCII code");
+//              }
+  } else {
+    addr->address = decodeDtmfSmsAddress(addr->origBytes, addr->numberOfDigits);
+  }
+}
+bool BearerData::decodeCallbackNumber(std::shared_ptr<BearerData> bData,
+    std::shared_ptr<BitwiseInputStream> inStream) {
+  const int EXPECTED_PARAM_SIZE = 1 * 8; //at least
+  int paramBits = inStream->read(8) * 8;
+  if (paramBits < EXPECTED_PARAM_SIZE) {
+    inStream->skip(paramBits);
+    return false;
+  }
+  std::shared_ptr<CdmaSmsAddress> addr = make_shared<CdmaSmsAddress>();
+  addr->digitMode = inStream->read(1);
+  uint8_t fieldBits = 4;
+  uint8_t consumedBits = 1;
+  if (addr->digitMode == CdmaSmsAddress::DIGIT_MODE_8BIT_CHAR) {
+    addr->ton = inStream->read(3);
+    addr->numberPlan = inStream->read(4);
+    fieldBits = 8;
+    consumedBits += 7;
+  }
+  addr->numberOfDigits = inStream->read(8);
+  consumedBits += 8;
+  int remainingBits = paramBits - consumedBits;
+  int dataBits = addr->numberOfDigits * fieldBits;
+  int paddingBits = remainingBits - dataBits;
+  if (remainingBits < dataBits) {
+    throw runtime_error(
+        string("CALLBACK_NUMBER subparam encoding size error (")
+            + string("remainingBits + ") + std::to_string(remainingBits)
+            + string(", dataBits + ") + std::to_string(dataBits)
+            + string(", paddingBits + ") + std::to_string(paddingBits)
+            + string(")"));
+  }
+  addr->origBytes = inStream->readByteVector(dataBits);
+  inStream->skip(paddingBits);
+  decodeSmsAddress(addr);
+  bData->callbackNumber = addr;
+  return true;
+}
+
+bool BearerData::decodeMsgStatus(std::shared_ptr<BearerData> bData,
+    std::shared_ptr<BitwiseInputStream> inStream) {
+  const int EXPECTED_PARAM_SIZE = 1 * 8;
+  bool decodeSuccess = false;
+  int paramBits = inStream->read(8) * 8;
+  if (paramBits >= EXPECTED_PARAM_SIZE) {
+    paramBits -= EXPECTED_PARAM_SIZE;
+    decodeSuccess = true;
+    bData->errorClass = inStream->read(2);
+    bData->messageStatus = inStream->read(6);
+  }
+  if ((!decodeSuccess) || (paramBits > 0)) {
+//      Rlog.d(LOG_TAG, "MESSAGE_STATUS decode " +
+//                (decodeSuccess ? "succeeded" : "failed") +
+//                " (extra bits = " + paramBits + ")");
+  }
+  inStream->skip(paramBits);
+  bData->messageStatusSet = decodeSuccess;
+  return decodeSuccess;
+}
+
+bool BearerData::decodeMsgCenterTimeStamp(std::shared_ptr<BearerData> bData,
+    std::shared_ptr<BitwiseInputStream> inStream) {
+  const int EXPECTED_PARAM_SIZE = 6 * 8;
+  bool decodeSuccess = false;
+  int paramBits = inStream->read(8) * 8;
+  if (paramBits >= EXPECTED_PARAM_SIZE) {
+    paramBits -= EXPECTED_PARAM_SIZE;
+    decodeSuccess = true;
+    fromByteArray(inStream->readByteVector(6 * 8), bData->msgCenterTimeStamp);
+  }
+  if ((!decodeSuccess) || (paramBits > 0)) {
+    /*      Rlog.d(LOG_TAG, "MESSAGE_CENTER_TIME_STAMP decode " +
+     (decodeSuccess ? "succeeded" : "failed") +
+     " (extra bits = " + paramBits + ")");*/
+  }
+  inStream->skip(paramBits);
+  return decodeSuccess;
+}
+
+bool BearerData::decodeValidityAbs(std::shared_ptr<BearerData> bData,
+    std::shared_ptr<BitwiseInputStream> inStream) {
+  const int EXPECTED_PARAM_SIZE = 6 * 8;
+  bool decodeSuccess = false;
+  int paramBits = inStream->read(8) * 8;
+  if (paramBits >= EXPECTED_PARAM_SIZE) {
+    paramBits -= EXPECTED_PARAM_SIZE;
+    decodeSuccess = true;
+    fromByteArray(inStream->readByteVector(6 * 8),
+        bData->validityPeriodAbsolute);
+  }
+  if ((!decodeSuccess) || (paramBits > 0)) {
+//      Rlog.d(LOG_TAG, "VALIDITY_PERIOD_ABSOLUTE decode " +
+//                (decodeSuccess ? "succeeded" : "failed") +
+//                " (extra bits = " + paramBits + ")");
+  }
+  inStream->skip(paramBits);
+  return decodeSuccess;
+}
+
+bool BearerData::decodeValidityRel(std::shared_ptr<BearerData> bData,
+    std::shared_ptr<BitwiseInputStream> inStream) {
+  const int EXPECTED_PARAM_SIZE = 1 * 8;
+  bool decodeSuccess = false;
+  int paramBits = inStream->read(8) * 8;
+  if (paramBits >= EXPECTED_PARAM_SIZE) {
+    paramBits -= EXPECTED_PARAM_SIZE;
+    decodeSuccess = true;
+    //bData->deferredDeliveryTimeRelative = inStream->read(8);
+    bData->validityPeriodRelative = inStream->read(8);
+  }
+  if ((!decodeSuccess) || (paramBits > 0)) {
+    /*      Rlog.d(LOG_TAG, "VALIDITY_PERIOD_RELATIVE decode " +
+     (decodeSuccess ? "succeeded" : "failed") +
+     " (extra bits = " + paramBits + ")");*/
+  }
+  inStream->skip(paramBits);
+  //bData->deferredDeliveryTimeRelativeSet = decodeSuccess;
+  bData->validityPeriodRelativeSet = decodeSuccess;
+  return decodeSuccess;
+}
+
+bool BearerData::decodeDeferredDeliveryAbs(std::shared_ptr<BearerData> bData,
+    std::shared_ptr<BitwiseInputStream> inStream) {
+  const int EXPECTED_PARAM_SIZE = 6 * 8;
+  bool decodeSuccess = false;
+  int paramBits = inStream->read(8) * 8;
+  if (paramBits >= EXPECTED_PARAM_SIZE) {
+    paramBits -= EXPECTED_PARAM_SIZE;
+    decodeSuccess = true;
+    fromByteArray(inStream->readByteVector(6 * 8),
+        bData->deferredDeliveryTimeAbsolute);
+  }
+  if ((!decodeSuccess) || (paramBits > 0)) {
+    /*      Rlog.d(LOG_TAG, "DEFERRED_DELIVERY_TIME_ABSOLUTE decode " +
+     (decodeSuccess ? "succeeded" : "failed") +
+     " (extra bits = " + paramBits + ")");*/
+  }
+  inStream->skip(paramBits);
+  return decodeSuccess;
+}
+
+bool BearerData::decodeDeferredDeliveryRel(std::shared_ptr<BearerData> bData,
+    std::shared_ptr<BitwiseInputStream> inStream) {
+  const int EXPECTED_PARAM_SIZE = 1 * 8;
+  bool decodeSuccess = false;
+  int paramBits = inStream->read(8) * 8;
+  if (paramBits >= EXPECTED_PARAM_SIZE) {
+    paramBits -= EXPECTED_PARAM_SIZE;
+    decodeSuccess = true;
+    //bData->validityPeriodRelative = inStream->read(8);
+    bData->deferredDeliveryTimeRelative = inStream->read(8);
+  }
+  if ((!decodeSuccess) || (paramBits > 0)) {
+    /*      Rlog.d(LOG_TAG, "DEFERRED_DELIVERY_TIME_RELATIVE decode " +
+     (decodeSuccess ? "succeeded" : "failed") +
+     " (extra bits = " + paramBits + ")");*/
+  }
+  inStream->skip(paramBits);
+  //bData->validityPeriodRelativeSet = decodeSuccess;
+  bData->deferredDeliveryTimeRelativeSet = decodeSuccess;
+  return decodeSuccess;
+}
+
+bool BearerData::decodePrivacyIndicator(std::shared_ptr<BearerData> bData,
+    std::shared_ptr<BitwiseInputStream> inStream) {
+  const int EXPECTED_PARAM_SIZE = 1 * 8;
+  bool decodeSuccess = false;
+  int paramBits = inStream->read(8) * 8;
+  if (paramBits >= EXPECTED_PARAM_SIZE) {
+    paramBits -= EXPECTED_PARAM_SIZE;
+    decodeSuccess = true;
+    bData->privacy = inStream->read(2);
+    inStream->skip(6);
+  }
+  if ((!decodeSuccess) || (paramBits > 0)) {
+    /*      Rlog.d(LOG_TAG, "PRIVACY_INDICATOR decode " +
+     (decodeSuccess ? "succeeded" : "failed") +
+     " (extra bits = " + paramBits + ")");*/
+  }
+  inStream->skip(paramBits);
+  bData->privacyIndicatorSet = decodeSuccess;
+  return decodeSuccess;
+}
+bool BearerData::decodeLanguageIndicator(std::shared_ptr<BearerData> bData,
+    std::shared_ptr<BitwiseInputStream> inStream) {
+  const int EXPECTED_PARAM_SIZE = 1 * 8;
+  bool decodeSuccess = false;
+  int paramBits = inStream->read(8) * 8;
+  if (paramBits >= EXPECTED_PARAM_SIZE) {
+    paramBits -= EXPECTED_PARAM_SIZE;
+    decodeSuccess = true;
+    bData->language = inStream->read(8);
+  }
+  if ((!decodeSuccess) || (paramBits > 0)) {
+    /*      Rlog.d(LOG_TAG, "LANGUAGE_INDICATOR decode " +
+     (decodeSuccess ? "succeeded" : "failed") +
+     " (extra bits = " + paramBits + ")");*/
+  }
+  inStream->skip(paramBits);
+  bData->languageIndicatorSet = decodeSuccess;
+  return decodeSuccess;
+}
+
+bool BearerData::decodeDisplayMode(std::shared_ptr<BearerData> bData,
+    std::shared_ptr<BitwiseInputStream> inStream) {
+  const int EXPECTED_PARAM_SIZE = 1 * 8;
+  bool decodeSuccess = false;
+  int paramBits = inStream->read(8) * 8;
+  if (paramBits >= EXPECTED_PARAM_SIZE) {
+    paramBits -= EXPECTED_PARAM_SIZE;
+    decodeSuccess = true;
+    bData->displayMode = inStream->read(2);
+    inStream->skip(6);
+  }
+//  if ((! decodeSuccess) || (paramBits > 0)) {
+//      Rlog.d(LOG_TAG, "DISPLAY_MODE decode " +
+//                (decodeSuccess ? "succeeded" : "failed") +
+//                " (extra bits = " + paramBits + ")");
+//  }
+  inStream->skip(paramBits);
+  bData->displayModeSet = decodeSuccess;
+  return decodeSuccess;
+}
+
+bool BearerData::decodePriorityIndicator(std::shared_ptr<BearerData> bData,
+    std::shared_ptr<BitwiseInputStream> inStream) {
+  const int EXPECTED_PARAM_SIZE = 1 * 8;
+  bool decodeSuccess = false;
+  int paramBits = inStream->read(8) * 8;
+  if (paramBits >= EXPECTED_PARAM_SIZE) {
+    paramBits -= EXPECTED_PARAM_SIZE;
+    decodeSuccess = true;
+    bData->priority = inStream->read(2);
+    inStream->skip(6);
+  }
+//  if ((! decodeSuccess) || (paramBits > 0)) {
+//      Rlog.d(LOG_TAG, "PRIORITY_INDICATOR decode " +
+//                (decodeSuccess ? "succeeded" : "failed") +
+//                " (extra bits = " + paramBits + ")");
+//  }
+  inStream->skip(paramBits);
+  bData->priorityIndicatorSet = decodeSuccess;
+  return decodeSuccess;
+}
+
+bool BearerData::decodeMsgDeliveryAlert(std::shared_ptr<BearerData> bData,
+    std::shared_ptr<BitwiseInputStream> inStream) {
+  const int EXPECTED_PARAM_SIZE = 1 * 8;
+  bool decodeSuccess = false;
+  int paramBits = inStream->read(8) * 8;
+  if (paramBits >= EXPECTED_PARAM_SIZE) {
+    paramBits -= EXPECTED_PARAM_SIZE;
+    decodeSuccess = true;
+    bData->alert = inStream->read(2);
+    inStream->skip(6);
+  }
+  if ((!decodeSuccess) || (paramBits > 0)) {
+//      Rlog.d(LOG_TAG, "ALERT_ON_MESSAGE_DELIVERY decode " +
+//                (decodeSuccess ? "succeeded" : "failed") +
+//                " (extra bits = " + paramBits + ")");
+  }
+  inStream->skip(paramBits);
+  bData->alertIndicatorSet = decodeSuccess;
+  return decodeSuccess;
+}
+
+bool BearerData::decodeDepositIndex(std::shared_ptr<BearerData> bData,
+    std::shared_ptr<BitwiseInputStream> inStream) {
+  const int EXPECTED_PARAM_SIZE = 2 * 8;
+  bool decodeSuccess = false;
+  int paramBits = inStream->read(8) * 8;
+  if (paramBits >= EXPECTED_PARAM_SIZE) {
+    paramBits -= EXPECTED_PARAM_SIZE;
+    decodeSuccess = true;
+    bData->depositIndex = (inStream->read(8) << 8) | inStream->read(8);
+  }
+  /*  if ((! decodeSuccess) || (paramBits > 0)) {
+   Rlog.d(LOG_TAG, "MESSAGE_DEPOSIT_INDEX decode " +
+   (decodeSuccess ? "succeeded" : "failed") +
+   " (extra bits = " + paramBits + ")");
+   }*/
+  inStream->skip(paramBits);
+  return decodeSuccess;
+}
+
+int BearerData::getBitsForNumFields(int msgEncoding, int numFields) {
+  switch (msgEncoding) {
+  case UserData::ENCODING_OCTET:
+  case UserData::ENCODING_SHIFT_JIS:
+  case UserData::ENCODING_KOREAN:
+  case UserData::ENCODING_LATIN:
+  case UserData::ENCODING_LATIN_HEBREW:
+    return numFields * 8;
+
+  case UserData::ENCODING_IA5:
+  case UserData::ENCODING_7BIT_ASCII:
+  case UserData::ENCODING_GSM_7BIT_ALPHABET:
+    return numFields * 7;
+
+  case UserData::ENCODING_UNICODE_16:
+    return numFields * 16;
+
+  default:
+    throw runtime_error("unsupported message encoding (" + msgEncoding + ')');
+  }
+}
+
+std::string BearerData::decodeUtf8(std::vector<uint8_t> data, int offset, int numFields)
+{
+    std::string str;
+    for (int i = offset; i < (offset + numFields); i++)
+    {
+        str.push_back((char)data[i]);
+    }
+    return str;
+}
+
+std::string BearerData::decodeLatin(std::vector<uint8_t> data, int offset, int numFields)
+{
+    std::string str;
+    for (int i = offset; i < (offset + numFields); i++)
+    {
+        str.push_back(data[i]);
+    }
+    char* text = g_convert (str.c_str(), numFields, "UTF-8", "ISO−8859−1", NULL, NULL, NULL);
+    if(!text) {
+        printf("convert (Latin) result is null\n");
+        return std::string("");
+    }
+    std::string ret(text);
+    g_free(text);
+    return ret;
+}
+
+std::string BearerData::decodeUtf16(std::vector<uint8_t> data, int offset, int numFields)
+{
+    std::string str;
+    for (int i = offset; i < (offset + numFields*2); i++)
+    {
+        str.push_back((char)data[i]);
+    }
+    char* text = g_convert (str.c_str(), numFields*2, "UTF-8", "UCS-2BE", NULL, NULL, NULL);
+    if(!text) {
+        printf("convert (Utf16) result is null\n");
+        return std::string("");
+    }
+    std::string ret(text);
+    g_free(text);
+    text = NULL;
+    return ret;
+}
+
+std::string BearerData::decode7bitAscii(std::vector<uint8_t> data, int offset,
+    int numFields) {
+    int headerSeptets = (offset * 8 + 6) / 7;
+    numFields -= headerSeptets;
+    std::string strBuf;
+    auto inStream = std::make_shared<BitwiseInputStream>(data);
+    int wantedBits = (headerSeptets + numFields) * 7;
+    if (inStream->available() < wantedBits) {
+      throw runtime_error(
+          "insufficient data (wanted " + std::to_string(wantedBits)
+              + " bits, but only have " + std::to_string(inStream->available())
+              + ")");
+    }
+    inStream->skip(headerSeptets * 7);
+  for (int i = 0; i < numFields; i++) {
+    int charCode = inStream->read(7);
+    if ((charCode >= UserData::ASCII_MAP_BASE_INDEX)
+        && (charCode <= UserData::ASCII_MAP_MAX_INDEX)) {
+      strBuf.push_back(
+          UserData::ASCII_MAP[charCode - UserData::ASCII_MAP_BASE_INDEX]);
+    } else if (charCode == UserData::ASCII_NL_INDEX) {
+      strBuf.push_back('\n');
+    } else if (charCode == UserData::ASCII_CR_INDEX) {
+      strBuf.push_back('\r');
+    } else {
+      /* For other charCodes, they are unprintable, and so simply use SPACE. */
+      strBuf.push_back(' ');
+    }
+  }
+  return strBuf;
+}
+
+std::string BearerData::decode7bitGsm(std::vector<uint8_t> data, int offset,
+    int numFields) {
+  // Start reading from the next 7-bit aligned boundary after offset.
+  int offsetBits = offset * 8;
+  int offsetSeptets = (offsetBits + 6) / 7;
+  numFields -= offsetSeptets;
+  int paddingBits = (offsetSeptets * 7) - offsetBits;
+  string result = GsmAlphabet::gsm7BitPackedToString(data, offset, numFields,
+      paddingBits, 0, 0);
+  if (result.empty()) {
+    throw runtime_error("7bit GSM decoding failed");
+  }
+  return result;
+}
+
+std::string BearerData::decodeGsmDcs(std::vector<uint8_t> data, int offset,
+    int numFields, int msgType) {
+  if ((msgType & 0xC0) != 0) {
+    throw runtime_error(
+        "unsupported coding group (" + std::to_string(msgType) + ")");
+  }
+
+  switch ((msgType >> 2) & 0x3) {
+  case UserData::ENCODING_GSM_DCS_7BIT:
+    return decode7bitGsm(data, offset, numFields);
+//  case UserData.ENCODING_GSM_DCS_8BIT:
+//      return decodeUtf8(data, offset, numFields);
+//  case UserData.ENCODING_GSM_DCS_16BIT:
+//      return decodeUtf16(data, offset, numFields);
+  default:
+    throw runtime_error(
+        "unsupported user msgType encoding (" + std::to_string(msgType) + ")");
+  }
+}
+
+void BearerData::decodeUserDataPayload(std::shared_ptr<UserData> userData,
+    bool hasUserDataHeader) {
+  int offset = 0;
+  //printf("1st,%s\n",userData->toString().c_str());
+  if (hasUserDataHeader) {
+    int udhLen = userData->payload[0] & 0x00FF;
+    offset += udhLen + 1;
+    /*      byte[] headerData = new byte[udhLen];
+     System.arraycopy(userData.payload, 1, headerData, 0, udhLen)*/;
+    std::vector<uint8_t> v;
+    v.insert(v.end(), userData->payload.begin() + 1,
+        userData->payload.begin() + udhLen);
+    userData->userDataHeader = SmsHeader::fromByteArray(v);
+    //for test cdma long sms, SmsHeader::fromByteArray get the sequence number,but it will always be the last sequence,
+    //maybe overwriten by the last sms part. we print here directly as a temporary solution.
+    if(udhLen == 5 && (userData->payload[1] & 0x00FF)==0x00)//0x00 is the concatenated SMS id
+    {
+        printf("udhLen=%d,refNumber=%d,msgCount=%d, seqNumber=%d\n", udhLen,
+        userData->payload[3] & 0x00FF,userData->payload[4] & 0x00FF,userData->payload[5] & 0x00FF);
+    }
+    else{
+        printf("udhLen=%d, not for test format!\n",udhLen);
+    }
+  }
+  //add for long sms test begin
+  //printf("offset: %d\n",offset);
+  //printf("2nd,%s\n",userData->toString().c_str());
+  //add for long sms test end
+  switch (userData->msgEncoding) {
+  case UserData::ENCODING_OCTET: {
+    /*
+     *  Octet decoding depends on the carrier service.
+     */
+    bool decodingtypeUTF8 = true;
+
+    // Strip off any padding bytes, meaning any differences between the length of the
+    // array and the target length specified by numFields.  This is to avoid any
+    // confusion by code elsewhere that only considers the payload array length.
+    int copyLen = userData->numFields < userData->payload.size() ? userData->numFields : userData->payload.size();
+    std::vector<uint8_t> payload;
+    payload.insert(payload.end(), userData->payload.begin(), userData->payload.begin() + copyLen);
+    userData->payload = payload;
+
+    if (!decodingtypeUTF8) {
+      // There are many devices in the market that send 8bit text sms (latin encoded) as
+      // octet encoded.
+      userData->payloadStr = decodeLatin(userData->payload, offset, userData->numFields);
+    } else {
+      userData->payloadStr = decodeUtf8(userData->payload, offset, userData->numFields);
+    }
+    break;
+  }
+  case UserData::ENCODING_IA5:
+  case UserData::ENCODING_7BIT_ASCII: {
+    userData->payloadStr = decode7bitAscii(userData->payload, offset, userData->numFields);
+    break;
+  case UserData::ENCODING_UNICODE_16:
+      userData->payloadStr = decodeUtf16(userData->payload, offset, userData->numFields);
+      break;
+  }
+  case UserData::ENCODING_GSM_7BIT_ALPHABET: {
+    userData->payloadStr = decode7bitGsm(userData->payload, offset, userData->numFields);
+    break;
+  }
+  case UserData::ENCODING_LATIN:
+      userData->payloadStr = decodeLatin(userData->payload, offset, userData->numFields);
+      break;
+//  case UserData::ENCODING_SHIFT_JIS:
+//     // userData->payloadStr = decodeShiftJis(userData->payload, offset, userData->numFields);
+//    //TBD "unsupported user data encoding"
+//      break;
+  case UserData::ENCODING_GSM_DCS: {
+    userData->payloadStr = decodeGsmDcs(userData->payload, offset,
+        userData->numFields, userData->msgType);
+    break;
+  }
+  default:
+      printf("unsupported user data encoding : %\n" ,std::to_string(userData->msgEncoding));
+//    throw runtime_error(
+//        "unsupported user data encoding ("
+//            + std::to_string(userData->msgEncoding) + ")");
+  }
+}
+bool BearerData::decodeServiceCategoryProgramData(
+    std::shared_ptr<BearerData> bData,
+    std::shared_ptr<BitwiseInputStream> inStream) {
+  if (inStream->available() < 13) {
+    throw runtime_error(
+        string("SERVICE_CATEGORY_PROGRAM_DATA decode failed: only ")
+            + std::to_string(inStream->available())
+            + string(" bits available"));
+  }
+
+  int paramBits = inStream->read(8) * 8;
+  int msgEncoding = inStream->read(5);
+  paramBits -= 5;
+
+  if (inStream->available() < paramBits) {
+    throw runtime_error(
+        string("SERVICE_CATEGORY_PROGRAM_DATA decode failed: only ")
+            + std::to_string(inStream->available())
+            + string(" bits available (") + std::to_string(paramBits)
+            + string(" bits expected)"));
+  }
+
+  auto programDataList = make_shared<list<shared_ptr<CdmaSmsCbProgramData>>>();
+  const int CATEGORY_FIELD_MIN_SIZE = 6 * 8;
+  bool decodeSuccess = false;
+  while (paramBits >= CATEGORY_FIELD_MIN_SIZE) {
+    int operation = inStream->read(4);
+    int category = (inStream->read(8) << 8) | inStream->read(8);
+    int language = inStream->read(8);
+    int maxMessages = inStream->read(8);
+    int alertOption = inStream->read(4);
+    int numFields = inStream->read(8);
+    paramBits -= CATEGORY_FIELD_MIN_SIZE;
+
+    int textBits = getBitsForNumFields(msgEncoding, numFields);
+    if (paramBits < textBits) {
+      throw runtime_error(
+          string("category name is ") + std::to_string(textBits)
+              + string(" bits in length,") + string(" but there are only ")
+              + std::to_string(paramBits) + string(" bits available"));
+    }
+
+    auto userData = make_shared<UserData>();
+    userData->msgEncoding = msgEncoding;
+    userData->msgEncodingSet = true;
+    userData->numFields = numFields;
+    userData->payload = inStream->readByteVector(textBits);
+    paramBits -= textBits;
+
+    decodeUserDataPayload(userData, false);
+    string categoryName = userData->payloadStr;
+    auto programData = std::make_shared<CdmaSmsCbProgramData>(operation,
+        category, language, maxMessages, alertOption, categoryName);
+    programDataList->push_back(programData);
+
+    decodeSuccess = true;
+  }
+
+  if ((!decodeSuccess) || (paramBits > 0)) {
+//      Rlog.d(LOG_TAG, "SERVICE_CATEGORY_PROGRAM_DATA decode " +
+//                (decodeSuccess ? "succeeded" : "failed") +
+//                " (extra bits = " + paramBits + ')');
+  }
+
+  inStream->skip(paramBits);
+  bData->serviceCategoryProgramData = programDataList;
+  return decodeSuccess;
+}
+
+bool BearerData::decodeReserved(std::shared_ptr<BearerData> bData,
+    std::shared_ptr<BitwiseInputStream> inStream, int subparamId) {
+  bool decodeSuccess = false;
+  int subparamLen = inStream->read(8); // SUBPARAM_LEN
+  int paramBits = subparamLen * 8;
+  if (paramBits <= inStream->available()) {
+    decodeSuccess = true;
+    inStream->skip(paramBits);
+  }
+//  Rlog.d(LOG_TAG, "RESERVED bearer data subparameter " + subparamId + " decode "
+//          + (decodeSuccess ? "succeeded" : "failed") + " (param bits = " + paramBits + ")");
+  if (!decodeSuccess) {
+    throw runtime_error(
+        "RESERVED bearer data subparameter " + std::to_string(subparamId)
+            + " had invalid SUBPARAM_LEN " + std::to_string(subparamLen));
+  }
+
+  return decodeSuccess;
+}
+bool BearerData::isCmasAlertCategory(int category) {
+  return category >= SmsEnvelope::SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT
+      && category <= SmsEnvelope::SERVICE_CATEGORY_CMAS_LAST_RESERVED_VALUE;
+}
+
+int BearerData::serviceCategoryToCmasMessageClass(int serviceCategory) {
+  switch (serviceCategory) {
+  case SmsEnvelope::SERVICE_CATEGORY_CMAS_PRESIDENTIAL_LEVEL_ALERT:
+    return SmsCbCmasInfo::CMAS_CLASS_PRESIDENTIAL_LEVEL_ALERT;
+
+  case SmsEnvelope::SERVICE_CATEGORY_CMAS_EXTREME_THREAT:
+    return SmsCbCmasInfo::CMAS_CLASS_EXTREME_THREAT;
+
+  case SmsEnvelope::SERVICE_CATEGORY_CMAS_SEVERE_THREAT:
+    return SmsCbCmasInfo::CMAS_CLASS_SEVERE_THREAT;
+
+  case SmsEnvelope::SERVICE_CATEGORY_CMAS_CHILD_ABDUCTION_EMERGENCY:
+    return SmsCbCmasInfo::CMAS_CLASS_CHILD_ABDUCTION_EMERGENCY;
+
+  case SmsEnvelope::SERVICE_CATEGORY_CMAS_TEST_MESSAGE:
+    return SmsCbCmasInfo::CMAS_CLASS_REQUIRED_MONTHLY_TEST;
+
+  default:
+    return SmsCbCmasInfo::CMAS_CLASS_UNKNOWN;
+  }
+}
+void BearerData::decodeCmasUserData(std::shared_ptr<BearerData> bData,
+    int serviceCategory) {
+  //uint8_t array[bData->userData->payload.size()];
+  //std::copy(bData->userData->payload.begin(), bData->userData->payload.end(), array);
+  auto inStream = make_shared<BitwiseInputStream>(bData->userData->payload);
+
+  if (inStream->available() < 8) {
+    throw runtime_error("emergency CB with no CMAE_protocol_version");
+  }
+  int protocolVersion = inStream->read(8);
+  if (protocolVersion != 0) {
+    throw runtime_error("unsupported CMAE_protocol_version " + protocolVersion);
+  }
+
+  int messageClass = serviceCategoryToCmasMessageClass(serviceCategory);
+  int category = SmsCbCmasInfo::CMAS_CATEGORY_UNKNOWN;
+  int responseType = SmsCbCmasInfo::CMAS_RESPONSE_TYPE_UNKNOWN;
+  int severity = SmsCbCmasInfo::CMAS_SEVERITY_UNKNOWN;
+  int urgency = SmsCbCmasInfo::CMAS_URGENCY_UNKNOWN;
+  int certainty = SmsCbCmasInfo::CMAS_CERTAINTY_UNKNOWN;
+
+  while (inStream->available() >= 16) {
+    int recordType = inStream->read(8);
+    int recordLen = inStream->read(8);
+    switch (recordType) {
+    case 0:     // Type 0 elements (Alert text)
+    {
+      auto alertUserData = make_shared<UserData>();
+      alertUserData->msgEncoding = inStream->read(5);
+      alertUserData->msgEncodingSet = true;
+      alertUserData->msgType = 0;
+
+      int numFields;                          // number of chars to decode
+      switch (alertUserData->msgEncoding) {
+      case UserData::ENCODING_OCTET:
+      case UserData::ENCODING_LATIN:
+        numFields = recordLen - 1;      // subtract 1 byte for encoding
+        break;
+
+      case UserData::ENCODING_IA5:
+      case UserData::ENCODING_7BIT_ASCII:
+      case UserData::ENCODING_GSM_7BIT_ALPHABET:
+        numFields = ((recordLen * 8) - 5) / 7;  // subtract 5 bits for encoding
+        break;
+
+      case UserData::ENCODING_UNICODE_16:
+        numFields = (recordLen - 1) / 2;
+        break;
+
+      default:
+        numFields = 0;      // unsupported encoding
+      }
+
+      alertUserData->numFields = numFields;
+      alertUserData->payload = inStream->readByteVector(recordLen * 8 - 5);
+      decodeUserDataPayload(alertUserData, false);
+      bData->userData = alertUserData;
+      break;
+    }
+    case 1:     // Type 1 elements
+    {
+      category = inStream->read(8);
+      responseType = inStream->read(8);
+      severity = inStream->read(4);
+      urgency = inStream->read(4);
+      certainty = inStream->read(4);
+      inStream->skip(recordLen * 8 - 28);
+      break;
+    }
+    default:
+      //Rlog.w(LOG_TAG, "skipping unsupported CMAS record type " + recordType);
+      inStream->skip(recordLen * 8);
+      break;
+    }
+  }
+
+  bData->cmasWarningInfo = make_shared<SmsCbCmasInfo>(messageClass, category,
+      responseType, severity, urgency, certainty);
+}
+
+void BearerData::decodeIs91VoicemailStatus(std::shared_ptr<BearerData> bData) {
+  //uint8_t array[bData->userData->payload.size()];
+  //std::copy(bData->userData->payload.begin(), bData->userData->payload.end(), array);
+  auto inStream = make_shared<BitwiseInputStream>(bData->userData->payload);
+
+  int dataLen = inStream->available() / 6;  // 6-bit packed character encoding.
+  int numFields = bData->userData->numFields;
+  if ((dataLen > 14) || (dataLen < 3) || (dataLen < numFields)) {
+    throw runtime_error("IS-91 voicemail status decoding failed");
+  }
+  string strbuf;
+  while (inStream->available() >= 6) {
+    strbuf.push_back(UserData::ASCII_MAP[inStream->read(6)]);
+  }
+  string data = strbuf;
+  bData->numberOfMessages = std::stoi(data.substr(0, 2));
+  char prioCode = data.at(2);
+  if (prioCode == ' ') {
+    bData->priority = PRIORITY_NORMAL;
+  } else if (prioCode == '!') {
+    bData->priority = PRIORITY_URGENT;
+  } else {
+    throw runtime_error(
+        string("IS-91 voicemail status decoding failed: ")
+            + string("illegal priority setting (") + std::to_string(prioCode)
+            + string(")"));
+  }
+  bData->priorityIndicatorSet = true;
+  bData->userData->payloadStr = data.substr(3, numFields - 6);
+}
+void BearerData::decodeIs91Cli(std::shared_ptr<BearerData> bData) {
+  //uint8_t array[bData->userData->payload.size()];
+  //std::copy(bData->userData->payload.begin(), bData->userData->payload.end(), array);
+  auto inStream = make_shared<BitwiseInputStream>(bData->userData->payload);
+  int dataLen = inStream->available() / 4;  // 4-bit packed DTMF digit encoding.
+  int numFields = bData->userData->numFields;
+  if ((dataLen > 14) || (dataLen < 3) || (dataLen < numFields)) {
+    throw runtime_error("IS-91 voicemail status decoding failed");
+  }
+  auto addr = make_shared<CdmaSmsAddress>();
+  addr->digitMode = CdmaSmsAddress::DIGIT_MODE_4BIT_DTMF;
+  addr->origBytes = bData->userData->payload;
+  addr->numberOfDigits = (uint8_t) numFields;
+  decodeSmsAddress(addr);
+  bData->callbackNumber = addr;
+}
+
+void BearerData::decodeIs91ShortMessage(std::shared_ptr<BearerData> bData) {
+  //uint8_t array[bData->userData->payload.size()];
+  //std::copy(bData->userData->payload.begin(), bData->userData->payload.end(), array);
+  auto inStream = make_shared<BitwiseInputStream>(bData->userData->payload);
+  int dataLen = inStream->available() / 6;  // 6-bit packed character encoding.
+  int numFields = bData->userData->numFields;
+  // dataLen may be > 14 characters due to octet padding
+  if ((numFields > 14) || (dataLen < numFields)) {
+    throw runtime_error("IS-91 short message decoding failed");
+  }
+  string strbuf;
+  for (int i = 0; i < numFields; i++) {
+    strbuf.push_back(UserData::ASCII_MAP[inStream->read(6)]);
+  }
+  bData->userData->payloadStr = strbuf;
+}
+
+void BearerData::decodeIs91(std::shared_ptr<BearerData> bData) {
+  switch (bData->userData->msgType) {
+  case UserData::IS91_MSG_TYPE_VOICEMAIL_STATUS:
+    decodeIs91VoicemailStatus(bData);
+    break;
+  case UserData::IS91_MSG_TYPE_CLI:
+    decodeIs91Cli(bData);
+    break;
+  case UserData::IS91_MSG_TYPE_SHORT_MESSAGE_FULL:
+  case UserData::IS91_MSG_TYPE_SHORT_MESSAGE:
+    decodeIs91ShortMessage(bData);
+    break;
+  default:
+    throw runtime_error(
+        string("unsupported IS-91 message type (")
+            + std::to_string(bData->userData->msgType) + string(")"));
+  }
+}
+std::shared_ptr<BearerData> BearerData::decode(std::vector<uint8_t> smsData,
+    int serviceCategory) {
+  //uint8_t array[smsData.size()];
+  //std::copy(smsData.begin(), smsData.end(), array);
+  auto inStream = make_shared<BitwiseInputStream>(smsData);
+  shared_ptr<BearerData> bData = make_shared<BearerData>();
+  int foundSubparamMask = 0;
+  while (inStream->available() > 0) {
+    uint32_t subparamId = inStream->read((uint32_t) 8);
+    int subparamIdBit = 1 << subparamId;
+    // int is 4 bytes. This duplicate check has a limit to Id number up to 32 (4*8)
+    // as 32th bit is the max bit in int.
+    // Per 3GPP2 C.S0015-B Table 4.5-1 Bearer Data Subparameter Identifiers:
+    // last defined subparam ID is 23 (00010111 = 0x17 = 23).
+    // Only do duplicate subparam ID check if subparam is within defined value as
+    // reserved subparams are just skipped.
+    if ((foundSubparamMask & subparamIdBit) != 0
+        && (subparamId >= SUBPARAM_MESSAGE_IDENTIFIER
+            && subparamId <= SUBPARAM_ID_LAST_DEFINED)) {
+      throw runtime_error(
+          string("illegal duplicate subparameter (")
+              + std::to_string(subparamId) + string(")"));
+    }
+    bool decodeSuccess;
+    switch (subparamId) {
+    case SUBPARAM_MESSAGE_IDENTIFIER:
+      decodeSuccess = decodeMessageId(bData, inStream);
+      break;
+    case SUBPARAM_USER_DATA:
+      decodeSuccess = decodeUserData(bData, inStream);
+      break;
+    case SUBPARAM_USER_RESPONSE_CODE:
+      decodeSuccess = decodeUserResponseCode(bData, inStream);
+      break;
+    case SUBPARAM_REPLY_OPTION:
+      decodeSuccess = decodeReplyOption(bData, inStream);
+      break;
+    case SUBPARAM_NUMBER_OF_MESSAGES:
+      decodeSuccess = decodeMsgCount(bData, inStream);
+      break;
+    case SUBPARAM_CALLBACK_NUMBER:
+      decodeSuccess = decodeCallbackNumber(bData, inStream);
+      break;
+    case SUBPARAM_MESSAGE_STATUS:
+      decodeSuccess = decodeMsgStatus(bData, inStream);
+      break;
+    case SUBPARAM_MESSAGE_CENTER_TIME_STAMP:
+      decodeSuccess = decodeMsgCenterTimeStamp(bData, inStream);
+      break;
+    case SUBPARAM_VALIDITY_PERIOD_ABSOLUTE:
+      decodeSuccess = decodeValidityAbs(bData, inStream);
+      break;
+    case SUBPARAM_VALIDITY_PERIOD_RELATIVE:
+      decodeSuccess = decodeValidityRel(bData, inStream);
+      break;
+    case SUBPARAM_DEFERRED_DELIVERY_TIME_ABSOLUTE:
+      decodeSuccess = decodeDeferredDeliveryAbs(bData, inStream);
+      break;
+    case SUBPARAM_DEFERRED_DELIVERY_TIME_RELATIVE:
+      decodeSuccess = decodeDeferredDeliveryRel(bData, inStream);
+      break;
+    case SUBPARAM_PRIVACY_INDICATOR:
+      decodeSuccess = decodePrivacyIndicator(bData, inStream);
+      break;
+    case SUBPARAM_LANGUAGE_INDICATOR:
+      decodeSuccess = decodeLanguageIndicator(bData, inStream);
+      break;
+    case SUBPARAM_MESSAGE_DISPLAY_MODE:
+      decodeSuccess = decodeDisplayMode(bData, inStream);
+      break;
+    case SUBPARAM_PRIORITY_INDICATOR:
+      decodeSuccess = decodePriorityIndicator(bData, inStream);
+      break;
+    case SUBPARAM_ALERT_ON_MESSAGE_DELIVERY:
+      decodeSuccess = decodeMsgDeliveryAlert(bData, inStream);
+      break;
+    case SUBPARAM_MESSAGE_DEPOSIT_INDEX:
+      decodeSuccess = decodeDepositIndex(bData, inStream);
+      break;
+    case SUBPARAM_SERVICE_CATEGORY_PROGRAM_DATA:
+      decodeSuccess = decodeServiceCategoryProgramData(bData, inStream);
+      break;
+    default:
+      decodeSuccess = decodeReserved(bData, inStream, subparamId);
+    }
+    if (decodeSuccess
+        && (subparamId >= SUBPARAM_MESSAGE_IDENTIFIER
+            && subparamId <= SUBPARAM_ID_LAST_DEFINED)) {
+      foundSubparamMask |= subparamIdBit;
+    }
+  }
+  if ((foundSubparamMask & (1 << SUBPARAM_MESSAGE_IDENTIFIER)) == 0) {
+    throw runtime_error("missing MESSAGE_IDENTIFIER subparam");
+  }
+  if (bData->userData != nullptr) {
+    if (isCmasAlertCategory(serviceCategory)) {
+      decodeCmasUserData(bData, serviceCategory);
+    } else if (bData->userData->msgEncoding
+        == UserData::ENCODING_IS91_EXTENDED_PROTOCOL) {
+      if ((foundSubparamMask ^ (1 << SUBPARAM_MESSAGE_IDENTIFIER)
+          ^ (1 << SUBPARAM_USER_DATA)) != 0) {
+//                          Rlog.e(LOG_TAG, "IS-91 must occur without extra subparams (" +
+//                                foundSubparamMask + ")");
+      }
+      decodeIs91(bData);
+    } else {
+      decodeUserDataPayload(bData->userData, bData->hasUserDataHeader);
+    }
+  }
+  return bData;
+}
+
+std::string BearerData::toString() {
+  string builder;
+  builder.append("BearerData ");
+  builder.append("{ messageType=" + std::to_string(messageType));
+  builder.append(", messageId=" + std::to_string(messageId));
+  builder.append(
+      string(", priority=")
+          + (priorityIndicatorSet ? std::to_string(priority) : "unset"));
+  builder.append(
+      string(", privacy=")
+          + (privacyIndicatorSet ? std::to_string(privacy) : "unset"));
+  builder.append(
+      string(", alert=")
+          + (alertIndicatorSet ? std::to_string(alert) : "unset"));
+  builder.append(
+      string(", displayMode=")
+          + (displayModeSet ? std::to_string(displayMode) : "unset"));
+  builder.append(
+      string(", language=")
+          + (languageIndicatorSet ? std::to_string(language) : "unset"));
+  builder.append(
+      string(", errorClass=")
+          + (messageStatusSet ? std::to_string(errorClass) : "unset"));
+  builder.append(
+      string(", msgStatus=")
+          + (messageStatusSet ? std::to_string(messageStatus) : "unset"));
+  builder.append(
+      string(
+          ", msgCenterTimeStamp= unset") /*+ string (std::asctime(&msgCenterTimeStamp))*/);
+  builder.append(
+      string(
+          ", validityPeriodAbsolute= unset")/* + string(std::asctime(&validityPeriodAbsolute)))*/);
+  builder.append(
+      string(", validityPeriodRelative= ")
+          + ((validityPeriodRelativeSet) ?
+              std::to_string(validityPeriodRelative) : "unset"));
+  builder.append(
+      string(
+          ", deferredDeliveryTimeAbsolute= ") /*+ string(std::asctime(&deferredDeliveryTimeAbsolute))*/);
+  builder.append(
+      string(", deferredDeliveryTimeRelative=")
+          + ((deferredDeliveryTimeRelativeSet) ?
+              std::to_string(deferredDeliveryTimeRelative) : "unset"));
+  builder.append(", userAckReq=" + std::to_string(userAckReq));
+  builder.append(", deliveryAckReq=" + std::to_string(deliveryAckReq));
+  builder.append(", readAckReq=" + std::to_string(readAckReq));
+  builder.append(", reportReq=" + std::to_string(reportReq));
+  builder.append(", numberOfMessages=" + std::to_string(numberOfMessages));
+  builder.append(string(", callbackNumber=") + string(callbackNumber ?  callbackNumber->toString() : "unset"));
+  builder.append(", depositIndex=" + std::to_string(depositIndex));
+  builder.append(", hasUserDataHeader=" + std::to_string(hasUserDataHeader));
+  builder.append(
+      ", userData=" + string(userData ? userData->toString() : "unset"));
+  builder.append(" }");
+  return builder;
+}