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