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