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