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 */ RcsPresence(IRcsPresence presenceService)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 */ requestCapability(List<String> contactsNumber, IRcsPresenceListener listener)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 */ requestAvailability(String contactNumber, IRcsPresenceListener listener)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 */ requestAvailabilityNoThrottle(String contactNumber, IRcsPresenceListener listener)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 */ getPublishState()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