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