Merge "Add APIs for ImsService RCS UCE implementation" am: 01f0935054 am: 3d36c75a4c

am: 6e3a861e5f

Change-Id: Ic17fc014dde2aadad6f27fe6f29370d00e0c7f1d
This commit is contained in:
Brad Ebinger
2019-07-29 15:03:47 -07:00
committed by android-build-merger
10 changed files with 1456 additions and 4 deletions

View File

@@ -0,0 +1,234 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.ims;
import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.content.Context;
import android.os.Binder;
import android.telephony.SubscriptionManager;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.RcsFeature;
import java.util.concurrent.Executor;
/**
* Manager for interfacing with the framework RCS services, including the User Capability Exchange
* (UCE) service, as well as managing user settings.
*
* Use {@link #createForSubscriptionId(Context, int)} to create an instance of this manager.
* @hide
*/
public class ImsRcsManager {
/**
* Receives RCS availability status updates from the ImsService.
*
* @see #isAvailable(int)
* @see #registerRcsAvailabilityCallback(Executor, AvailabilityCallback)
* @see #unregisterRcsAvailabilityCallback(AvailabilityCallback)
*/
public static class AvailabilityCallback {
private static class CapabilityBinder extends IImsCapabilityCallback.Stub {
private final AvailabilityCallback mLocalCallback;
private Executor mExecutor;
CapabilityBinder(AvailabilityCallback c) {
mLocalCallback = c;
}
@Override
public void onCapabilitiesStatusChanged(int config) {
if (mLocalCallback == null) return;
Binder.withCleanCallingIdentity(() ->
mExecutor.execute(() -> mLocalCallback.onAvailabilityChanged(
new RcsFeature.RcsImsCapabilities(config))));
}
@Override
public void onQueryCapabilityConfiguration(int capability, int radioTech,
boolean isEnabled) {
// This is not used for public interfaces.
}
@Override
public void onChangeCapabilityConfigurationError(int capability, int radioTech,
@ImsFeature.ImsCapabilityError int reason) {
// This is not used for public interfaces
}
private void setExecutor(Executor executor) {
mExecutor = executor;
}
}
private final CapabilityBinder mBinder = new CapabilityBinder(this);
/**
* The availability of the feature's capabilities has changed to either available or
* unavailable.
* <p>
* If unavailable, the feature does not support the capability at the current time. This may
* be due to network or subscription provisioning changes, such as the IMS registration
* being lost, network type changing, or OMA-DM provisioning updates.
*
* @param capabilities The new availability of the capabilities.
*/
public void onAvailabilityChanged(RcsFeature.RcsImsCapabilities capabilities) {
}
/**@hide*/
public final IImsCapabilityCallback getBinder() {
return mBinder;
}
private void setExecutor(Executor executor) {
mBinder.setExecutor(executor);
}
}
private final int mSubId;
private final Context mContext;
/**
* Create an instance of ImsRcsManager for the subscription id specified.
*
* @param context The context to create this ImsRcsManager instance within.
* @param subscriptionId The ID of the subscription that this ImsRcsManager will use.
* @see android.telephony.SubscriptionManager#getActiveSubscriptionInfoList()
* @throws IllegalArgumentException if the subscription is invalid.
* @hide
*/
public static ImsRcsManager createForSubscriptionId(Context context, int subscriptionId) {
if (!SubscriptionManager.isValidSubscriptionId(subscriptionId)) {
throw new IllegalArgumentException("Invalid subscription ID");
}
return new ImsRcsManager(context, subscriptionId);
}
/**
* Use {@link #createForSubscriptionId(Context, int)} to create an instance of this class.
*/
private ImsRcsManager(Context context, int subId) {
mContext = context;
mSubId = subId;
}
/**
* Registers an {@link AvailabilityCallback} with the system, which will provide RCS
* availability updates for the subscription specified.
*
* Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to
* subscription changed events and call
* {@link #unregisterRcsAvailabilityCallback(AvailabilityCallback)} to clean up after a
* subscription is removed.
* <p>
* When the callback is registered, it will initiate the callback c to be called with the
* current capabilities.
*
* @param executor The executor the callback events should be run on.
* @param c The RCS {@link AvailabilityCallback} to be registered.
* @see #unregisterRcsAvailabilityCallback(AvailabilityCallback)
* @throws ImsException if the subscription associated with this instance of
* {@link ImsRcsManager} is valid, but the ImsService associated with the subscription is not
* available. This can happen if the ImsService has crashed, for example, or if the subscription
* becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void registerRcsAvailabilityCallback(@CallbackExecutor Executor executor,
@NonNull AvailabilityCallback c) throws ImsException {
if (c == null) {
throw new IllegalArgumentException("Must include a non-null AvailabilityCallback.");
}
if (executor == null) {
throw new IllegalArgumentException("Must include a non-null Executor.");
}
c.setExecutor(executor);
throw new UnsupportedOperationException("registerRcsAvailabilityCallback is not"
+ "supported.");
}
/**
* Removes an existing RCS {@link AvailabilityCallback}.
* <p>
* When the subscription associated with this callback is removed (SIM removed, ESIM swap,
* etc...), this callback will automatically be unregistered. If this method is called for an
* inactive subscription, it will result in a no-op.
* @param c The RCS {@link AvailabilityCallback} to be removed.
* @see #registerRcsAvailabilityCallback(Executor, AvailabilityCallback)
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void unregisterRcsAvailabilityCallback(@NonNull AvailabilityCallback c) {
if (c == null) {
throw new IllegalArgumentException("Must include a non-null AvailabilityCallback.");
}
throw new UnsupportedOperationException("unregisterRcsAvailabilityCallback is not"
+ "supported.");
}
/**
* Query for the capability of an IMS RCS service provided by the framework.
* <p>
* This only reports the status of RCS capabilities provided by the framework, not necessarily
* RCS capabilities provided over-the-top by applications.
*
* @param capability The RCS capability to query.
* @return true if the RCS capability is capable for this subscription, false otherwise. This
* does not necessarily mean that we are registered for IMS and the capability is available, but
* rather the subscription is capable of this service over IMS.
* @see #isAvailable(int)
* @see android.telephony.CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public boolean isCapable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) {
throw new UnsupportedOperationException("isCapable is not supported.");
}
/**
* Query the availability of an IMS RCS capability.
* <p>
* This only reports the status of RCS capabilities provided by the framework, not necessarily
* RCS capabilities provided by over-the-top by applications.
*
* @param capability the RCS capability to query.
* @return true if the RCS capability is currently available for the associated subscription,
* false otherwise. If the capability is available, IMS is registered and the service is
* currently available over IMS.
* @see #isCapable(int)
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public boolean isAvailable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) {
throw new UnsupportedOperationException("isAvailable is not supported.");
}
/**
* @return A new {@link RcsUceAdapter} used for User Capability Exchange (UCE) operations for
* this subscription.
*/
@NonNull
public RcsUceAdapter getUceAdapter() {
return new RcsUceAdapter(mSubId);
}
}

