1 /*
2  * Copyright (C) 2014 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.mms.service;
18 
19 import android.content.BroadcastReceiver;
20 import android.content.Context;
21 import android.content.Intent;
22 import android.content.IntentFilter;
23 import android.os.Bundle;
24 import android.telephony.CarrierConfigManager;
25 import android.telephony.SmsManager;
26 import android.telephony.SubscriptionInfo;
27 import android.telephony.SubscriptionManager;
28 import android.util.ArrayMap;
29 
30 import java.util.List;
31 import java.util.Map;
32 
33 /**
34  * This class manages cached copies of all the MMS configuration for each subscription ID.
35  * A subscription ID loosely corresponds to a particular SIM. See the
36  * {@link android.telephony.SubscriptionManager} for more details.
37  *
38  */
39 public class MmsConfigManager {
40     private static volatile MmsConfigManager sInstance = new MmsConfigManager();
41 
getInstance()42     public static MmsConfigManager getInstance() {
43         return sInstance;
44     }
45 
46     // Map the various subIds to their corresponding MmsConfigs.
47     private final Map<Integer, Bundle> mSubIdConfigMap = new ArrayMap<Integer, Bundle>();
48     private Context mContext;
49     private SubscriptionManager mSubscriptionManager;
50 
51     /** This receiver listens to ACTION_CARRIER_CONFIG_CHANGED to load the MMS config. */
52     private final BroadcastReceiver mReceiver =
53             new BroadcastReceiver() {
54                 public void onReceive(Context context, Intent intent) {
55                     LogUtil.i("MmsConfigManager receives ACTION_CARRIER_CONFIG_CHANGED");
56                     loadInBackground();
57                 }
58             };
59 
init(final Context context)60     public void init(final Context context) {
61         mContext = context;
62         mSubscriptionManager = SubscriptionManager.from(context);
63         context.registerReceiver(
64                 mReceiver, new IntentFilter(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED));
65         LogUtil.i("MmsConfigManager loads mms config in init()");
66         load(context);
67     }
68 
loadInBackground()69     private void loadInBackground() {
70         // TODO (ywen) - AsyncTask to avoid creating a new thread?
71         new Thread() {
72             @Override
73             public void run() {
74                 load(mContext);
75             }
76         }.start();
77     }
78 
79     /**
80      * Find and return the MMS config for a particular subscription id.
81      *
82      * @param subId Subscription Id of the desired MMS config bundle
83      * @return MMS config bundle for the particular subscription Id. This function can return null
84      *         if the MMS config is not loaded yet.
85      */
getMmsConfigBySubId(int subId)86     public Bundle getMmsConfigBySubId(int subId) {
87         Bundle mmsConfig;
88         synchronized(mSubIdConfigMap) {
89             mmsConfig = mSubIdConfigMap.get(subId);
90         }
91         LogUtil.i("mms config for sub " + subId + ": " + mmsConfig);
92         // Return a copy so that callers can mutate it.
93         if (mmsConfig != null) {
94           return new Bundle(mmsConfig);
95         }
96         return null;
97     }
98 
99     /**
100      * This loads the MMS config for each active subscription.
101      *
102      * MMS config is fetched from SmsManager#getCarrierConfigValues(). The resulting bundles are
103      * stored in mSubIdConfigMap.
104      */
load(Context context)105     private void load(Context context) {
106         List<SubscriptionInfo> subs = mSubscriptionManager.getActiveSubscriptionInfoList();
107         if (subs == null || subs.size() < 1) {
108             LogUtil.e(" Failed to load mms config: empty getActiveSubInfoList");
109             return;
110         }
111         // Load all the config bundles into a new map and then swap it with the real map to avoid
112         // blocking.
113         final Map<Integer, Bundle> newConfigMap = new ArrayMap<Integer, Bundle>();
114         for (SubscriptionInfo sub : subs) {
115             final int subId = sub.getSubscriptionId();
116             LogUtil.i("MmsConfigManager loads mms config for "
117                     + sub.getMccString() + "/" +  sub.getMncString()
118                     + ", CarrierId " + sub.getCarrierId());
119             newConfigMap.put(
120                     subId,
121                     SmsManager.getSmsManagerForSubscriptionId(subId).getCarrierConfigValues());
122         }
123         synchronized(mSubIdConfigMap) {
124             mSubIdConfigMap.clear();
125             mSubIdConfigMap.putAll(newConfigMap);
126         }
127     }
128 
129 }
130