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