1/*
2 * Copyright (C) 2009 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
17package com.android.internal.telephony.cdma;
18
19import android.content.Context;
20import android.content.res.Resources;
21import android.content.res.XmlResourceParser;
22import android.telephony.Rlog;
23import android.util.Xml;
24
25import com.android.internal.telephony.PhoneBase;
26import com.android.internal.util.XmlUtils;
27
28
29import org.xmlpull.v1.XmlPullParser;
30import org.xmlpull.v1.XmlPullParserException;
31
32import java.io.FileInputStream;
33import java.io.FileNotFoundException;
34import java.io.IOException;
35import java.util.HashMap;
36
37/**
38 * EriManager loads the ERI file definitions and manages the CDMA roaming information.
39 *
40 */
41public final class EriManager {
42
43    class EriFile {
44
45        int mVersionNumber;                      // File version number
46        int mNumberOfEriEntries;                 // Number of entries
47        int mEriFileType;                        // Eri Phase 0/1
48        //int mNumberOfIconImages;               // reserved for future use
49        //int mIconImageType;                    // reserved for future use
50        String[] mCallPromptId;                  // reserved for future use
51        HashMap<Integer, EriInfo> mRoamIndTable; // Roaming Indicator Table
52
53        EriFile() {
54            mVersionNumber = -1;
55            mNumberOfEriEntries = 0;
56            mEriFileType = -1;
57            mCallPromptId = new String[] { "", "", "" };
58            mRoamIndTable = new HashMap<Integer, EriInfo>();
59        }
60    }
61
62    class EriDisplayInformation {
63        int mEriIconIndex;
64        int mEriIconMode;
65        String mEriIconText;
66
67        EriDisplayInformation(int eriIconIndex, int eriIconMode, String eriIconText) {
68            mEriIconIndex = eriIconIndex;
69            mEriIconMode = eriIconMode;
70            mEriIconText = eriIconText;
71        }
72
73//        public void setParameters(int eriIconIndex, int eriIconMode, String eriIconText){
74//            mEriIconIndex = eriIconIndex;
75//            mEriIconMode = eriIconMode;
76//            mEriIconText = eriIconText;
77//        }
78
79        @Override
80        public String toString() {
81            return "EriDisplayInformation: {" + " IconIndex: " + mEriIconIndex + " EriIconMode: "
82                    + mEriIconMode + " EriIconText: " + mEriIconText + " }";
83        }
84    }
85
86    private static final String LOG_TAG = "CDMA";
87    private static final boolean DBG = true;
88    private static final boolean VDBG = false;
89
90    static final int ERI_FROM_XML          = 0;
91    static final int ERI_FROM_FILE_SYSTEM  = 1;
92    static final int ERI_FROM_MODEM        = 2;
93
94    private Context mContext;
95    private int mEriFileSource = ERI_FROM_XML;
96    private boolean mIsEriFileLoaded;
97    private EriFile mEriFile;
98
99    public EriManager(PhoneBase phone, Context context, int eriFileSource) {
100        mContext = context;
101        mEriFileSource = eriFileSource;
102        mEriFile = new EriFile();
103    }
104
105    public void dispose() {
106        mEriFile = new EriFile();
107        mIsEriFileLoaded = false;
108    }
109
110
111    public void loadEriFile() {
112        switch (mEriFileSource) {
113        case ERI_FROM_MODEM:
114            loadEriFileFromModem();
115            break;
116
117        case ERI_FROM_FILE_SYSTEM:
118            loadEriFileFromFileSystem();
119            break;
120
121        case ERI_FROM_XML:
122        default:
123            loadEriFileFromXml();
124            break;
125        }
126    }
127
128    /**
129     * Load the ERI file from the MODEM through chipset specific RIL_REQUEST_OEM_HOOK
130     *
131     * In this case the ERI file can be updated from the Phone Support Tool available
132     * from the Chipset vendor
133     */
134    private void loadEriFileFromModem() {
135        // NOT IMPLEMENTED, Chipset vendor/Operator specific
136    }
137
138    /**
139     * Load the ERI file from a File System file
140     *
141     * In this case the a Phone Support Tool to update the ERI file must be provided
142     * to the Operator
143     */
144    private void loadEriFileFromFileSystem() {
145        // NOT IMPLEMENTED, Chipset vendor/Operator specific
146    }
147
148    /**
149     * Load the ERI file from the application framework resources encoded in XML
150     *
151     */
152    private void loadEriFileFromXml() {
153        XmlPullParser parser = null;
154        FileInputStream stream = null;
155        Resources r = mContext.getResources();
156
157        try {
158            if (DBG) Rlog.d(LOG_TAG, "loadEriFileFromXml: check for alternate file");
159            stream = new FileInputStream(
160                            r.getString(com.android.internal.R.string.alternate_eri_file));
161            parser = Xml.newPullParser();
162            parser.setInput(stream, null);
163            if (DBG) Rlog.d(LOG_TAG, "loadEriFileFromXml: opened alternate file");
164        } catch (FileNotFoundException e) {
165            if (DBG) Rlog.d(LOG_TAG, "loadEriFileFromXml: no alternate file");
166            parser = null;
167        } catch (XmlPullParserException e) {
168            if (DBG) Rlog.d(LOG_TAG, "loadEriFileFromXml: no parser for alternate file");
169            parser = null;
170        }
171
172        if (parser == null) {
173            if (DBG) Rlog.d(LOG_TAG, "loadEriFileFromXml: open normal file");
174            parser = r.getXml(com.android.internal.R.xml.eri);
175        }
176
177        try {
178            XmlUtils.beginDocument(parser, "EriFile");
179            mEriFile.mVersionNumber = Integer.parseInt(
180                    parser.getAttributeValue(null, "VersionNumber"));
181            mEriFile.mNumberOfEriEntries = Integer.parseInt(
182                    parser.getAttributeValue(null, "NumberOfEriEntries"));
183            mEriFile.mEriFileType = Integer.parseInt(
184                    parser.getAttributeValue(null, "EriFileType"));
185
186            int parsedEriEntries = 0;
187            while(true) {
188                XmlUtils.nextElement(parser);
189                String name = parser.getName();
190                if (name == null) {
191                    if (parsedEriEntries != mEriFile.mNumberOfEriEntries)
192                        Rlog.e(LOG_TAG, "Error Parsing ERI file: " +  mEriFile.mNumberOfEriEntries
193                                + " defined, " + parsedEriEntries + " parsed!");
194                    break;
195                } else if (name.equals("CallPromptId")) {
196                    int id = Integer.parseInt(parser.getAttributeValue(null, "Id"));
197                    String text = parser.getAttributeValue(null, "CallPromptText");
198                    if (id >= 0 && id <= 2) {
199                        mEriFile.mCallPromptId[id] = text;
200                    } else {
201                        Rlog.e(LOG_TAG, "Error Parsing ERI file: found" + id + " CallPromptId");
202                    }
203
204                } else if (name.equals("EriInfo")) {
205                    int roamingIndicator = Integer.parseInt(
206                            parser.getAttributeValue(null, "RoamingIndicator"));
207                    int iconIndex = Integer.parseInt(parser.getAttributeValue(null, "IconIndex"));
208                    int iconMode = Integer.parseInt(parser.getAttributeValue(null, "IconMode"));
209                    String eriText = parser.getAttributeValue(null, "EriText");
210                    int callPromptId = Integer.parseInt(
211                            parser.getAttributeValue(null, "CallPromptId"));
212                    int alertId = Integer.parseInt(parser.getAttributeValue(null, "AlertId"));
213                    parsedEriEntries++;
214                    mEriFile.mRoamIndTable.put(roamingIndicator, new EriInfo (roamingIndicator,
215                            iconIndex, iconMode, eriText, callPromptId, alertId));
216                }
217            }
218
219            if (DBG) Rlog.d(LOG_TAG, "loadEriFileFromXml: eri parsing successful, file loaded");
220            mIsEriFileLoaded = true;
221
222        } catch (Exception e) {
223            Rlog.e(LOG_TAG, "Got exception while loading ERI file.", e);
224        } finally {
225            if (parser instanceof XmlResourceParser) {
226                ((XmlResourceParser)parser).close();
227            }
228            try {
229                if (stream != null) {
230                    stream.close();
231                }
232            } catch (IOException e) {
233                // Ignore
234            }
235        }
236    }
237
238    /**
239     * Returns the version of the ERI file
240     *
241     */
242    public int getEriFileVersion() {
243        return mEriFile.mVersionNumber;
244    }
245
246    /**
247     * Returns the number of ERI entries parsed
248     *
249     */
250    public int getEriNumberOfEntries() {
251        return mEriFile.mNumberOfEriEntries;
252    }
253
254    /**
255     * Returns the ERI file type value ( 0 for Phase 0, 1 for Phase 1)
256     *
257     */
258    public int getEriFileType() {
259        return mEriFile.mEriFileType;
260    }
261
262    /**
263     * Returns if the ERI file has been loaded
264     *
265     */
266    public boolean isEriFileLoaded() {
267        return mIsEriFileLoaded;
268    }
269
270    /**
271     * Returns the EriInfo record associated with roamingIndicator
272     * or null if the entry is not found
273     */
274    private EriInfo getEriInfo(int roamingIndicator) {
275        if (mEriFile.mRoamIndTable.containsKey(roamingIndicator)) {
276            return mEriFile.mRoamIndTable.get(roamingIndicator);
277        } else {
278            return null;
279        }
280    }
281
282    private EriDisplayInformation getEriDisplayInformation(int roamInd, int defRoamInd){
283        EriDisplayInformation ret;
284
285        // Carrier can use eri.xml to customize any built-in roaming display indications
286        if (mIsEriFileLoaded) {
287            EriInfo eriInfo = getEriInfo(roamInd);
288            if (eriInfo != null) {
289                if (VDBG) Rlog.v(LOG_TAG, "ERI roamInd " + roamInd + " found in ERI file");
290                ret = new EriDisplayInformation(
291                        eriInfo.iconIndex,
292                        eriInfo.iconMode,
293                        eriInfo.eriText);
294                return ret;
295            }
296        }
297
298        switch (roamInd) {
299        // Handling the standard roaming indicator (non-ERI)
300        case EriInfo.ROAMING_INDICATOR_ON:
301            ret = new EriDisplayInformation(
302                    EriInfo.ROAMING_INDICATOR_ON,
303                    EriInfo.ROAMING_ICON_MODE_NORMAL,
304                    mContext.getText(com.android.internal.R.string.roamingText0).toString());
305            break;
306
307        case EriInfo.ROAMING_INDICATOR_OFF:
308            ret = new EriDisplayInformation(
309                    EriInfo.ROAMING_INDICATOR_OFF,
310                    EriInfo.ROAMING_ICON_MODE_NORMAL,
311                    mContext.getText(com.android.internal.R.string.roamingText1).toString());
312            break;
313
314        case EriInfo.ROAMING_INDICATOR_FLASH:
315            ret = new EriDisplayInformation(
316                    EriInfo.ROAMING_INDICATOR_FLASH,
317                    EriInfo.ROAMING_ICON_MODE_FLASH,
318                    mContext.getText(com.android.internal.R.string.roamingText2).toString());
319            break;
320
321
322        // Handling the standard ERI
323        case 3:
324            ret = new EriDisplayInformation(
325                    roamInd,
326                    EriInfo.ROAMING_ICON_MODE_NORMAL,
327                    mContext.getText(com.android.internal.R.string.roamingText3).toString());
328            break;
329
330        case 4:
331            ret = new EriDisplayInformation(
332                    roamInd,
333                    EriInfo.ROAMING_ICON_MODE_NORMAL,
334                    mContext.getText(com.android.internal.R.string.roamingText4).toString());
335            break;
336
337        case 5:
338            ret = new EriDisplayInformation(
339                    roamInd,
340                    EriInfo.ROAMING_ICON_MODE_NORMAL,
341                    mContext.getText(com.android.internal.R.string.roamingText5).toString());
342            break;
343
344        case 6:
345            ret = new EriDisplayInformation(
346                    roamInd,
347                    EriInfo.ROAMING_ICON_MODE_NORMAL,
348                    mContext.getText(com.android.internal.R.string.roamingText6).toString());
349            break;
350
351        case 7:
352            ret = new EriDisplayInformation(
353                    roamInd,
354                    EriInfo.ROAMING_ICON_MODE_NORMAL,
355                    mContext.getText(com.android.internal.R.string.roamingText7).toString());
356            break;
357
358        case 8:
359            ret = new EriDisplayInformation(
360                    roamInd,
361                    EriInfo.ROAMING_ICON_MODE_NORMAL,
362                    mContext.getText(com.android.internal.R.string.roamingText8).toString());
363            break;
364
365        case 9:
366            ret = new EriDisplayInformation(
367                    roamInd,
368                    EriInfo.ROAMING_ICON_MODE_NORMAL,
369                    mContext.getText(com.android.internal.R.string.roamingText9).toString());
370            break;
371
372        case 10:
373            ret = new EriDisplayInformation(
374                    roamInd,
375                    EriInfo.ROAMING_ICON_MODE_NORMAL,
376                    mContext.getText(com.android.internal.R.string.roamingText10).toString());
377            break;
378
379        case 11:
380            ret = new EriDisplayInformation(
381                    roamInd,
382                    EriInfo.ROAMING_ICON_MODE_NORMAL,
383                    mContext.getText(com.android.internal.R.string.roamingText11).toString());
384            break;
385
386        case 12:
387            ret = new EriDisplayInformation(
388                    roamInd,
389                    EriInfo.ROAMING_ICON_MODE_NORMAL,
390                    mContext.getText(com.android.internal.R.string.roamingText12).toString());
391            break;
392
393        // Handling the non standard Enhanced Roaming Indicator (roamInd > 63)
394        default:
395            if (!mIsEriFileLoaded) {
396                // ERI file NOT loaded
397                if (DBG) Rlog.d(LOG_TAG, "ERI File not loaded");
398                if(defRoamInd > 2) {
399                    if (VDBG) Rlog.v(LOG_TAG, "ERI defRoamInd > 2 ...flashing");
400                    ret = new EriDisplayInformation(
401                            EriInfo.ROAMING_INDICATOR_FLASH,
402                            EriInfo.ROAMING_ICON_MODE_FLASH,
403                            mContext.getText(com.android.internal
404                                                            .R.string.roamingText2).toString());
405                } else {
406                    if (VDBG) Rlog.v(LOG_TAG, "ERI defRoamInd <= 2");
407                    switch (defRoamInd) {
408                    case EriInfo.ROAMING_INDICATOR_ON:
409                        ret = new EriDisplayInformation(
410                                EriInfo.ROAMING_INDICATOR_ON,
411                                EriInfo.ROAMING_ICON_MODE_NORMAL,
412                                mContext.getText(com.android.internal
413                                                            .R.string.roamingText0).toString());
414                        break;
415
416                    case EriInfo.ROAMING_INDICATOR_OFF:
417                        ret = new EriDisplayInformation(
418                                EriInfo.ROAMING_INDICATOR_OFF,
419                                EriInfo.ROAMING_ICON_MODE_NORMAL,
420                                mContext.getText(com.android.internal
421                                                            .R.string.roamingText1).toString());
422                        break;
423
424                    case EriInfo.ROAMING_INDICATOR_FLASH:
425                        ret = new EriDisplayInformation(
426                                EriInfo.ROAMING_INDICATOR_FLASH,
427                                EriInfo.ROAMING_ICON_MODE_FLASH,
428                                mContext.getText(com.android.internal
429                                                            .R.string.roamingText2).toString());
430                        break;
431
432                    default:
433                        ret = new EriDisplayInformation(-1, -1, "ERI text");
434                    }
435                }
436            } else {
437                // ERI file loaded
438                EriInfo eriInfo = getEriInfo(roamInd);
439                EriInfo defEriInfo = getEriInfo(defRoamInd);
440                if (eriInfo == null) {
441                    if (VDBG) {
442                        Rlog.v(LOG_TAG, "ERI roamInd " + roamInd
443                            + " not found in ERI file ...using defRoamInd " + defRoamInd);
444                    }
445                    if(defEriInfo == null) {
446                        Rlog.e(LOG_TAG, "ERI defRoamInd " + defRoamInd
447                                + " not found in ERI file ...on");
448                        ret = new EriDisplayInformation(
449                                EriInfo.ROAMING_INDICATOR_ON,
450                                EriInfo.ROAMING_ICON_MODE_NORMAL,
451                                mContext.getText(com.android.internal
452                                                             .R.string.roamingText0).toString());
453
454                    } else {
455                        if (VDBG) {
456                            Rlog.v(LOG_TAG, "ERI defRoamInd " + defRoamInd + " found in ERI file");
457                        }
458                        ret = new EriDisplayInformation(
459                                defEriInfo.iconIndex,
460                                defEriInfo.iconMode,
461                                defEriInfo.eriText);
462                    }
463                } else {
464                    if (VDBG) Rlog.v(LOG_TAG, "ERI roamInd " + roamInd + " found in ERI file");
465                    ret = new EriDisplayInformation(
466                            eriInfo.iconIndex,
467                            eriInfo.iconMode,
468                            eriInfo.eriText);
469                }
470            }
471            break;
472        }
473        if (VDBG) Rlog.v(LOG_TAG, "Displaying ERI " + ret.toString());
474        return ret;
475    }
476
477    public int getCdmaEriIconIndex(int roamInd, int defRoamInd){
478        return getEriDisplayInformation(roamInd, defRoamInd).mEriIconIndex;
479    }
480
481    public int getCdmaEriIconMode(int roamInd, int defRoamInd){
482        return getEriDisplayInformation(roamInd, defRoamInd).mEriIconMode;
483    }
484
485    public String getCdmaEriText(int roamInd, int defRoamInd){
486        return getEriDisplayInformation(roamInd, defRoamInd).mEriIconText;
487    }
488}
489