diff --git a/core/api/system-current.txt b/core/api/system-current.txt index 92c18c68c4ff..86f1eaeea3ad 100644 --- a/core/api/system-current.txt +++ b/core/api/system-current.txt @@ -11745,6 +11745,7 @@ package android.telephony.ims { method @Nullable public android.telephony.ims.RcsContactPresenceTuple getCapabilityTuple(@NonNull String); method @NonNull public java.util.List getCapabilityTuples(); method @NonNull public android.net.Uri getContactUri(); + method @NonNull public java.util.Set getFeatureTags(); method public int getRequestResult(); method public int getSourceType(); method public void writeToParcel(@NonNull android.os.Parcel, int); @@ -11759,6 +11760,14 @@ package android.telephony.ims { field public static final int SOURCE_TYPE_NETWORK = 0; // 0x0 } + public static final class RcsContactUceCapability.OptionsBuilder { + ctor public RcsContactUceCapability.OptionsBuilder(@NonNull android.net.Uri); + method @NonNull public android.telephony.ims.RcsContactUceCapability.OptionsBuilder addFeatureTag(@NonNull String); + method @NonNull public android.telephony.ims.RcsContactUceCapability.OptionsBuilder addFeatureTags(@NonNull java.util.Set); + method @NonNull public android.telephony.ims.RcsContactUceCapability build(); + method @NonNull public android.telephony.ims.RcsContactUceCapability.OptionsBuilder setRequestResult(int); + } + public static final class RcsContactUceCapability.PresenceBuilder { ctor public RcsContactUceCapability.PresenceBuilder(@NonNull android.net.Uri, int, int); method @NonNull public android.telephony.ims.RcsContactUceCapability.PresenceBuilder addCapabilityTuple(@NonNull android.telephony.ims.RcsContactPresenceTuple); @@ -12052,7 +12061,7 @@ package android.telephony.ims.feature { package android.telephony.ims.stub { public interface CapabilityExchangeEventListener { - method public void onRemoteCapabilityRequest(@NonNull android.net.Uri, @NonNull java.util.List, @NonNull android.telephony.ims.stub.CapabilityExchangeEventListener.OptionsRequestCallback) throws android.telephony.ims.ImsException; + method public void onRemoteCapabilityRequest(@NonNull android.net.Uri, @NonNull java.util.Set, @NonNull android.telephony.ims.stub.CapabilityExchangeEventListener.OptionsRequestCallback) throws android.telephony.ims.ImsException; method public void onRequestPublishCapabilities(int) throws android.telephony.ims.ImsException; method public void onUnpublish() throws android.telephony.ims.ImsException; } @@ -12248,7 +12257,7 @@ package android.telephony.ims.stub { public class RcsCapabilityExchangeImplBase { ctor public RcsCapabilityExchangeImplBase(@NonNull java.util.concurrent.Executor); method public void publishCapabilities(@NonNull String, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.PublishResponseCallback); - method public void sendOptionsCapabilityRequest(@NonNull android.net.Uri, @NonNull java.util.List, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.OptionsResponseCallback); + method public void sendOptionsCapabilityRequest(@NonNull android.net.Uri, @NonNull java.util.Set, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.OptionsResponseCallback); method public void subscribeForCapabilities(@NonNull java.util.Collection, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.SubscribeResponseCallback); field public static final int COMMAND_CODE_FETCH_ERROR = 3; // 0x3 field public static final int COMMAND_CODE_GENERIC_FAILURE = 1; // 0x1 diff --git a/telephony/java/android/telephony/ims/RcsContactUceCapability.java b/telephony/java/android/telephony/ims/RcsContactUceCapability.java index 52d0f036788c..a133eadb3517 100644 --- a/telephony/java/android/telephony/ims/RcsContactUceCapability.java +++ b/telephony/java/android/telephony/ims/RcsContactUceCapability.java @@ -29,7 +29,9 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.ArrayList; import java.util.Collections; +import java.util.HashSet; import java.util.List; +import java.util.Set; /** * Contains the User Capability Exchange capabilities corresponding to a contact's URI. @@ -110,7 +112,6 @@ public final class RcsContactUceCapability implements Parcelable { /** * Builder to help construct {@link RcsContactUceCapability} instances when capabilities were * queried through SIP OPTIONS. - * @hide */ public static final class OptionsBuilder { @@ -151,7 +152,7 @@ public final class RcsContactUceCapability implements Parcelable { * @param tags the list of the supported feature tags * @return this OptionBuilder */ - public @NonNull OptionsBuilder addFeatureTags(@NonNull List tags) { + public @NonNull OptionsBuilder addFeatureTags(@NonNull Set tags) { mCapabilities.mFeatureTags.addAll(tags); return this; } @@ -220,7 +221,7 @@ public final class RcsContactUceCapability implements Parcelable { private @CapabilityMechanism int mCapabilityMechanism; private @RequestResult int mRequestResult; - private final List mFeatureTags = new ArrayList<>(); + private final Set mFeatureTags = new HashSet<>(); private final List mPresenceTuples = new ArrayList<>(); private RcsContactUceCapability(@NonNull Uri contactUri, @CapabilityMechanism int mechanism, @@ -235,7 +236,9 @@ public final class RcsContactUceCapability implements Parcelable { mCapabilityMechanism = in.readInt(); mSourceType = in.readInt(); mRequestResult = in.readInt(); - in.readStringList(mFeatureTags); + List featureTagList = new ArrayList<>(); + in.readStringList(featureTagList); + mFeatureTags.addAll(featureTagList); in.readParcelableList(mPresenceTuples, RcsContactPresenceTuple.class.getClassLoader()); } @@ -245,7 +248,7 @@ public final class RcsContactUceCapability implements Parcelable { out.writeInt(mCapabilityMechanism); out.writeInt(mSourceType); out.writeInt(mRequestResult); - out.writeStringList(mFeatureTags); + out.writeStringList(new ArrayList<>(mFeatureTags)); out.writeParcelableList(mPresenceTuples, flags); } @@ -285,7 +288,20 @@ public final class RcsContactUceCapability implements Parcelable { if (mCapabilityMechanism != CAPABILITY_MECHANISM_OPTIONS) { return Collections.emptyList(); } - return Collections.unmodifiableList(mFeatureTags); + return Collections.unmodifiableList(new ArrayList<>(mFeatureTags)); + } + + /** + * @return The feature tags present in the OPTIONS response from the network. + *

+ * Note: this is only populated if {@link #getCapabilityMechanism} is + * {@link RcsContactUceCapability#CAPABILITY_MECHANISM_OPTIONS} + */ + public @NonNull Set getFeatureTags() { + if (mCapabilityMechanism != CAPABILITY_MECHANISM_OPTIONS) { + return Collections.emptySet(); + } + return Collections.unmodifiableSet(mFeatureTags); } /** diff --git a/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java index a217d1321342..c3d7325f2e0a 100644 --- a/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java +++ b/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java @@ -26,7 +26,8 @@ import android.telephony.ims.RcsContactUceCapability; import android.telephony.ims.stub.CapabilityExchangeEventListener; import android.util.Log; -import java.util.List; +import java.util.ArrayList; +import java.util.Set; /** * The ICapabilityExchangeEventListener wrapper class to store the listener which is registered by @@ -84,7 +85,7 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis * request to the framework. */ public void onRemoteCapabilityRequest(@NonNull Uri contactUri, - @NonNull List remoteCapabilities, @NonNull OptionsRequestCallback callback) + @NonNull Set remoteCapabilities, @NonNull OptionsRequestCallback callback) throws ImsException { ICapabilityExchangeEventListener listener = mListenerBinder; if (listener == null) { @@ -114,7 +115,8 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis }; try { - listener.onRemoteCapabilityRequest(contactUri, remoteCapabilities, internalCallback); + listener.onRemoteCapabilityRequest(contactUri, new ArrayList<>(remoteCapabilities), + internalCallback); } catch (RemoteException e) { Log.w(LOG_TAG, "Remote capability request exception: " + e); throw new ImsException("Remote is not available", diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java index 85703f8de5e5..6315b242184a 100644 --- a/telephony/java/android/telephony/ims/feature/RcsFeature.java +++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java @@ -47,6 +47,7 @@ import com.android.internal.telephony.util.TelephonyUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.HashSet; import java.util.List; import java.util.concurrent.CancellationException; import java.util.concurrent.CompletableFuture; @@ -145,8 +146,8 @@ public class RcsFeature extends ImsFeature { throws RemoteException { OptionsResponseCallback callbackWrapper = new RcsOptionsResponseAidlWrapper(callback); executeMethodAsync(() -> mReference.getCapabilityExchangeImplBaseInternal() - .sendOptionsCapabilityRequest(contactUri, myCapabilities, callbackWrapper), - "sendOptionsCapabilityRequest"); + .sendOptionsCapabilityRequest(contactUri, new HashSet<>(myCapabilities), + callbackWrapper), "sendOptionsCapabilityRequest"); } // Call the methods with a clean calling identity on the executor and wait indefinitely for diff --git a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java index 62955487897f..a3be8dab2891 100644 --- a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java +++ b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java @@ -26,7 +26,7 @@ import android.telephony.ims.RcsUceAdapter; import android.telephony.ims.feature.ImsFeature; import android.telephony.ims.feature.RcsFeature; -import java.util.List; +import java.util.Set; /** * The interface that is used by the framework to listen to events from the vendor RCS stack @@ -98,7 +98,8 @@ public interface CapabilityExchangeEventListener { * {@link OptionsRequestCallback#onRespondToCapabilityRequestWithError}. * @param contactUri The URI associated with the remote contact that is * requesting capabilities. - * @param remoteCapabilities The remote contact's capability information. + * @param remoteCapabilities The remote contact's capability information. The capability + * information is in the format defined in RCC.07 section 2.6.1.3. * @param callback The callback of this request which is sent from the remote user. * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is not * currently connected to the framework. This can happen if the {@link RcsFeature} is not @@ -107,6 +108,6 @@ public interface CapabilityExchangeEventListener { * cases when the Telephony stack has crashed. */ void onRemoteCapabilityRequest(@NonNull Uri contactUri, - @NonNull List remoteCapabilities, + @NonNull Set remoteCapabilities, @NonNull OptionsRequestCallback callback) throws ImsException; } diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java index 03e17fbc2c0d..25b9446152ac 100644 --- a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java +++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java @@ -33,6 +33,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.util.Collection; import java.util.List; +import java.util.Set; import java.util.concurrent.Executor; /** @@ -433,6 +434,7 @@ public class RcsCapabilityExchangeImplBase { * @param contactUri The URI of the remote user that we wish to get the capabilities of. * @param myCapabilities The capabilities of this device to send to the remote user. * @param callback The callback of this request which is sent from the remote user. + * @hide */ // executor used is defined in the constructor. @SuppressLint("ExecutorRegistration") @@ -446,4 +448,27 @@ public class RcsCapabilityExchangeImplBase { // Do not do anything, this is a stub implementation. } } + + /** + * 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 use {@link OptionsResponseCallback} to send the response of + * this query from the network back to the framework. + * @param contactUri The URI of the remote user that we wish to get the capabilities of. + * @param myCapabilities The capabilities of this device to send to the remote user. + * @param callback The callback of this request which is sent from the remote user. + */ + // executor used is defined in the constructor. + @SuppressLint("ExecutorRegistration") + public void sendOptionsCapabilityRequest(@NonNull Uri contactUri, + @NonNull Set myCapabilities, @NonNull OptionsResponseCallback callback) { + // Stub - to be implemented by service + Log.w(LOG_TAG, "sendOptionsCapabilityRequest called with no implementation."); + try { + callback.onCommandError(COMMAND_CODE_NOT_SUPPORTED); + } catch (ImsException e) { + // Do not do anything, this is a stub implementation. + } + } }