Merge "Telephony: Add 7bit Ascii support for long message"
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index 0c63b60..1b7228a 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -2424,6 +2424,14 @@
             "5g_icon_configuration_string";
 
     /**
+     * Support ASCII 7-BIT encoding for long SMS. This carrier config is used to enable
+     * this feature.
+     * @hide
+     */
+    public static final String KEY_ASCII_7_BIT_SUPPORT_FOR_LONG_MESSAGE_BOOL =
+            "ascii_7_bit_support_for_long_message_bool";
+
+    /**
      * Controls RSRP threshold at which OpportunisticNetworkService will decide whether
      * the opportunistic network is good enough for internet data.
      */
@@ -2961,6 +2969,7 @@
         sDefaults.putInt(KEY_CALL_WAITING_SERVICE_CLASS_INT, 1 /* SERVICE_CLASS_VOICE */);
         sDefaults.putString(KEY_5G_ICON_CONFIGURATION_STRING,
                 "connected_mmwave:None,connected:5G,not_restricted:None,restricted:None");
+        sDefaults.putBoolean(KEY_ASCII_7_BIT_SUPPORT_FOR_LONG_MESSAGE_BOOL, false);
         /* Default value is minimum RSRP level needed for SIGNAL_STRENGTH_GOOD */
         sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_RSRP_INT, -108);
         /* Default value is minimum RSRP level needed for SIGNAL_STRENGTH_MODERATE */
diff --git a/telephony/java/com/android/internal/telephony/cdma/BearerData.java b/telephony/java/com/android/internal/telephony/cdma/BearerData.java
index a4cd56b..694cc69 100644
--- a/telephony/java/com/android/internal/telephony/cdma/BearerData.java
+++ b/telephony/java/com/android/internal/telephony/cdma/BearerData.java
@@ -596,6 +596,45 @@
         System.arraycopy(payload, 0, uData.payload, udhBytes, payload.length);
     }
 
+    private static void encode7bitAsciiEms(UserData uData, byte[] udhData, boolean force)
+            throws CodingException
+    {
+        try {
+            Rlog.d(LOG_TAG, "encode7bitAsciiEms");
+            int udhBytes = udhData.length + 1;  // Add length octet.
+            int udhSeptets = ((udhBytes * 8) + 6) / 7;
+            int paddingBits = (udhSeptets * 7) - (udhBytes * 8);
+            String msg = uData.payloadStr;
+            byte[] payload ;
+            int msgLen = msg.length();
+            BitwiseOutputStream outStream = new BitwiseOutputStream(msgLen +
+                    (paddingBits > 0 ? 1 : 0));
+            outStream.write(paddingBits, 0);
+            for (int i = 0; i < msgLen; i++) {
+                int charCode = UserData.charToAscii.get(msg.charAt(i), -1);
+                if (charCode == -1) {
+                    if (force) {
+                        outStream.write(7, UserData.UNENCODABLE_7_BIT_CHAR);
+                    } else {
+                        throw new CodingException("cannot ASCII encode (" + msg.charAt(i) + ")");
+                    }
+                } else {
+                    outStream.write(7, charCode);
+                }
+            }
+            payload = outStream.toByteArray();
+            uData.msgEncoding = UserData.ENCODING_7BIT_ASCII;
+            uData.msgEncodingSet = true;
+            uData.numFields = udhSeptets + uData.payloadStr.length();
+            uData.payload = new byte[udhBytes + payload.length];
+            uData.payload[0] = (byte)udhData.length;
+            System.arraycopy(udhData, 0, uData.payload, 1, udhData.length);
+            System.arraycopy(payload, 0, uData.payload, udhBytes, payload.length);
+        } catch (BitwiseOutputStream.AccessException ex) {
+            throw new CodingException("7bit ASCII encode failed: " + ex);
+        }
+    }
+
     private static void encodeEmsUserDataPayload(UserData uData)
         throws CodingException
     {
@@ -605,6 +644,8 @@
                 encode7bitEms(uData, headerData, true);
             } else if (uData.msgEncoding == UserData.ENCODING_UNICODE_16) {
                 encode16bitEms(uData, headerData);
+            } else if (uData.msgEncoding == UserData.ENCODING_7BIT_ASCII) {
+                encode7bitAsciiEms(uData, headerData, true);
             } else {
                 throw new CodingException("unsupported EMS user data encoding (" +
                                           uData.msgEncoding + ")");
@@ -1056,15 +1097,18 @@
         throws CodingException
     {
         try {
-            offset *= 8;
+            int offsetBits = offset * 8;
+            int offsetSeptets = (offsetBits + 6) / 7;
+            numFields -= offsetSeptets;
+
             StringBuffer strBuf = new StringBuffer(numFields);
             BitwiseInputStream inStream = new BitwiseInputStream(data);
-            int wantedBits = (offset * 8) + (numFields * 7);
+            int wantedBits = (offsetSeptets * 7) + (numFields * 7);
             if (inStream.available() < wantedBits) {
                 throw new CodingException("insufficient data (wanted " + wantedBits +
                                           " bits, but only have " + inStream.available() + ")");
             }
-            inStream.skip(offset);
+            inStream.skip(offsetSeptets * 7);
             for (int i = 0; i < numFields; i++) {
                 int charCode = inStream.read(7);
                 if ((charCode >= UserData.ASCII_MAP_BASE_INDEX) &&
diff --git a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
index 9080e23..1da5eac 100644
--- a/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
+++ b/telephony/java/com/android/internal/telephony/cdma/SmsMessage.java
@@ -864,8 +864,9 @@
             Rlog.d(LOG_TAG, "MO raw BearerData = '" + HexDump.toHexString(encodedBearerData) + "'");
         }
 
-        int teleservice = bearerData.hasUserDataHeader ?
-                SmsEnvelope.TELESERVICE_WEMT : SmsEnvelope.TELESERVICE_WMT;
+        int teleservice = (bearerData.hasUserDataHeader
+                && userData.msgEncoding != UserData.ENCODING_7BIT_ASCII)
+                ? SmsEnvelope.TELESERVICE_WEMT : SmsEnvelope.TELESERVICE_WMT;
 
         SmsEnvelope envelope = new SmsEnvelope();
         envelope.messageType = SmsEnvelope.MESSAGE_TYPE_POINT_TO_POINT;