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