Home | History | Annotate | Download | only in ims
      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