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