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