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