Home | History | Annotate | Download | only in sms
      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 com.android.messaging.sms;
     18 
     19 import android.content.Context;
     20 import android.content.res.Configuration;
     21 import android.content.res.Resources;
     22 import android.content.res.XmlResourceParser;
     23 import android.os.Bundle;
     24 import android.support.v7.mms.CarrierConfigValuesLoader;
     25 import android.util.SparseArray;
     26 
     27 import com.android.messaging.R;
     28 import com.android.messaging.util.LogUtil;
     29 import com.android.messaging.util.OsUtil;
     30 import com.android.messaging.util.PhoneUtils;
     31 
     32 /**
     33  * Carrier configuration loader
     34  *
     35  * Loader tries to load from resources. If there is MMS API available, also
     36  * load from system.
     37  */
     38 public class BugleCarrierConfigValuesLoader implements CarrierConfigValuesLoader {
     39     /*
     40      * Key types
     41      */
     42     public static final String KEY_TYPE_INT = "int";
     43     public static final String KEY_TYPE_BOOL = "bool";
     44     public static final String KEY_TYPE_STRING = "string";
     45 
     46     private final Context mContext;
     47 
     48     // Cached values for subIds
     49     private final SparseArray<Bundle> mValuesCache;
     50 
     51     public BugleCarrierConfigValuesLoader(final Context context) {
     52         mContext = context;
     53         mValuesCache = new SparseArray<>();
     54     }
     55 
     56     @Override
     57     public Bundle get(int subId) {
     58         subId = PhoneUtils.getDefault().getEffectiveSubId(subId);
     59         Bundle values;
     60         String loadSource = null;
     61         synchronized (this) {
     62             values = mValuesCache.get(subId);
     63             if (values == null) {
     64                 values = new Bundle();
     65                 mValuesCache.put(subId, values);
     66                 loadSource = loadLocked(subId, values);
     67             }
     68         }
     69         if (loadSource != null) {
     70             LogUtil.i(LogUtil.BUGLE_TAG, "Carrier configs loaded: " + values
     71                     + " from " + loadSource + " for subId=" + subId);
     72         }
     73         return values;
     74     }
     75 
     76     /**
     77      * Clear the cache for reloading
     78      */
     79     public void reset() {
     80         synchronized (this) {
     81             mValuesCache.clear();
     82         }
     83     }
     84 
     85     /**
     86      * Loading carrier config values
     87      *
     88      * @param subId which SIM to load for
     89      * @param values the result to add to
     90      * @return the source of the config, could be "resources" or "resources+system"
     91      */
     92     private String loadLocked(final int subId, final Bundle values) {
     93         // Load from resources in earlier platform
     94         loadFromResources(subId, values);
     95         if (OsUtil.isAtLeastL()) {
     96             // Load from system to override if system API exists
     97             loadFromSystem(subId, values);
     98             return "resources+system";
     99         }
    100         return "resources";
    101     }
    102 
    103     /**
    104      * Load from system, using MMS API
    105      *
    106      * @param subId which SIM to load for
    107      * @param values the result to add to
    108      */
    109     private static void loadFromSystem(final int subId, final Bundle values) {
    110         try {
    111             final Bundle systemValues =
    112                     PhoneUtils.get(subId).getSmsManager().getCarrierConfigValues();
    113             if (systemValues != null) {
    114                 values.putAll(systemValues);
    115             }
    116         } catch (final Exception e) {
    117             LogUtil.w(LogUtil.BUGLE_TAG, "Calling system getCarrierConfigValues exception", e);
    118         }
    119     }
    120 
    121     /**
    122      * Load from SIM-dependent resources
    123      *
    124      * @param subId which SIM to load for
    125      * @param values the result to add to
    126      */
    127     private void loadFromResources(final int subId, final Bundle values) {
    128         // Get a subscription-dependent context for loading the mms_config.xml
    129         final Context subContext = getSubDepContext(mContext, subId);
    130         // Load and parse the XML
    131         XmlResourceParser parser = null;
    132         try {
    133             parser = subContext.getResources().getXml(R.xml.mms_config);
    134             final ApnsXmlProcessor processor = ApnsXmlProcessor.get(parser);
    135             processor.setMmsConfigHandler(new ApnsXmlProcessor.MmsConfigHandler() {
    136                 @Override
    137                 public void process(final String mccMnc, final String key, final String value,
    138                         final String type) {
    139                     update(values, type, key, value);
    140                 }
    141             });
    142             processor.process();
    143         } catch (final Resources.NotFoundException e) {
    144             LogUtil.w(LogUtil.BUGLE_TAG, "Can not find mms_config.xml");
    145         } finally {
    146             if (parser != null) {
    147                 parser.close();
    148             }
    149         }
    150     }
    151 
    152     /**
    153      * Get a subscription's Context so we can load resources from it
    154      *
    155      * @param context the sub-independent Context
    156      * @param subId the SIM's subId
    157      * @return the sub-dependent Context
    158      */
    159     private static Context getSubDepContext(final Context context, final int subId) {
    160         if (!OsUtil.isAtLeastL_MR1()) {
    161             return context;
    162         }
    163         final int[] mccMnc = PhoneUtils.get(subId).getMccMnc();
    164         final int mcc = mccMnc[0];
    165         final int mnc = mccMnc[1];
    166         final Configuration subConfig = new Configuration();
    167         if (mcc == 0 && mnc == 0) {
    168             Configuration config = context.getResources().getConfiguration();
    169             subConfig.mcc = config.mcc;
    170             subConfig.mnc = config.mnc;
    171         } else {
    172             subConfig.mcc = mcc;
    173             subConfig.mnc = mnc;
    174         }
    175         return context.createConfigurationContext(subConfig);
    176     }
    177 
    178     /**
    179      * Add or update a carrier config key/value pair to the Bundle
    180      *
    181      * @param values the result Bundle to add to
    182      * @param type the value type
    183      * @param key the key
    184      * @param value the value
    185      */
    186     public static void update(final Bundle values, final String type, final String key,
    187             final String value) {
    188         try {
    189             if (KEY_TYPE_INT.equals(type)) {
    190                 values.putInt(key, Integer.parseInt(value));
    191             } else if (KEY_TYPE_BOOL.equals(type)) {
    192                 values.putBoolean(key, Boolean.parseBoolean(value));
    193             } else if (KEY_TYPE_STRING.equals(type)){
    194                 values.putString(key, value);
    195             }
    196         } catch (final NumberFormatException e) {
    197             LogUtil.w(LogUtil.BUGLE_TAG, "Add carrier values: "
    198                     + "invalid " + key + "," + value + "," + type);
    199         }
    200     }
    201 }
    202