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.ContentValues;
20d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport android.provider.Telephony;
21d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
22d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.Assert;
23d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.LogUtil;
24d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.android.messaging.util.PhoneUtils;
25d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport com.google.common.collect.Maps;
26d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
27d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport org.xmlpull.v1.XmlPullParser;
28d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport org.xmlpull.v1.XmlPullParserException;
29d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
30d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.io.IOException;
31d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddimport java.util.Map;
32d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
33d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd/*
34d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * XML processor for the following files:
35d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 1. res/xml/apns.xml
36d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd * 2. res/xml/mms_config.xml (or related overlay files)
37d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd */
38d3b009ae55651f1e60950342468e3c37fdeb0796Mike Doddclass ApnsXmlProcessor {
39d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public interface ApnHandler {
40d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        public void process(ContentValues apnValues);
41d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
42d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
43d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public interface MmsConfigHandler {
44d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        public void process(String mccMnc, String key, String value, String type);
45d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
46d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
47d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String TAG = LogUtil.BUGLE_TAG;
48d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
49d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final Map<String, String> APN_ATTRIBUTE_MAP = Maps.newHashMap();
50d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    static {
51d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        APN_ATTRIBUTE_MAP.put("mcc", Telephony.Carriers.MCC);
52d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        APN_ATTRIBUTE_MAP.put("mnc", Telephony.Carriers.MNC);
53d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        APN_ATTRIBUTE_MAP.put("carrier", Telephony.Carriers.NAME);
54d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        APN_ATTRIBUTE_MAP.put("apn", Telephony.Carriers.APN);
55d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        APN_ATTRIBUTE_MAP.put("mmsc", Telephony.Carriers.MMSC);
56d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        APN_ATTRIBUTE_MAP.put("mmsproxy", Telephony.Carriers.MMSPROXY);
57d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        APN_ATTRIBUTE_MAP.put("mmsport", Telephony.Carriers.MMSPORT);
58d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        APN_ATTRIBUTE_MAP.put("type", Telephony.Carriers.TYPE);
59d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        APN_ATTRIBUTE_MAP.put("user", Telephony.Carriers.USER);
60d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        APN_ATTRIBUTE_MAP.put("password", Telephony.Carriers.PASSWORD);
61d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        APN_ATTRIBUTE_MAP.put("authtype", Telephony.Carriers.AUTH_TYPE);
62d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        APN_ATTRIBUTE_MAP.put("mvno_match_data", Telephony.Carriers.MVNO_MATCH_DATA);
63d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        APN_ATTRIBUTE_MAP.put("mvno_type", Telephony.Carriers.MVNO_TYPE);
64d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        APN_ATTRIBUTE_MAP.put("protocol", Telephony.Carriers.PROTOCOL);
65d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        APN_ATTRIBUTE_MAP.put("bearer", Telephony.Carriers.BEARER);
66d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        APN_ATTRIBUTE_MAP.put("server", Telephony.Carriers.SERVER);
67d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        APN_ATTRIBUTE_MAP.put("roaming_protocol", Telephony.Carriers.ROAMING_PROTOCOL);
68d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        APN_ATTRIBUTE_MAP.put("proxy", Telephony.Carriers.PROXY);
69d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        APN_ATTRIBUTE_MAP.put("port", Telephony.Carriers.PORT);
70d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        APN_ATTRIBUTE_MAP.put("carrier_enabled", Telephony.Carriers.CARRIER_ENABLED);
71d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
72d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
73d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String TAG_APNS = "apns";
74d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String TAG_APN = "apn";
75d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static final String TAG_MMS_CONFIG = "mms_config";
76d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
77d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    // Handler to process one apn
78d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private ApnHandler mApnHandler;
79d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    // Handler to process one mms_config key/value pair
80d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private MmsConfigHandler mMmsConfigHandler;
81d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
82d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private final StringBuilder mLogStringBuilder = new StringBuilder();
83d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
84d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private final XmlPullParser mInputParser;
85d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
86d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private ApnsXmlProcessor(XmlPullParser parser) {
87d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mInputParser = parser;
88d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mApnHandler = null;
89d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mMmsConfigHandler = null;
90d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
91d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
92d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public static ApnsXmlProcessor get(XmlPullParser parser) {
93d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        Assert.notNull(parser);
94d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return new ApnsXmlProcessor(parser);
95d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
96d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
97d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public ApnsXmlProcessor setApnHandler(ApnHandler handler) {
98d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mApnHandler = handler;
99d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return this;
100d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
101d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
102d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public ApnsXmlProcessor setMmsConfigHandler(MmsConfigHandler handler) {
103d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mMmsConfigHandler = handler;
104d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return this;
105d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
106d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
107d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
108d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * Move XML parser forward to next event type or the end of doc
109d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     *
110d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @param eventType
111d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @return The final event type we meet
112d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @throws XmlPullParserException
113d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @throws IOException
114d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
115d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private int advanceToNextEvent(int eventType) throws XmlPullParserException, IOException {
116d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        for (;;) {
117d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            int nextEvent = mInputParser.next();
118d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (nextEvent == eventType
119d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    || nextEvent == XmlPullParser.END_DOCUMENT) {
120d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                return nextEvent;
121d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
122d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
123d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
124d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
125d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    public void process() {
126d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        try {
127d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // Find the first element
128d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (advanceToNextEvent(XmlPullParser.START_TAG) != XmlPullParser.START_TAG) {
129d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                throw new XmlPullParserException("ApnsXmlProcessor: expecting start tag @"
130d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        + xmlParserDebugContext());
131d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
132d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // A single ContentValues object for holding the parsing result of
133d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // an apn element
134d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final ContentValues values = new ContentValues();
135d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            String tagName = mInputParser.getName();
136d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // Top level tag can be "apns" (apns.xml)
137d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // or "mms_config" (mms_config.xml)
138d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (TAG_APNS.equals(tagName)) {
139d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                // For "apns", there could be "apn" or both "apn" and "mms_config"
140d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                for (;;) {
141d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    if (advanceToNextEvent(XmlPullParser.START_TAG) != XmlPullParser.START_TAG) {
142d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        break;
143d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    }
144d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    tagName = mInputParser.getName();
145d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    if (TAG_APN.equals(tagName)) {
146d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        processApn(values);
147d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    } else if (TAG_MMS_CONFIG.equals(tagName)) {
148d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        processMmsConfig();
149d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    }
150d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                }
151d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            } else if (TAG_MMS_CONFIG.equals(tagName)) {
152d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                // mms_config.xml resource
153d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                processMmsConfig();
154d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
155d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        } catch (IOException e) {
156d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            LogUtil.e(TAG, "ApnsXmlProcessor: I/O failure " + e, e);
157d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        } catch (XmlPullParserException e) {
158d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            LogUtil.e(TAG, "ApnsXmlProcessor: parsing failure " + e, e);
159d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
160d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
161d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
162d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private Integer parseInt(String text, Integer defaultValue, String logHint) {
163d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        Integer value = defaultValue;
164d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        try {
165d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            value = Integer.parseInt(text);
166d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        } catch (Exception e) {
167d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            LogUtil.e(TAG,
168d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    "Invalid value " + text + "for" + logHint + " @" + xmlParserDebugContext());
169d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
170d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return value;
171d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
172d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
173d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private Boolean parseBoolean(String text, Boolean defaultValue, String logHint) {
174d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        Boolean value = defaultValue;
175d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        try {
176d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            value = Boolean.parseBoolean(text);
177d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        } catch (Exception e) {
178d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            LogUtil.e(TAG,
179d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    "Invalid value " + text + "for" + logHint + " @" + xmlParserDebugContext());
180d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
181d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return value;
182d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
183d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
184d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private static String xmlParserEventString(int event) {
185d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        switch (event) {
186d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            case XmlPullParser.START_DOCUMENT: return "START_DOCUMENT";
187d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            case XmlPullParser.END_DOCUMENT: return "END_DOCUMENT";
188d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            case XmlPullParser.START_TAG: return "START_TAG";
189d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            case XmlPullParser.END_TAG: return "END_TAG";
190d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            case XmlPullParser.TEXT: return "TEXT";
191d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
192d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return Integer.toString(event);
193d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
194d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
195d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
196d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @return The debugging information of the parser's current position
197d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
198d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private String xmlParserDebugContext() {
199d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        mLogStringBuilder.setLength(0);
200d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (mInputParser != null) {
201d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            try {
202d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                final int eventType = mInputParser.getEventType();
203d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                mLogStringBuilder.append(xmlParserEventString(eventType));
204d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                if (eventType == XmlPullParser.START_TAG
205d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        || eventType == XmlPullParser.END_TAG
206d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        || eventType == XmlPullParser.TEXT) {
207d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    mLogStringBuilder.append('<').append(mInputParser.getName());
208d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    for (int i = 0; i < mInputParser.getAttributeCount(); i++) {
209d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        mLogStringBuilder.append(' ')
210d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                            .append(mInputParser.getAttributeName(i))
211d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                            .append('=')
212d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                            .append(mInputParser.getAttributeValue(i));
213d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    }
214d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    mLogStringBuilder.append("/>");
215d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                }
216d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                return mLogStringBuilder.toString();
217d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            } catch (XmlPullParserException e) {
218d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                LogUtil.e(TAG, "xmlParserDebugContext: " + e, e);
219d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
220d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
221d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        return "Unknown";
222d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
223d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
224d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
225d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * Process one apn
226d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     *
227d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @param apnValues Where we store the parsed apn
228d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @throws IOException
229d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @throws XmlPullParserException
230d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
231d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private void processApn(ContentValues apnValues) throws IOException, XmlPullParserException {
232d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        Assert.notNull(apnValues);
233d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        apnValues.clear();
234d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Collect all the attributes
235d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        for (int i = 0; i < mInputParser.getAttributeCount(); i++) {
236d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            final String key = APN_ATTRIBUTE_MAP.get(mInputParser.getAttributeName(i));
237d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (key != null) {
238d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                apnValues.put(key, mInputParser.getAttributeValue(i));
239d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
240d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
241d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Set numeric to be canonicalized mcc/mnc like "310120", always 6 digits
242d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String canonicalMccMnc = PhoneUtils.canonicalizeMccMnc(
243d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                apnValues.getAsString(Telephony.Carriers.MCC),
244d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                apnValues.getAsString(Telephony.Carriers.MNC));
245d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        apnValues.put(Telephony.Carriers.NUMERIC, canonicalMccMnc);
246d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Some of the values should not be string type, converting them to desired types
247d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String authType = apnValues.getAsString(Telephony.Carriers.AUTH_TYPE);
248d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (authType != null) {
249d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            apnValues.put(Telephony.Carriers.AUTH_TYPE, parseInt(authType, -1, "apn authtype"));
250d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
251d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String carrierEnabled = apnValues.getAsString(Telephony.Carriers.CARRIER_ENABLED);
252d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (carrierEnabled != null) {
253d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            apnValues.put(Telephony.Carriers.CARRIER_ENABLED,
254d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    parseBoolean(carrierEnabled, null, "apn carrierEnabled"));
255d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
256d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String bearer = apnValues.getAsString(Telephony.Carriers.BEARER);
257d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (bearer != null) {
258d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            apnValues.put(Telephony.Carriers.BEARER, parseInt(bearer, 0, "apn bearer"));
259d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
260d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // We are at the end tag
261d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (mInputParser.next() != XmlPullParser.END_TAG) {
262d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            throw new XmlPullParserException("Apn: expecting end tag @"
263d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    + xmlParserDebugContext());
264d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
265d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // We are done parsing one APN, call the handler
266d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (mApnHandler != null) {
267d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mApnHandler.process(apnValues);
268d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
269d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
270d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
271d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
272d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * Process one mms_config.
273d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     *
274d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @throws IOException
275d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @throws XmlPullParserException
276d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
277d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private void processMmsConfig()
278d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            throws IOException, XmlPullParserException {
279d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // Get the mcc and mnc attributes
280d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String canonicalMccMnc = PhoneUtils.canonicalizeMccMnc(
281d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                mInputParser.getAttributeValue(null, "mcc"),
282d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                mInputParser.getAttributeValue(null, "mnc"));
283d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // We are at the start tag
284d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        for (;;) {
285d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            int nextEvent;
286d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            // Skipping spaces
287d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            while ((nextEvent = mInputParser.next()) == XmlPullParser.TEXT) {
288d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
289d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            if (nextEvent == XmlPullParser.START_TAG) {
290d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                // Parse one mms config key/value
291d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                processMmsConfigKeyValue(canonicalMccMnc);
292d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            } else if (nextEvent == XmlPullParser.END_TAG) {
293d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                break;
294d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            } else {
295d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                throw new XmlPullParserException("MmsConfig: expecting start or end tag @"
296d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                        + xmlParserDebugContext());
297d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            }
298d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
299d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
300d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd
301d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    /**
302d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * Process one mms_config key/value pair
303d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     *
304d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @param mccMnc The mcc and mnc of this mms_config
305d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @throws IOException
306d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     * @throws XmlPullParserException
307d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd     */
308d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    private void processMmsConfigKeyValue(String mccMnc)
309d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            throws IOException, XmlPullParserException {
310d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String key = mInputParser.getAttributeValue(null, "name");
311d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // We are at the start tag, the name of the tag is the type
312d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // e.g. <int name="key">value</int>
313d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        final String type = mInputParser.getName();
314d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        int nextEvent = mInputParser.next();
315d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        String value = null;
316d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (nextEvent == XmlPullParser.TEXT) {
317d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            value = mInputParser.getText();
318d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            nextEvent = mInputParser.next();
319d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
320d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (nextEvent != XmlPullParser.END_TAG) {
321d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            throw new XmlPullParserException("ApnsXmlProcessor: expecting end tag @"
322d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd                    + xmlParserDebugContext());
323d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
324d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        // We are done parsing one mms_config key/value, call the handler
325d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        if (mMmsConfigHandler != null) {
326d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd            mMmsConfigHandler.process(mccMnc, key, value, type);
327d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd        }
328d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd    }
329d3b009ae55651f1e60950342468e3c37fdeb0796Mike Dodd}
330