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 androidx.appcompat.mms; 18 19 import android.app.PendingIntent; 20 import android.content.Context; 21 import android.net.Uri; 22 import android.os.Bundle; 23 import android.telephony.SmsManager; 24 import android.util.SparseArray; 25 26 /** 27 * The public interface of MMS library 28 */ 29 public class MmsManager { 30 /** 31 * Default subscription ID 32 */ 33 public static final int DEFAULT_SUB_ID = -1; 34 35 // Whether to force legacy MMS sending 36 private static volatile boolean sForceLegacyMms = false; 37 38 // Cached computed overrides for carrier configuration values 39 private static SparseArray<Bundle> sConfigOverridesMap = new SparseArray<>(); 40 41 /** 42 * Set the flag about whether to force to use legacy system APIs instead of system MMS API 43 * 44 * @param forceLegacyMms value to set 45 */ setForceLegacyMms(boolean forceLegacyMms)46 public static void setForceLegacyMms(boolean forceLegacyMms) { 47 sForceLegacyMms = forceLegacyMms; 48 } 49 50 /** 51 * Set the size of thread pool for request execution. 52 * 53 * Default is 4 54 * 55 * Note: if system MMS API is used, this has no effect 56 * 57 * @param size thread pool size 58 */ setThreadPoolSize(int size)59 public static void setThreadPoolSize(int size) { 60 MmsService.setThreadPoolSize(size); 61 } 62 63 /** 64 * Set whether to use wake lock while sending or downloading MMS. 65 * 66 * Default value is true 67 * 68 * Note: if system MMS API is used, this has no effect 69 * 70 * @param useWakeLock true to use wake lock, false otherwise 71 */ setUseWakeLock(final boolean useWakeLock)72 public static void setUseWakeLock(final boolean useWakeLock) { 73 MmsService.setUseWakeLock(useWakeLock); 74 } 75 76 /** 77 * Set the optional carrier config values loader 78 * 79 * Note: if system MMS API is used, this is used to compute the overrides 80 * of carrier configuration values 81 * 82 * @param loader the carrier config values loader 83 */ setCarrierConfigValuesLoader(CarrierConfigValuesLoader loader)84 public static void setCarrierConfigValuesLoader(CarrierConfigValuesLoader loader) { 85 if (loader == null) { 86 throw new IllegalArgumentException("Carrier configuration loader can not be empty"); 87 } 88 synchronized (sConfigOverridesMap) { 89 MmsService.setCarrierConfigValuesLoader(loader); 90 sConfigOverridesMap.clear(); 91 } 92 } 93 94 /** 95 * Set the optional APN settings loader 96 * 97 * Note: if system MMS API is used, this has no effect 98 * 99 * @param loader the APN settings loader 100 */ setApnSettingsLoader(ApnSettingsLoader loader)101 public static void setApnSettingsLoader(ApnSettingsLoader loader) { 102 if (loader == null) { 103 throw new IllegalArgumentException("APN settings loader can not be empty"); 104 } 105 MmsService.setApnSettingsLoader(loader); 106 } 107 108 /** 109 * Set user agent info loader 110 * 111 * Note: if system MMS API is used, this is used to compute the overrides 112 * of carrier configuration values 113 114 * @param loader the user agent info loader 115 */ setUserAgentInfoLoader(final UserAgentInfoLoader loader)116 public static void setUserAgentInfoLoader(final UserAgentInfoLoader loader) { 117 if (loader == null) { 118 throw new IllegalArgumentException("User agent info loader can not be empty"); 119 } 120 synchronized (sConfigOverridesMap) { 121 MmsService.setUserAgentInfoLoader(loader); 122 sConfigOverridesMap.clear(); 123 } 124 } 125 126 /** 127 * Send MMS via platform MMS API (if platform supports and not forced to 128 * use legacy APIs) or legacy APIs 129 * 130 * @param subId the subscription ID of the SIM to use 131 * @param context the Context to use 132 * @param contentUri the content URI of the PDU to be sent 133 * @param locationUrl the optional location URL to use for sending 134 * @param sentIntent the pending intent for returning results 135 */ sendMultimediaMessage(int subId, Context context, Uri contentUri, String locationUrl, PendingIntent sentIntent)136 public static void sendMultimediaMessage(int subId, Context context, Uri contentUri, 137 String locationUrl, PendingIntent sentIntent) { 138 if (shouldUseLegacyMms()) { 139 MmsService.startRequest(context, new SendRequest(locationUrl, contentUri, sentIntent)); 140 } else { 141 subId = Utils.getEffectiveSubscriptionId(subId); 142 final SmsManager smsManager = Utils.getSmsManager(subId); 143 smsManager.sendMultimediaMessage(context, contentUri, locationUrl, 144 getConfigOverrides(subId), sentIntent); 145 } 146 } 147 148 /** 149 * Download MMS via platform MMS API (if platform supports and not forced to 150 * use legacy APIs) or legacy APIs 151 * 152 * @param subId the subscription ID of the SIM to use 153 * @param context the Context to use 154 * @param contentUri the content URI of the PDU to be sent 155 * @param locationUrl the optional location URL to use for sending 156 * @param downloadedIntent the pending intent for returning results 157 */ downloadMultimediaMessage(int subId, Context context, String locationUrl, Uri contentUri, PendingIntent downloadedIntent)158 public static void downloadMultimediaMessage(int subId, Context context, String locationUrl, 159 Uri contentUri, PendingIntent downloadedIntent) { 160 if (shouldUseLegacyMms()) { 161 MmsService.startRequest(context, 162 new DownloadRequest(locationUrl, contentUri, downloadedIntent)); 163 } else { 164 subId = Utils.getEffectiveSubscriptionId(subId); 165 final SmsManager smsManager = Utils.getSmsManager(subId); 166 smsManager.downloadMultimediaMessage(context, locationUrl, contentUri, 167 getConfigOverrides(subId), downloadedIntent); 168 } 169 } 170 171 /** 172 * Checks if we should use legacy APIs for MMS. 173 * 174 * @return true if forced to use legacy APIs or platform doesn't supports MMS APIs. 175 */ shouldUseLegacyMms()176 public static boolean shouldUseLegacyMms() { 177 return sForceLegacyMms || !Utils.hasMmsApi(); 178 } 179 180 /** 181 * Get carrier configuration values overrides when platform MMS API is called. 182 * We only need to compute this if customized carrier config values loader or 183 * user agent info loader are set 184 * 185 * @param subId the ID of the SIM to use 186 * @return a Bundle containing the overrides 187 */ getConfigOverrides(final int subId)188 private static Bundle getConfigOverrides(final int subId) { 189 if (!Utils.hasMmsApi()) { 190 // If MMS API is not present, it is not necessary to compute overrides 191 return null; 192 } 193 Bundle overrides = null; 194 synchronized (sConfigOverridesMap) { 195 overrides = sConfigOverridesMap.get(subId); 196 if (overrides == null) { 197 overrides = new Bundle(); 198 sConfigOverridesMap.put(subId, overrides); 199 computeOverridesLocked(subId, overrides); 200 } 201 } 202 return overrides; 203 } 204 205 /** 206 * Compute the overrides, incorporating the user agent info 207 * 208 * @param subId the subId of the SIM to use 209 * @param overrides the computed values overrides 210 */ computeOverridesLocked(final int subId, final Bundle overrides)211 private static void computeOverridesLocked(final int subId, final Bundle overrides) { 212 // Overrides not computed yet 213 final CarrierConfigValuesLoader carrierConfigValuesLoader = 214 MmsService.getCarrierConfigValuesLoader(); 215 if (carrierConfigValuesLoader != null && 216 !(carrierConfigValuesLoader instanceof DefaultCarrierConfigValuesLoader)) { 217 // Compute the overrides for carrier config values first if the config loader 218 // is not the default one. 219 final Bundle systemValues = Utils.getSmsManager(subId).getCarrierConfigValues(); 220 final Bundle callerValues = 221 MmsService.getCarrierConfigValuesLoader().get(subId); 222 if (systemValues != null && callerValues != null) { 223 computeConfigDelta(systemValues, callerValues, overrides); 224 } else if (systemValues == null && callerValues != null) { 225 overrides.putAll(callerValues); 226 } 227 } 228 final UserAgentInfoLoader userAgentInfoLoader = MmsService.getUserAgentInfoLoader(); 229 if (userAgentInfoLoader != null && 230 !(userAgentInfoLoader instanceof DefaultUserAgentInfoLoader)) { 231 // Also set the user agent and ua prof url via the overrides 232 // if the user agent loader is not the default one. 233 overrides.putString(UserAgentInfoLoader.CONFIG_USER_AGENT, 234 userAgentInfoLoader.getUserAgent()); 235 overrides.putString(UserAgentInfoLoader.CONFIG_UA_PROF_URL, 236 userAgentInfoLoader.getUAProfUrl()); 237 } 238 } 239 240 /** 241 * Compute the delta between two sets of carrier configuration values: system and caller 242 * 243 * @param systemValues the system config values 244 * @param callerValues the caller's config values 245 * @param delta the delta of values (caller - system), using caller value to override system's 246 */ computeConfigDelta(final Bundle systemValues, final Bundle callerValues, final Bundle delta)247 private static void computeConfigDelta(final Bundle systemValues, final Bundle callerValues, 248 final Bundle delta) { 249 for (final String key : callerValues.keySet()) { 250 final Object callerValue = callerValues.get(key); 251 final Object systemValue = systemValues.get(key); 252 if ((callerValue != null && systemValue != null && !callerValue.equals(systemValue)) || 253 (callerValue != null && systemValue == null) || 254 (callerValue == null && systemValue != null)) { 255 if (callerValue == null || callerValue instanceof String) { 256 delta.putString(key, (String) callerValue); 257 } else if (callerValue instanceof Integer) { 258 delta.putInt(key, (Integer) callerValue); 259 } else if (callerValue instanceof Boolean) { 260 delta.putBoolean(key, (Boolean) callerValue); 261 } 262 } 263 } 264 } 265 } 266