1 /* 2 * Copyright (C) 2018 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 android.telephony.ims.stub; 18 19 import android.annotation.IntDef; 20 import android.annotation.NonNull; 21 import android.annotation.Nullable; 22 import android.net.Uri; 23 import android.os.RemoteException; 24 import android.telephony.ims.ImsException; 25 import android.telephony.ims.RcsContactUceCapability; 26 import android.telephony.ims.feature.ImsFeature; 27 import android.telephony.ims.feature.RcsFeature; 28 import android.util.Log; 29 30 import java.lang.annotation.Retention; 31 import java.lang.annotation.RetentionPolicy; 32 33 /** 34 * Base implementation for RCS User Capability Exchange using SIP OPTIONS. 35 * 36 * @hide 37 */ 38 public class RcsSipOptionsImplBase extends RcsCapabilityExchange { 39 40 private static final String LOG_TAG = "RcsSipOptionsImplBase"; 41 42 /** 43 * Indicates a SIP response from the remote user other than 200, 480, 408, 404, or 604. 44 */ 45 public static final int RESPONSE_GENERIC_FAILURE = -1; 46 47 /** 48 * Indicates that the remote user responded with a 200 OK response. 49 */ 50 public static final int RESPONSE_SUCCESS = 0; 51 52 /** 53 * Indicates that the remote user responded with a 480 TEMPORARY UNAVAILABLE response. 54 */ 55 public static final int RESPONSE_TEMPORARILY_UNAVAILABLE = 1; 56 57 /** 58 * Indicates that the remote user responded with a 408 REQUEST TIMEOUT response. 59 */ 60 public static final int RESPONSE_REQUEST_TIMEOUT = 2; 61 62 /** 63 * Indicates that the remote user responded with a 404 NOT FOUND response. 64 */ 65 public static final int RESPONSE_NOT_FOUND = 3; 66 67 /** 68 * Indicates that the remote user responded with a 604 DOES NOT EXIST ANYWHERE response. 69 */ 70 public static final int RESPONSE_DOES_NOT_EXIST_ANYWHERE = 4; 71 72 /** 73 * Indicates that the remote user responded with a 400 BAD REQUEST response. 74 */ 75 public static final int RESPONSE_BAD_REQUEST = 5; 76 77 /** @hide*/ 78 @Retention(RetentionPolicy.SOURCE) 79 @IntDef(prefix = "RESPONSE_", value = { 80 RESPONSE_GENERIC_FAILURE, 81 RESPONSE_SUCCESS, 82 RESPONSE_TEMPORARILY_UNAVAILABLE, 83 RESPONSE_REQUEST_TIMEOUT, 84 RESPONSE_NOT_FOUND, 85 RESPONSE_DOES_NOT_EXIST_ANYWHERE, 86 RESPONSE_BAD_REQUEST 87 }) 88 public @interface SipResponseCode {} 89 90 /** 91 * Send the response of a SIP OPTIONS capability exchange to the framework. If {@code code} is 92 * {@link #RESPONSE_SUCCESS}, info must be non-null. 93 * @param code The SIP response code that was sent by the network in response to the request 94 * sent by {@link #sendCapabilityRequest(Uri, RcsContactUceCapability, int)}. 95 * @param reason The optional SIP response reason sent by the network. If none was sent, this 96 * should be an empty string. 97 * @param info the contact's UCE capabilities associated with the capability request. 98 * @param operationToken The token associated with the original capability request, set by 99 * {@link #sendCapabilityRequest(Uri, RcsContactUceCapability, int)}. 100 * @throws ImsException If this {@link RcsSipOptionsImplBase} instance is not currently 101 * connected to the framework. This can happen if the {@link RcsFeature} is not 102 * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the 103 * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the 104 * Telephony stack has crashed. 105 */ onCapabilityRequestResponse(@ipResponseCode int code, @NonNull String reason, @Nullable RcsContactUceCapability info, int operationToken)106 public final void onCapabilityRequestResponse(@SipResponseCode int code, @NonNull String reason, 107 @Nullable RcsContactUceCapability info, int operationToken) throws ImsException { 108 try { 109 getListener().onCapabilityRequestResponseOptions(code, reason, info, operationToken); 110 } catch (RemoteException e) { 111 throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 112 } 113 } 114 115 /** 116 * Inform the framework of a query for this device's UCE capabilities. 117 * <p> 118 * The framework will respond via the 119 * {@link #respondToCapabilityRequest(String, RcsContactUceCapability, int)} or 120 * {@link #respondToCapabilityRequestWithError(Uri, int, String, int)} method. 121 * @param contactUri The URI associated with the remote contact that is requesting capabilities. 122 * @param remoteInfo The remote contact's capability information. 123 * @param operationToken An unique operation token that you have generated that will be returned 124 * by the framework in 125 * {@link #respondToCapabilityRequest(String, RcsContactUceCapability, int)}. 126 * @throws ImsException If this {@link RcsSipOptionsImplBase} instance is not currently 127 * connected to the framework. This can happen if the {@link RcsFeature} is not 128 * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the 129 * {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the 130 * Telephony stack has crashed. 131 */ onRemoteCapabilityRequest(@onNull Uri contactUri, @NonNull RcsContactUceCapability remoteInfo, int operationToken)132 public final void onRemoteCapabilityRequest(@NonNull Uri contactUri, 133 @NonNull RcsContactUceCapability remoteInfo, int operationToken) throws ImsException { 134 try { 135 getListener().onRemoteCapabilityRequest(contactUri, remoteInfo, operationToken); 136 } catch (RemoteException e) { 137 throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); 138 } 139 } 140 141 /** 142 * Push one's own capabilities to a remote user via the SIP OPTIONS presence exchange mechanism 143 * in order to receive the capabilities of the remote user in response. 144 * <p> 145 * The implementer must call 146 * {@link #onCapabilityRequestResponse(int, String, RcsContactUceCapability, int)} to send the 147 * response of this query back to the framework. 148 * @param contactUri The URI of the remote user that we wish to get the capabilities of. 149 * @param capabilities The capabilities of this device to send to the remote user. 150 * @param operationToken A token generated by the framework that will be passed through 151 * {@link #onCapabilityRequestResponse(int, String, RcsContactUceCapability, int)} when this 152 * operation has succeeded. 153 */ sendCapabilityRequest(@onNull Uri contactUri, @NonNull RcsContactUceCapability capabilities, int operationToken)154 public void sendCapabilityRequest(@NonNull Uri contactUri, 155 @NonNull RcsContactUceCapability capabilities, int operationToken) { 156 // Stub - to be implemented by service 157 Log.w(LOG_TAG, "sendCapabilityRequest called with no implementation."); 158 try { 159 getListener().onCommandUpdate(COMMAND_CODE_NOT_SUPPORTED, operationToken); 160 } catch (RemoteException | ImsException e) { 161 // Do not do anything, this is a stub implementation. 162 } 163 } 164 165 /** 166 * Respond to a remote capability request from the contact specified with the capabilities of 167 * this device. 168 * <p> 169 * The framework will use the same token and uri as what was passed in to 170 * {@link #onRemoteCapabilityRequest(Uri, RcsContactUceCapability, int)}. 171 * @param contactUri The URI of the remote contact. 172 * @param ownCapabilities The capabilities of this device. 173 * @param operationToken The token generated by the framework that this service obtained when 174 * {@link #onRemoteCapabilityRequest(Uri, RcsContactUceCapability, int)} was called. 175 */ respondToCapabilityRequest(@onNull String contactUri, @NonNull RcsContactUceCapability ownCapabilities, int operationToken)176 public void respondToCapabilityRequest(@NonNull String contactUri, 177 @NonNull RcsContactUceCapability ownCapabilities, int operationToken) { 178 // Stub - to be implemented by service 179 Log.w(LOG_TAG, "respondToCapabilityRequest called with no implementation."); 180 try { 181 getListener().onCommandUpdate(COMMAND_CODE_NOT_SUPPORTED, operationToken); 182 } catch (RemoteException | ImsException e) { 183 // Do not do anything, this is a stub implementation. 184 } 185 } 186 187 /** 188 * Respond to a remote capability request from the contact specified with the specified error. 189 * <p> 190 * The framework will use the same token and uri as what was passed in to 191 * {@link #onRemoteCapabilityRequest(Uri, RcsContactUceCapability, int)}. 192 * @param contactUri A URI containing the remote contact. 193 * @param code The SIP response code to respond with. 194 * @param reason A non-null String containing the reason associated with the SIP code. 195 * @param operationToken The token provided by the framework when 196 * {@link #onRemoteCapabilityRequest(Uri, RcsContactUceCapability, int)} was called. 197 */ respondToCapabilityRequestWithError(@onNull Uri contactUri, @SipResponseCode int code, @NonNull String reason, int operationToken)198 public void respondToCapabilityRequestWithError(@NonNull Uri contactUri, 199 @SipResponseCode int code, @NonNull String reason, int operationToken) { 200 // Stub - to be implemented by service 201 Log.w(LOG_TAG, "respondToCapabiltyRequestWithError called with no implementation."); 202 try { 203 getListener().onCommandUpdate(COMMAND_CODE_NOT_SUPPORTED, operationToken); 204 } catch (RemoteException | ImsException e) { 205 // Do not do anything, this is a stub implementation. 206 } 207 } 208 } 209