1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package com.android.messaging.datamodel; 18 19 import android.telephony.SmsMessage; 20 21 import com.android.messaging.sms.MmsConfig; 22 23 public class MessageTextStats { 24 private boolean mMessageLengthRequiresMms; 25 private int mMessageCount; 26 private int mCodePointsRemainingInCurrentMessage; 27 MessageTextStats()28 public MessageTextStats() { 29 mCodePointsRemainingInCurrentMessage = Integer.MAX_VALUE; 30 } 31 getNumMessagesToBeSent()32 public int getNumMessagesToBeSent() { 33 return mMessageCount; 34 } 35 getCodePointsRemainingInCurrentMessage()36 public int getCodePointsRemainingInCurrentMessage() { 37 return mCodePointsRemainingInCurrentMessage; 38 } 39 getMessageLengthRequiresMms()40 public boolean getMessageLengthRequiresMms() { 41 return mMessageLengthRequiresMms; 42 } 43 updateMessageTextStats(final int selfSubId, final String messageText)44 public void updateMessageTextStats(final int selfSubId, final String messageText) { 45 final int[] params = SmsMessage.calculateLength(messageText, false); 46 /* SmsMessage.calculateLength returns an int[4] with: 47 * int[0] being the number of SMS's required, 48 * int[1] the number of code points used, 49 * int[2] is the number of code points remaining until the next message. 50 * int[3] is the encoding type that should be used for the message. 51 */ 52 mMessageCount = params[0]; 53 mCodePointsRemainingInCurrentMessage = params[2]; 54 55 final MmsConfig mmsConfig = MmsConfig.get(selfSubId); 56 if (!mmsConfig.getMultipartSmsEnabled() && 57 !mmsConfig.getSendMultipartSmsAsSeparateMessages()) { 58 // The provider doesn't support multi-part sms's and we should use MMS to 59 // send multi-part sms, so as soon as the user types 60 // an sms longer than one segment, we have to turn the message into an mms. 61 mMessageLengthRequiresMms = mMessageCount > 1; 62 } else { 63 final int threshold = mmsConfig.getSmsToMmsTextThreshold(); 64 mMessageLengthRequiresMms = threshold > 0 && mMessageCount > threshold; 65 } 66 // Some carriers require any SMS message longer than 80 to be sent as MMS 67 // see b/12122333 68 int smsToMmsLengthThreshold = mmsConfig.getSmsToMmsTextLengthThreshold(); 69 if (smsToMmsLengthThreshold > 0) { 70 final int usedInCurrentMessage = params[1]; 71 /* 72 * A little hacky way to find out if we should count characters in double bytes. 73 * SmsMessage.calculateLength counts message code units based on the characters 74 * in input. If all of them are ascii, the max length is 75 * SmsMessage.MAX_USER_DATA_SEPTETS (160). If any of them are double-byte, like 76 * Korean or Chinese, the max length is SmsMessage.MAX_USER_DATA_BYTES (140) bytes 77 * (70 code units). 78 * Here we check if the total code units we can use is smaller than 140. If so, 79 * we know we should count threshold in double-byte, so divide the threshold by 2. 80 * In this way, we will count Korean text correctly with regard to the length threshold. 81 */ 82 if (usedInCurrentMessage + mCodePointsRemainingInCurrentMessage 83 < SmsMessage.MAX_USER_DATA_BYTES) { 84 smsToMmsLengthThreshold /= 2; 85 } 86 if (usedInCurrentMessage > smsToMmsLengthThreshold) { 87 mMessageLengthRequiresMms = true; 88 } 89 } 90 } 91 92 } 93