View File

@@ -387,6 +387,24 @@ public class ProvisioningManager {
}
}
/**
* Notify the framework that an RCS autoconfiguration XML file has been received for
* provisioning.
* @param config The XML file to be read. ASCII/UTF8 encoded text if not compressed.
* @param isCompressed The XML file is compressed in gzip format and must be decompressed
* before being read.
* @hide
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void notifyRcsAutoConfigurationReceived(@NonNull byte[] config, boolean isCompressed) {
if (config == null) {
throw new IllegalArgumentException("Must include a non-null config XML file.");
}
// TODO: Connect to ImsConfigImplBase.
throw new UnsupportedOperationException("notifyRcsAutoConfigurationReceived is not"
+ "supported");
}
private static boolean isImsAvailableOnDevice() {
IPackageManager pm = IPackageManager.Stub.asInterface(ServiceManager.getService("package"));
if (pm == null) {

View File

@@ -0,0 +1,20 @@
/*
* Copyright (c) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.ims;
parcelable RcsContactUceCapability;

View File

@@ -0,0 +1,291 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.ims;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Contains the User Capability Exchange capabilities corresponding to a contact's URI.
* @hide
*/
public final class RcsContactUceCapability implements Parcelable {
/** Supports 1-to-1 chat */
public static final int CAPABILITY_CHAT_STANDALONE = (1 << 0);
/** Supports group chat */
public static final int CAPABILITY_CHAT_SESSION = (1 << 1);
/** Supports full store and forward group chat information. */
public static final int CAPABILITY_CHAT_SESSION_STORE_FORWARD = (1 << 2);
/**
* Supports file transfer via Message Session Relay Protocol (MSRP) without Store and Forward.
*/
public static final int CAPABILITY_FILE_TRANSFER = (1 << 3);
/** Supports File Transfer Thumbnail */
public static final int CAPABILITY_FILE_TRANSFER_THUMBNAIL = (1 << 4);
/** Supports File Transfer with Store and Forward */
public static final int CAPABILITY_FILE_TRANSFER_STORE_FORWARD = (1 << 5);
/** Supports File Transfer via HTTP */
public static final int CAPABILITY_FILE_TRANSFER_HTTP = (1 << 6);
/** Supports file transfer via SMS */
public static final int CAPABILITY_FILE_TRANSFER_SMS = (1 << 7);
/** Supports image sharing */
public static final int CAPABILITY_IMAGE_SHARE = (1 << 8);
/** Supports video sharing during a circuit-switch call (IR.74)*/
public static final int CAPABILITY_VIDEO_SHARE_DURING_CS_CALL = (1 << 9);
/** Supports video share outside of voice call (IR.84) */
public static final int CAPABILITY_VIDEO_SHARE = (1 << 10);
/** Supports social presence information */
public static final int CAPABILITY_SOCIAL_PRESENCE = (1 << 11);
/** Supports capability discovery via presence */
public static final int CAPABILITY_DISCOVERY_VIA_PRESENCE = (1 << 12);
/** Supports IP Voice calling over LTE or IWLAN (IR.92/IR.51) */
public static final int CAPABILITY_IP_VOICE_CALL = (1 << 13);
/** Supports IP video calling (IR.94) */
public static final int CAPABILITY_IP_VIDEO_CALL = (1 << 14);
/** Supports Geolocation PUSH during 1-to-1 or multiparty chat */
public static final int CAPABILITY_GEOLOCATION_PUSH = (1 << 15);
/** Supports Geolocation PUSH via SMS for fallback. */
public static final int CAPABILITY_GEOLOCATION_PUSH_SMS = (1 << 16);
/** Supports Geolocation pull. */
public static final int CAPABILITY_GEOLOCATION_PULL = (1 << 17);
/** Supports Geolocation pull using file transfer support. */
public static final int CAPABILITY_GEOLOCATION_PULL_FILE_TRANSFER = (1 << 18);
/** Supports RCS voice calling */
public static final int CAPABILITY_RCS_VOICE_CALL = (1 << 19);
/** Supports RCS video calling */
public static final int CAPABILITY_RCS_VIDEO_CALL = (1 << 20);
/** Supports RCS video calling, where video media can not be dropped */
public static final int CAPABILITY_RCS_VIDEO_ONLY_CALL = (1 << 21);
/** @hide*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "CAPABILITY_", flag = true, value = {
CAPABILITY_CHAT_STANDALONE,
CAPABILITY_CHAT_SESSION,
CAPABILITY_CHAT_SESSION_STORE_FORWARD,
CAPABILITY_FILE_TRANSFER,
CAPABILITY_FILE_TRANSFER_THUMBNAIL,
CAPABILITY_FILE_TRANSFER_STORE_FORWARD,
CAPABILITY_FILE_TRANSFER_HTTP,
CAPABILITY_FILE_TRANSFER_SMS,
CAPABILITY_IMAGE_SHARE,
CAPABILITY_VIDEO_SHARE_DURING_CS_CALL,
CAPABILITY_VIDEO_SHARE,
CAPABILITY_SOCIAL_PRESENCE,
CAPABILITY_DISCOVERY_VIA_PRESENCE,
CAPABILITY_IP_VOICE_CALL,
CAPABILITY_IP_VIDEO_CALL,
CAPABILITY_GEOLOCATION_PUSH,
CAPABILITY_GEOLOCATION_PUSH_SMS,
CAPABILITY_GEOLOCATION_PULL,
CAPABILITY_GEOLOCATION_PULL_FILE_TRANSFER,
CAPABILITY_RCS_VOICE_CALL,
CAPABILITY_RCS_VIDEO_CALL,
CAPABILITY_RCS_VIDEO_ONLY_CALL
})
public @interface CapabilityFlag {}
/**
* Builder to help construct {@link RcsContactUceCapability} instances.
*/
public static class Builder {
private final RcsContactUceCapability mCapabilities;
/**
* Create the Builder, which can be used to set UCE capabilities as well as custom
* capability extensions.
* @param contact The contact URI that the capabilities are attached to.
*/
public Builder(@NonNull Uri contact) {
mCapabilities = new RcsContactUceCapability(contact);
}
/**
* Add a UCE capability bit-field as well as the associated URI that the framework should
* use for those services. This is mainly used for capabilities that may use a URI separate
* from the contact's URI, for example the URI to use for VT calls.
* @param type The capability to map to a service URI that is different from the contact's
* URI.
*/
public Builder add(@CapabilityFlag int type, @NonNull Uri serviceUri) {
mCapabilities.mCapabilities |= type;
// Put each of these capabilities into the map separately.
for (int shift = 0; shift < Integer.SIZE; shift++) {
int cap = type & (1 << shift);
if (cap != 0) {
mCapabilities.mServiceMap.put(cap, serviceUri);
// remove that capability from the field.
type &= ~cap;
}
if (type == 0) {
// no need to keep going, end early.
break;
}
}
return this;
}
/**
* Add a UCE capability flag that this contact supports.
* @param type the capability that the contact supports.
*/
public Builder add(@CapabilityFlag int type) {
mCapabilities.mCapabilities |= type;
return this;
}
/**
* Add a carrier specific service tag.
* @param extension A string containing a carrier specific service tag that is an extension
* of the {@link CapabilityFlag}s that are defined here.
*/
public Builder add(@NonNull String extension) {
mCapabilities.mExtensionTags.add(extension);
return this;
}
/**
* @return the constructed instance.
*/
public RcsContactUceCapability build() {
return mCapabilities;
}
}
private final Uri mContactUri;
private int mCapabilities;
private List<String> mExtensionTags = new ArrayList<>();
private Map<Integer, Uri> mServiceMap = new HashMap<>();
/**
* Use {@link Builder} to build an instance of this interface.
* @param contact The URI associated with this capability information.
* @hide
*/
RcsContactUceCapability(@NonNull Uri contact) {
mContactUri = contact;
}
private RcsContactUceCapability(Parcel in) {
mContactUri = in.readParcelable(Uri.class.getClassLoader());
mCapabilities = in.readInt();
in.readStringList(mExtensionTags);
// read mServiceMap as key,value pair
int mapSize = in.readInt();
for (int i = 0; i < mapSize; i++) {
mServiceMap.put(in.readInt(), in.readParcelable(Uri.class.getClassLoader()));
}
}
public static final Creator<RcsContactUceCapability> CREATOR =
new Creator<RcsContactUceCapability>() {
@Override
public RcsContactUceCapability createFromParcel(Parcel in) {
return new RcsContactUceCapability(in);
}
@Override
public RcsContactUceCapability[] newArray(int size) {
return new RcsContactUceCapability[size];
}
};
@Override
public void writeToParcel(Parcel out, int flags) {
out.writeParcelable(mContactUri, 0);
out.writeInt(mCapabilities);
out.writeStringList(mExtensionTags);
// write mServiceMap as key,value pairs
int mapSize = mServiceMap.keySet().size();
out.writeInt(mapSize);
for (int key : mServiceMap.keySet()) {
out.writeInt(key);
out.writeParcelable(mServiceMap.get(key), 0);
}
}
@Override
public int describeContents() {
return 0;
}
/**
* Query for a capability
* @param type The capability flag to query.
* @return true if the capability flag specified is set, false otherwise.
*/
public boolean isCapable(@CapabilityFlag int type) {
return (mCapabilities & type) > 0;
}
/**
* @return true if the extension service tag is set, false otherwise.
*/
public boolean isCapable(@NonNull String extensionTag) {
return mExtensionTags.contains(extensionTag);
}
/**
* @return An immutable list containing all of the extension tags that have been set as capable.
* @throws UnsupportedOperationException if this list is modified.
*/
public @NonNull List<String> getCapableExtensionTags() {
return Collections.unmodifiableList(mExtensionTags);
}
/**
* Retrieves the {@link Uri} associated with the capability being queried.
* <p>
* This will typically be the contact {@link Uri} available via {@link #getContactUri()} unless
* a different service {@link Uri} was associated with this capability using
* {@link Builder#add(int, Uri)}.
*
* @return a String containing the {@link Uri} associated with the service tag or
* {@code null} if this capability is not set as capable.
* @see #isCapable(int)
*/
public @Nullable Uri getServiceUri(@CapabilityFlag int type) {
Uri result = mServiceMap.getOrDefault(type, null);
// If the capability is capable, but does not have a service URI associated, use the default
// contact URI.
if (result == null) {
return isCapable(type) ? getContactUri() : null;
}
return result;
}
/**
* @return the URI representing the contact associated with the capabilities.
*/
public @NonNull Uri getContactUri() {
return mContactUri;
}
}

