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