Home | History | Annotate | Download | only in ims
      1 /*
      2  * Copyright (c) 2015, Motorola Mobility LLC
      3  * All rights reserved.
      4  *
      5  * Redistribution and use in source and binary forms, with or without
      6  * modification, are permitted provided that the following conditions are met:
      7  *     - Redistributions of source code must retain the above copyright
      8  *       notice, this list of conditions and the following disclaimer.
      9  *     - Redistributions in binary form must reproduce the above copyright
     10  *       notice, this list of conditions and the following disclaimer in the
     11  *       documentation and/or other materials provided with the distribution.
     12  *     - Neither the name of Motorola Mobility nor the
     13  *       names of its contributors may be used to endorse or promote products
     14  *       derived from this software without specific prior written permission.
     15  *
     16  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     18  * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     19  * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MOTOROLA MOBILITY LLC BE LIABLE
     20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
     22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
     26  * DAMAGE.
     27  */
     28 
     29 package com.android.ims;
     30 
     31 import java.util.List;
     32 import java.util.ArrayList;
     33 import android.content.Intent;
     34 import android.os.RemoteException;
     35 import android.util.Log;
     36 
     37 import com.android.ims.internal.IRcsPresence;
     38 import com.android.ims.RcsManager.ResultCode;
     39 
     40 /**
     41  *
     42  * @hide
     43  */
     44 public class RcsPresence {
     45     static final String TAG = "RcsPresence";
     46     private boolean DBG = true;
     47     private IRcsPresence mIRcsPresence = null;
     48 
     49     /**
     50      * Key to retrieve the RcsPresenceInfo list from intent ACTION_PRESENCE_CHANGED
     51      * The RcsPresenceInfo list can be got by the following function call:
     52      * ArrayList<RcsPresenceInfo> rcsPresenceInfoList = intent.getParcelableArrayListExtra(
     53      *           RcsPresence.EXTRA_PRESENCE_INFO_LIST);
     54      *
     55      * @see RcsPresenceInfo
     56      */
     57     public static final String EXTRA_PRESENCE_INFO_LIST = "presence_info_list";
     58 
     59     /**
     60      * Key to retrieve the subscription ID. This is for muliti-SIM implementation.
     61      */
     62     public static final String EXTRA_SUBID = "android:subid";
     63 
     64     /**
     65      * The intent will be broadcasted when the presence changed.
     66      * It happens on the following cases:
     67      *   1. When the phone gets a NOTIFY from network.
     68      *   2. When the phone gets some SUBSCRIBE error from network for some case (such as 404).
     69      * It takes two extra parameters:
     70      *   1. EXTRA_PRESENCE_INFO_LIST
     71      *     need to get it by the following statement:
     72      *     ArrayList<RcsPresenceInfo> rcsPresenceInfoList = intent.getParcelableArrayListExtra(
     73      *             RcsPresence.EXTRA_PRESENCE_INFO_LIST);
     74      *   2. EXTRA_SUBID
     75      *
     76      * @see RcsPresenceInfO
     77      * @see EXTRA_PRESENCE_INFO_LIST
     78      * @see EXTRA_SUBID
     79      */
     80     public static final String ACTION_PRESENCE_CHANGED = "com.android.ims.ACTION_PRESENCE_CHANGED";
     81 
     82     /**
     83      * Key to retrieve "publish_state" for
     84      * intent ACTION_PUBLISH_STATE_CHANGED.
     85      *
     86      * @See PublishState.
     87      * @see ACTION_PUBLISH_STATE_CHANGED
     88      */
     89     public static final String EXTRA_PUBLISH_STATE = "publish_state";
     90 
     91     /**
     92      * The intent will be broadcasted when latest publish status changed
     93      * It takes two extra parameters:
     94      * 1. EXTRA_PUBLISH_STATE
     95      * 2. EXTRA_SUBID
     96      *
     97      * @see #EXTRA_PUBLISH_STATE
     98      * @see #EXTRA_SUBID
     99      * @see PublishState
    100      */
    101     public static final String ACTION_PUBLISH_STATE_CHANGED =
    102             "com.android.ims.ACTION_PUBLISH_STATUS_CHANGED";
    103 
    104     /**
    105      *  The last publish state
    106      */
    107     public static class PublishState {
    108         /**
    109          * The phone is PUBLISH_STATE_200_OK when
    110          * the response of the last publish is "200 OK"
    111          */
    112         public static final int PUBLISH_STATE_200_OK = 0;
    113 
    114         /**
    115          * The phone didn't publish after power on.
    116          * the phone didn't get any publish response yet.
    117          */
    118         public static final int PUBLISH_STATE_NOT_PUBLISHED = 1;
    119 
    120         /**
    121          * The phone is PUBLISH_STATE_VOLTE_PROVISION_ERROR when the response is one of items
    122           * in config_volte_provision_error_on_publish_response for PUBLISH or
    123           * in config_volte_provision_error_on_subscribe_response for SUBSCRIBE.
    124          */
    125         public static final int PUBLISH_STATE_VOLTE_PROVISION_ERROR = 2;
    126 
    127         /**
    128          * The phone is PUBLISH_STATE_RCS_PROVISION_ERROR when the response is one of items
    129           * in config_rcs_provision_error_on_publish_response for PUBLISH or
    130           * in config_rcs_provision_error_on_subscribe_response for SUBSCRIBE.
    131          */
    132         public static final int PUBLISH_STATE_RCS_PROVISION_ERROR = 3;
    133 
    134         /**
    135          * The phone is PUBLISH_STATE_REQUEST_TIMEOUT when
    136          * The response of the last publish is "408 Request Timeout".
    137          */
    138         public static final int PUBLISH_STATE_REQUEST_TIMEOUT = 4;
    139 
    140         /**
    141          * The phone is PUBLISH_STATE_OTHER_ERROR when
    142          * the response of the last publish is other temp error. Such as
    143          * 503 Service Unavailable
    144          * Device shall retry with exponential back-off
    145          *
    146          * 423 Interval Too Short. Requested expiry interval too short and server rejects it
    147          * Device shall re-attempt subscription after changing the expiration interval in
    148          * the Expires header field to be equal to or greater than the expiration interval
    149          * within the Min-Expires header field of the 423 response
    150          *
    151          * ...
    152          */
    153         public static final int PUBLISH_STATE_OTHER_ERROR = 5;
    154     };
    155 
    156     /**
    157      * Constructor.
    158      * @param presenceService the IRcsPresence which get by RcsManager.getRcsPresenceInterface.
    159      *
    160      * @see RcsManager#getRcsPresenceInterface
    161      */
    162     public RcsPresence(IRcsPresence presenceService) {
    163         if (DBG) Log.d(TAG, "IRcsPresence creates");
    164 
    165         mIRcsPresence = presenceService;
    166     }
    167 
    168     /**
    169      * Send the request to the server to get the capability.
    170      *   1. If the presence service sent the request to network successfully
    171      * then it will return the request ID (>0). It will not wait for the response from
    172      * network. The response from network will be returned by callback onSuccess() or onError().
    173      *   2. If the presence service failed to send the request to network then it will return error
    174      *  code which is defined by RcsManager.ResultCode (<0).
    175      *   3. If the network returns "200 OK" for a request then the listener.onSuccess() will be
    176      * called by presence service.
    177      *   4. If the network resturns "404" for a single target number then it means the target
    178      * number is not VoLte capable, so the listener.onSuccess() will be called and intent
    179      * ACTION_PRESENCE_CHANGED will be broadcasted by presence service.
    180      *   5. If the network returns other error then the listener.onError() will be called by
    181      * presence service.
    182      *   6. If the network returns "200 OK" then we can expect the presence service receives notify
    183      * from network. If the presence service receives notify then it will broadcast the
    184      * intent ACTION_PRESENCE_CHANGED. If the notify state is "terminated" then the
    185      * listener.onFinish() will be called by presence service as well.
    186      *   7. If the presence service doesn't get response after "Subscribe Expiration + T1" then the
    187      * listener.onTimeout() will be called by presence service.
    188      *
    189      * @param contactsNumber the contact number list which will be requested.
    190      * @param listener the IRcsPresenceListener which will return the status and response.
    191      *
    192      * @return the request ID if it is >0. Or it is RcsManager.ResultCode for error.
    193      *
    194      * @see IRcsPresenceListener
    195      * @see RcsManager.ResultCode
    196      */
    197     public int requestCapability(List<String> contactsNumber,
    198             IRcsPresenceListener listener) throws RcsException {
    199         if (DBG) Log.d(TAG, "call requestCapability, contactsNumber=" + contactsNumber);
    200         int ret = ResultCode.ERROR_SERVICE_NOT_AVAILABLE;
    201 
    202         try {
    203             ret = mIRcsPresence.requestCapability(contactsNumber, listener);
    204         }  catch (RemoteException e) {
    205             throw new RcsException("requestCapability", e,
    206                     ResultCode.ERROR_SERVICE_NOT_AVAILABLE);
    207         }
    208 
    209         if (DBG) Log.d(TAG, "requestCapability ret =" + ret);
    210         return ret;
    211     }
    212 
    213     /**
    214      * Send the request to the server to get the availability.
    215      *   1. If the presence service sent the request to network successfully then it will return
    216      * the request ID (>0).
    217      *   2. If the presence serive failed to send the request to network then it will return error
    218      * code which is defined by RcsManager.ResultCode (<0).
    219      *   3. If the network returns "200 OK" for a request then the listener.onSuccess() will be
    220      * called by presence service.
    221      *   4. If the network resturns "404" then it means the target number is not VoLte capable,
    222      * so the listener.onSuccess() will be called and intent ACTION_PRESENCE_CHANGED will be
    223      * broadcasted by presence service.
    224      *   5. If the network returns other error code then the listener.onError() will be called by
    225      * presence service.
    226      *   6. If the network returns "200 OK" then we can expect the presence service receives notify
    227      * from network. If the presence service receives notify then it will broadcast the intent
    228      * ACTION_PRESENCE_CHANGED. If the notify state is "terminated" then the listener.onFinish()
    229      * will be called by presence service as well.
    230      *   7. If the presence service doesn't get response after "Subscribe Expiration + T1" then it
    231      * will call listener.onTimeout().
    232      *
    233      * @param contactNumber the contact which will request the availability.
    234      *     Only support phone number at present.
    235      * @param listener the IRcsPresenceListener to get the response.
    236      *
    237      * @return the request ID if it is >0. Or it is RcsManager.ResultCode for error.
    238      *
    239      * @see IRcsPresenceListener
    240      * @see RcsManager.ResultCode
    241      * @see RcsPresence.ACTION_PRESENCE_CHANGED
    242      */
    243     public int requestAvailability(String contactNumber, IRcsPresenceListener listener)
    244              throws RcsException {
    245         if (DBG) Log.d(TAG, "call requestAvailability, contactNumber=" + contactNumber);
    246         int ret = ResultCode.ERROR_SERVICE_NOT_AVAILABLE;
    247 
    248         try {
    249             ret = mIRcsPresence.requestAvailability(contactNumber, listener);
    250         }  catch (RemoteException e) {
    251             throw new RcsException("requestAvailability", e,
    252                     ResultCode.ERROR_SERVICE_NOT_AVAILABLE);
    253         }
    254 
    255         if (DBG) Log.d(TAG, "requestAvailability ret =" + ret);
    256         return ret;
    257     }
    258 
    259     /**
    260      * Same as requestAvailability. but requestAvailability will consider throttle to avoid too
    261      * fast call. Which means it will not send the request to network in next 60s for the same
    262      * request.
    263      * The error code SUBSCRIBE_TOO_FREQUENTLY will be returned under the case.
    264      * But for this funcation it will always send the request to network.
    265      *
    266      * @see IRcsPresenceListener
    267      * @see RcsManager.ResultCode
    268      * @see RcsPresence.ACTION_PRESENCE_CHANGED
    269      * @see ResultCode.SUBSCRIBE_TOO_FREQUENTLY
    270      */
    271     public int requestAvailabilityNoThrottle(String contactNumber, IRcsPresenceListener listener)
    272              throws RcsException {
    273         if (DBG) Log.d(TAG, "call requestAvailabilityNoThrottle, contactNumber=" + contactNumber);
    274         int ret = ResultCode.ERROR_SERVICE_NOT_AVAILABLE;
    275 
    276         try {
    277             ret = mIRcsPresence.requestAvailabilityNoThrottle(contactNumber, listener);
    278         }  catch (RemoteException e) {
    279             throw new RcsException("requestAvailabilityNoThrottle", e,
    280                     ResultCode.ERROR_SERVICE_NOT_AVAILABLE);
    281         }
    282 
    283         if (DBG) Log.d(TAG, "requestAvailabilityNoThrottle ret =" + ret);
    284         return ret;
    285     }
    286 
    287     /**
    288      * Get the latest publish state.
    289      *
    290      * @see PublishState
    291      */
    292     public int getPublishState() throws RcsException {
    293         int ret = PublishState.PUBLISH_STATE_NOT_PUBLISHED;
    294         try {
    295             ret = mIRcsPresence.getPublishState();
    296         }  catch (RemoteException e) {
    297             throw new RcsException("getPublishState", e,
    298                     ResultCode.ERROR_SERVICE_NOT_AVAILABLE);
    299         }
    300 
    301         if (DBG) Log.d(TAG, "getPublishState ret =" + ret);
    302         return ret;
    303     }
    304 }
    305 
    306