176b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor/* 276b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * Copyright (C) 2014 The Android Open Source Project 376b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * 476b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * Licensed under the Apache License, Version 2.0 (the "License"); 576b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * you may not use this file except in compliance with the License. 676b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * You may obtain a copy of the License at 776b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * 876b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * http://www.apache.org/licenses/LICENSE-2.0 976b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * 1076b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * Unless required by applicable law or agreed to in writing, software 1176b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * distributed under the License is distributed on an "AS IS" BASIS, 1276b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 1376b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * See the License for the specific language governing permissions and 1476b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * limitations under the License. 1576b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor */ 1676b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor 1776b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylorpackage com.android.mms.service; 1876b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor 1976b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylorimport android.content.BroadcastReceiver; 2076b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylorimport android.content.Context; 2176b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylorimport android.content.Intent; 2276b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylorimport android.content.IntentFilter; 2376b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylorimport android.content.res.Configuration; 244467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseriimport android.os.Bundle; 254467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseriimport android.os.PersistableBundle; 264467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseriimport android.telephony.CarrierConfigManager; 274467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseriimport android.telephony.SmsManager; 28ed6f8f86f6cf3036a9db44d29dc40d96235686b1Wink Savilleimport android.telephony.SubscriptionInfo; 294467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseriimport android.telephony.SubscriptionManager; 308153aed48a84305533f26c06a07a51bd358cee41Ye Wenimport android.telephony.SubscriptionManager.OnSubscriptionsChangedListener; 3176b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylorimport android.util.ArrayMap; 328153aed48a84305533f26c06a07a51bd358cee41Ye Wen 338153aed48a84305533f26c06a07a51bd358cee41Ye Wenimport com.android.internal.telephony.IccCardConstants; 3476b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor 3576b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylorimport java.util.List; 3676b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylorimport java.util.Map; 3776b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor 3876b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor/** 3976b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * This class manages cached copies of all the MMS configuration for each subscription ID. 4076b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * A subscription ID loosely corresponds to a particular SIM. See the 4176b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * {@link android.telephony.SubscriptionManager} for more details. 4276b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * 4376b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor */ 4476b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylorpublic class MmsConfigManager { 4576b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor private static volatile MmsConfigManager sInstance = new MmsConfigManager(); 4676b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor 4776b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor public static MmsConfigManager getInstance() { 4876b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor return sInstance; 4976b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor } 5076b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor 5176b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor // Map the various subIds to their corresponding MmsConfigs. 524467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri private final Map<Integer, Bundle> mSubIdConfigMap = new ArrayMap<Integer, Bundle>(); 5376b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor private Context mContext; 5479ab3ac28d02ba5f05d012a63cffa73931070a85Wink Saville private SubscriptionManager mSubscriptionManager; 5576b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor 5676b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor /** 5776b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * This receiver listens for changes made to SubInfoRecords and for a broadcast telling us 5876b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * the TelephonyManager has loaded the information needed in order to get the mcc/mnc's for 5976b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * each subscription Id. When either of these broadcasts are received, we rebuild the 6076b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * MmsConfig table. 6176b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * 6276b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor */ 6376b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor private final BroadcastReceiver mReceiver = new BroadcastReceiver() { 6476b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor public void onReceive(Context context, Intent intent) { 6576b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor String action = intent.getAction(); 668153aed48a84305533f26c06a07a51bd358cee41Ye Wen LogUtil.i("MmsConfigManager receiver action: " + action); 67ed6f8f86f6cf3036a9db44d29dc40d96235686b1Wink Saville if (action.equals(IccCardConstants.INTENT_VALUE_ICC_LOADED)) { 6876b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor loadInBackground(); 6976b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor } 7076b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor } 7176b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor }; 7276b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor 7379ab3ac28d02ba5f05d012a63cffa73931070a85Wink Saville private final OnSubscriptionsChangedListener mOnSubscriptionsChangedListener = 7479ab3ac28d02ba5f05d012a63cffa73931070a85Wink Saville new OnSubscriptionsChangedListener() { 75ed6f8f86f6cf3036a9db44d29dc40d96235686b1Wink Saville @Override 7679ab3ac28d02ba5f05d012a63cffa73931070a85Wink Saville public void onSubscriptionsChanged() { 77ed6f8f86f6cf3036a9db44d29dc40d96235686b1Wink Saville loadInBackground(); 78ed6f8f86f6cf3036a9db44d29dc40d96235686b1Wink Saville } 79ed6f8f86f6cf3036a9db44d29dc40d96235686b1Wink Saville }; 80ed6f8f86f6cf3036a9db44d29dc40d96235686b1Wink Saville 8179ab3ac28d02ba5f05d012a63cffa73931070a85Wink Saville 8276b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor public void init(final Context context) { 83ed6f8f86f6cf3036a9db44d29dc40d96235686b1Wink Saville mContext = context; 8479ab3ac28d02ba5f05d012a63cffa73931070a85Wink Saville mSubscriptionManager = SubscriptionManager.from(context); 85ed6f8f86f6cf3036a9db44d29dc40d96235686b1Wink Saville 86ed6f8f86f6cf3036a9db44d29dc40d96235686b1Wink Saville // TODO: When this object "finishes" we should unregister. 878153aed48a84305533f26c06a07a51bd358cee41Ye Wen final IntentFilter intentFilterLoaded = 8876b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor new IntentFilter(IccCardConstants.INTENT_VALUE_ICC_LOADED); 8976b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor context.registerReceiver(mReceiver, intentFilterLoaded); 9076b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor 91ed6f8f86f6cf3036a9db44d29dc40d96235686b1Wink Saville // TODO: When this object "finishes" we should unregister by invoking 9279ab3ac28d02ba5f05d012a63cffa73931070a85Wink Saville // SubscriptionManager.getInstance(mContext).unregister(mOnSubscriptionsChangedListener); 93ed6f8f86f6cf3036a9db44d29dc40d96235686b1Wink Saville // This is not strictly necessary because it will be unregistered if the 94ed6f8f86f6cf3036a9db44d29dc40d96235686b1Wink Saville // notification fails but it is good form. 95ed6f8f86f6cf3036a9db44d29dc40d96235686b1Wink Saville 96ed6f8f86f6cf3036a9db44d29dc40d96235686b1Wink Saville // Register for SubscriptionInfo list changes which is guaranteed 9779ab3ac28d02ba5f05d012a63cffa73931070a85Wink Saville // to invoke onSubscriptionsChanged the first time. 9892db751be222025dae8005bb595a963cb191ec87Wink Saville SubscriptionManager.from(mContext).addOnSubscriptionsChangedListener( 9979ab3ac28d02ba5f05d012a63cffa73931070a85Wink Saville mOnSubscriptionsChangedListener); 10076b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor } 10176b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor 10276b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor private void loadInBackground() { 10376b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor // TODO (ywen) - AsyncTask to avoid creating a new thread? 10476b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor new Thread() { 10576b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor @Override 10676b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor public void run() { 10776b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor Configuration configuration = mContext.getResources().getConfiguration(); 10876b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor // Always put the mnc/mcc in the log so we can tell which mms_config.xml 10976b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor // was loaded. 1108153aed48a84305533f26c06a07a51bd358cee41Ye Wen LogUtil.i("MmsConfigManager loads in background mcc/mnc: " + 11176b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor configuration.mcc + "/" + configuration.mnc); 11276b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor load(mContext); 11376b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor } 11476b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor }.start(); 11576b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor } 11676b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor 11776b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor /** 1184467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri * Find and return the MMS config for a particular subscription id. 11976b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * 1204467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri * @param subId Subscription id of the desired MMS config bundle 1214467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri * @return MMS config bundle for the particular subscription id. This function can return null 1224467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri * if the MMS config cannot be found or if this function is called before the 1234467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri * TelephonyManager has set up the SIMs, or if loadInBackground is still spawning a 124ed6f8f86f6cf3036a9db44d29dc40d96235686b1Wink Saville * thread after a recent LISTEN_SUBSCRIPTION_INFO_LIST_CHANGED event. 12576b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor */ 1264467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri public Bundle getMmsConfigBySubId(int subId) { 1274467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri Bundle mmsConfig; 12876b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor synchronized(mSubIdConfigMap) { 1292ce1dd938ca372bcbaf37d83311dab14b3687c3cTom Taylor mmsConfig = mSubIdConfigMap.get(subId); 13076b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor } 1318153aed48a84305533f26c06a07a51bd358cee41Ye Wen LogUtil.i("mms config for sub " + subId + ": " + mmsConfig); 1324467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri // Return a copy so that callers can mutate it. 1334467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri if (mmsConfig != null) { 1344467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri return new Bundle(mmsConfig); 1354467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri } 1364467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri return null; 13776b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor } 13876b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor 13976b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor /** 1404467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri * This loads the MMS config for each active subscription. 14176b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor * 1424467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri * MMS config is fetched from CarrierConfigManager and filtered to only include MMS config 1434467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri * variables. The resulting bundles are stored in mSubIdConfigMap. 14476b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor */ 14576b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor private void load(Context context) { 14679ab3ac28d02ba5f05d012a63cffa73931070a85Wink Saville List<SubscriptionInfo> subs = mSubscriptionManager.getActiveSubscriptionInfoList(); 1474ed37352fed9c277f602b82998cba619c5b29363Ye Wen if (subs == null || subs.size() < 1) { 1488153aed48a84305533f26c06a07a51bd358cee41Ye Wen LogUtil.e(" Failed to load mms config: empty getActiveSubInfoList"); 14976b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor return; 15076b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor } 1514467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri // Load all the config bundles into a new map and then swap it with the real map to avoid 1524467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri // blocking. 1534467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri final Map<Integer, Bundle> newConfigMap = new ArrayMap<Integer, Bundle>(); 1548153aed48a84305533f26c06a07a51bd358cee41Ye Wen final CarrierConfigManager configManager = 1554467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri (CarrierConfigManager) context.getSystemService(Context.CARRIER_CONFIG_SERVICE); 156ed6f8f86f6cf3036a9db44d29dc40d96235686b1Wink Saville for (SubscriptionInfo sub : subs) { 1578153aed48a84305533f26c06a07a51bd358cee41Ye Wen final int subId = sub.getSubscriptionId(); 1584467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri PersistableBundle config = configManager.getConfigForSubId(subId); 1594467007f09a9f2319ba25aa18e04f54693e6bfa1Jonathan Basseri newConfigMap.put(subId, SmsManager.getMmsConfig(config)); 16076b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor } 16176b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor synchronized(mSubIdConfigMap) { 16276b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor mSubIdConfigMap.clear(); 16376b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor mSubIdConfigMap.putAll(newConfigMap); 16476b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor } 16576b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor } 16676b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor 16776b0e8693a8004001663044f5188d5b9fe4203e8Tom Taylor} 168