1 /* 2 * Copyright (C) 2018 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.phone; 18 19 import android.content.Context; 20 import android.content.res.XmlResourceParser; 21 import android.support.annotation.VisibleForTesting; 22 import android.telephony.TelephonyManager; 23 import android.text.TextUtils; 24 import android.util.Log; 25 26 import org.xmlpull.v1.XmlPullParser; 27 import org.xmlpull.v1.XmlPullParserException; 28 29 import java.io.IOException; 30 import java.util.ArrayList; 31 import java.util.HashMap; 32 import java.util.Map; 33 import java.util.Vector; 34 import java.util.regex.Matcher; 35 import java.util.regex.Pattern; 36 37 /** 38 * CarrierXmlParser is a xml parser. It parses the carrier's ussd format from carrier_ss_string.xml. 39 * The carrier_ss_string.xml defines carrier's ussd structure and meaning in res/xml folder. 40 * Some carrier has specific ussd structure ,developer can add new xml and xml is named 41 * carrier_ss_string_carrierId.xml. The carrierId is a number and is defined in 42 * <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/carrier_list.textpb">here</a> 43 * For example: carrier_ss_string_850.xml 44 * <p> 45 * How do use CarrierXmlParser? 46 * For example: 47 * @see CallForwardEditPreference 48 * TelephonyManager telephonyManager = new TelephonyManager(getContext(),phone.getSubId()); 49 * CarrierXmlParser = new CarrierXmlParser(getContext(), telephonyManager.getSimCarrierId()); 50 * 51 * //make a ussd command 52 * String newUssdCommand = mCarrierXmlParser.getFeature( 53 * CarrierXmlParser.FEATURE_CALL_FORWARDING).makeCommand(inputAction, inputCfInfo); 54 * //analyze ussd result 55 * HashMap<String, String> analysisResult = mCarrierXmlParser.getFeature( 56 * CarrierXmlParser.FEATURE_CALL_FORWARDING) 57 * .getResponseSet(mSsAction, response.toString()); 58 */ 59 public class CarrierXmlParser { 60 public static final String LOG_TAG = "CarrierXmlParser"; 61 private static final boolean DEBUG = true; 62 63 private static final String STAR_SIGN = "*"; 64 private static final String POUND_SIGN = "#"; 65 66 private static final String TAG_SIGN = "tag_"; 67 68 // To define feature's item name in xml 69 public static final String FEATURE_CALL_FORWARDING = "callforwarding"; 70 public static final String FEATURE_CALL_WAITING = "callwaiting"; 71 public static final String FEATURE_CALLER_ID = "callerid"; 72 73 // COMMAND_NAME is xml's command name. 74 public static final String TAG_COMMAND_NAME_QUERY = "query"; 75 public static final String TAG_COMMAND_NAME_ACTIVATE = "activate"; 76 public static final String TAG_COMMAND_NAME_DEACTIVATE = "deactivate"; 77 78 // To define string level in xml. 79 // level 1 80 private static final String TAG_FEATURE = "feature"; 81 private static final String TAG_REGULAR_PARSER = "regular_parser"; 82 // level 2 83 private static final String TAG_COMMAND = "command"; 84 // level 3 85 private static final String TAG_SERVICE_CODE = "service_code"; 86 private static final String TAG_ACTION_CODE = "action_code"; 87 private static final String TAG_PARAMETER = "parameter"; 88 private static final String TAG_RESPONSE_FORMAT = "response_format"; 89 private static final String TAG_COMMAND_RESULT = "command_result"; 90 // level 4 91 private static final String TAG_ENTRY = "entry"; 92 93 private static final String ATTR_NAME = "name"; 94 private static final String ATTR_PARAMETER_NUM = "number"; 95 private static final String ATTR_POSITION = "position"; 96 private static final String ATTR_RESULT_KEY = "key"; 97 private static final String ATTR_DEFINITION_KEY = "definition"; 98 99 HashMap<String, SsFeature> mFeatureMaps; 100 101 @VisibleForTesting(otherwise = VisibleForTesting.PRIVATE) 102 static String sParserFormat = ""; 103 104 // TAG_ENTRY_NUMBER and TAG_ENTRY_TIME is xml's entry value. 105 // This is mapping user's input value. For example: number,time ... 106 // When UI makes command ,it will map the value and insert this value at position location. 107 // How to use it? 108 // The UI calls CarrierXmlParser's makeCommand function and inputs the hashmap which 109 // includes tag_name and user's input value. 110 // For example: User calls CarrierXmlParser's makeCommand in call forwarding , and inputs 111 // the hashmap {<TAG_ENTRY_NUMBER,0123456789>,<TAG_ENTRY_TIME,20>} 112 // If developer wants to add new one, xml string should the same as hashmap's name. 113 public static final String TAG_ENTRY_NUMBER = "tag_number"; 114 public static final String TAG_ENTRY_TIME = "tag_time"; 115 116 // "response_format" key 117 // The key of "response_format" should define as below in xml. 118 // The UI will use it to define value from the response command 119 // and use the data show the screen. 120 public static final String TAG_RESPONSE_STATUS = "status_code"; 121 public static final String TAG_RESPONSE_STATUS_ERROR = "RESPONSE_ERROR"; 122 public static final String TAG_RESPONSE_NUMBER = "number"; 123 public static final String TAG_RESPONSE_TIME = "time"; 124 125 // This is the definition for the entry's key in response_format. 126 // Xml's COMMAND_RESULT_DEFINITION should same as below. 127 public static final String TAG_COMMAND_RESULT_DEFINITION_ACTIVATE = "activate"; 128 public static final String TAG_COMMAND_RESULT_DEFINITION_DEACTIVATE = "deactivate"; 129 public static final String TAG_COMMAND_RESULT_DEFINITION_UNREGISTER = "unregister"; 130 public static final String TAG_COMMAND_RESULT_DEFINITION_OK = "ok"; 131 public static final String TAG_COMMAND_RESULT_DEFINITION_FAIL = "fail"; 132 133 /** 134 * UssdParser is a string parser. It parses the USSD response message. 135 */ 136 public static class UssdParser { 137 private Vector<String> mParserStr = new Vector<String>(); 138 private Pattern mPatternSuppServiceResponse; 139 UssdParser(String inputParserFormat)140 public UssdParser(String inputParserFormat) { 141 mPatternSuppServiceResponse = Pattern.compile(inputParserFormat); 142 } 143 144 /** 145 * This function is a parser and analyzes the USSD responses message. 146 * 147 * @param responseString The USSD responses message. 148 */ newFromResponseString(String responseString)149 public void newFromResponseString(String responseString) { 150 Matcher m; 151 m = mPatternSuppServiceResponse.matcher(responseString); 152 if (m.matches()) { 153 mParserStr.clear(); 154 int groupSize = m.groupCount(); 155 for (int i = 0; i <= groupSize; i++) { 156 if (!TextUtils.isEmpty(m.group(i))) { 157 mParserStr.add(m.group(i)); 158 } else { 159 mParserStr.add(""); 160 } 161 } 162 } else { 163 Log.d(LOG_TAG, "no match"); 164 } 165 } 166 167 /** 168 * To get the UssdParser result. 169 */ getResult()170 public Vector<String> getResult() { 171 return mParserStr; 172 } 173 } 174 175 /** 176 * CarrierXmlParser parses command from xml and saves in SsEntry class. 177 */ 178 public static class SsEntry { 179 public enum SSAction { 180 UNKNOWN, 181 QUERY, 182 UPDATE_ACTIVATE, 183 UPDATE_DEACTIVATE 184 } 185 186 public String serviceCode; 187 public SSAction ssAction = SSAction.UNKNOWN; 188 public String actionCode; 189 public HashMap<Integer, String> commandParameter = new HashMap<Integer, String>(); 190 public HashMap<Integer, String> responseFormat = new HashMap<Integer, String>(); 191 SsEntry(String action)192 public SsEntry(String action) { 193 if (action.equals(TAG_COMMAND_NAME_QUERY)) { 194 ssAction = SSAction.QUERY; 195 } else if (action.equals(TAG_COMMAND_NAME_ACTIVATE)) { 196 ssAction = SSAction.UPDATE_ACTIVATE; 197 } else if (action.equals(TAG_COMMAND_NAME_DEACTIVATE)) { 198 ssAction = SSAction.UPDATE_DEACTIVATE; 199 } 200 } 201 202 @Override toString()203 public String toString() { 204 return "SsEntry serviceCode:" + serviceCode 205 + ", ssAction:" + ssAction 206 + ", actionCode:" + actionCode 207 + ", commandParameter:" + commandParameter.toString() 208 + ", responseFormat:" + responseFormat.toString(); 209 } 210 211 /** 212 * To get the caller id command by xml's structure. 213 */ getCommandStructure()214 public String getCommandStructure() { 215 String result = actionCode + serviceCode; 216 int mapSize = commandParameter.size(); 217 int parameterIndex = 0; 218 while (parameterIndex < mapSize) { 219 parameterIndex++; 220 if (commandParameter.containsKey(parameterIndex)) { 221 if (commandParameter.get(parameterIndex) != null) { 222 result = result + STAR_SIGN + commandParameter.get(parameterIndex); 223 } 224 } 225 } 226 result = result + POUND_SIGN; 227 Log.d(LOG_TAG, "getCommandStructure result:" + result); 228 return result; 229 } 230 231 /** 232 * To make ussd command by xml's structure. 233 * 234 * @param inputInformationSet This is a map which includes parameters from UI. 235 * The name of map is mapping parameter's key of entry in xml. 236 */ makeCommand(Map<String, String> inputInformationSet)237 public String makeCommand(Map<String, String> inputInformationSet) { 238 String result = actionCode + serviceCode; 239 int mapSize = commandParameter.size(); 240 int parameterIndex = 0; 241 int counter = 1; 242 Map<String, String> informationSet = inputInformationSet; 243 while (parameterIndex < mapSize) { 244 if (commandParameter.containsKey(counter)) { 245 String getInputValue = ""; 246 // need to handle tag_XXXX 247 if (informationSet != null && informationSet.size() > 0 248 && informationSet.containsKey(commandParameter.get(counter))) { 249 getInputValue = informationSet.get(commandParameter.get(counter)); 250 } 251 if (TextUtils.isEmpty(getInputValue)) { 252 result = result + STAR_SIGN + commandParameter.get(counter); 253 } else { 254 result = result + STAR_SIGN + informationSet.get( 255 commandParameter.get(counter)); 256 } 257 parameterIndex++; 258 } else { 259 result = result + STAR_SIGN; 260 } 261 counter++; 262 } 263 result = result + POUND_SIGN; 264 return result; 265 } 266 267 /** 268 * To parse the specific key and value from response message. 269 * 270 * @param inputResponse This is a ussd response message from network. 271 * @param responseDefine This is the definition for "command_result" in xml. 272 */ getResponseSet(String inputResponse, HashMap<String, ArrayList<SsResultEntry>> responseDefine)273 public HashMap<String, String> getResponseSet(String inputResponse, 274 HashMap<String, ArrayList<SsResultEntry>> responseDefine) { 275 HashMap<String, String> responseSet = new HashMap<String, String>(); 276 if (TextUtils.isEmpty(sParserFormat)) { 277 return responseSet; 278 } 279 UssdParser parserResult = new UssdParser(sParserFormat); 280 parserResult.newFromResponseString(inputResponse); 281 if (parserResult == null) { 282 return responseSet; 283 } 284 285 Vector<String> result = parserResult.getResult(); 286 287 if (result == null) { 288 return responseSet; 289 } 290 for (int i = 0; i < result.size(); i++) { 291 if (responseFormat.containsKey(i)) { 292 String defineString = ""; 293 if (responseDefine.containsKey(responseFormat.get(i))) { 294 for (int x = 0; x < responseDefine.get(responseFormat.get(i)).size(); x++) { 295 defineString = ((SsResultEntry) responseDefine.get( 296 responseFormat.get(i)).get(x)).getDefinitionByCompareValue( 297 result.get(i)); 298 if (!TextUtils.isEmpty(defineString)) { 299 break; 300 } 301 } 302 // if status_code do not match definition value, we will set command error. 303 if (TAG_RESPONSE_STATUS.equals(responseFormat.get(i))) { 304 if (TextUtils.isEmpty(defineString)) { 305 responseSet.put(TAG_RESPONSE_STATUS_ERROR, 306 TAG_RESPONSE_STATUS_ERROR); 307 } 308 } 309 } 310 if (TextUtils.isEmpty(defineString)) { 311 responseSet.put(responseFormat.get(i), result.get(i)); 312 } else { 313 responseSet.put(responseFormat.get(i), defineString); 314 } 315 } 316 } 317 return responseSet; 318 } 319 } 320 321 /** 322 * CarrierXmlParser parses command_result from xml and saves in SsResultEntry class. 323 */ 324 public static class SsResultEntry { 325 String mDefinition; 326 String mCompareValue; 327 SsResultEntry()328 public SsResultEntry() { 329 } 330 331 @Override toString()332 public String toString() { 333 return "SsResultEntry mDefinition:" + mDefinition 334 + ", mCompareValue:" + mCompareValue; 335 } 336 337 /** 338 * If mCompareValue item is the same as compare value,it will return the mDefinition. 339 * 340 * @param inputValue This is the entry of response command's value. 341 * @return mDefinition or null. 342 */ getDefinitionByCompareValue(String inputValue)343 public String getDefinitionByCompareValue(String inputValue) { 344 if (mCompareValue.equals(inputValue)) { 345 return mDefinition; 346 } 347 return null; 348 } 349 } 350 351 /** 352 * CarrierXmlParser parses feature from xml and saves in SsFeature class. 353 */ 354 public class SsFeature { 355 public HashMap<SsEntry.SSAction, SsEntry> ssEntryHashMap = 356 new HashMap<SsEntry.SSAction, SsEntry>(); 357 public HashMap<String, ArrayList<SsResultEntry>> responseCode = 358 new HashMap<String, ArrayList<SsResultEntry>>(); 359 SsFeature()360 public SsFeature() { 361 } 362 getResponseCodeString()363 private String getResponseCodeString() { 364 String result = ""; 365 for (Map.Entry<String, ArrayList<SsResultEntry>> entry : responseCode.entrySet()) { 366 ArrayList<SsResultEntry> values = entry.getValue(); 367 for (int i = 0; i < values.size(); i++) { 368 result += "value of i is " + ((SsResultEntry) values.get(i)).toString(); 369 } 370 } 371 return result; 372 } 373 374 @Override toString()375 public String toString() { 376 return getResponseCodeString(); 377 } 378 379 /** 380 * To get the caller id command by xml's structure. 381 * 382 * @param inputAction This is action_code of command item from xml. 383 */ getCommandStructure(SsEntry.SSAction inputAction)384 public String getCommandStructure(SsEntry.SSAction inputAction) { 385 SsEntry entry = ssEntryHashMap.get(inputAction); 386 return entry.getCommandStructure(); 387 } 388 389 /** 390 * To make the ussd command by xml structure 391 * 392 * @param inputAction This is action_code of command item from xml. 393 * @param inputInformationSet This is for parameter of command. 394 * @return The ussd command string. 395 */ makeCommand(SsEntry.SSAction inputAction, Map<String, String> inputInformationSet)396 public String makeCommand(SsEntry.SSAction inputAction, 397 Map<String, String> inputInformationSet) { 398 SsEntry entry = ssEntryHashMap.get(inputAction); 399 return entry.makeCommand(inputInformationSet); 400 } 401 402 /** 403 * To parse the special key and value from response message. 404 * 405 * @param inputAction This is action_code of command item from xml. 406 * @param inputResponse This is response message from network. 407 * @return The set includes specific key and value. 408 */ getResponseSet(SsEntry.SSAction inputAction, String inputResponse)409 public HashMap<String, String> getResponseSet(SsEntry.SSAction inputAction, 410 String inputResponse) { 411 SsEntry entry = ssEntryHashMap.get(inputAction); 412 return entry.getResponseSet(inputResponse, responseCode); 413 } 414 } 415 416 /** 417 * @param context context to get res's xml 418 * @param carrierId carrier id of the current subscription. The carrier ID is an Android 419 * platform-wide identifier for a carrier. AOSP maintains carrier ID assignments in 420 * <a href="https://android.googlesource.com/platform/packages/providers/TelephonyProvider/+/master/assets/carrier_list.textpb">here</a> 421 */ CarrierXmlParser(Context context, int carrierId)422 public CarrierXmlParser(Context context, int carrierId) { 423 try { 424 int xmlResId = 0; 425 if (carrierId != TelephonyManager.UNKNOWN_CARRIER_ID) { 426 String xmlResIdName = "carrier_ss_string" + "_" + carrierId; 427 xmlResId = context.getResources().getIdentifier(xmlResIdName, "xml", 428 context.getPackageName()); 429 } 430 if (xmlResId == 0) { 431 xmlResId = R.xml.carrier_ss_string; 432 } 433 Log.d(LOG_TAG, "carrierId: " + carrierId); 434 435 XmlResourceParser parser = context.getResources().getXml(xmlResId); 436 mFeatureMaps = parseXml(parser); 437 } catch (Exception e) { 438 Log.d(LOG_TAG, "Error parsing XML " + e.toString()); 439 } 440 } 441 parseXml(XmlResourceParser parser)442 private HashMap<String, SsFeature> parseXml(XmlResourceParser parser) throws IOException { 443 HashMap<String, SsFeature> features = new HashMap<String, SsFeature>(); 444 try { 445 int eventType = parser.getEventType(); 446 while (eventType != XmlPullParser.END_DOCUMENT) { 447 if (eventType == XmlPullParser.START_TAG) { 448 if (TAG_REGULAR_PARSER.equals(parser.getName())) { 449 sParserFormat = readText(parser); 450 Log.d(LOG_TAG, "sParserFormat " + sParserFormat); 451 } else if (TAG_FEATURE.equals(parser.getName())) { 452 String featureName = getSpecificAttributeValue(parser, ATTR_NAME); 453 if (!TextUtils.isEmpty(featureName)) { 454 SsFeature feature = generateFeatureList(parser); 455 features.put(featureName, feature); 456 Log.d(LOG_TAG, "add " + featureName + " to map:" + feature.toString()); 457 } 458 } 459 } 460 parser.next(); 461 eventType = parser.getEventType(); 462 } 463 } catch (XmlPullParserException e) { 464 e.printStackTrace(); 465 } 466 return features; 467 } 468 generateFeatureList(XmlResourceParser parser)469 private SsFeature generateFeatureList(XmlResourceParser parser) 470 throws XmlPullParserException, IOException { 471 SsFeature ssfeature = new SsFeature(); 472 int outerDepth = parser.getDepth(); 473 474 Log.d(LOG_TAG, "generateFeatureList outerDepth" + outerDepth); 475 476 while (parser.next() != XmlPullParser.END_DOCUMENT) { 477 Log.d(LOG_TAG, "generateFeatureList parser.getDepth()" + parser.getDepth()); 478 479 int eventType = parser.getEventType(); 480 if (eventType == XmlPullParser.END_TAG 481 && outerDepth == parser.getDepth()) { 482 break; 483 } 484 485 if (eventType != XmlPullParser.START_TAG) { 486 continue; 487 } 488 String name = parser.getName(); 489 // Starts by looking for the command tag. 490 if (TAG_COMMAND.equals(name)) { 491 SsEntry entry = readCommandEntry(parser); 492 ssfeature.ssEntryHashMap.put(entry.ssAction, entry); 493 } else if (TAG_COMMAND_RESULT.equals(name)) { 494 readCommandResultEntry(parser, ssfeature); 495 } 496 } 497 return ssfeature; 498 } 499 readCommandResultEntry(XmlResourceParser parser, SsFeature ssFeature)500 private void readCommandResultEntry(XmlResourceParser parser, SsFeature ssFeature) 501 throws XmlPullParserException, IOException { 502 while (parser.next() != XmlPullParser.END_DOCUMENT) { 503 int eventType = parser.getEventType(); 504 if (eventType == XmlPullParser.END_TAG 505 && TAG_COMMAND_RESULT.equals(parser.getName())) { 506 break; 507 } 508 if (eventType == XmlPullParser.START_TAG 509 && TAG_ENTRY.equals(parser.getName())) { 510 String key = getSpecificAttributeValue(parser, ATTR_RESULT_KEY); 511 if (!TextUtils.isEmpty(key)) { 512 SsResultEntry entry = new SsResultEntry(); 513 entry.mDefinition = getSpecificAttributeValue(parser, ATTR_DEFINITION_KEY); 514 entry.mCompareValue = readText(parser); 515 if (ssFeature.responseCode.containsKey(key)) { 516 ssFeature.responseCode.get(key).add(entry); 517 } else { 518 ArrayList<SsResultEntry> arrayList = new ArrayList<>(); 519 arrayList.add(entry); 520 ssFeature.responseCode.put(key, arrayList); 521 } 522 } 523 } 524 } 525 } 526 readCommandEntry(XmlResourceParser parser)527 private SsEntry readCommandEntry(XmlResourceParser parser) 528 throws XmlPullParserException, IOException { 529 int outerDepth = parser.getDepth(); 530 String command_action = getSpecificAttributeValue(parser, ATTR_NAME); 531 SsEntry entry = new SsEntry(command_action); 532 533 while (parser.next() != XmlPullParser.END_DOCUMENT) { 534 int eventType = parser.getEventType(); 535 if (eventType == XmlPullParser.END_TAG 536 && outerDepth == parser.getDepth()) { 537 break; 538 } 539 540 if (eventType != XmlPullParser.START_TAG) { 541 continue; 542 } 543 544 String name = parser.getName(); 545 if (TAG_SERVICE_CODE.equals(name)) { 546 entry.serviceCode = readText(parser); 547 } else if (TAG_ACTION_CODE.equals(name)) { 548 entry.actionCode = readText(parser); 549 } else if (TAG_PARAMETER.equals(name)) { 550 String number = getSpecificAttributeValue(parser, ATTR_PARAMETER_NUM); 551 if (!TextUtils.isEmpty(number)) { 552 readParameters(parser, entry, Integer.valueOf(number), TAG_PARAMETER); 553 } 554 } else if (TAG_RESPONSE_FORMAT.equals(name)) { 555 String number = getSpecificAttributeValue(parser, ATTR_PARAMETER_NUM); 556 if (!TextUtils.isEmpty(number)) { 557 readParameters(parser, entry, Integer.valueOf(number), TAG_RESPONSE_FORMAT); 558 } 559 } 560 } 561 Log.d(LOG_TAG, "ssEntry:" + entry.toString()); 562 return entry; 563 } 564 readParameters(XmlResourceParser parser, SsEntry entry, int num, String parentTag)565 private void readParameters(XmlResourceParser parser, SsEntry entry, int num, String parentTag) 566 throws IOException, XmlPullParserException { 567 Log.d(LOG_TAG, "readParameters() nume:" + num); 568 int i = 0; 569 while (i < num) { 570 if (parser.next() == XmlPullParser.START_TAG) { 571 String name = parser.getName(); 572 if (TAG_ENTRY.equals(name)) { 573 String position = getSpecificAttributeValue(parser, ATTR_POSITION); 574 if (!TextUtils.isEmpty(position)) { 575 if (TAG_PARAMETER.equals(parentTag)) { 576 String value = readText(parser); 577 if (!TextUtils.isEmpty(value)) { 578 entry.commandParameter.put(Integer.valueOf(position), value); 579 } 580 } else if (TAG_RESPONSE_FORMAT.equals(parentTag)) { 581 String key = getSpecificAttributeValue(parser, ATTR_RESULT_KEY); 582 if (!TextUtils.isEmpty(key)) { 583 entry.responseFormat.put(Integer.valueOf(position), key); 584 } 585 } 586 i++; 587 } 588 } 589 } 590 } 591 } 592 getSpecificAttributeValue(XmlResourceParser parser, String attrTag)593 private String getSpecificAttributeValue(XmlResourceParser parser, String attrTag) { 594 String value = ""; 595 for (int i = 0; i < parser.getAttributeCount(); i++) { 596 if (attrTag.equals(parser.getAttributeName(i))) { 597 value = parser.getAttributeValue(i); 598 } 599 } 600 return value; 601 } 602 readText(XmlResourceParser parser)603 private String readText(XmlResourceParser parser) throws IOException, XmlPullParserException { 604 String result = ""; 605 if (parser.next() == XmlPullParser.TEXT) { 606 result = parser.getText(); 607 parser.nextTag(); 608 } 609 return result; 610 } 611 612 /** 613 * CarrierXmlParser parses the xml and saves in mFeatureMap. 614 * To use this function get feature from the mFeatureMaps. 615 * 616 * @param inputFeatureName This is feature's name from xml. 617 */ getFeature(String inputFeatureName)618 public SsFeature getFeature(String inputFeatureName) { 619 return mFeatureMaps.get(inputFeatureName); 620 } 621 622 /** 623 * To check the command which is dialed by user is caller id command. 624 * <p> 625 * If it is a caller id command which sets to activate, return the {@code 626 * SsEntry.SSAction.UPDATE_ACTIVATE}. 627 * If it is a caller id command which sets to deactivate, return the {@code 628 * SsEntry.SSAction.UPDATE_DEACTIVATE}. 629 * If it is not a caller id command, return the {@code SsEntry.SSAction.UNKNOWN}. 630 * 631 * @param inputCommand This is caller id's ussd command which is dialed by user. 632 * @return {@link SsEntry.SSAction} 633 */ getCallerIdUssdCommandAction(String inputCommand)634 public SsEntry.SSAction getCallerIdUssdCommandAction(String inputCommand) { 635 if (isCallerIdActivate(inputCommand)) { 636 return SsEntry.SSAction.UPDATE_ACTIVATE; 637 } 638 if (isCallerIdDeactivate(inputCommand)) { 639 return SsEntry.SSAction.UPDATE_DEACTIVATE; 640 } 641 return SsEntry.SSAction.UNKNOWN; 642 } 643 getCallerIdActivateCommandFromXml()644 private String getCallerIdActivateCommandFromXml() { 645 return getFeature(FEATURE_CALLER_ID).getCommandStructure(SsEntry.SSAction.UPDATE_ACTIVATE); 646 } 647 getCallerIdDeactivateCommandFromXml()648 private String getCallerIdDeactivateCommandFromXml() { 649 return getFeature(FEATURE_CALLER_ID).getCommandStructure( 650 SsEntry.SSAction.UPDATE_DEACTIVATE); 651 } 652 isCallerIdActivate(String inputStr)653 private boolean isCallerIdActivate(String inputStr) { 654 String activateStr = getCallerIdActivateCommandFromXml(); 655 return compareCommand(activateStr, inputStr); 656 } 657 isCallerIdDeactivate(String inputStr)658 private boolean isCallerIdDeactivate(String inputStr) { 659 String activateStr = getCallerIdDeactivateCommandFromXml(); 660 return compareCommand(activateStr, inputStr); 661 } 662 compareCommand(String activateStr, String inputStr)663 private boolean compareCommand(String activateStr, String inputStr) { 664 String[] activateArray = activateStr.split("\\" + STAR_SIGN); 665 String[] inputArray = inputStr.split("\\" + STAR_SIGN); 666 667 if (activateArray.length == 0 || inputArray.length == 0) { 668 return false; 669 } 670 for (int i = 0; i < activateArray.length; i++) { 671 if (activateArray[i].startsWith(TAG_SIGN)) { 672 continue; 673 } 674 if (!activateArray[i].equals(inputArray[i])) { 675 Log.d(LOG_TAG, "compare fails:" + activateStr + "," + inputStr); 676 return false; 677 } 678 } 679 Log.d(LOG_TAG, "compare success"); 680 return true; 681 } 682 } 683