1 /* 2 * Copyright (c) 2013 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.ims; 18 19 import java.util.HashMap; 20 import java.util.Map; 21 22 import android.os.AsyncResult; 23 import android.os.Bundle; 24 import android.os.Message; 25 import android.os.RemoteException; 26 import android.telephony.Rlog; 27 28 import com.android.ims.internal.IImsUt; 29 import com.android.ims.internal.IImsUtListener; 30 31 /** 32 * Provides APIs for the supplementary service settings using IMS (Ut interface). 33 * It is created from 3GPP TS 24.623 (XCAP(XML Configuration Access Protocol) 34 * over the Ut interface for manipulating supplementary services). 35 * 36 * @hide 37 */ 38 public class ImsUt implements ImsUtInterface { 39 /** 40 * Key string for an additional supplementary service configurations. 41 */ 42 /** 43 * Actions : string format of ImsUtInterface#ACTION_xxx 44 * "0" (deactivation), "1" (activation), "2" (not_used), 45 * "3" (registration), "4" (erasure), "5" (Interrogation) 46 */ 47 public static final String KEY_ACTION = "action"; 48 /** 49 * Categories : 50 * "OIP", "OIR", "TIP", "TIR", "CDIV", "CB", "CW", "CONF", 51 * "ACR", "MCID", "ECT", "CCBS", "AOC", "MWI", "FA", "CAT" 52 * 53 * Detailed parameter name will be determined according to the properties 54 * of the supplementary service configuration. 55 */ 56 public static final String KEY_CATEGORY = "category"; 57 public static final String CATEGORY_OIP = "OIP"; 58 public static final String CATEGORY_OIR = "OIR"; 59 public static final String CATEGORY_TIP = "TIP"; 60 public static final String CATEGORY_TIR = "TIR"; 61 public static final String CATEGORY_CDIV = "CDIV"; 62 public static final String CATEGORY_CB = "CB"; 63 public static final String CATEGORY_CW = "CW"; 64 public static final String CATEGORY_CONF = "CONF"; 65 66 private static final String TAG = "ImsUt"; 67 private static final boolean DBG = true; 68 69 // For synchronization of private variables 70 private Object mLockObj = new Object(); 71 private final IImsUt miUt; 72 private HashMap<Integer, Message> mPendingCmds = 73 new HashMap<Integer, Message>(); 74 75 public ImsUt(IImsUt iUt) { 76 miUt = iUt; 77 78 if (miUt != null) { 79 try { 80 miUt.setListener(new IImsUtListenerProxy()); 81 } catch (RemoteException e) { 82 } 83 } 84 } 85 86 public void close() { 87 synchronized(mLockObj) { 88 if (miUt != null) { 89 try { 90 miUt.close(); 91 } catch (RemoteException e) { 92 } 93 } 94 95 if (!mPendingCmds.isEmpty()) { 96 Map.Entry<Integer, Message>[] entries = 97 mPendingCmds.entrySet().toArray(new Map.Entry[mPendingCmds.size()]); 98 99 for (Map.Entry<Integer, Message> entry : entries) { 100 sendFailureReport(entry.getValue(), 101 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 102 } 103 104 mPendingCmds.clear(); 105 } 106 } 107 } 108 109 /** 110 * Operations for the supplementary service configuration 111 */ 112 113 /** 114 * Retrieves the configuration of the call barring. 115 * 116 * @param cbType type of call barring to be queried; ImsUtInterface#CB_XXX 117 * @param result message to pass the result of this operation 118 * The return value of ((AsyncResult)result.obj) is an array of {@link ImsSsInfo}. 119 */ 120 @Override 121 public void queryCallBarring(int cbType, Message result) { 122 if (DBG) { 123 log("queryCallBarring :: Ut=" + miUt + ", cbType=" + cbType); 124 } 125 126 synchronized(mLockObj) { 127 try { 128 int id = miUt.queryCallBarring(cbType); 129 130 if (id < 0) { 131 sendFailureReport(result, 132 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 133 return; 134 } 135 136 mPendingCmds.put(Integer.valueOf(id), result); 137 } catch (RemoteException e) { 138 sendFailureReport(result, 139 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 140 } 141 } 142 } 143 144 /** 145 * Retrieves the configuration of the call forward. 146 * The return value of ((AsyncResult)result.obj) is an array of {@link ImsCallForwardInfo}. 147 */ 148 @Override 149 public void queryCallForward(int condition, String number, Message result) { 150 if (DBG) { 151 log("queryCallForward :: Ut=" + miUt + ", condition=" + condition 152 + ", number=" + number); 153 } 154 155 synchronized(mLockObj) { 156 try { 157 int id = miUt.queryCallForward(condition, number); 158 159 if (id < 0) { 160 sendFailureReport(result, 161 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 162 return; 163 } 164 165 mPendingCmds.put(Integer.valueOf(id), result); 166 } catch (RemoteException e) { 167 sendFailureReport(result, 168 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 169 } 170 } 171 } 172 173 /** 174 * Retrieves the configuration of the call waiting. 175 * The return value of ((AsyncResult)result.obj) is an array of {@link ImsSsInfo}. 176 */ 177 @Override 178 public void queryCallWaiting(Message result) { 179 if (DBG) { 180 log("queryCallWaiting :: Ut=" + miUt); 181 } 182 183 synchronized(mLockObj) { 184 try { 185 int id = miUt.queryCallWaiting(); 186 187 if (id < 0) { 188 sendFailureReport(result, 189 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 190 return; 191 } 192 193 mPendingCmds.put(Integer.valueOf(id), result); 194 } catch (RemoteException e) { 195 sendFailureReport(result, 196 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 197 } 198 } 199 } 200 201 /** 202 * Retrieves the default CLIR setting. 203 */ 204 @Override 205 public void queryCLIR(Message result) { 206 if (DBG) { 207 log("queryCLIR :: Ut=" + miUt); 208 } 209 210 synchronized(mLockObj) { 211 try { 212 int id = miUt.queryCLIR(); 213 214 if (id < 0) { 215 sendFailureReport(result, 216 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 217 return; 218 } 219 220 mPendingCmds.put(Integer.valueOf(id), result); 221 } catch (RemoteException e) { 222 sendFailureReport(result, 223 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 224 } 225 } 226 } 227 228 /** 229 * Retrieves the CLIP call setting. 230 */ 231 public void queryCLIP(Message result) { 232 if (DBG) { 233 log("queryCLIP :: Ut=" + miUt); 234 } 235 236 synchronized(mLockObj) { 237 try { 238 int id = miUt.queryCLIP(); 239 240 if (id < 0) { 241 sendFailureReport(result, 242 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 243 return; 244 } 245 246 mPendingCmds.put(Integer.valueOf(id), result); 247 } catch (RemoteException e) { 248 sendFailureReport(result, 249 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 250 } 251 } 252 } 253 254 /** 255 * Retrieves the COLR call setting. 256 */ 257 public void queryCOLR(Message result) { 258 if (DBG) { 259 log("queryCOLR :: Ut=" + miUt); 260 } 261 262 synchronized(mLockObj) { 263 try { 264 int id = miUt.queryCOLR(); 265 266 if (id < 0) { 267 sendFailureReport(result, 268 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 269 return; 270 } 271 272 mPendingCmds.put(Integer.valueOf(id), result); 273 } catch (RemoteException e) { 274 sendFailureReport(result, 275 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 276 } 277 } 278 } 279 280 /** 281 * Retrieves the COLP call setting. 282 */ 283 public void queryCOLP(Message result) { 284 if (DBG) { 285 log("queryCOLP :: Ut=" + miUt); 286 } 287 288 synchronized(mLockObj) { 289 try { 290 int id = miUt.queryCOLP(); 291 292 if (id < 0) { 293 sendFailureReport(result, 294 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 295 return; 296 } 297 298 mPendingCmds.put(Integer.valueOf(id), result); 299 } catch (RemoteException e) { 300 sendFailureReport(result, 301 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 302 } 303 } 304 } 305 306 /** 307 * Modifies the configuration of the call barring. 308 */ 309 @Override 310 public void updateCallBarring(int cbType, boolean enable, Message result, String[] barrList) { 311 if (DBG) { 312 if (barrList != null) { 313 String bList = new String(); 314 for (int i = 0; i < barrList.length; i++) { 315 bList.concat(barrList[i] + " "); 316 } 317 log("updateCallBarring :: Ut=" + miUt + ", cbType=" + cbType 318 + ", enable=" + enable + ", barrList=" + bList); 319 } 320 else { 321 log("updateCallBarring :: Ut=" + miUt + ", cbType=" + cbType 322 + ", enable=" + enable); 323 } 324 } 325 326 synchronized(mLockObj) { 327 try { 328 int id = miUt.updateCallBarring(cbType, enable, barrList); 329 330 if (id < 0) { 331 sendFailureReport(result, 332 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 333 return; 334 } 335 336 mPendingCmds.put(Integer.valueOf(id), result); 337 } catch (RemoteException e) { 338 sendFailureReport(result, 339 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 340 } 341 } 342 } 343 344 /** 345 * Modifies the configuration of the call forward. 346 */ 347 @Override 348 public void updateCallForward(int action, int condition, String number, 349 int timeSeconds, Message result) { 350 if (DBG) { 351 log("updateCallForward :: Ut=" + miUt + ", action=" + action 352 + ", condition=" + condition + ", number=" + number 353 + ", timeSeconds=" + timeSeconds); 354 } 355 356 synchronized(mLockObj) { 357 try { 358 int id = miUt.updateCallForward(action, condition, number, timeSeconds); 359 360 if (id < 0) { 361 sendFailureReport(result, 362 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 363 return; 364 } 365 366 mPendingCmds.put(Integer.valueOf(id), result); 367 } catch (RemoteException e) { 368 sendFailureReport(result, 369 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 370 } 371 } 372 } 373 374 /** 375 * Modifies the configuration of the call waiting. 376 */ 377 @Override 378 public void updateCallWaiting(boolean enable, Message result) { 379 if (DBG) { 380 log("updateCallWaiting :: Ut=" + miUt + ", enable=" + enable); 381 } 382 383 synchronized(mLockObj) { 384 try { 385 int id = miUt.updateCallWaiting(enable); 386 387 if (id < 0) { 388 sendFailureReport(result, 389 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 390 return; 391 } 392 393 mPendingCmds.put(Integer.valueOf(id), result); 394 } catch (RemoteException e) { 395 sendFailureReport(result, 396 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 397 } 398 } 399 } 400 401 /** 402 * Updates the configuration of the CLIR supplementary service. 403 */ 404 @Override 405 public void updateCLIR(int clirMode, Message result) { 406 if (DBG) { 407 log("updateCLIR :: Ut=" + miUt + ", clirMode=" + clirMode); 408 } 409 410 synchronized(mLockObj) { 411 try { 412 int id = miUt.updateCLIR(clirMode); 413 414 if (id < 0) { 415 sendFailureReport(result, 416 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 417 return; 418 } 419 420 mPendingCmds.put(Integer.valueOf(id), result); 421 } catch (RemoteException e) { 422 sendFailureReport(result, 423 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 424 } 425 } 426 } 427 428 /** 429 * Updates the configuration of the CLIP supplementary service. 430 */ 431 @Override 432 public void updateCLIP(boolean enable, Message result) { 433 if (DBG) { 434 log("updateCLIP :: Ut=" + miUt + ", enable=" + enable); 435 } 436 437 synchronized(mLockObj) { 438 try { 439 int id = miUt.updateCLIP(enable); 440 441 if (id < 0) { 442 sendFailureReport(result, 443 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 444 return; 445 } 446 447 mPendingCmds.put(Integer.valueOf(id), result); 448 } catch (RemoteException e) { 449 sendFailureReport(result, 450 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 451 } 452 } 453 } 454 455 /** 456 * Updates the configuration of the COLR supplementary service. 457 */ 458 @Override 459 public void updateCOLR(int presentation, Message result) { 460 if (DBG) { 461 log("updateCOLR :: Ut=" + miUt + ", presentation=" + presentation); 462 } 463 464 synchronized(mLockObj) { 465 try { 466 int id = miUt.updateCOLR(presentation); 467 468 if (id < 0) { 469 sendFailureReport(result, 470 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 471 return; 472 } 473 474 mPendingCmds.put(Integer.valueOf(id), result); 475 } catch (RemoteException e) { 476 sendFailureReport(result, 477 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 478 } 479 } 480 } 481 482 /** 483 * Updates the configuration of the COLP supplementary service. 484 */ 485 @Override 486 public void updateCOLP(boolean enable, Message result) { 487 if (DBG) { 488 log("updateCallWaiting :: Ut=" + miUt + ", enable=" + enable); 489 } 490 491 synchronized(mLockObj) { 492 try { 493 int id = miUt.updateCOLP(enable); 494 495 if (id < 0) { 496 sendFailureReport(result, 497 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 498 return; 499 } 500 501 mPendingCmds.put(Integer.valueOf(id), result); 502 } catch (RemoteException e) { 503 sendFailureReport(result, 504 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 505 } 506 } 507 } 508 509 public void transact(Bundle ssInfo, Message result) { 510 if (DBG) { 511 log("transact :: Ut=" + miUt + ", ssInfo=" + ssInfo); 512 } 513 514 synchronized(mLockObj) { 515 try { 516 int id = miUt.transact(ssInfo); 517 518 if (id < 0) { 519 sendFailureReport(result, 520 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 521 return; 522 } 523 524 mPendingCmds.put(Integer.valueOf(id), result); 525 } catch (RemoteException e) { 526 sendFailureReport(result, 527 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 528 } 529 } 530 } 531 532 private void sendFailureReport(Message result, ImsReasonInfo error) { 533 if (result == null || error == null) { 534 return; 535 } 536 537 String errorString; 538 // If ImsReasonInfo object does not have a String error code, use a 539 // default error string. 540 if (error.mExtraMessage == null) { 541 errorString = new String("IMS UT exception"); 542 } 543 else { 544 errorString = new String(error.mExtraMessage); 545 } 546 AsyncResult.forMessage(result, null, new ImsException(errorString, error.mCode)); 547 result.sendToTarget(); 548 } 549 550 private void sendSuccessReport(Message result) { 551 if (result == null) { 552 return; 553 } 554 555 AsyncResult.forMessage(result, null, null); 556 result.sendToTarget(); 557 } 558 559 private void sendSuccessReport(Message result, Object ssInfo) { 560 if (result == null) { 561 return; 562 } 563 564 AsyncResult.forMessage(result, ssInfo, null); 565 result.sendToTarget(); 566 } 567 568 private void log(String s) { 569 Rlog.d(TAG, s); 570 } 571 572 private void loge(String s) { 573 Rlog.e(TAG, s); 574 } 575 576 private void loge(String s, Throwable t) { 577 Rlog.e(TAG, s, t); 578 } 579 580 /** 581 * A listener type for the result of the supplementary service configuration. 582 */ 583 private class IImsUtListenerProxy extends IImsUtListener.Stub { 584 /** 585 * Notifies the result of the supplementary service configuration udpate. 586 */ 587 @Override 588 public void utConfigurationUpdated(IImsUt ut, int id) { 589 Integer key = Integer.valueOf(id); 590 591 synchronized(mLockObj) { 592 sendSuccessReport(mPendingCmds.get(key)); 593 mPendingCmds.remove(key); 594 } 595 } 596 597 @Override 598 public void utConfigurationUpdateFailed(IImsUt ut, int id, ImsReasonInfo error) { 599 Integer key = Integer.valueOf(id); 600 601 synchronized(mLockObj) { 602 sendFailureReport(mPendingCmds.get(key), error); 603 mPendingCmds.remove(key); 604 } 605 } 606 607 /** 608 * Notifies the result of the supplementary service configuration query. 609 */ 610 @Override 611 public void utConfigurationQueried(IImsUt ut, int id, Bundle ssInfo) { 612 Integer key = Integer.valueOf(id); 613 614 synchronized(mLockObj) { 615 sendSuccessReport(mPendingCmds.get(key), ssInfo); 616 mPendingCmds.remove(key); 617 } 618 } 619 620 @Override 621 public void utConfigurationQueryFailed(IImsUt ut, int id, ImsReasonInfo error) { 622 Integer key = Integer.valueOf(id); 623 624 synchronized(mLockObj) { 625 sendFailureReport(mPendingCmds.get(key), error); 626 mPendingCmds.remove(key); 627 } 628 } 629 630 /** 631 * Notifies the status of the call barring supplementary service. 632 */ 633 @Override 634 public void utConfigurationCallBarringQueried(IImsUt ut, 635 int id, ImsSsInfo[] cbInfo) { 636 Integer key = Integer.valueOf(id); 637 638 synchronized(mLockObj) { 639 sendSuccessReport(mPendingCmds.get(key), cbInfo); 640 mPendingCmds.remove(key); 641 } 642 } 643 644 /** 645 * Notifies the status of the call forwarding supplementary service. 646 */ 647 @Override 648 public void utConfigurationCallForwardQueried(IImsUt ut, 649 int id, ImsCallForwardInfo[] cfInfo) { 650 Integer key = Integer.valueOf(id); 651 652 synchronized(mLockObj) { 653 sendSuccessReport(mPendingCmds.get(key), cfInfo); 654 mPendingCmds.remove(key); 655 } 656 } 657 658 /** 659 * Notifies the status of the call waiting supplementary service. 660 */ 661 @Override 662 public void utConfigurationCallWaitingQueried(IImsUt ut, 663 int id, ImsSsInfo[] cwInfo) { 664 Integer key = Integer.valueOf(id); 665 666 synchronized(mLockObj) { 667 sendSuccessReport(mPendingCmds.get(key), cwInfo); 668 mPendingCmds.remove(key); 669 } 670 } 671 } 672 } 673