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