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.sms;
18 
19 import android.os.Bundle;
20 import android.support.v7.mms.CarrierConfigValuesLoader;
21 import android.telephony.SubscriptionInfo;
22 
23 import com.android.messaging.Factory;
24 import com.android.messaging.datamodel.data.ParticipantData;
25 import com.android.messaging.util.Assert;
26 import com.android.messaging.util.LogUtil;
27 import com.android.messaging.util.OsUtil;
28 import com.android.messaging.util.PhoneUtils;
29 import com.android.messaging.util.SafeAsyncTask;
30 import com.google.common.collect.Maps;
31 
32 import java.util.List;
33 import java.util.Map;
34 import java.util.Set;
35 
36 /**
37  * MMS configuration.
38  *
39  * This is now a wrapper around the BugleCarrierConfigValuesLoader, which does
40  * the actual loading and stores the values in a Bundle. This class provides getter
41  * methods for values used in the app, which is easier to use than the raw loader
42  * class.
43  */
44 public class MmsConfig {
45     private static final String TAG = LogUtil.BUGLE_TAG;
46 
47     private static final int DEFAULT_MAX_TEXT_LENGTH = 2000;
48 
49     /*
50      * Key types
51      */
52     public static final String KEY_TYPE_INT = "int";
53     public static final String KEY_TYPE_BOOL = "bool";
54     public static final String KEY_TYPE_STRING = "string";
55 
56     private static final Map<String, String> sKeyTypeMap = Maps.newHashMap();
57     static {
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLED_MMS, KEY_TYPE_BOOL)58         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLED_MMS, KEY_TYPE_BOOL);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLED_TRANS_ID, KEY_TYPE_BOOL)59         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLED_TRANS_ID, KEY_TYPE_BOOL);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLED_NOTIFY_WAP_MMSC, KEY_TYPE_BOOL)60         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLED_NOTIFY_WAP_MMSC, KEY_TYPE_BOOL);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ALIAS_ENABLED, KEY_TYPE_BOOL)61         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ALIAS_ENABLED, KEY_TYPE_BOOL);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ALLOW_ATTACH_AUDIO, KEY_TYPE_BOOL)62         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ALLOW_ATTACH_AUDIO, KEY_TYPE_BOOL);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLE_MULTIPART_SMS, KEY_TYPE_BOOL)63         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLE_MULTIPART_SMS, KEY_TYPE_BOOL);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLE_SMS_DELIVERY_REPORTS, KEY_TYPE_BOOL)64         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLE_SMS_DELIVERY_REPORTS,
65                 KEY_TYPE_BOOL);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLE_GROUP_MMS, KEY_TYPE_BOOL)66         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLE_GROUP_MMS, KEY_TYPE_BOOL);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION, KEY_TYPE_BOOL)67         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION,
68                 KEY_TYPE_BOOL);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_CELL_BROADCAST_APP_LINKS, KEY_TYPE_BOOL)69         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_CELL_BROADCAST_APP_LINKS, KEY_TYPE_BOOL);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES, KEY_TYPE_BOOL)70         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES,
71                 KEY_TYPE_BOOL);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLE_MMS_READ_REPORTS, KEY_TYPE_BOOL)72         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLE_MMS_READ_REPORTS, KEY_TYPE_BOOL);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLE_MMS_DELIVERY_REPORTS, KEY_TYPE_BOOL)73         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ENABLE_MMS_DELIVERY_REPORTS,
74                 KEY_TYPE_BOOL);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_SUPPORT_HTTP_CHARSET_HEADER, KEY_TYPE_BOOL)75         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_SUPPORT_HTTP_CHARSET_HEADER,
76                 KEY_TYPE_BOOL);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_MAX_MESSAGE_SIZE, KEY_TYPE_INT)77         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_MAX_MESSAGE_SIZE, KEY_TYPE_INT);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_MAX_IMAGE_HEIGHT, KEY_TYPE_INT)78         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_MAX_IMAGE_HEIGHT, KEY_TYPE_INT);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_MAX_IMAGE_WIDTH, KEY_TYPE_INT)79         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_MAX_IMAGE_WIDTH, KEY_TYPE_INT);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_RECIPIENT_LIMIT, KEY_TYPE_INT)80         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_RECIPIENT_LIMIT, KEY_TYPE_INT);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_HTTP_SOCKET_TIMEOUT, KEY_TYPE_INT)81         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_HTTP_SOCKET_TIMEOUT, KEY_TYPE_INT);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ALIAS_MIN_CHARS, KEY_TYPE_INT)82         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ALIAS_MIN_CHARS, KEY_TYPE_INT);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ALIAS_MAX_CHARS, KEY_TYPE_INT)83         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_ALIAS_MAX_CHARS, KEY_TYPE_INT);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_SMS_TO_MMS_TEXT_THRESHOLD, KEY_TYPE_INT)84         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_SMS_TO_MMS_TEXT_THRESHOLD, KEY_TYPE_INT);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD, KEY_TYPE_INT)85         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD,
86                 KEY_TYPE_INT);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_MAX_MESSAGE_TEXT_SIZE, KEY_TYPE_INT)87         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_MAX_MESSAGE_TEXT_SIZE, KEY_TYPE_INT);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_MAX_SUBJECT_LENGTH, KEY_TYPE_INT)88         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_MAX_SUBJECT_LENGTH, KEY_TYPE_INT);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_UA_PROF_TAG_NAME, KEY_TYPE_STRING)89         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_UA_PROF_TAG_NAME, KEY_TYPE_STRING);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_HTTP_PARAMS, KEY_TYPE_STRING)90         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_HTTP_PARAMS, KEY_TYPE_STRING);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_EMAIL_GATEWAY_NUMBER, KEY_TYPE_STRING)91         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_EMAIL_GATEWAY_NUMBER, KEY_TYPE_STRING);
sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_NAI_SUFFIX, KEY_TYPE_STRING)92         sKeyTypeMap.put(CarrierConfigValuesLoader.CONFIG_NAI_SUFFIX, KEY_TYPE_STRING);
93     }
94 
95     // A map that stores all MmsConfigs, one per active subscription. For pre-LMSim, this will
96     // contain just one entry with the default self sub id; for LMSim and above, this will contain
97     // all active sub ids but the default subscription id - the default subscription id will be
98     // resolved to an active sub id during runtime.
99     private static final Map<Integer, MmsConfig> sSubIdToMmsConfigMap = Maps.newHashMap();
100     // The fallback values
101     private static final MmsConfig sFallback =
102             new MmsConfig(ParticipantData.DEFAULT_SELF_SUB_ID, new Bundle());
103 
104     // Per-subscription configuration values.
105     private final Bundle mValues;
106     private final int mSubId;
107 
108     /**
109      * Retrieves the MmsConfig instance associated with the given {@code subId}
110      */
get(final int subId)111     public static MmsConfig get(final int subId) {
112         final int realSubId = PhoneUtils.getDefault().getEffectiveSubId(subId);
113         synchronized (sSubIdToMmsConfigMap) {
114             final MmsConfig mmsConfig = sSubIdToMmsConfigMap.get(realSubId);
115             if (mmsConfig == null) {
116                 // The subId is no longer valid. Fall back to the default config.
117                 LogUtil.e(LogUtil.BUGLE_TAG, "Get mms config failed: invalid subId. subId=" + subId
118                         + ", real subId=" + realSubId
119                         + ", map=" + sSubIdToMmsConfigMap.keySet());
120                 return sFallback;
121             }
122             return mmsConfig;
123         }
124     }
125 
MmsConfig(final int subId, final Bundle values)126     private MmsConfig(final int subId, final Bundle values) {
127         mSubId = subId;
128         mValues = values;
129     }
130 
131     /**
132      * Same as load() but doing it using an async thread from SafeAsyncTask thread pool.
133      */
loadAsync()134     public static void loadAsync() {
135         SafeAsyncTask.executeOnThreadPool(new Runnable() {
136             @Override
137             public void run() {
138                 load();
139             }
140         });
141     }
142 
143     /**
144      * Reload the device and per-subscription settings.
145      */
load()146     public static synchronized void load() {
147         final BugleCarrierConfigValuesLoader loader = Factory.get().getCarrierConfigValuesLoader();
148         // Rebuild the entire MmsConfig map.
149         sSubIdToMmsConfigMap.clear();
150         loader.reset();
151         if (OsUtil.isAtLeastL_MR1()) {
152             final List<SubscriptionInfo> subInfoRecords =
153                     PhoneUtils.getDefault().toLMr1().getActiveSubscriptionInfoList();
154             if (subInfoRecords == null) {
155                 LogUtil.w(TAG, "Loading mms config failed: no active SIM");
156                 return;
157             }
158             for (SubscriptionInfo subInfoRecord : subInfoRecords) {
159                 final int subId = subInfoRecord.getSubscriptionId();
160                 final Bundle values = loader.get(subId);
161                 addMmsConfig(new MmsConfig(subId, values));
162             }
163         } else {
164             final Bundle values = loader.get(ParticipantData.DEFAULT_SELF_SUB_ID);
165             addMmsConfig(new MmsConfig(ParticipantData.DEFAULT_SELF_SUB_ID, values));
166         }
167     }
168 
addMmsConfig(MmsConfig mmsConfig)169     private static void addMmsConfig(MmsConfig mmsConfig) {
170         Assert.isTrue(OsUtil.isAtLeastL_MR1() !=
171                 (mmsConfig.mSubId == ParticipantData.DEFAULT_SELF_SUB_ID));
172         sSubIdToMmsConfigMap.put(mmsConfig.mSubId, mmsConfig);
173     }
174 
getSmsToMmsTextThreshold()175     public int getSmsToMmsTextThreshold() {
176         return mValues.getInt(CarrierConfigValuesLoader.CONFIG_SMS_TO_MMS_TEXT_THRESHOLD,
177                 CarrierConfigValuesLoader.CONFIG_SMS_TO_MMS_TEXT_THRESHOLD_DEFAULT);
178     }
179 
getSmsToMmsTextLengthThreshold()180     public int getSmsToMmsTextLengthThreshold() {
181         return mValues.getInt(CarrierConfigValuesLoader.CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD,
182                 CarrierConfigValuesLoader.CONFIG_SMS_TO_MMS_TEXT_LENGTH_THRESHOLD_DEFAULT);
183     }
184 
getMaxMessageSize()185     public int getMaxMessageSize() {
186         return mValues.getInt(CarrierConfigValuesLoader.CONFIG_MAX_MESSAGE_SIZE,
187                 CarrierConfigValuesLoader.CONFIG_MAX_MESSAGE_SIZE_DEFAULT);
188     }
189 
190     /**
191      * Return the largest MaxMessageSize for any subid
192      */
getMaxMaxMessageSize()193     public static int getMaxMaxMessageSize() {
194         int maxMax = 0;
195         for (MmsConfig config : sSubIdToMmsConfigMap.values()) {
196             maxMax = Math.max(maxMax, config.getMaxMessageSize());
197         }
198         return maxMax > 0 ? maxMax : sFallback.getMaxMessageSize();
199     }
200 
getTransIdEnabled()201     public boolean getTransIdEnabled() {
202         return mValues.getBoolean(CarrierConfigValuesLoader.CONFIG_ENABLED_TRANS_ID,
203                 CarrierConfigValuesLoader.CONFIG_ENABLED_TRANS_ID_DEFAULT);
204     }
205 
getEmailGateway()206     public String getEmailGateway() {
207         return mValues.getString(CarrierConfigValuesLoader.CONFIG_EMAIL_GATEWAY_NUMBER,
208                 CarrierConfigValuesLoader.CONFIG_EMAIL_GATEWAY_NUMBER_DEFAULT);
209     }
210 
getMaxImageHeight()211     public int getMaxImageHeight() {
212         return mValues.getInt(CarrierConfigValuesLoader.CONFIG_MAX_IMAGE_HEIGHT,
213                 CarrierConfigValuesLoader.CONFIG_MAX_IMAGE_HEIGHT_DEFAULT);
214     }
215 
getMaxImageWidth()216     public int getMaxImageWidth() {
217         return mValues.getInt(CarrierConfigValuesLoader.CONFIG_MAX_IMAGE_WIDTH,
218                 CarrierConfigValuesLoader.CONFIG_MAX_IMAGE_WIDTH_DEFAULT);
219     }
220 
getRecipientLimit()221     public int getRecipientLimit() {
222         final int limit = mValues.getInt(CarrierConfigValuesLoader.CONFIG_RECIPIENT_LIMIT,
223                 CarrierConfigValuesLoader.CONFIG_RECIPIENT_LIMIT_DEFAULT);
224         return limit < 0 ? Integer.MAX_VALUE : limit;
225     }
226 
getMaxTextLimit()227     public int getMaxTextLimit() {
228         final int max = mValues.getInt(CarrierConfigValuesLoader.CONFIG_MAX_MESSAGE_TEXT_SIZE,
229                 CarrierConfigValuesLoader.CONFIG_MAX_MESSAGE_TEXT_SIZE_DEFAULT);
230         return max > -1 ? max : DEFAULT_MAX_TEXT_LENGTH;
231     }
232 
getMultipartSmsEnabled()233     public boolean getMultipartSmsEnabled() {
234         return mValues.getBoolean(CarrierConfigValuesLoader.CONFIG_ENABLE_MULTIPART_SMS,
235                 CarrierConfigValuesLoader.CONFIG_ENABLE_MULTIPART_SMS_DEFAULT);
236     }
237 
getSendMultipartSmsAsSeparateMessages()238     public boolean getSendMultipartSmsAsSeparateMessages() {
239         return mValues.getBoolean(
240                 CarrierConfigValuesLoader.CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES,
241                 CarrierConfigValuesLoader.CONFIG_SEND_MULTIPART_SMS_AS_SEPARATE_MESSAGES_DEFAULT);
242     }
243 
getSMSDeliveryReportsEnabled()244     public boolean getSMSDeliveryReportsEnabled() {
245         return mValues.getBoolean(CarrierConfigValuesLoader.CONFIG_ENABLE_SMS_DELIVERY_REPORTS,
246                 CarrierConfigValuesLoader.CONFIG_ENABLE_SMS_DELIVERY_REPORTS_DEFAULT);
247     }
248 
getNotifyWapMMSC()249     public boolean getNotifyWapMMSC() {
250         return mValues.getBoolean(CarrierConfigValuesLoader.CONFIG_ENABLED_NOTIFY_WAP_MMSC,
251                 CarrierConfigValuesLoader.CONFIG_ENABLED_NOTIFY_WAP_MMSC_DEFAULT);
252     }
253 
isAliasEnabled()254     public boolean isAliasEnabled() {
255         return mValues.getBoolean(CarrierConfigValuesLoader.CONFIG_ALIAS_ENABLED,
256                 CarrierConfigValuesLoader.CONFIG_ALIAS_ENABLED_DEFAULT);
257     }
258 
getAliasMinChars()259     public int getAliasMinChars() {
260         return mValues.getInt(CarrierConfigValuesLoader.CONFIG_ALIAS_MIN_CHARS,
261                 CarrierConfigValuesLoader.CONFIG_ALIAS_MIN_CHARS_DEFAULT);
262     }
263 
getAliasMaxChars()264     public int getAliasMaxChars() {
265         return mValues.getInt(CarrierConfigValuesLoader.CONFIG_ALIAS_MAX_CHARS,
266                 CarrierConfigValuesLoader.CONFIG_ALIAS_MAX_CHARS_DEFAULT);
267     }
268 
getAllowAttachAudio()269     public boolean getAllowAttachAudio() {
270         return mValues.getBoolean(CarrierConfigValuesLoader.CONFIG_ALLOW_ATTACH_AUDIO,
271                 CarrierConfigValuesLoader.CONFIG_ALLOW_ATTACH_AUDIO_DEFAULT);
272     }
273 
getMaxSubjectLength()274     public int getMaxSubjectLength() {
275         return mValues.getInt(CarrierConfigValuesLoader.CONFIG_MAX_SUBJECT_LENGTH,
276                 CarrierConfigValuesLoader.CONFIG_MAX_SUBJECT_LENGTH_DEFAULT);
277     }
278 
getGroupMmsEnabled()279     public boolean getGroupMmsEnabled() {
280         return mValues.getBoolean(CarrierConfigValuesLoader.CONFIG_ENABLE_GROUP_MMS,
281                 CarrierConfigValuesLoader.CONFIG_ENABLE_GROUP_MMS_DEFAULT);
282     }
283 
getSupportMmsContentDisposition()284     public boolean getSupportMmsContentDisposition() {
285         return mValues.getBoolean(CarrierConfigValuesLoader.CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION,
286                 CarrierConfigValuesLoader.CONFIG_SUPPORT_MMS_CONTENT_DISPOSITION_DEFAULT);
287     }
288 
getShowCellBroadcast()289     public boolean getShowCellBroadcast() {
290         return mValues.getBoolean(CarrierConfigValuesLoader.CONFIG_CELL_BROADCAST_APP_LINKS,
291                 CarrierConfigValuesLoader.CONFIG_CELL_BROADCAST_APP_LINKS_DEFAULT);
292     }
293 
getValue(final String key)294     public Object getValue(final String key) {
295         return mValues.get(key);
296     }
297 
keySet()298     public Set<String> keySet() {
299         return mValues.keySet();
300     }
301 
getKeyType(final String key)302     public static String getKeyType(final String key) {
303         return sKeyTypeMap.get(key);
304     }
305 
update(final String type, final String key, final String value)306     public void update(final String type, final String key, final String value) {
307         BugleCarrierConfigValuesLoader.update(mValues, type, key, value);
308     }
309 }
310