View File

@@ -0,0 +1,276 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.ims;
import android.Manifest;
import android.annotation.CallbackExecutor;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.content.Context;
import android.net.Uri;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.concurrent.Executor;
/**
* Manages RCS User Capability Exchange for the subscription specified.
*
* @see ImsRcsManager#getUceAdapter() for information on creating an instance of this class.
* @hide
*/
public class RcsUceAdapter {
/**
* An unknown error has caused the request to fail.
*/
public static final int ERROR_GENERIC_FAILURE = 1;
/**
* The carrier network does not have UCE support enabled for this subscriber.
*/
public static final int ERROR_NOT_ENABLED = 2;
/**
* The data network that the device is connected to does not support UCE currently (e.g. it is
* 1x only currently).
*/
public static final int ERROR_NOT_AVAILABLE = 3;
/**
* The network has responded with SIP 403 error and a reason "User not registered."
*/
public static final int ERROR_NOT_REGISTERED = 4;
/**
* The network has responded to this request with a SIP 403 error and reason "not authorized for
* presence" for this subscriber.
*/
public static final int ERROR_NOT_AUTHORIZED = 5;
/**
* The network has responded to this request with a SIP 403 error and no reason.
*/
public static final int ERROR_FORBIDDEN = 6;
/**
* The contact URI requested is not provisioned for VoLTE or it is not known as an IMS
* subscriber to the carrier network.
*/
public static final int ERROR_NOT_FOUND = 7;
/**
* The capabilities request contained too many URIs for the carrier network to handle. Retry
* with a lower number of contact numbers. The number varies per carrier.
*/
// TODO: Try to integrate this into the API so that the service will split based on carrier.
public static final int ERROR_REQUEST_TOO_LARGE = 8;
/**
* The network did not respond to the capabilities request before the request timed out.
*/
public static final int ERROR_REQUEST_TIMEOUT = 10;
/**
* The request failed due to the service having insufficient memory.
*/
public static final int ERROR_INSUFFICIENT_MEMORY = 11;
/**
* The network was lost while trying to complete the request.
*/
public static final int ERROR_LOST_NETWORK = 12;
/**
* The request has failed because the same request has already been added to the queue.
*/
public static final int ERROR_ALREADY_IN_QUEUE = 13;
/**@hide*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "ERROR_", value = {
ERROR_GENERIC_FAILURE,
ERROR_NOT_ENABLED,
ERROR_NOT_AVAILABLE,
ERROR_NOT_REGISTERED,
ERROR_NOT_AUTHORIZED,
ERROR_FORBIDDEN,
ERROR_NOT_FOUND,
ERROR_REQUEST_TOO_LARGE,
ERROR_REQUEST_TIMEOUT,
ERROR_INSUFFICIENT_MEMORY,
ERROR_LOST_NETWORK,
ERROR_ALREADY_IN_QUEUE
})
public @interface ErrorCode {}
/**
* The last publish has resulted in a "200 OK" response or the device is using SIP OPTIONS for
* UCE.
*/
public static final int PUBLISH_STATE_200_OK = 1;
/**
* The hasn't published its capabilities since boot or hasn't gotten any publish response yet.
*/
public static final int PUBLISH_STATE_NOT_PUBLISHED = 2;
/**
* The device has tried to publish its capabilities, which has resulted in an error. This error
* is related to the fact that the device is not VoLTE provisioned.
*/
public static final int PUBLISH_STATE_VOLTE_PROVISION_ERROR = 3;
/**
* The device has tried to publish its capabilities, which has resulted in an error. This error
* is related to the fact that the device is not RCS or UCE provisioned.
*/
public static final int PUBLISH_STATE_RCS_PROVISION_ERROR = 4;
/**
* The last publish resulted in a "408 Request Timeout" response.
*/
public static final int PUBLISH_STATE_REQUEST_TIMEOUT = 5;
/**
* The last publish resulted in another unknown error, such as SIP 503 - "Service Unavailable"
* or SIP 423 - "Interval too short".
* <p>
* Device shall retry with exponential back-off.
*/
public static final int PUBLISH_STATE_OTHER_ERROR = 6;
/**@hide*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "PUBLISH_STATE_", value = {
PUBLISH_STATE_200_OK,
PUBLISH_STATE_NOT_PUBLISHED,
PUBLISH_STATE_VOLTE_PROVISION_ERROR,
PUBLISH_STATE_RCS_PROVISION_ERROR,
PUBLISH_STATE_REQUEST_TIMEOUT,
PUBLISH_STATE_OTHER_ERROR
})
public @interface PublishState {}
/**
* Provides a one-time callback for the response to a UCE request. After this callback is called
* by the framework, the reference to this callback will be discarded on the service side.
* @see #requestCapabilities(Executor, List, CapabilitiesCallback)
*/
public static class CapabilitiesCallback {
/**
* Notify this application that the pending capability request has returned successfully.
* @param contactCapabilities List of capabilities associated with each contact requested.
*/
public void onCapabilitiesReceived(
@NonNull List<RcsContactUceCapability> contactCapabilities) {
}
/**
* The pending request has resulted in an error and may need to be retried, depending on the
* error code.
* @param errorCode The reason for the framework being unable to process the request.
*/
public void onError(@ErrorCode int errorCode) {
}
}
private final int mSubId;
/**
* Not to be instantiated directly, use
* {@link ImsRcsManager#createForSubscriptionId(Context, int)} and
* {@link ImsRcsManager#getUceAdapter()} to instantiate this manager class.
*/
RcsUceAdapter(int subId) {
mSubId = subId;
}
/**
* Request the User Capability Exchange capabilities for one or more contacts.
* <p>
* Be sure to check the availability of this feature using
* {@link ImsRcsManager#isAvailable(int)} and ensuring
* {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} or
* {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE} is enabled or else
* this operation will fail with {@link #ERROR_NOT_AVAILABLE} or {@link #ERROR_NOT_ENABLED}.
*
* @param executor The executor that will be used when the request is completed and the
* {@link CapabilitiesCallback} is called.
* @param contactNumbers A list of numbers that the capabilities are being requested for.
* @param c A one-time callback for when the request for capabilities completes or there is an
* error processing the request.
* @throws ImsException if the subscription associated with this instance of
* {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not
* available. This can happen if the ImsService has crashed, for example, or if the subscription
* becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void requestCapabilities(@CallbackExecutor Executor executor,
@NonNull List<Uri> contactNumbers,
@NonNull CapabilitiesCallback c) throws ImsException {
throw new UnsupportedOperationException("isUceSettingEnabled is not supported.");
}
/**
* Gets the last publish result from the UCE service if the device is using an RCS presence
* server.
* @return The last publish result from the UCE service. If the device is using SIP OPTIONS,
* this method will return {@link #PUBLISH_STATE_200_OK} as well.
* @throws ImsException if the subscription associated with this instance of
* {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not
* available. This can happen if the ImsService has crashed, for example, or if the subscription
* becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public @PublishState int getUcePublishState() throws ImsException {
throw new UnsupportedOperationException("getPublishState is not supported.");
}
/**
* The users setting for whether or not Presence and User Capability Exchange (UCE) is enabled
* for the associated subscription.
*
* @return true if the users setting for UCE is enabled, false otherwise. If false,
* {@link ImsRcsManager#isCapable(int)} will return false for
* {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} and
* {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE}
* @see #setUceSettingEnabled(boolean)
* @throws ImsException if the subscription associated with this instance of
* {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not
* available. This can happen if the ImsService has crashed, for example, or if the subscription
* becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public boolean isUceSettingEnabled() throws ImsException {
// TODO: add SubscriptionController column for this property.
throw new UnsupportedOperationException("isUceSettingEnabled is not supported.");
}
/**
* Change the users setting for whether or not UCE is enabled for the associated subscription.
* @param isEnabled the user's setting for whether or not they wish for Presence and User
* Capability Exchange to be enabled. If false,
* {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} and
* {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE} capability will be
* disabled, depending on which type of UCE the carrier supports.
* @see #isUceSettingEnabled()
* @throws ImsException if the subscription associated with this instance of
* {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not
* available. This can happen if the ImsService has crashed, for example, or if the subscription
* becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
public void setUceSettingEnabled(boolean isEnabled) throws ImsException {
// TODO: add SubscriptionController column for this property.
throw new UnsupportedOperationException("setUceSettingEnabled is not supported.");
}
}

View File

@@ -16,8 +16,14 @@
package android.telephony.ims.feature;
import android.annotation.IntDef;
import android.annotation.SystemApi;
import android.telephony.ims.aidl.IImsRcsFeature;
import android.telephony.ims.stub.RcsPresenceExchangeImplBase;
import android.telephony.ims.stub.RcsSipOptionsImplBase;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Base implementation of the RcsFeature APIs. Any ImsService wishing to support RCS should extend
@@ -32,18 +38,165 @@ public class RcsFeature extends ImsFeature {
// Empty Default Implementation.
};
/**
* Contains the capabilities defined and supported by a {@link RcsFeature} in the
* form of a bitmask. The capabilities that are used in the RcsFeature are
* defined as:
* {@link RcsImsCapabilityFlag#CAPABILITY_TYPE_OPTIONS_UCE}
* {@link RcsImsCapabilityFlag#CAPABILITY_TYPE_PRESENCE_UCE}
*
* The enabled capabilities of this RcsFeature will be set by the framework
* using {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}.
* After the capabilities have been set, the RcsFeature may then perform the necessary bring up
* of the capability and notify the capability status as true using
* {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. This will signal to the
* framework that the capability is available for usage.
* @hide
*/
public static class RcsImsCapabilities extends Capabilities {
/** @hide*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "CAPABILITY_TYPE_", flag = true, value = {
CAPABILITY_TYPE_OPTIONS_UCE,
CAPABILITY_TYPE_PRESENCE_UCE
})
public @interface RcsImsCapabilityFlag {}
public RcsFeature() {
super();
/**
* This carrier supports User Capability Exchange using SIP OPTIONS as defined by the
* framework. If set, the RcsFeature should support capability exchange using SIP OPTIONS.
* If not set, this RcsFeature should not service capability requests.
* @hide
*/
public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1 << 0;
/**
* This carrier supports User Capability Exchange using a presence server as defined by the
* framework. If set, the RcsFeature should support capability exchange using a presence
* server. If not set, this RcsFeature should not publish capabilities or service capability
* requests using presence.
* @hide
*/
public static final int CAPABILITY_TYPE_PRESENCE_UCE = 1 << 1;
/**@hide*/
public RcsImsCapabilities(@RcsImsCapabilityFlag int capabilities) {
}
/**@hide*/
@Override
public void addCapabilities(@RcsImsCapabilityFlag int capabilities) {
}
/**@hide*/
@Override
public void removeCapabilities(@RcsImsCapabilityFlag int capabilities) {
}
/**@hide*/
@Override
public boolean isCapable(@RcsImsCapabilityFlag int capabilities) {
return false;
}
}
/**
* Query the current {@link RcsImsCapabilities} status set by the RcsFeature. If a capability is
* set, the {@link RcsFeature} has brought up the capability and is ready for framework
* requests. To change the status of the capabilities
* {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)} should be called.
* @hide
*/
@Override
public final RcsImsCapabilities queryCapabilityStatus() {
throw new UnsupportedOperationException();
}
/**
* {@inheritDoc}
* Notify the framework that the capabilities status has changed. If a capability is enabled,
* this signals to the framework that the capability has been initialized and is ready.
* Call {@link #queryCapabilityStatus()} to return the current capability status.
* @hide
*/
public final void notifyCapabilitiesStatusChanged(RcsImsCapabilities c) {
throw new UnsupportedOperationException();
}
/**
* Provides the RcsFeature with the ability to return the framework capability configuration set
* by the framework. When the framework calls
* {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)} to
* enable or disable capability A, this method should return the correct configuration for
* capability A afterwards (until it has changed).
* @hide
*/
public boolean queryCapabilityConfiguration(
@RcsImsCapabilities.RcsImsCapabilityFlag int capability) {
throw new UnsupportedOperationException();
}
/**
* Called from the framework when the {@link RcsImsCapabilities} that have been configured for
* this {@link RcsFeature} has changed.
* <p>
* For each newly enabled capability flag, the corresponding capability should be brought up in
* the {@link RcsFeature} and registered on the network. For each newly disabled capability
* flag, the corresponding capability should be brought down, and deregistered. Once a new
* capability has been initialized and is ready for usage, the status of that capability should
* also be set to true using {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. This
* will notify the framework that the capability is ready.
* <p>
* If for some reason one or more of these capabilities can not be enabled/disabled,
* {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError(int, int, int)} should
* be called for each capability change that resulted in an error.
* @hide
*/
@Override
public void changeEnabledCapabilities(CapabilityChangeRequest request,
CapabilityCallbackProxy c) {
// Do nothing for base implementation.
throw new UnsupportedOperationException();
}
/**
* Retrieve the implementation of SIP OPTIONS for this {@link RcsFeature}.
* <p>
* Will only be requested by the framework if capability exchange via SIP OPTIONS is
* configured as capable during a
* {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}
* operation and the RcsFeature sets the status of the capability to true using
* {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}.
*
* @return An instance of {@link RcsSipOptionsImplBase} that implements SIP options exchange if
* it is supported by the device.
* @hide
*/
public RcsSipOptionsImplBase getOptionsExchangeImpl() {
// Base Implementation, override to implement functionality
return new RcsSipOptionsImplBase();
}
/**
* Retrieve the implementation of UCE presence for this {@link RcsFeature}.
* Will only be requested by the framework if presence exchang is configured as capable during
* a {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}
* operation and the RcsFeature sets the status of the capability to true using
* {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}.
*
* @return An instance of {@link RcsPresenceExchangeImplBase} that implements presence
* exchange if it is supported by the device.
* @hide
*/
public RcsPresenceExchangeImplBase getPresenceExchangeImpl() {
// Base Implementation, override to implement functionality.
return new RcsPresenceExchangeImplBase();
}
/**
* Construct a new {@link RcsFeature} instance.
*/
public RcsFeature() {
super();
}
/**{@inheritDoc}*/

View File

@@ -341,6 +341,17 @@ public class ImsConfigImplBase {
}
}
/**
* The framework has received an RCS autoconfiguration XML file for provisioning.
*
* @param config The XML file to be read, if not compressed, it should be in ASCII/UTF8 format.
* @param isCompressed The XML file is compressed in gzip format and must be decompressed
* before being read.
* @hide
*/
public void notifyRcsAutoConfigurationReceived(byte[] config, boolean isCompressed) {
}
/**
* Sets the configuration value for this ImsService.
*

View File

@@ -0,0 +1,89 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.ims.stub;
import android.annotation.IntDef;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Base class for different types of Capability exchange, presence using
* {@link RcsPresenceExchangeImplBase} and SIP OPTIONS exchange using {@link RcsSipOptionsImplBase}.
*
* @hide
*/
public class RcsCapabilityExchange {
/** Service is unknown. */
public static final int COMMAND_CODE_SERVICE_UNKNOWN = 0;
/** The command completed successfully. */
public static final int COMMAND_CODE_SUCCESS = 1;
/** The command failed with an unknown error. */
public static final int COMMAND_CODE_GENERIC_FAILURE = 2;
/** Invalid parameter(s). */
public static final int COMMAND_CODE_INVALID_PARAM = 3;
/** Fetch error. */
public static final int COMMAND_CODE_FETCH_ERROR = 4;
/** Request timed out. */
public static final int COMMAND_CODE_REQUEST_TIMEOUT = 5;
/** Failure due to insufficient memory available. */
public static final int COMMAND_CODE_INSUFFICIENT_MEMORY = 6;
/** Network connection is lost. */
public static final int COMMAND_CODE_LOST_NETWORK_CONNECTION = 7;
/** Requested feature/resource is not supported. */
public static final int COMMAND_CODE_NOT_SUPPORTED = 8;
/** Contact or resource is not found. */
public static final int COMMAND_CODE_NOT_FOUND = 9;
/** Service is not available. */
public static final int COMMAND_CODE_SERVICE_UNAVAILABLE = 10;
/** No Change in Capabilities */
public static final int COMMAND_CODE_NO_CHANGE_IN_CAP = 11;
/** @hide*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "COMMAND_CODE_", value = {
COMMAND_CODE_SERVICE_UNKNOWN,
COMMAND_CODE_SUCCESS,
COMMAND_CODE_GENERIC_FAILURE,
COMMAND_CODE_INVALID_PARAM,
COMMAND_CODE_FETCH_ERROR,
COMMAND_CODE_REQUEST_TIMEOUT,
COMMAND_CODE_INSUFFICIENT_MEMORY,
COMMAND_CODE_LOST_NETWORK_CONNECTION,
COMMAND_CODE_NOT_SUPPORTED,
COMMAND_CODE_NOT_FOUND,
COMMAND_CODE_SERVICE_UNAVAILABLE,
COMMAND_CODE_NO_CHANGE_IN_CAP
})
public @interface CommandCode {}
/**
* Provides the framework with an update as to whether or not a command completed successfully
* locally. This includes capabilities requests and updates from the network. If it does not
* complete successfully, then the framework may retry the command again later, depending on the
* error. If the command does complete successfully, the framework will then wait for network
* updates.
*
* @param code The result of the pending command. If {@link #COMMAND_CODE_SUCCESS}, further
* updates will be sent for this command using the associated operationToken.
* @param operationToken the token associated with the pending command.
*/
public final void onCommandUpdate(@CommandCode int code, int operationToken) {
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,191 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.ims.stub;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.net.Uri;
import android.telephony.ims.RcsContactUceCapability;
import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
/**
* Base implementation for RCS User Capability Exchange using Presence. Any ImsService implementing
* this service must implement the stub methods {@link #requestCapabilities(List, int)} and
* {@link #updateCapabilities(RcsContactUceCapability, int)}.
*
* @hide
*/
public class RcsPresenceExchangeImplBase extends RcsCapabilityExchange {
private static final String LOG_TAG = "RcsPresenceExchangeIB";
/**
* The request has resulted in any other 4xx/5xx/6xx that is not covered below. No retry will be
* attempted.
*/
public static final int RESPONSE_SUBSCRIBE_GENERIC_FAILURE = -1;
/**
* The request has succeeded with a “200” message from the network.
*/
public static final int RESPONSE_SUCCESS = 0;
/**
* The request has resulted in a “403” (User Not Registered) error from the network. Will retry
* capability polling with an exponential backoff.
*/
public static final int RESPONSE_NOT_REGISTERED = 1;
/**
* The request has resulted in a “403” (not authorized (Requestor)) error from the network. No
* retry will be attempted.
*/
public static final int RESPONSE_NOT_AUTHORIZED_FOR_PRESENCE = 2;
/**
* The request has resulted in a "403” (Forbidden) or other “403” error from the network and
* will be handled the same as “404” Not found. No retry will be attempted.
*/
public static final int RESPONSE_FORBIDDEN = 3;
/**
* The request has resulted in a “404” (Not found) result from the network. No retry will be
* attempted.
*/
public static final int RESPONSE_NOT_FOUND = 4;
/**
* The request has resulted in a “408” response. Retry after exponential backoff.
*/
public static final int RESPONSE_SIP_REQUEST_TIMEOUT = 5;
/**
* The network has responded with a “413” (Too Large) response from the network. Capability
* request contains too many items and must be shrunk before the request will be accepted.
*/
public static final int RESPONSE_SUBSCRIBE_TOO_LARGE = 6;
/**
* The request has resulted in a “423” response. Retry after exponential backoff.
*/
public static final int RESPONSE_SIP_INTERVAL_TOO_SHORT = 7;
/**
* The request has resulted in a “503” response. Retry after exponential backoff.
*/
public static final int RESPONSE_SIP_SERVICE_UNAVAILABLE = 8;
/** @hide*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "RESPONSE_", value = {
RESPONSE_SUBSCRIBE_GENERIC_FAILURE,
RESPONSE_SUCCESS,
RESPONSE_NOT_REGISTERED,
RESPONSE_NOT_AUTHORIZED_FOR_PRESENCE,
RESPONSE_FORBIDDEN,
RESPONSE_NOT_FOUND,
RESPONSE_SIP_REQUEST_TIMEOUT,
RESPONSE_SUBSCRIBE_TOO_LARGE,
RESPONSE_SIP_INTERVAL_TOO_SHORT,
RESPONSE_SIP_SERVICE_UNAVAILABLE
})
public @interface PresenceResponseCode {}
/**
* Provide the framework with a subsequent network response update to
* {@link #updateCapabilities(RcsContactUceCapability, int)} and
* {@link #requestCapabilities(List, int)} operations.
* @param code The SIP response code sent from the network for the operation token specified.
* @param reason The optional reason response from the network. If the network provided no
* reason with the code, the string should be empty.
* @param operationToken The token associated with the operation this service is providing a
* response for.
*/
public final void onNetworkResponse(@PresenceResponseCode int code, @NonNull String reason,
int operationToken) {
throw new UnsupportedOperationException();
}
/**
* Provides the framework with the requested contacts capabilities requested by the framework
* using {@link #requestCapabilities(List, int)} .
*/
public final void onCapabilityRequestResponse(@NonNull List<RcsContactUceCapability> infos,
int operationToken) {
throw new UnsupportedOperationException();
}
/**
* Trigger the framework to provide a capability update using
* {@link #updateCapabilities(RcsContactUceCapability, int)}. This is typically used when trying
* to generate an initial PUBLISH for a new subscription to the network.
* <p>
* The device will cache all presence publications after boot until this method is called once.
*/
public final void onNotifyUpdateCapabilites() {
throw new UnsupportedOperationException();
}
/**
* Notify the framework that the devices capabilities have been unpublished from the network.
*/
public final void onUnpublish() {
throw new UnsupportedOperationException();
}
/**
* The user capabilities of one or multiple contacts have been requested.
* <p>
* This must be followed up with one call to {@link #onCommandUpdate(int, int)} with an update
* as to whether or not the command completed as well as subsequent network
* updates using {@link #onNetworkResponse(int, String, int)}. When the operation is completed,
* {@link #onCapabilityRequestResponse(List, int)} should be called with
* the presence information for the contacts specified.
* @param uris A {@link List} of the URIs that the framework is requesting the UCE capabilities
* for.
* @param operationToken The token associated with this operation. Updates to this request using
* {@link #onCommandUpdate(int, int)}, {@link #onNetworkResponse(int, String, int)}, and
* {@link #onCapabilityRequestResponse(List, int)} must use the same operation token
* in response.
*/
public void requestCapabilities(@NonNull List<Uri> uris, int operationToken) {
// Stub - to be implemented by service
Log.w(LOG_TAG, "requestCapabilities called with no implementation.");
onCommandUpdate(COMMAND_CODE_GENERIC_FAILURE, operationToken);
}
/**
* The capabilities of this device have been updated and should be published
* to the network. The framework will expect one {@link #onCommandUpdate(int, int)} call to
* indicate whether or not this operation failed first as well as network response
* updates to this update using {@link #onNetworkResponse(int, String, int)}.
* @param capabilities The capabilities for this device.
* @param operationToken The token associated with this operation. Any subsequent
* {@link #onCommandUpdate(int, int)} or {@link #onNetworkResponse(int, String, int)}
* calls regarding this update must use the same token.
*/
public void updateCapabilities(@NonNull RcsContactUceCapability capabilities,
int operationToken) {
// Stub - to be implemented by service
Log.w(LOG_TAG, "updateCapabilities called with no implementation.");
onCommandUpdate(COMMAND_CODE_GENERIC_FAILURE, operationToken);
}
}

View File

@@ -0,0 +1,169 @@
/*
* Copyright (C) 2018 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.ims.stub;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.Uri;
import android.telephony.ims.RcsContactUceCapability;
import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Base implementation for RCS User Capability Exchange using SIP OPTIONS.
*
* @hide
*/
public class RcsSipOptionsImplBase extends RcsCapabilityExchange {
private static final String LOG_TAG = "RcsSipOptionsImplBase";
/**
* Indicates a SIP response from the remote user other than 200, 480, 408, 404, or 604.
*/
public static final int RESPONSE_GENERIC_FAILURE = -1;
/**
* Indicates that the remote user responded with a 200 OK response.
*/
public static final int RESPONSE_SUCCESS = 0;
/**
* Indicates that the remote user responded with a 480 TEMPORARY UNAVAILABLE response.
*/
public static final int RESPONSE_TEMPORARILY_UNAVAILABLE = 1;
/**
* Indicates that the remote user responded with a 408 REQUEST TIMEOUT response.
*/
public static final int RESPONSE_REQUEST_TIMEOUT = 2;
/**
* Indicates that the remote user responded with a 404 NOT FOUND response.
*/
public static final int RESPONSE_NOT_FOUND = 3;
/**
* Indicates that the remote user responded with a 604 DOES NOT EXIST ANYWHERE response.
*/
public static final int RESPONSE_DOES_NOT_EXIST_ANYWHERE = 4;
/** @hide*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "RESPONSE_", value = {
RESPONSE_GENERIC_FAILURE,
RESPONSE_SUCCESS,
RESPONSE_TEMPORARILY_UNAVAILABLE,
RESPONSE_REQUEST_TIMEOUT,
RESPONSE_NOT_FOUND,
RESPONSE_DOES_NOT_EXIST_ANYWHERE
})
public @interface SipResponseCode {}
/**
* Send the response of a SIP OPTIONS capability exchange to the framework. If {@code code} is
* {@link #RESPONSE_SUCCESS}, info must be non-null.
* @param code The SIP response code that was sent by the network in response to the request
* sent by {@link #sendCapabilityRequest(Uri, RcsContactUceCapability, int)}.
* @param reason The optional SIP response reason sent by the network. If none was sent, this
* should be an empty string.
* @param info the contact's UCE capabilities associated with the capability request.
* @param operationToken The token associated with the original capability request, set by
* {@link #sendCapabilityRequest(Uri, RcsContactUceCapability, int)}.
*/
public final void onCapabilityRequestResponse(@SipResponseCode int code, @NonNull String reason,
@Nullable RcsContactUceCapability info, int operationToken) {
throw new UnsupportedOperationException();
}
/**
* Inform the framework of a query for this device's UCE capabilities.
* <p>
* The framework will respond via the
* {@link #respondToCapabilityRequest(String, RcsContactUceCapability, int)} or
* {@link #respondToCapabilityRequestWithError(Uri, int, String, int)} method.
* @param contactUri The URI associated with the remote contact that is requesting capabilities.
* @param remoteInfo The remote contact's capability information.
* @param operationToken An unique operation token that you have generated that will be returned
* by the framework in
* {@link #respondToCapabilityRequest(String, RcsContactUceCapability, int)}.
*/
public final void onRemoteCapabilityRequest(@NonNull Uri contactUri,
@NonNull RcsContactUceCapability remoteInfo, int operationToken) {
throw new UnsupportedOperationException();
}
/**
* Push one's own capabilities to a remote user via the SIP OPTIONS presence exchange mechanism
* in order to receive the capabilities of the remote user in response.
* <p>
* The implementer must call
* {@link #onCapabilityRequestResponse(int, String, RcsContactUceCapability, int)} to send the
* response of this query back to the framework.
* @param contactUri The URI of the remote user that we wish to get the capabilities of.
* @param capabilities The capabilities of this device to send to the remote user.
* @param operationToken A token generated by the framework that will be passed through
* {@link #onCapabilityRequestResponse(int, String, RcsContactUceCapability, int)} when this
* operation has succeeded.
*/
public void sendCapabilityRequest(@NonNull Uri contactUri,
@NonNull RcsContactUceCapability capabilities, int operationToken) {
// Stub - to be implemented by service
Log.w(LOG_TAG, "sendCapabilityRequest called with no implementation.");
onCommandUpdate(COMMAND_CODE_GENERIC_FAILURE, operationToken);
}
/**
* Respond to a remote capability request from the contact specified with the capabilities of
* this device.
* <p>
* The framework will use the same token and uri as what was passed in to
* {@link #onRemoteCapabilityRequest(Uri, RcsContactUceCapability, int)}.
* @param contactUri The URI of the remote contact.
* @param ownCapabilities The capabilities of this device.
* @param operationToken The token generated by the framework that this service obtained when
* {@link #onRemoteCapabilityRequest(Uri, RcsContactUceCapability, int)} was called.
*/
public void respondToCapabilityRequest(@NonNull String contactUri,
@NonNull RcsContactUceCapability ownCapabilities, int operationToken) {
// Stub - to be implemented by service
Log.w(LOG_TAG, "respondToCapabilityRequest called with no implementation.");
onCommandUpdate(COMMAND_CODE_GENERIC_FAILURE, operationToken);
}
/**
* Respond to a remote capability request from the contact specified with the specified error.
* <p>
* The framework will use the same token and uri as what was passed in to
* {@link #onRemoteCapabilityRequest(Uri, RcsContactUceCapability, int)}.
* @param contactUri A URI containing the remote contact.
* @param code The SIP response code to respond with.
* @param reason A non-null String containing the reason associated with the SIP code.
* @param operationToken The token provided by the framework when
* {@link #onRemoteCapabilityRequest(Uri, RcsContactUceCapability, int)} was called.
*
*/
public void respondToCapabilityRequestWithError(@NonNull Uri contactUri,
@SipResponseCode int code, @NonNull String reason, int operationToken) {
// Stub - to be implemented by service
Log.w(LOG_TAG, "respondToCapabiltyRequestWithError called with no implementation.");
onCommandUpdate(COMMAND_CODE_GENERIC_FAILURE, operationToken);
}
}