1 /* 2 * Copyright (C) 2007 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.cat; 18 19 import android.graphics.Bitmap; 20 import android.os.Handler; 21 import android.os.Message; 22 23 import com.android.internal.telephony.GsmAlphabet; 24 import com.android.internal.telephony.IccFileHandler; 25 26 import java.util.Iterator; 27 import java.util.List; 28 29 /** 30 * Factory class, used for decoding raw byte arrays, received from baseband, 31 * into a CommandParams object. 32 * 33 */ 34 class CommandParamsFactory extends Handler { 35 private static CommandParamsFactory sInstance = null; 36 private IconLoader mIconLoader; 37 private CommandParams mCmdParams = null; 38 private int mIconLoadState = LOAD_NO_ICON; 39 private RilMessageDecoder mCaller = null; 40 41 // constants 42 static final int MSG_ID_LOAD_ICON_DONE = 1; 43 44 // loading icons state parameters. 45 static final int LOAD_NO_ICON = 0; 46 static final int LOAD_SINGLE_ICON = 1; 47 static final int LOAD_MULTI_ICONS = 2; 48 49 // Command Qualifier values for refresh command 50 static final int REFRESH_NAA_INIT_AND_FULL_FILE_CHANGE = 0x00; 51 static final int REFRESH_NAA_INIT_AND_FILE_CHANGE = 0x02; 52 static final int REFRESH_NAA_INIT = 0x03; 53 static final int REFRESH_UICC_RESET = 0x04; 54 55 // Command Qualifier values for PLI command 56 static final int DTTZ_SETTING = 0x03; 57 static final int LANGUAGE_SETTING = 0x04; 58 59 static synchronized CommandParamsFactory getInstance(RilMessageDecoder caller, 60 IccFileHandler fh) { 61 if (sInstance != null) { 62 return sInstance; 63 } 64 if (fh != null) { 65 return new CommandParamsFactory(caller, fh); 66 } 67 return null; 68 } 69 70 private CommandParamsFactory(RilMessageDecoder caller, IccFileHandler fh) { 71 mCaller = caller; 72 mIconLoader = IconLoader.getInstance(this, fh); 73 } 74 75 private CommandDetails processCommandDetails(List<ComprehensionTlv> ctlvs) { 76 CommandDetails cmdDet = null; 77 78 if (ctlvs != null) { 79 // Search for the Command Details object. 80 ComprehensionTlv ctlvCmdDet = searchForTag( 81 ComprehensionTlvTag.COMMAND_DETAILS, ctlvs); 82 if (ctlvCmdDet != null) { 83 try { 84 cmdDet = ValueParser.retrieveCommandDetails(ctlvCmdDet); 85 } catch (ResultException e) { 86 CatLog.d(this, 87 "processCommandDetails: Failed to procees command details e=" + e); 88 } 89 } 90 } 91 return cmdDet; 92 } 93 94 void make(BerTlv berTlv) { 95 if (berTlv == null) { 96 return; 97 } 98 // reset global state parameters. 99 mCmdParams = null; 100 mIconLoadState = LOAD_NO_ICON; 101 // only proactive command messages are processed. 102 if (berTlv.getTag() != BerTlv.BER_PROACTIVE_COMMAND_TAG) { 103 sendCmdParams(ResultCode.CMD_TYPE_NOT_UNDERSTOOD); 104 return; 105 } 106 boolean cmdPending = false; 107 List<ComprehensionTlv> ctlvs = berTlv.getComprehensionTlvs(); 108 // process command dtails from the tlv list. 109 CommandDetails cmdDet = processCommandDetails(ctlvs); 110 if (cmdDet == null) { 111 sendCmdParams(ResultCode.CMD_TYPE_NOT_UNDERSTOOD); 112 return; 113 } 114 115 // extract command type enumeration from the raw value stored inside 116 // the Command Details object. 117 AppInterface.CommandType cmdType = AppInterface.CommandType 118 .fromInt(cmdDet.typeOfCommand); 119 if (cmdType == null) { 120 // This PROACTIVE COMMAND is presently not handled. Hence set 121 // result code as BEYOND_TERMINAL_CAPABILITY in TR. 122 mCmdParams = new CommandParams(cmdDet); 123 sendCmdParams(ResultCode.BEYOND_TERMINAL_CAPABILITY); 124 return; 125 } 126 127 try { 128 switch (cmdType) { 129 case SET_UP_MENU: 130 cmdPending = processSelectItem(cmdDet, ctlvs); 131 break; 132 case SELECT_ITEM: 133 cmdPending = processSelectItem(cmdDet, ctlvs); 134 break; 135 case DISPLAY_TEXT: 136 cmdPending = processDisplayText(cmdDet, ctlvs); 137 break; 138 case SET_UP_IDLE_MODE_TEXT: 139 cmdPending = processSetUpIdleModeText(cmdDet, ctlvs); 140 break; 141 case GET_INKEY: 142 cmdPending = processGetInkey(cmdDet, ctlvs); 143 break; 144 case GET_INPUT: 145 cmdPending = processGetInput(cmdDet, ctlvs); 146 break; 147 case SEND_DTMF: 148 case SEND_SMS: 149 case SEND_SS: 150 case SEND_USSD: 151 cmdPending = processEventNotify(cmdDet, ctlvs); 152 break; 153 case SET_UP_CALL: 154 cmdPending = processSetupCall(cmdDet, ctlvs); 155 break; 156 case REFRESH: 157 processRefresh(cmdDet, ctlvs); 158 cmdPending = false; 159 break; 160 case LAUNCH_BROWSER: 161 cmdPending = processLaunchBrowser(cmdDet, ctlvs); 162 break; 163 case PLAY_TONE: 164 cmdPending = processPlayTone(cmdDet, ctlvs); 165 break; 166 case PROVIDE_LOCAL_INFORMATION: 167 cmdPending = processProvideLocalInfo(cmdDet, ctlvs); 168 break; 169 case OPEN_CHANNEL: 170 case CLOSE_CHANNEL: 171 case RECEIVE_DATA: 172 case SEND_DATA: 173 cmdPending = processBIPClient(cmdDet, ctlvs); 174 break; 175 default: 176 // unsupported proactive commands 177 mCmdParams = new CommandParams(cmdDet); 178 sendCmdParams(ResultCode.BEYOND_TERMINAL_CAPABILITY); 179 return; 180 } 181 } catch (ResultException e) { 182 CatLog.d(this, "make: caught ResultException e=" + e); 183 mCmdParams = new CommandParams(cmdDet); 184 sendCmdParams(e.result()); 185 return; 186 } 187 if (!cmdPending) { 188 sendCmdParams(ResultCode.OK); 189 } 190 } 191 192 @Override 193 public void handleMessage(Message msg) { 194 switch (msg.what) { 195 case MSG_ID_LOAD_ICON_DONE: 196 sendCmdParams(setIcons(msg.obj)); 197 break; 198 } 199 } 200 201 private ResultCode setIcons(Object data) { 202 Bitmap[] icons = null; 203 int iconIndex = 0; 204 205 if (data == null) { 206 return ResultCode.PRFRMD_ICON_NOT_DISPLAYED; 207 } 208 switch(mIconLoadState) { 209 case LOAD_SINGLE_ICON: 210 mCmdParams.setIcon((Bitmap) data); 211 break; 212 case LOAD_MULTI_ICONS: 213 icons = (Bitmap[]) data; 214 // set each item icon. 215 for (Bitmap icon : icons) { 216 mCmdParams.setIcon(icon); 217 } 218 break; 219 } 220 return ResultCode.OK; 221 } 222 223 private void sendCmdParams(ResultCode resCode) { 224 mCaller.sendMsgParamsDecoded(resCode, mCmdParams); 225 } 226 227 /** 228 * Search for a COMPREHENSION-TLV object with the given tag from a list 229 * 230 * @param tag A tag to search for 231 * @param ctlvs List of ComprehensionTlv objects used to search in 232 * 233 * @return A ComprehensionTlv object that has the tag value of {@code tag}. 234 * If no object is found with the tag, null is returned. 235 */ 236 private ComprehensionTlv searchForTag(ComprehensionTlvTag tag, 237 List<ComprehensionTlv> ctlvs) { 238 Iterator<ComprehensionTlv> iter = ctlvs.iterator(); 239 return searchForNextTag(tag, iter); 240 } 241 242 /** 243 * Search for the next COMPREHENSION-TLV object with the given tag from a 244 * list iterated by {@code iter}. {@code iter} points to the object next to 245 * the found object when this method returns. Used for searching the same 246 * list for similar tags, usually item id. 247 * 248 * @param tag A tag to search for 249 * @param iter Iterator for ComprehensionTlv objects used for search 250 * 251 * @return A ComprehensionTlv object that has the tag value of {@code tag}. 252 * If no object is found with the tag, null is returned. 253 */ 254 private ComprehensionTlv searchForNextTag(ComprehensionTlvTag tag, 255 Iterator<ComprehensionTlv> iter) { 256 int tagValue = tag.value(); 257 while (iter.hasNext()) { 258 ComprehensionTlv ctlv = iter.next(); 259 if (ctlv.getTag() == tagValue) { 260 return ctlv; 261 } 262 } 263 return null; 264 } 265 266 /** 267 * Processes DISPLAY_TEXT proactive command from the SIM card. 268 * 269 * @param cmdDet Command Details container object. 270 * @param ctlvs List of ComprehensionTlv objects following Command Details 271 * object and Device Identities object within the proactive command 272 * @return true if the command is processing is pending and additional 273 * asynchronous processing is required. 274 * @throws ResultException 275 */ 276 private boolean processDisplayText(CommandDetails cmdDet, 277 List<ComprehensionTlv> ctlvs) 278 throws ResultException { 279 280 CatLog.d(this, "process DisplayText"); 281 282 TextMessage textMsg = new TextMessage(); 283 IconId iconId = null; 284 285 ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.TEXT_STRING, 286 ctlvs); 287 if (ctlv != null) { 288 textMsg.text = ValueParser.retrieveTextString(ctlv); 289 } 290 // If the tlv object doesn't exist or the it is a null object reply 291 // with command not understood. 292 if (textMsg.text == null) { 293 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); 294 } 295 296 ctlv = searchForTag(ComprehensionTlvTag.IMMEDIATE_RESPONSE, ctlvs); 297 if (ctlv != null) { 298 textMsg.responseNeeded = false; 299 } 300 // parse icon identifier 301 ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs); 302 if (ctlv != null) { 303 iconId = ValueParser.retrieveIconId(ctlv); 304 textMsg.iconSelfExplanatory = iconId.selfExplanatory; 305 } 306 // parse tone duration 307 ctlv = searchForTag(ComprehensionTlvTag.DURATION, ctlvs); 308 if (ctlv != null) { 309 textMsg.duration = ValueParser.retrieveDuration(ctlv); 310 } 311 312 // Parse command qualifier parameters. 313 textMsg.isHighPriority = (cmdDet.commandQualifier & 0x01) != 0; 314 textMsg.userClear = (cmdDet.commandQualifier & 0x80) != 0; 315 316 mCmdParams = new DisplayTextParams(cmdDet, textMsg); 317 318 if (iconId != null) { 319 mIconLoadState = LOAD_SINGLE_ICON; 320 mIconLoader.loadIcon(iconId.recordNumber, this 321 .obtainMessage(MSG_ID_LOAD_ICON_DONE)); 322 return true; 323 } 324 return false; 325 } 326 327 /** 328 * Processes SET_UP_IDLE_MODE_TEXT proactive command from the SIM card. 329 * 330 * @param cmdDet Command Details container object. 331 * @param ctlvs List of ComprehensionTlv objects following Command Details 332 * object and Device Identities object within the proactive command 333 * @return true if the command is processing is pending and additional 334 * asynchronous processing is required. 335 * @throws ResultException 336 */ 337 private boolean processSetUpIdleModeText(CommandDetails cmdDet, 338 List<ComprehensionTlv> ctlvs) throws ResultException { 339 340 CatLog.d(this, "process SetUpIdleModeText"); 341 342 TextMessage textMsg = new TextMessage(); 343 IconId iconId = null; 344 345 ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.TEXT_STRING, 346 ctlvs); 347 if (ctlv != null) { 348 textMsg.text = ValueParser.retrieveTextString(ctlv); 349 } 350 // load icons only when text exist. 351 if (textMsg.text != null) { 352 ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs); 353 if (ctlv != null) { 354 iconId = ValueParser.retrieveIconId(ctlv); 355 textMsg.iconSelfExplanatory = iconId.selfExplanatory; 356 } 357 } 358 359 mCmdParams = new DisplayTextParams(cmdDet, textMsg); 360 361 if (iconId != null) { 362 mIconLoadState = LOAD_SINGLE_ICON; 363 mIconLoader.loadIcon(iconId.recordNumber, this 364 .obtainMessage(MSG_ID_LOAD_ICON_DONE)); 365 return true; 366 } 367 return false; 368 } 369 370 /** 371 * Processes GET_INKEY proactive command from the SIM card. 372 * 373 * @param cmdDet Command Details container object. 374 * @param ctlvs List of ComprehensionTlv objects following Command Details 375 * object and Device Identities object within the proactive command 376 * @return true if the command is processing is pending and additional 377 * asynchronous processing is required. 378 * @throws ResultException 379 */ 380 private boolean processGetInkey(CommandDetails cmdDet, 381 List<ComprehensionTlv> ctlvs) throws ResultException { 382 383 CatLog.d(this, "process GetInkey"); 384 385 Input input = new Input(); 386 IconId iconId = null; 387 388 ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.TEXT_STRING, 389 ctlvs); 390 if (ctlv != null) { 391 input.text = ValueParser.retrieveTextString(ctlv); 392 } else { 393 throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING); 394 } 395 // parse icon identifier 396 ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs); 397 if (ctlv != null) { 398 iconId = ValueParser.retrieveIconId(ctlv); 399 } 400 401 // parse duration 402 ctlv = searchForTag(ComprehensionTlvTag.DURATION, ctlvs); 403 if (ctlv != null) { 404 input.duration = ValueParser.retrieveDuration(ctlv); 405 } 406 407 input.minLen = 1; 408 input.maxLen = 1; 409 410 input.digitOnly = (cmdDet.commandQualifier & 0x01) == 0; 411 input.ucs2 = (cmdDet.commandQualifier & 0x02) != 0; 412 input.yesNo = (cmdDet.commandQualifier & 0x04) != 0; 413 input.helpAvailable = (cmdDet.commandQualifier & 0x80) != 0; 414 input.echo = true; 415 416 mCmdParams = new GetInputParams(cmdDet, input); 417 418 if (iconId != null) { 419 mIconLoadState = LOAD_SINGLE_ICON; 420 mIconLoader.loadIcon(iconId.recordNumber, this 421 .obtainMessage(MSG_ID_LOAD_ICON_DONE)); 422 return true; 423 } 424 return false; 425 } 426 427 /** 428 * Processes GET_INPUT proactive command from the SIM card. 429 * 430 * @param cmdDet Command Details container object. 431 * @param ctlvs List of ComprehensionTlv objects following Command Details 432 * object and Device Identities object within the proactive command 433 * @return true if the command is processing is pending and additional 434 * asynchronous processing is required. 435 * @throws ResultException 436 */ 437 private boolean processGetInput(CommandDetails cmdDet, 438 List<ComprehensionTlv> ctlvs) throws ResultException { 439 440 CatLog.d(this, "process GetInput"); 441 442 Input input = new Input(); 443 IconId iconId = null; 444 445 ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.TEXT_STRING, 446 ctlvs); 447 if (ctlv != null) { 448 input.text = ValueParser.retrieveTextString(ctlv); 449 } else { 450 throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING); 451 } 452 453 ctlv = searchForTag(ComprehensionTlvTag.RESPONSE_LENGTH, ctlvs); 454 if (ctlv != null) { 455 try { 456 byte[] rawValue = ctlv.getRawValue(); 457 int valueIndex = ctlv.getValueIndex(); 458 input.minLen = rawValue[valueIndex] & 0xff; 459 input.maxLen = rawValue[valueIndex + 1] & 0xff; 460 } catch (IndexOutOfBoundsException e) { 461 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); 462 } 463 } else { 464 throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING); 465 } 466 467 ctlv = searchForTag(ComprehensionTlvTag.DEFAULT_TEXT, ctlvs); 468 if (ctlv != null) { 469 input.defaultText = ValueParser.retrieveTextString(ctlv); 470 } 471 // parse icon identifier 472 ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs); 473 if (ctlv != null) { 474 iconId = ValueParser.retrieveIconId(ctlv); 475 } 476 477 input.digitOnly = (cmdDet.commandQualifier & 0x01) == 0; 478 input.ucs2 = (cmdDet.commandQualifier & 0x02) != 0; 479 input.echo = (cmdDet.commandQualifier & 0x04) == 0; 480 input.packed = (cmdDet.commandQualifier & 0x08) != 0; 481 input.helpAvailable = (cmdDet.commandQualifier & 0x80) != 0; 482 483 mCmdParams = new GetInputParams(cmdDet, input); 484 485 if (iconId != null) { 486 mIconLoadState = LOAD_SINGLE_ICON; 487 mIconLoader.loadIcon(iconId.recordNumber, this 488 .obtainMessage(MSG_ID_LOAD_ICON_DONE)); 489 return true; 490 } 491 return false; 492 } 493 494 /** 495 * Processes REFRESH proactive command from the SIM card. 496 * 497 * @param cmdDet Command Details container object. 498 * @param ctlvs List of ComprehensionTlv objects following Command Details 499 * object and Device Identities object within the proactive command 500 */ 501 private boolean processRefresh(CommandDetails cmdDet, 502 List<ComprehensionTlv> ctlvs) { 503 504 CatLog.d(this, "process Refresh"); 505 506 // REFRESH proactive command is rerouted by the baseband and handled by 507 // the telephony layer. IDLE TEXT should be removed for a REFRESH command 508 // with "initialization" or "reset" 509 switch (cmdDet.commandQualifier) { 510 case REFRESH_NAA_INIT_AND_FULL_FILE_CHANGE: 511 case REFRESH_NAA_INIT_AND_FILE_CHANGE: 512 case REFRESH_NAA_INIT: 513 case REFRESH_UICC_RESET: 514 mCmdParams = new DisplayTextParams(cmdDet, null); 515 break; 516 } 517 return false; 518 } 519 520 /** 521 * Processes SELECT_ITEM proactive command from the SIM card. 522 * 523 * @param cmdDet Command Details container object. 524 * @param ctlvs List of ComprehensionTlv objects following Command Details 525 * object and Device Identities object within the proactive command 526 * @return true if the command is processing is pending and additional 527 * asynchronous processing is required. 528 * @throws ResultException 529 */ 530 private boolean processSelectItem(CommandDetails cmdDet, 531 List<ComprehensionTlv> ctlvs) throws ResultException { 532 533 CatLog.d(this, "process SelectItem"); 534 535 Menu menu = new Menu(); 536 IconId titleIconId = null; 537 ItemsIconId itemsIconId = null; 538 Iterator<ComprehensionTlv> iter = ctlvs.iterator(); 539 540 ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID, 541 ctlvs); 542 if (ctlv != null) { 543 menu.title = ValueParser.retrieveAlphaId(ctlv); 544 } 545 546 while (true) { 547 ctlv = searchForNextTag(ComprehensionTlvTag.ITEM, iter); 548 if (ctlv != null) { 549 menu.items.add(ValueParser.retrieveItem(ctlv)); 550 } else { 551 break; 552 } 553 } 554 555 // We must have at least one menu item. 556 if (menu.items.size() == 0) { 557 throw new ResultException(ResultCode.REQUIRED_VALUES_MISSING); 558 } 559 560 ctlv = searchForTag(ComprehensionTlvTag.ITEM_ID, ctlvs); 561 if (ctlv != null) { 562 // CAT items are listed 1...n while list start at 0, need to 563 // subtract one. 564 menu.defaultItem = ValueParser.retrieveItemId(ctlv) - 1; 565 } 566 567 ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs); 568 if (ctlv != null) { 569 mIconLoadState = LOAD_SINGLE_ICON; 570 titleIconId = ValueParser.retrieveIconId(ctlv); 571 menu.titleIconSelfExplanatory = titleIconId.selfExplanatory; 572 } 573 574 ctlv = searchForTag(ComprehensionTlvTag.ITEM_ICON_ID_LIST, ctlvs); 575 if (ctlv != null) { 576 mIconLoadState = LOAD_MULTI_ICONS; 577 itemsIconId = ValueParser.retrieveItemsIconId(ctlv); 578 menu.itemsIconSelfExplanatory = itemsIconId.selfExplanatory; 579 } 580 581 boolean presentTypeSpecified = (cmdDet.commandQualifier & 0x01) != 0; 582 if (presentTypeSpecified) { 583 if ((cmdDet.commandQualifier & 0x02) == 0) { 584 menu.presentationType = PresentationType.DATA_VALUES; 585 } else { 586 menu.presentationType = PresentationType.NAVIGATION_OPTIONS; 587 } 588 } 589 menu.softKeyPreferred = (cmdDet.commandQualifier & 0x04) != 0; 590 menu.helpAvailable = (cmdDet.commandQualifier & 0x80) != 0; 591 592 mCmdParams = new SelectItemParams(cmdDet, menu, titleIconId != null); 593 594 // Load icons data if needed. 595 switch(mIconLoadState) { 596 case LOAD_NO_ICON: 597 return false; 598 case LOAD_SINGLE_ICON: 599 mIconLoader.loadIcon(titleIconId.recordNumber, this 600 .obtainMessage(MSG_ID_LOAD_ICON_DONE)); 601 break; 602 case LOAD_MULTI_ICONS: 603 int[] recordNumbers = itemsIconId.recordNumbers; 604 if (titleIconId != null) { 605 // Create a new array for all the icons (title and items). 606 recordNumbers = new int[itemsIconId.recordNumbers.length + 1]; 607 recordNumbers[0] = titleIconId.recordNumber; 608 System.arraycopy(itemsIconId.recordNumbers, 0, recordNumbers, 609 1, itemsIconId.recordNumbers.length); 610 } 611 mIconLoader.loadIcons(recordNumbers, this 612 .obtainMessage(MSG_ID_LOAD_ICON_DONE)); 613 break; 614 } 615 return true; 616 } 617 618 /** 619 * Processes EVENT_NOTIFY message from baseband. 620 * 621 * @param cmdDet Command Details container object. 622 * @param ctlvs List of ComprehensionTlv objects following Command Details 623 * object and Device Identities object within the proactive command 624 * @return true if the command is processing is pending and additional 625 * asynchronous processing is required. 626 */ 627 private boolean processEventNotify(CommandDetails cmdDet, 628 List<ComprehensionTlv> ctlvs) throws ResultException { 629 630 CatLog.d(this, "process EventNotify"); 631 632 TextMessage textMsg = new TextMessage(); 633 IconId iconId = null; 634 635 ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID, 636 ctlvs); 637 textMsg.text = ValueParser.retrieveAlphaId(ctlv); 638 639 ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs); 640 if (ctlv != null) { 641 iconId = ValueParser.retrieveIconId(ctlv); 642 textMsg.iconSelfExplanatory = iconId.selfExplanatory; 643 } 644 645 textMsg.responseNeeded = false; 646 mCmdParams = new DisplayTextParams(cmdDet, textMsg); 647 648 if (iconId != null) { 649 mIconLoadState = LOAD_SINGLE_ICON; 650 mIconLoader.loadIcon(iconId.recordNumber, this 651 .obtainMessage(MSG_ID_LOAD_ICON_DONE)); 652 return true; 653 } 654 return false; 655 } 656 657 /** 658 * Processes SET_UP_EVENT_LIST proactive command from the SIM card. 659 * 660 * @param cmdDet Command Details object retrieved. 661 * @param ctlvs List of ComprehensionTlv objects following Command Details 662 * object and Device Identities object within the proactive command 663 * @return true if the command is processing is pending and additional 664 * asynchronous processing is required. 665 */ 666 private boolean processSetUpEventList(CommandDetails cmdDet, 667 List<ComprehensionTlv> ctlvs) { 668 669 CatLog.d(this, "process SetUpEventList"); 670 // 671 // ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.EVENT_LIST, 672 // ctlvs); 673 // if (ctlv != null) { 674 // try { 675 // byte[] rawValue = ctlv.getRawValue(); 676 // int valueIndex = ctlv.getValueIndex(); 677 // int valueLen = ctlv.getLength(); 678 // 679 // } catch (IndexOutOfBoundsException e) {} 680 // } 681 return true; 682 } 683 684 /** 685 * Processes LAUNCH_BROWSER proactive command from the SIM card. 686 * 687 * @param cmdDet Command Details container object. 688 * @param ctlvs List of ComprehensionTlv objects following Command Details 689 * object and Device Identities object within the proactive command 690 * @return true if the command is processing is pending and additional 691 * asynchronous processing is required. 692 * @throws ResultException 693 */ 694 private boolean processLaunchBrowser(CommandDetails cmdDet, 695 List<ComprehensionTlv> ctlvs) throws ResultException { 696 697 CatLog.d(this, "process LaunchBrowser"); 698 699 TextMessage confirmMsg = new TextMessage(); 700 IconId iconId = null; 701 String url = null; 702 703 ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.URL, ctlvs); 704 if (ctlv != null) { 705 try { 706 byte[] rawValue = ctlv.getRawValue(); 707 int valueIndex = ctlv.getValueIndex(); 708 int valueLen = ctlv.getLength(); 709 if (valueLen > 0) { 710 url = GsmAlphabet.gsm8BitUnpackedToString(rawValue, 711 valueIndex, valueLen); 712 } else { 713 url = null; 714 } 715 } catch (IndexOutOfBoundsException e) { 716 throw new ResultException(ResultCode.CMD_DATA_NOT_UNDERSTOOD); 717 } 718 } 719 720 // parse alpha identifier. 721 ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID, ctlvs); 722 confirmMsg.text = ValueParser.retrieveAlphaId(ctlv); 723 724 // parse icon identifier 725 ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs); 726 if (ctlv != null) { 727 iconId = ValueParser.retrieveIconId(ctlv); 728 confirmMsg.iconSelfExplanatory = iconId.selfExplanatory; 729 } 730 731 // parse command qualifier value. 732 LaunchBrowserMode mode; 733 switch (cmdDet.commandQualifier) { 734 case 0x00: 735 default: 736 mode = LaunchBrowserMode.LAUNCH_IF_NOT_ALREADY_LAUNCHED; 737 break; 738 case 0x02: 739 mode = LaunchBrowserMode.USE_EXISTING_BROWSER; 740 break; 741 case 0x03: 742 mode = LaunchBrowserMode.LAUNCH_NEW_BROWSER; 743 break; 744 } 745 746 mCmdParams = new LaunchBrowserParams(cmdDet, confirmMsg, url, mode); 747 748 if (iconId != null) { 749 mIconLoadState = LOAD_SINGLE_ICON; 750 mIconLoader.loadIcon(iconId.recordNumber, this 751 .obtainMessage(MSG_ID_LOAD_ICON_DONE)); 752 return true; 753 } 754 return false; 755 } 756 757 /** 758 * Processes PLAY_TONE proactive command from the SIM card. 759 * 760 * @param cmdDet Command Details container object. 761 * @param ctlvs List of ComprehensionTlv objects following Command Details 762 * object and Device Identities object within the proactive command 763 * @return true if the command is processing is pending and additional 764 * asynchronous processing is required.t 765 * @throws ResultException 766 */ 767 private boolean processPlayTone(CommandDetails cmdDet, 768 List<ComprehensionTlv> ctlvs) throws ResultException { 769 770 CatLog.d(this, "process PlayTone"); 771 772 Tone tone = null; 773 TextMessage textMsg = new TextMessage(); 774 Duration duration = null; 775 IconId iconId = null; 776 777 ComprehensionTlv ctlv = searchForTag(ComprehensionTlvTag.TONE, ctlvs); 778 if (ctlv != null) { 779 // Nothing to do for null objects. 780 if (ctlv.getLength() > 0) { 781 try { 782 byte[] rawValue = ctlv.getRawValue(); 783 int valueIndex = ctlv.getValueIndex(); 784 int toneVal = rawValue[valueIndex]; 785 tone = Tone.fromInt(toneVal); 786 } catch (IndexOutOfBoundsException e) { 787 throw new ResultException( 788 ResultCode.CMD_DATA_NOT_UNDERSTOOD); 789 } 790 } 791 } 792 // parse alpha identifier 793 ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID, ctlvs); 794 if (ctlv != null) { 795 textMsg.text = ValueParser.retrieveAlphaId(ctlv); 796 } 797 // parse tone duration 798 ctlv = searchForTag(ComprehensionTlvTag.DURATION, ctlvs); 799 if (ctlv != null) { 800 duration = ValueParser.retrieveDuration(ctlv); 801 } 802 // parse icon identifier 803 ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs); 804 if (ctlv != null) { 805 iconId = ValueParser.retrieveIconId(ctlv); 806 textMsg.iconSelfExplanatory = iconId.selfExplanatory; 807 } 808 809 boolean vibrate = (cmdDet.commandQualifier & 0x01) != 0x00; 810 811 textMsg.responseNeeded = false; 812 mCmdParams = new PlayToneParams(cmdDet, textMsg, tone, duration, vibrate); 813 814 if (iconId != null) { 815 mIconLoadState = LOAD_SINGLE_ICON; 816 mIconLoader.loadIcon(iconId.recordNumber, this 817 .obtainMessage(MSG_ID_LOAD_ICON_DONE)); 818 return true; 819 } 820 return false; 821 } 822 823 /** 824 * Processes SETUP_CALL proactive command from the SIM card. 825 * 826 * @param cmdDet Command Details object retrieved from the proactive command 827 * object 828 * @param ctlvs List of ComprehensionTlv objects following Command Details 829 * object and Device Identities object within the proactive command 830 * @return true if the command is processing is pending and additional 831 * asynchronous processing is required. 832 */ 833 private boolean processSetupCall(CommandDetails cmdDet, 834 List<ComprehensionTlv> ctlvs) throws ResultException { 835 CatLog.d(this, "process SetupCall"); 836 837 Iterator<ComprehensionTlv> iter = ctlvs.iterator(); 838 ComprehensionTlv ctlv = null; 839 // User confirmation phase message. 840 TextMessage confirmMsg = new TextMessage(); 841 // Call set up phase message. 842 TextMessage callMsg = new TextMessage(); 843 IconId confirmIconId = null; 844 IconId callIconId = null; 845 846 // get confirmation message string. 847 ctlv = searchForNextTag(ComprehensionTlvTag.ALPHA_ID, iter); 848 confirmMsg.text = ValueParser.retrieveAlphaId(ctlv); 849 850 ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs); 851 if (ctlv != null) { 852 confirmIconId = ValueParser.retrieveIconId(ctlv); 853 confirmMsg.iconSelfExplanatory = confirmIconId.selfExplanatory; 854 } 855 856 // get call set up message string. 857 ctlv = searchForNextTag(ComprehensionTlvTag.ALPHA_ID, iter); 858 if (ctlv != null) { 859 callMsg.text = ValueParser.retrieveAlphaId(ctlv); 860 } 861 862 ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs); 863 if (ctlv != null) { 864 callIconId = ValueParser.retrieveIconId(ctlv); 865 callMsg.iconSelfExplanatory = callIconId.selfExplanatory; 866 } 867 868 mCmdParams = new CallSetupParams(cmdDet, confirmMsg, callMsg); 869 870 if (confirmIconId != null || callIconId != null) { 871 mIconLoadState = LOAD_MULTI_ICONS; 872 int[] recordNumbers = new int[2]; 873 recordNumbers[0] = confirmIconId != null 874 ? confirmIconId.recordNumber : -1; 875 recordNumbers[1] = callIconId != null ? callIconId.recordNumber 876 : -1; 877 878 mIconLoader.loadIcons(recordNumbers, this 879 .obtainMessage(MSG_ID_LOAD_ICON_DONE)); 880 return true; 881 } 882 return false; 883 } 884 885 private boolean processProvideLocalInfo(CommandDetails cmdDet, List<ComprehensionTlv> ctlvs) 886 throws ResultException { 887 CatLog.d(this, "process ProvideLocalInfo"); 888 switch (cmdDet.commandQualifier) { 889 case DTTZ_SETTING: 890 CatLog.d(this, "PLI [DTTZ_SETTING]"); 891 mCmdParams = new CommandParams(cmdDet); 892 break; 893 case LANGUAGE_SETTING: 894 CatLog.d(this, "PLI [LANGUAGE_SETTING]"); 895 mCmdParams = new CommandParams(cmdDet); 896 break; 897 default: 898 CatLog.d(this, "PLI[" + cmdDet.commandQualifier + "] Command Not Supported"); 899 mCmdParams = new CommandParams(cmdDet); 900 throw new ResultException(ResultCode.BEYOND_TERMINAL_CAPABILITY); 901 } 902 return false; 903 } 904 905 private boolean processBIPClient(CommandDetails cmdDet, 906 List<ComprehensionTlv> ctlvs) throws ResultException { 907 AppInterface.CommandType commandType = 908 AppInterface.CommandType.fromInt(cmdDet.typeOfCommand); 909 if (commandType != null) { 910 CatLog.d(this, "process "+ commandType.name()); 911 } 912 913 TextMessage textMsg = new TextMessage(); 914 IconId iconId = null; 915 ComprehensionTlv ctlv = null; 916 boolean has_alpha_id = false; 917 918 // parse alpha identifier 919 ctlv = searchForTag(ComprehensionTlvTag.ALPHA_ID, ctlvs); 920 if (ctlv != null) { 921 textMsg.text = ValueParser.retrieveAlphaId(ctlv); 922 CatLog.d(this, "alpha TLV text=" + textMsg.text); 923 has_alpha_id = true; 924 } 925 926 // parse icon identifier 927 ctlv = searchForTag(ComprehensionTlvTag.ICON_ID, ctlvs); 928 if (ctlv != null) { 929 iconId = ValueParser.retrieveIconId(ctlv); 930 textMsg.iconSelfExplanatory = iconId.selfExplanatory; 931 } 932 933 textMsg.responseNeeded = false; 934 mCmdParams = new BIPClientParams(cmdDet, textMsg, has_alpha_id); 935 936 if (iconId != null) { 937 mIconLoadState = LOAD_SINGLE_ICON; 938 mIconLoader.loadIcon(iconId.recordNumber, this.obtainMessage(MSG_ID_LOAD_ICON_DONE)); 939 return true; 940 } 941 return false; 942 } 943 } 944