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 android.os.RemoteException; 33 import android.util.Log; 34 35 import com.android.ims.internal.IRcsPresence; 36 37 /** 38 * 39 * @hide 40 */ 41 public class RcsPresence { 42 static final String TAG = "RcsPresence"; 43 private boolean DBG = true; 44 private IRcsPresence mIRcsPresence = null; 45 46 /** 47 * Key to retrieve the RcsPresenceInfo list from intent ACTION_PRESENCE_CHANGED 48 * The RcsPresenceInfo list can be got by the following function call: 49 * ArrayList<RcsPresenceInfo> rcsPresenceInfoList = intent.getParcelableArrayListExtra( 50 * RcsPresence.EXTRA_PRESENCE_INFO_LIST); 51 * 52 * @see RcsPresenceInfo 53 */ 54 public static final String EXTRA_PRESENCE_INFO_LIST = "presence_info_list"; 55 56 /** 57 * Key to retrieve the subscription ID. This is for muliti-SIM implementation. 58 */ 59 public static final String EXTRA_SUBID = "android:subid"; 60 61 /** 62 * The intent will be broadcasted when the presence changed. 63 * It happens on the following cases: 64 * 1. When the phone gets a NOTIFY from network. 65 * 2. When the phone gets some SUBSCRIBE error from network for some case (such as 404). 66 * It takes two extra parameters: 67 * 1. EXTRA_PRESENCE_INFO_LIST 68 * need to get it by the following statement: 69 * ArrayList<RcsPresenceInfo> rcsPresenceInfoList = intent.getParcelableArrayListExtra( 70 * RcsPresence.EXTRA_PRESENCE_INFO_LIST); 71 * 2. EXTRA_SUBID 72 * 73 * @see RcsPresenceInfO 74 * @see EXTRA_PRESENCE_INFO_LIST 75 * @see EXTRA_SUBID 76 */ 77 public static final String ACTION_PRESENCE_CHANGED = "com.android.ims.ACTION_PRESENCE_CHANGED"; 78 79 /** 80 * Key to retrieve "publish_state" for 81 * intent ACTION_PUBLISH_STATE_CHANGED. 82 * 83 * @See PublishState. 84 * @see ACTION_PUBLISH_STATE_CHANGED 85 */ 86 public static final String EXTRA_PUBLISH_STATE = "publish_state"; 87 88 /** 89 * The intent will be broadcasted when latest publish status changed 90 * It takes two extra parameters: 91 * 1. EXTRA_PUBLISH_STATE 92 * 2. EXTRA_SUBID 93 * 94 * @see #EXTRA_PUBLISH_STATE 95 * @see #EXTRA_SUBID 96 * @see PublishState 97 */ 98 public static final String ACTION_PUBLISH_STATE_CHANGED = 99 "com.android.ims.ACTION_PUBLISH_STATUS_CHANGED"; 100 101 /** 102 * The last publish state 103 */ 104 public static class PublishState { 105 /** 106 * The phone is PUBLISH_STATE_200_OK when 107 * the response of the last publish is "200 OK" 108 */ 109 public static final int PUBLISH_STATE_200_OK = 0; 110 111 /** 112 * The phone didn't publish after power on. 113 * the phone didn't get any publish response yet. 114 */ 115 public static final int PUBLISH_STATE_NOT_PUBLISHED = 1; 116 117 /** 118 * The phone is PUBLISH_STATE_VOLTE_PROVISION_ERROR when the response is one of items 119 * in config_volte_provision_error_on_publish_response for PUBLISH or 120 * in config_volte_provision_error_on_subscribe_response for SUBSCRIBE. 121 */ 122 public static final int PUBLISH_STATE_VOLTE_PROVISION_ERROR = 2; 123 124 /** 125 * The phone is PUBLISH_STATE_RCS_PROVISION_ERROR when the response is one of items 126 * in config_rcs_provision_error_on_publish_response for PUBLISH or 127 * in config_rcs_provision_error_on_subscribe_response for SUBSCRIBE. 128 */ 129 public static final int PUBLISH_STATE_RCS_PROVISION_ERROR = 3; 130 131 /** 132 * The phone is PUBLISH_STATE_REQUEST_TIMEOUT when 133 * The response of the last publish is "408 Request Timeout". 134 */ 135 public static final int PUBLISH_STATE_REQUEST_TIMEOUT = 4; 136 137 /** 138 * The phone is PUBLISH_STATE_OTHER_ERROR when 139 * the response of the last publish is other temp error. Such as 140 * 503 Service Unavailable 141 * Device shall retry with exponential back-off 142 * 143 * 423 Interval Too Short. Requested expiry interval too short and server rejects it 144 * Device shall re-attempt subscription after changing the expiration interval in 145 * the Expires header field to be equal to or greater than the expiration interval 146 * within the Min-Expires header field of the 423 response 147 * 148 * ... 149 */ 150 public static final int PUBLISH_STATE_OTHER_ERROR = 5; 151 }; 152 153 /** 154 * Constructor. 155 * @param presenceService the IRcsPresence which get by RcsManager.getRcsPresenceInterface. 156 * 157 * @see RcsManager#getRcsPresenceInterface 158 */ RcsPresence(IRcsPresence presenceService)159 public RcsPresence(IRcsPresence presenceService) { 160 if (DBG) Log.d(TAG, "IRcsPresence creates"); 161 162 mIRcsPresence = presenceService; 163 } 164 165 /** 166 * Send the request to the server to get the capability. 167 * 1. If the presence service sent the request to network successfully 168 * then it will return the request ID (>0). It will not wait for the response from 169 * network. The response from network will be returned by callback onSuccess() or onError(). 170 * 2. If the presence service failed to send the request to network then it will return error 171 * code which is defined by RcsManager.ResultCode (<0). 172 * 3. If the network returns "200 OK" for a request then the listener.onSuccess() will be 173 * called by presence service. 174 * 4. If the network resturns "404" for a single target number then it means the target 175 * number is not VoLte capable, so the listener.onSuccess() will be called and intent 176 * ACTION_PRESENCE_CHANGED will be broadcasted by presence service. 177 * 5. If the network returns other error then the listener.onError() will be called by 178 * presence service. 179 * 6. If the network returns "200 OK" then we can expect the presence service receives notify 180 * from network. If the presence service receives notify then it will broadcast the 181 * intent ACTION_PRESENCE_CHANGED. If the notify state is "terminated" then the 182 * listener.onFinish() will be called by presence service as well. 183 * 7. If the presence service doesn't get response after "Subscribe Expiration + T1" then the 184 * listener.onTimeout() will be called by presence service. 185 * 186 * @param contactsNumber the contact number list which will be requested. 187 * @param listener the IRcsPresenceListener which will return the status and response. 188 * 189 * @return the request ID if it is >0. Or it is RcsManager.ResultCode for error. 190 * 191 * @see IRcsPresenceListener 192 * @see ResultCode 193 */ requestCapability(List<String> contactsNumber, IRcsPresenceListener listener)194 public int requestCapability(List<String> contactsNumber, 195 IRcsPresenceListener listener) throws RcsException { 196 if (DBG) Log.d(TAG, "call requestCapability, contactsNumber=" + contactsNumber); 197 int ret = ResultCode.ERROR_SERVICE_NOT_AVAILABLE; 198 199 try { 200 ret = mIRcsPresence.requestCapability(contactsNumber, listener); 201 } catch (RemoteException e) { 202 throw new RcsException("requestCapability", e, 203 ResultCode.ERROR_SERVICE_NOT_AVAILABLE); 204 } 205 206 if (DBG) Log.d(TAG, "requestCapability ret =" + ret); 207 return ret; 208 } 209 210 /** 211 * Send the request to the server to get the availability. 212 * 1. If the presence service sent the request to network successfully then it will return 213 * the request ID (>0). 214 * 2. If the presence serive failed to send the request to network then it will return error 215 * code which is defined by RcsManager.ResultCode (<0). 216 * 3. If the network returns "200 OK" for a request then the listener.onSuccess() will be 217 * called by presence service. 218 * 4. If the network resturns "404" then it means the target number is not VoLte capable, 219 * so the listener.onSuccess() will be called and intent ACTION_PRESENCE_CHANGED will be 220 * broadcasted by presence service. 221 * 5. If the network returns other error code then the listener.onError() will be called by 222 * presence service. 223 * 6. If the network returns "200 OK" then we can expect the presence service receives notify 224 * from network. If the presence service receives notify then it will broadcast the intent 225 * ACTION_PRESENCE_CHANGED. If the notify state is "terminated" then the listener.onFinish() 226 * will be called by presence service as well. 227 * 7. If the presence service doesn't get response after "Subscribe Expiration + T1" then it 228 * will call listener.onTimeout(). 229 * 230 * @param contactNumber the contact which will request the availability. 231 * Only support phone number at present. 232 * @param listener the IRcsPresenceListener to get the response. 233 * 234 * @return the request ID if it is >0. Or it is RcsManager.ResultCode for error. 235 * 236 * @see IRcsPresenceListener 237 * @see ResultCode 238 * @see RcsPresence.ACTION_PRESENCE_CHANGED 239 */ requestAvailability(String contactNumber, IRcsPresenceListener listener)240 public int requestAvailability(String contactNumber, IRcsPresenceListener listener) 241 throws RcsException { 242 if (DBG) Log.d(TAG, "call requestAvailability, contactNumber=" + contactNumber); 243 int ret = ResultCode.ERROR_SERVICE_NOT_AVAILABLE; 244 245 try { 246 ret = mIRcsPresence.requestAvailability(contactNumber, listener); 247 } catch (RemoteException e) { 248 throw new RcsException("requestAvailability", e, 249 ResultCode.ERROR_SERVICE_NOT_AVAILABLE); 250 } 251 252 if (DBG) Log.d(TAG, "requestAvailability ret =" + ret); 253 return ret; 254 } 255 256 /** 257 * Same as requestAvailability. but requestAvailability will consider throttle to avoid too 258 * fast call. Which means it will not send the request to network in next 60s for the same 259 * request. 260 * The error code SUBSCRIBE_TOO_FREQUENTLY will be returned under the case. 261 * But for this funcation it will always send the request to network. 262 * 263 * @see IRcsPresenceListener 264 * @see ResultCode 265 * @see RcsPresence.ACTION_PRESENCE_CHANGED 266 * @see ResultCode.SUBSCRIBE_TOO_FREQUENTLY 267 */ requestAvailabilityNoThrottle(String contactNumber, IRcsPresenceListener listener)268 public int requestAvailabilityNoThrottle(String contactNumber, IRcsPresenceListener listener) 269 throws RcsException { 270 if (DBG) Log.d(TAG, "call requestAvailabilityNoThrottle, contactNumber=" + contactNumber); 271 int ret = ResultCode.ERROR_SERVICE_NOT_AVAILABLE; 272 273 try { 274 ret = mIRcsPresence.requestAvailabilityNoThrottle(contactNumber, listener); 275 } catch (RemoteException e) { 276 throw new RcsException("requestAvailabilityNoThrottle", e, 277 ResultCode.ERROR_SERVICE_NOT_AVAILABLE); 278 } 279 280 if (DBG) Log.d(TAG, "requestAvailabilityNoThrottle ret =" + ret); 281 return ret; 282 } 283 284 /** 285 * Get the latest publish state. 286 * 287 * @see PublishState 288 */ getPublishState()289 public int getPublishState() throws RcsException { 290 int ret = PublishState.PUBLISH_STATE_NOT_PUBLISHED; 291 try { 292 ret = mIRcsPresence.getPublishState(); 293 } catch (RemoteException e) { 294 throw new RcsException("getPublishState", e, 295 ResultCode.ERROR_SERVICE_NOT_AVAILABLE); 296 } 297 298 if (DBG) Log.d(TAG, "getPublishState ret =" + ret); 299 return ret; 300 } 301 } 302 303