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 
17 package com.android.internal.telephony.cdma;
18 
19 import android.content.Context;
20 import android.content.res.Resources;
21 import android.content.res.XmlResourceParser;
22 import android.telephony.Rlog;
23 import android.util.Xml;
24 
25 import com.android.internal.telephony.PhoneBase;
26 import com.android.internal.util.XmlUtils;
27 
28 
29 import org.xmlpull.v1.XmlPullParser;
30 import org.xmlpull.v1.XmlPullParserException;
31 
32 import java.io.FileInputStream;
33 import java.io.FileNotFoundException;
34 import java.io.IOException;
35 import java.util.HashMap;
36 
37 /**
38  * EriManager loads the ERI file definitions and manages the CDMA roaming information.
39  *
40  */
41 public 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 
EriFile()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 
EriDisplayInformation(int eriIconIndex, int eriIconMode, String eriIconText)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
toString()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 
EriManager(PhoneBase phone, Context context, int eriFileSource)99     public EriManager(PhoneBase phone, Context context, int eriFileSource) {
100         mContext = context;
101         mEriFileSource = eriFileSource;
102         mEriFile = new EriFile();
103     }
104 
dispose()105     public void dispose() {
106         mEriFile = new EriFile();
107         mIsEriFileLoaded = false;
108     }
109 
110 
loadEriFile()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      */
loadEriFileFromModem()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      */
loadEriFileFromFileSystem()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      */
loadEriFileFromXml()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      */
getEriFileVersion()242     public int getEriFileVersion() {
243         return mEriFile.mVersionNumber;
244     }
245 
246     /**
247      * Returns the number of ERI entries parsed
248      *
249      */
getEriNumberOfEntries()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      */
getEriFileType()258     public int getEriFileType() {
259         return mEriFile.mEriFileType;
260     }
261 
262     /**
263      * Returns if the ERI file has been loaded
264      *
265      */
isEriFileLoaded()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      */
getEriInfo(int roamingIndicator)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 
getEriDisplayInformation(int roamInd, int defRoamInd)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 
getCdmaEriIconIndex(int roamInd, int defRoamInd)477     public int getCdmaEriIconIndex(int roamInd, int defRoamInd){
478         return getEriDisplayInformation(roamInd, defRoamInd).mEriIconIndex;
479     }
480 
getCdmaEriIconMode(int roamInd, int defRoamInd)481     public int getCdmaEriIconMode(int roamInd, int defRoamInd){
482         return getEriDisplayInformation(roamInd, defRoamInd).mEriIconMode;
483     }
484 
getCdmaEriText(int roamInd, int defRoamInd)485     public String getCdmaEriText(int roamInd, int defRoamInd){
486         return getEriDisplayInformation(roamInd, defRoamInd).mEriIconText;
487     }
488 }
489