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, int action, 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 + ", action=" + action + ", barrList=" + bList); 319 } 320 else { 321 log("updateCallBarring :: Ut=" + miUt + ", cbType=" + cbType 322 + ", action=" + action); 323 } 324 } 325 326 synchronized(mLockObj) { 327 try { 328 int id = miUt.updateCallBarring(cbType, action, 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 serviceClass, int timeSeconds, Message result) { 350 if (DBG) { 351 log("updateCallForward :: Ut=" + miUt + ", action=" + action 352 + ", condition=" + condition + ", number=" + number 353 + ", serviceClass=" + serviceClass + ", timeSeconds=" + timeSeconds); 354 } 355 356 synchronized(mLockObj) { 357 try { 358 int id = miUt.updateCallForward(action, condition, number, serviceClass, 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, int serviceClass, Message result) { 379 if (DBG) { 380 log("updateCallWaiting :: Ut=" + miUt + ", enable=" + enable 381 + ",serviceClass=" + serviceClass); 382 } 383 384 synchronized(mLockObj) { 385 try { 386 int id = miUt.updateCallWaiting(enable, serviceClass); 387 388 if (id < 0) { 389 sendFailureReport(result, 390 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 391 return; 392 } 393 394 mPendingCmds.put(Integer.valueOf(id), result); 395 } catch (RemoteException e) { 396 sendFailureReport(result, 397 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 398 } 399 } 400 } 401 402 /** 403 * Updates the configuration of the CLIR supplementary service. 404 */ 405 @Override 406 public void updateCLIR(int clirMode, Message result) { 407 if (DBG) { 408 log("updateCLIR :: Ut=" + miUt + ", clirMode=" + clirMode); 409 } 410 411 synchronized(mLockObj) { 412 try { 413 int id = miUt.updateCLIR(clirMode); 414 415 if (id < 0) { 416 sendFailureReport(result, 417 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 418 return; 419 } 420 421 mPendingCmds.put(Integer.valueOf(id), result); 422 } catch (RemoteException e) { 423 sendFailureReport(result, 424 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 425 } 426 } 427 } 428 429 /** 430 * Updates the configuration of the CLIP supplementary service. 431 */ 432 @Override 433 public void updateCLIP(boolean enable, Message result) { 434 if (DBG) { 435 log("updateCLIP :: Ut=" + miUt + ", enable=" + enable); 436 } 437 438 synchronized(mLockObj) { 439 try { 440 int id = miUt.updateCLIP(enable); 441 442 if (id < 0) { 443 sendFailureReport(result, 444 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 445 return; 446 } 447 448 mPendingCmds.put(Integer.valueOf(id), result); 449 } catch (RemoteException e) { 450 sendFailureReport(result, 451 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 452 } 453 } 454 } 455 456 /** 457 * Updates the configuration of the COLR supplementary service. 458 */ 459 @Override 460 public void updateCOLR(int presentation, Message result) { 461 if (DBG) { 462 log("updateCOLR :: Ut=" + miUt + ", presentation=" + presentation); 463 } 464 465 synchronized(mLockObj) { 466 try { 467 int id = miUt.updateCOLR(presentation); 468 469 if (id < 0) { 470 sendFailureReport(result, 471 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 472 return; 473 } 474 475 mPendingCmds.put(Integer.valueOf(id), result); 476 } catch (RemoteException e) { 477 sendFailureReport(result, 478 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 479 } 480 } 481 } 482 483 /** 484 * Updates the configuration of the COLP supplementary service. 485 */ 486 @Override 487 public void updateCOLP(boolean enable, Message result) { 488 if (DBG) { 489 log("updateCallWaiting :: Ut=" + miUt + ", enable=" + enable); 490 } 491 492 synchronized(mLockObj) { 493 try { 494 int id = miUt.updateCOLP(enable); 495 496 if (id < 0) { 497 sendFailureReport(result, 498 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 499 return; 500 } 501 502 mPendingCmds.put(Integer.valueOf(id), result); 503 } catch (RemoteException e) { 504 sendFailureReport(result, 505 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 506 } 507 } 508 } 509 510 public void transact(Bundle ssInfo, Message result) { 511 if (DBG) { 512 log("transact :: Ut=" + miUt + ", ssInfo=" + ssInfo); 513 } 514 515 synchronized(mLockObj) { 516 try { 517 int id = miUt.transact(ssInfo); 518 519 if (id < 0) { 520 sendFailureReport(result, 521 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 522 return; 523 } 524 525 mPendingCmds.put(Integer.valueOf(id), result); 526 } catch (RemoteException e) { 527 sendFailureReport(result, 528 new ImsReasonInfo(ImsReasonInfo.CODE_UT_SERVICE_UNAVAILABLE, 0)); 529 } 530 } 531 } 532 533 private void sendFailureReport(Message result, ImsReasonInfo error) { 534 if (result == null || error == null) { 535 return; 536 } 537 538 String errorString; 539 // If ImsReasonInfo object does not have a String error code, use a 540 // default error string. 541 if (error.mExtraMessage == null) { 542 errorString = new String("IMS UT exception"); 543 } 544 else { 545 errorString = new String(error.mExtraMessage); 546 } 547 AsyncResult.forMessage(result, null, new ImsException(errorString, error.mCode)); 548 result.sendToTarget(); 549 } 550 551 private void sendSuccessReport(Message result) { 552 if (result == null) { 553 return; 554 } 555 556 AsyncResult.forMessage(result, null, null); 557 result.sendToTarget(); 558 } 559 560 private void sendSuccessReport(Message result, Object ssInfo) { 561 if (result == null) { 562 return; 563 } 564 565 AsyncResult.forMessage(result, ssInfo, null); 566 result.sendToTarget(); 567 } 568 569 private void log(String s) { 570 Rlog.d(TAG, s); 571 } 572 573 private void loge(String s) { 574 Rlog.e(TAG, s); 575 } 576 577 private void loge(String s, Throwable t) { 578 Rlog.e(TAG, s, t); 579 } 580 581 /** 582 * A listener type for the result of the supplementary service configuration. 583 */ 584 private class IImsUtListenerProxy extends IImsUtListener.Stub { 585 /** 586 * Notifies the result of the supplementary service configuration udpate. 587 */ 588 @Override 589 public void utConfigurationUpdated(IImsUt ut, int id) { 590 Integer key = Integer.valueOf(id); 591 592 synchronized(mLockObj) { 593 sendSuccessReport(mPendingCmds.get(key)); 594 mPendingCmds.remove(key); 595 } 596 } 597 598 @Override 599 public void utConfigurationUpdateFailed(IImsUt ut, int id, ImsReasonInfo error) { 600 Integer key = Integer.valueOf(id); 601 602 synchronized(mLockObj) { 603 sendFailureReport(mPendingCmds.get(key), error); 604 mPendingCmds.remove(key); 605 } 606 } 607 608 /** 609 * Notifies the result of the supplementary service configuration query. 610 */ 611 @Override 612 public void utConfigurationQueried(IImsUt ut, int id, Bundle ssInfo) { 613 Integer key = Integer.valueOf(id); 614 615 synchronized(mLockObj) { 616 sendSuccessReport(mPendingCmds.get(key), ssInfo); 617 mPendingCmds.remove(key); 618 } 619 } 620 621 @Override 622 public void utConfigurationQueryFailed(IImsUt ut, int id, ImsReasonInfo error) { 623 Integer key = Integer.valueOf(id); 624 625 synchronized(mLockObj) { 626 sendFailureReport(mPendingCmds.get(key), error); 627 mPendingCmds.remove(key); 628 } 629 } 630 631 /** 632 * Notifies the status of the call barring supplementary service. 633 */ 634 @Override 635 public void utConfigurationCallBarringQueried(IImsUt ut, 636 int id, ImsSsInfo[] cbInfo) { 637 Integer key = Integer.valueOf(id); 638 639 synchronized(mLockObj) { 640 sendSuccessReport(mPendingCmds.get(key), cbInfo); 641 mPendingCmds.remove(key); 642 } 643 } 644 645 /** 646 * Notifies the status of the call forwarding supplementary service. 647 */ 648 @Override 649 public void utConfigurationCallForwardQueried(IImsUt ut, 650 int id, ImsCallForwardInfo[] cfInfo) { 651 Integer key = Integer.valueOf(id); 652 653 synchronized(mLockObj) { 654 sendSuccessReport(mPendingCmds.get(key), cfInfo); 655 mPendingCmds.remove(key); 656 } 657 } 658 659 /** 660 * Notifies the status of the call waiting supplementary service. 661 */ 662 @Override 663 public void utConfigurationCallWaitingQueried(IImsUt ut, 664 int id, ImsSsInfo[] cwInfo) { 665 Integer key = Integer.valueOf(id); 666 667 synchronized(mLockObj) { 668 sendSuccessReport(mPendingCmds.get(key), cwInfo); 669 mPendingCmds.remove(key); 670 } 671 } 672 } 673 } 674