diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java new file mode 100644 index 0000000000000..3c343dd19a86d --- /dev/null +++ b/telephony/java/android/telephony/ims/ImsRcsManager.java @@ -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. + *
+ * 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. + *
+ * 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}. + *
+ * 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. + *
+ * 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. + *
+ * 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);
+ }
+}
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index cc037e3ea8142..effdf48067c36 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -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) {
diff --git a/telephony/java/android/telephony/ims/RcsContactUceCapability.aidl b/telephony/java/android/telephony/ims/RcsContactUceCapability.aidl
new file mode 100644
index 0000000000000..bef6a4037feae
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsContactUceCapability.aidl
@@ -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;
diff --git a/telephony/java/android/telephony/ims/RcsContactUceCapability.java b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
new file mode 100644
index 0000000000000..492170b1069ad
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
@@ -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
+ * 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;
+ }
+}
diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java
new file mode 100644
index 0000000000000..a6a7a84c2c65c
--- /dev/null
+++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java
@@ -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".
+ *
+ * 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
+ * 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
+ * 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.
+ *
+ * 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}.
+ *
+ * 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}*/
diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
index 321bfff406521..4bd49e006da88 100644
--- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java
@@ -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.
*
diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java
new file mode 100644
index 0000000000000..289fd4c8a1343
--- /dev/null
+++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java
@@ -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();
+ }
+}
diff --git a/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java
new file mode 100644
index 0000000000000..44024703042d6
--- /dev/null
+++ b/telephony/java/android/telephony/ims/stub/RcsPresenceExchangeImplBase.java
@@ -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
+ * 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 device’s 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.
+ *
+ * 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
+ * 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.
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * 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);
+ }
+}