Merge "[RCS UCE] Refactor the class RcsContactUceCapability" am: e279b0d14f am: 8774c473ef am: f0d37bdaba

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1459883

Change-Id: I4330bb296c948c9a1d2af78a6ab636cd9b01e95d
This commit is contained in:
James Lin
2020-10-16 01:42:14 +00:00
committed by Automerger Merge Worker
3 changed files with 611 additions and 210 deletions

View File

@@ -0,0 +1,20 @@
/*
* Copyright (c) 2020 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 RcsContactPresenceTuple;

View File

@@ -0,0 +1,360 @@
/*
* Copyright (C) 2020 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.NonNull;
import android.annotation.Nullable;
import android.annotation.StringDef;
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.List;
/**
* Represents a PIDF tuple element that is part of the presence element returned from the carrier
* network during a SUBSCRIBE request. See RFC3863 for more information.
* @hide
*/
public class RcsContactPresenceTuple implements Parcelable {
/** The service id of the MMTEL */
public static final String SERVICE_ID_MMTEL = "org.3gpp.urn:urn-7:3gpp-service.ims.icsi.mmtel";
/** The service capabilities is available. */
public static final String TUPLE_BASIC_STATUS_OPEN = "open";
/** The service capabilities is unavailable. */
public static final String TUPLE_BASIC_STATUS_CLOSED = "closed";
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@StringDef(prefix = "TUPLE_BASIC_STATUS_", value = {
TUPLE_BASIC_STATUS_OPEN,
TUPLE_BASIC_STATUS_CLOSED
})
public @interface BasicStatus {}
/**
* An optional addition to the PIDF Presence Tuple containing service capabilities, which is
* defined in the servcaps element. See RFC5196, section 3.2.1.
*/
public static class ServiceCapabilities implements Parcelable {
/** The service can simultaneously send and receive data. */
public static final String DUPLEX_MODE_FULL = "full";
/** The service can alternate between sending and receiving data.*/
public static final String DUPLEX_MODE_HALF = "half";
/** The service can only receive data. */
public static final String DUPLEX_MODE_RECEIVE_ONLY = "receive-only";
/** The service can only send data. */
public static final String DUPLEX_MODE_SEND_ONLY = "send-only";
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@StringDef(prefix = "DUPLEX_MODE_", value = {
DUPLEX_MODE_FULL,
DUPLEX_MODE_HALF,
DUPLEX_MODE_RECEIVE_ONLY,
DUPLEX_MODE_SEND_ONLY
})
public @interface DuplexMode {}
/**
* Builder to help construct {@link ServiceCapabilities} instances.
*/
public static class Builder {
private ServiceCapabilities mCapabilities;
/**
* Create the ServiceCapabilities builder, which can be used to set service capabilities
* as well as custom capability extensions.
* @param isAudioCapable Whether the audio is capable or not.
* @param isVideoCapable Whether the video is capable or not.
*/
public Builder(boolean isAudioCapable, boolean isVideoCapable) {
mCapabilities = new ServiceCapabilities(isAudioCapable, isVideoCapable);
}
/**
* Add the supported duplex mode.
* @param mode The supported duplex mode
*/
public Builder addSupportedDuplexMode(@NonNull @DuplexMode String mode) {
mCapabilities.mSupportedDuplexModeList.add(mode);
return this;
}
/**
* Add the unsupported duplex mode.
* @param mode The unsupported duplex mode
*/
public Builder addUnsupportedDuplexMode(@NonNull @DuplexMode String mode) {
mCapabilities.mUnsupportedDuplexModeList.add(mode);
return this;
}
/**
* @return the ServiceCapabilities instance.
*/
public ServiceCapabilities build() {
return mCapabilities;
}
}
private final boolean mIsAudioCapable;
private final boolean mIsVideoCapable;
private final @DuplexMode List<String> mSupportedDuplexModeList = new ArrayList<>();
private final @DuplexMode List<String> mUnsupportedDuplexModeList = new ArrayList<>();
/**
* Use {@link Builder} to build an instance of this interface.
* @param isAudioCapable Whether the audio is capable.
* @param isVideoCapable Whether the video is capable.
*/
ServiceCapabilities(boolean isAudioCapable, boolean isVideoCapable) {
mIsAudioCapable = isAudioCapable;
mIsVideoCapable = isVideoCapable;
}
private ServiceCapabilities(Parcel in) {
mIsAudioCapable = in.readBoolean();
mIsVideoCapable = in.readBoolean();
in.readStringList(mSupportedDuplexModeList);
in.readStringList(mUnsupportedDuplexModeList);
}
@Override
public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeBoolean(mIsAudioCapable);
out.writeBoolean(mIsVideoCapable);
out.writeStringList(mSupportedDuplexModeList);
out.writeStringList(mUnsupportedDuplexModeList);
}
@Override
public int describeContents() {
return 0;
}
public static final @NonNull Creator<ServiceCapabilities> CREATOR =
new Creator<ServiceCapabilities>() {
@Override
public ServiceCapabilities createFromParcel(Parcel in) {
return new ServiceCapabilities(in);
}
@Override
public ServiceCapabilities[] newArray(int size) {
return new ServiceCapabilities[size];
}
};
/**
* Query the audio capable.
* @return true if the audio is capable, false otherwise.
*/
public boolean isAudioCapable() {
return mIsAudioCapable;
}
/**
* Query the video capable.
* @return true if the video is capable, false otherwise.
*/
public boolean isVideoCapable() {
return mIsVideoCapable;
}
/**
* Get the supported duplex mode list.
* @return The list of supported duplex mode
*/
public @NonNull @DuplexMode List<String> getSupportedDuplexModes() {
return Collections.unmodifiableList(mSupportedDuplexModeList);
}
/**
* Get the unsupported duplex mode list.
* @return The list of unsupported duplex mode
*/
public @NonNull @DuplexMode List<String> getUnsupportedDuplexModes() {
return Collections.unmodifiableList(mUnsupportedDuplexModeList);
}
}
/**
* Builder to help construct {@link RcsContactPresenceTuple} instances.
*/
public static class Builder {
private RcsContactPresenceTuple mPresenceTuple;
/**
* Builds a RcsContactPresenceTuple instance.
* @param serviceId The OMA Presence service-id associated with this capability. See the
* OMA Presence SIMPLE specification v1.1, section 10.5.1.
* @param serviceVersion The OMA Presence version associated with the service capability.
* See the OMA Presence SIMPLE specification v1.1, section 10.5.1.
*/
public Builder(@NonNull @BasicStatus String status, @NonNull String serviceId,
@NonNull String serviceVersion) {
mPresenceTuple = new RcsContactPresenceTuple(status, serviceId, serviceVersion);
}
/**
* The optional SIP Contact URI associated with the PIDF tuple element.
*/
public Builder addContactUri(@NonNull Uri contactUri) {
mPresenceTuple.mContactUri = contactUri;
return this;
}
/**
* The optional timestamp indicating the data and time of the status change of this tuple.
* See RFC3863, section 4.1.7 for more information on the expected format.
*/
public Builder addTimeStamp(@NonNull String timestamp) {
mPresenceTuple.mTimestamp = timestamp;
return this;
}
/**
* An optional parameter containing the description element of the service-description. See
* OMA Presence SIMPLE specification v1.1
*/
public Builder addDescription(@NonNull String description) {
mPresenceTuple.mServiceDescription = description;
return this;
}
/**
* An optional parameter containing the service capabilities of the presence tuple if they
* are present in the servcaps element.
*/
public Builder addServiceCapabilities(@NonNull ServiceCapabilities caps) {
mPresenceTuple.mServiceCapabilities = caps;
return this;
}
/**
* @return the constructed instance.
*/
public RcsContactPresenceTuple build() {
return mPresenceTuple;
}
}
private Uri mContactUri;
private String mTimestamp;
private @BasicStatus String mStatus;
// The service information in the service-description element.
private String mServiceId;
private String mServiceVersion;
private String mServiceDescription;
private ServiceCapabilities mServiceCapabilities;
private RcsContactPresenceTuple(@NonNull @BasicStatus String status, @NonNull String serviceId,
@NonNull String serviceVersion) {
mStatus = status;
mServiceId = serviceId;
mServiceVersion = serviceVersion;
}
private RcsContactPresenceTuple(Parcel in) {
mContactUri = in.readParcelable(Uri.class.getClassLoader());
mTimestamp = in.readString();
mStatus = in.readString();
mServiceId = in.readString();
mServiceVersion = in.readString();
mServiceDescription = in.readString();
mServiceCapabilities = in.readParcelable(ServiceCapabilities.class.getClassLoader());
}
@Override
public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeParcelable(mContactUri, flags);
out.writeString(mTimestamp);
out.writeString(mStatus);
out.writeString(mServiceId);
out.writeString(mServiceVersion);
out.writeString(mServiceDescription);
out.writeParcelable(mServiceCapabilities, flags);
}
@Override
public int describeContents() {
return 0;
}
public static final @NonNull Creator<RcsContactPresenceTuple> CREATOR =
new Creator<RcsContactPresenceTuple>() {
@Override
public RcsContactPresenceTuple createFromParcel(Parcel in) {
return new RcsContactPresenceTuple(in);
}
@Override
public RcsContactPresenceTuple[] newArray(int size) {
return new RcsContactPresenceTuple[size];
}
};
/** @return the status of the tuple element. */
public @NonNull @BasicStatus String getStatus() {
return mStatus;
}
/** @return the service-id element of the service-description */
public @NonNull String getServiceId() {
return mServiceId;
}
/** @return the version element of the service-description */
public @NonNull String getServiceVersion() {
return mServiceVersion;
}
/** @return the SIP URI contained in the contact element of the tuple if it exists. */
public @Nullable Uri getContactUri() {
return mContactUri;
}
/** @return the timestamp element contained in the tuple if it exists */
public @Nullable String getTimestamp() {
return mTimestamp;
}
/** @return the description element contained in the service-description if it exists */
public @Nullable String getServiceDescription() {
return mServiceDescription;
}
/** @return the {@link ServiceCapabilities} of the tuple if it exists. */
public @Nullable ServiceCapabilities getServiceCapabilities() {
return mServiceCapabilities;
}
}

View File

@@ -16,7 +16,7 @@
package android.telephony.ims; package android.telephony.ims;
import android.annotation.LongDef; import android.annotation.IntDef;
import android.annotation.NonNull; import android.annotation.NonNull;
import android.annotation.Nullable; import android.annotation.Nullable;
import android.net.Uri; import android.net.Uri;
@@ -27,9 +27,7 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map;
/** /**
* Contains the User Capability Exchange capabilities corresponding to a contact's URI. * Contains the User Capability Exchange capabilities corresponding to a contact's URI.
@@ -37,114 +35,80 @@ import java.util.Map;
*/ */
public final class RcsContactUceCapability implements Parcelable { public final class RcsContactUceCapability implements Parcelable {
/** Supports 1-to-1 chat */ /** Contains presence information associated with the contact */
public static final int CAPABILITY_CHAT_STANDALONE = (1 << 0); public static final int CAPABILITY_MECHANISM_PRESENCE = 1;
/** 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);
/** Supports call composer, where outgoing calls can be enriched with pre-call content.*/
public static final int CAPABILITY_CALL_COMPOSER = (1 << 22);
/** Supports post call information that is included in the call if the call is missed.*/
public static final int CAPABILITY_POST_CALL = (1 << 23);
/** Supports sharing a map where the user can draw, share markers, and share their position. */
public static final int CAPABILITY_SHARED_MAP = (1 << 24);
/** Supports sharing a canvas, where users can draw, add images, and change background colors.*/
public static final int CAPABILITY_SHARED_SKETCH = (1 << 25);
/** Supports communication with Chatbots. */
public static final int CAPABILITY_CHAT_BOT = (1 << 26);
/** Supports Chatbot roles. */
public static final int CAPABILITY_CHAT_BOT_ROLE = (1 << 27);
/** Supports the unidirectional plug-ins framework. */
public static final int CAPABILITY_PLUG_IN = (1 << 28);
/** Supports standalone Chatbot communication. */
public static final int CAPABILITY_STANDALONE_CHAT_BOT = (1 << 29);
/** Supports MMTEL based call composer. */
public static final int CAPABILITY_MMTEL_CALL_COMPOSER = (1 << 30);
/** Contains OPTIONS information associated with the contact */
public static final int CAPABILITY_MECHANISM_OPTIONS = 2;
/** @hide */
/** @hide*/
@Retention(RetentionPolicy.SOURCE) @Retention(RetentionPolicy.SOURCE)
@LongDef(prefix = "CAPABILITY_", flag = true, value = { @IntDef(prefix = "CAPABILITY_MECHANISM_", value = {
CAPABILITY_CHAT_STANDALONE, CAPABILITY_MECHANISM_PRESENCE,
CAPABILITY_CHAT_SESSION, CAPABILITY_MECHANISM_OPTIONS
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,
CAPABILITY_CALL_COMPOSER,
CAPABILITY_POST_CALL,
CAPABILITY_SHARED_MAP,
CAPABILITY_SHARED_SKETCH,
CAPABILITY_CHAT_BOT,
CAPABILITY_CHAT_BOT_ROLE,
CAPABILITY_PLUG_IN,
CAPABILITY_STANDALONE_CHAT_BOT,
CAPABILITY_MMTEL_CALL_COMPOSER
}) })
public @interface CapabilityFlag {} public @interface CapabilityMechanism {}
/** /**
* Builder to help construct {@link RcsContactUceCapability} instances. * The capabilities of this contact were requested recently enough to still be considered in
* the availability window.
*/ */
public static class Builder { public static final int SOURCE_TYPE_NETWORK = 0;
/**
* The capabilities of this contact were retrieved from the cached information in the Enhanced
* Address Book.
*/
public static final int SOURCE_TYPE_CACHED = 1;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "SOURCE_TYPE_", value = {
SOURCE_TYPE_NETWORK,
SOURCE_TYPE_CACHED
})
public @interface SourceType {}
/**
* The requested contact was found to be offline when queried. This is only applicable to
* contact capabilities that were queried via OPTIONS requests and the network returned a
* 408/480 response.
*/
public static final int REQUEST_RESULT_NOT_ONLINE = 0;
/**
* Capability information for the requested contact was not found. The contact should not be
* considered an RCS user.
*/
public static final int REQUEST_RESULT_NOT_FOUND = 1;
/**
* Capability information for the requested contact was found successfully.
*/
public static final int REQUEST_RESULT_FOUND = 2;
/**
* Capability information for the requested contact has expired and can not be refreshed due to
* a temporary network error. This is a temporary error and the capabilities of the contact
* should be queried again at a later time.
*/
public static final int REQUEST_RESULT_UNKNOWN = 3;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "REQUEST_RESULT_", value = {
REQUEST_RESULT_NOT_ONLINE,
REQUEST_RESULT_NOT_FOUND,
REQUEST_RESULT_FOUND,
REQUEST_RESULT_UNKNOWN
})
public @interface RequestResult {}
/**
* Builder to help construct {@link RcsContactUceCapability} instances when capabilities were
* queried through SIP OPTIONS.
*/
public static class OptionsBuilder {
private final RcsContactUceCapability mCapabilities; private final RcsContactUceCapability mCapabilities;
@@ -153,51 +117,38 @@ public final class RcsContactUceCapability implements Parcelable {
* capability extensions. * capability extensions.
* @param contact The contact URI that the capabilities are attached to. * @param contact The contact URI that the capabilities are attached to.
*/ */
public Builder(@NonNull Uri contact) { public OptionsBuilder(@NonNull Uri contact) {
mCapabilities = new RcsContactUceCapability(contact); mCapabilities = new RcsContactUceCapability(contact, CAPABILITY_MECHANISM_OPTIONS,
SOURCE_TYPE_NETWORK);
} }
/** /**
* Add a UCE capability bit-field as well as the associated URI that the framework should * Set the result of the capabilities request.
* use for those services. This is mainly used for capabilities that may use a URI separate * @param requestResult the request result
* from the contact's URI, for example the URI to use for VT calls. * @return this OptionBuilder
* @param type The capability to map to a service URI that is different from the contact's
* URI.
*/ */
public @NonNull Builder add(@CapabilityFlag long type, @NonNull Uri serviceUri) { public @NonNull OptionsBuilder setRequestResult(@RequestResult int requestResult) {
mCapabilities.mCapabilities |= type; mCapabilities.mRequestResult = requestResult;
// Put each of these capabilities into the map separately.
for (long shift = 0; shift < Integer.SIZE; shift++) {
long 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; return this;
} }
/** /**
* Add a UCE capability flag that this contact supports. * Add the feature tag into the capabilities instance.
* @param type the capability that the contact supports. * @param tag the supported feature tag
* @return this OptionBuilder
*/ */
public @NonNull Builder add(@CapabilityFlag long type) { public @NonNull OptionsBuilder addFeatureTag(String tag) {
mCapabilities.mCapabilities |= type; mCapabilities.mFeatureTags.add(tag);
return this; return this;
} }
/** /**
* Add a carrier specific service tag. * Add the list of feature tag into the capabilities instance.
* @param extension A string containing a carrier specific service tag that is an extension * @param tags the list of the supported feature tags
* of the {@link CapabilityFlag}s that are defined here. * @return this OptionBuilder
*/ */
public @NonNull Builder add(@NonNull String extension) { public @NonNull OptionsBuilder addFeatureTags(List<String> tags) {
mCapabilities.mExtensionTags.add(extension); mCapabilities.mFeatureTags.addAll(tags);
return this; return this;
} }
@@ -209,56 +160,88 @@ public final class RcsContactUceCapability implements Parcelable {
} }
} }
private final Uri mContactUri;
private long mCapabilities;
private List<String> mExtensionTags = new ArrayList<>();
private Map<Long, Uri> mServiceMap = new HashMap<>();
/** /**
* Use {@link Builder} to build an instance of this interface. * Builder to help construct {@link RcsContactUceCapability} instances when capabilities were
* @param contact The URI associated with this capability information. * queried through a presence server.
* @hide
*/ */
RcsContactUceCapability(@NonNull Uri contact) { public static class PresenceBuilder {
mContactUri = contact;
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.
* @param sourceType The type where the capabilities of this contact were retrieved from.
* @param requestResult the request result
*/
public PresenceBuilder(@NonNull Uri contact, @SourceType int sourceType,
@RequestResult int requestResult) {
mCapabilities = new RcsContactUceCapability(contact, CAPABILITY_MECHANISM_PRESENCE,
sourceType);
mCapabilities.mRequestResult = requestResult;
}
/**
* Add the {@link RcsContactPresenceTuple} into the capabilities instance.
* @param tuple The {@link RcsContactPresenceTuple} to be added into.
* @return this PresenceBuilder
*/
public @NonNull PresenceBuilder addCapabilityTuple(RcsContactPresenceTuple tuple) {
mCapabilities.mPresenceTuples.add(tuple);
return this;
}
/**
* Add the list of {@link RcsContactPresenceTuple} into the capabilities instance.
* @param tuples The list of the {@link RcsContactPresenceTuple} to be added into.
* @return this PresenceBuilder
*/
public @NonNull PresenceBuilder addCapabilityTuples(List<RcsContactPresenceTuple> tuples) {
mCapabilities.mPresenceTuples.addAll(tuples);
return this;
}
/**
* @return the RcsContactUceCapability instance.
*/
public @NonNull RcsContactUceCapability build() {
return mCapabilities;
}
}
private final Uri mContactUri;
private @SourceType int mSourceType;
private @CapabilityMechanism int mCapabilityMechanism;
private @RequestResult int mRequestResult;
private final List<String> mFeatureTags = new ArrayList<>();
private final List<RcsContactPresenceTuple> mPresenceTuples = new ArrayList<>();
private RcsContactUceCapability(@NonNull Uri contactUri, @CapabilityMechanism int mechanism,
@SourceType int sourceType) {
mContactUri = contactUri;
mCapabilityMechanism = mechanism;
mSourceType = sourceType;
} }
private RcsContactUceCapability(Parcel in) { private RcsContactUceCapability(Parcel in) {
mContactUri = in.readParcelable(Uri.class.getClassLoader()); mContactUri = in.readParcelable(Uri.class.getClassLoader());
mCapabilities = in.readLong(); mCapabilityMechanism = in.readInt();
in.readStringList(mExtensionTags); mSourceType = in.readInt();
// read mServiceMap as key,value pair mRequestResult = in.readInt();
int mapSize = in.readInt(); in.readStringList(mFeatureTags);
for (int i = 0; i < mapSize; i++) { in.readParcelableList(mPresenceTuples, RcsContactPresenceTuple.class.getClassLoader());
mServiceMap.put(in.readLong(), in.readParcelable(Uri.class.getClassLoader()));
}
} }
public static final @NonNull 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 @Override
public void writeToParcel(@NonNull Parcel out, int flags) { public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeParcelable(mContactUri, 0); out.writeParcelable(mContactUri, flags);
out.writeLong(mCapabilities); out.writeInt(mCapabilityMechanism);
out.writeStringList(mExtensionTags); out.writeInt(mSourceType);
// write mServiceMap as key,value pairs out.writeInt(mRequestResult);
int mapSize = mServiceMap.keySet().size(); out.writeStringList(mFeatureTags);
out.writeInt(mapSize); out.writeParcelableList(mPresenceTuples, flags);
for (long key : mServiceMap.keySet()) {
out.writeLong(key);
out.writeParcelable(mServiceMap.get(key), 0);
}
} }
@Override @Override
@@ -266,49 +249,87 @@ public final class RcsContactUceCapability implements Parcelable {
return 0; return 0;
} }
public static final @NonNull 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];
}
};
/** /**
* Query for a capability * @return The mechanism used to get the capabilities.
* @param type The capability flag to query.
* @return true if the capability flag specified is set, false otherwise.
*/ */
public boolean isCapable(@CapabilityFlag long type) { public @CapabilityMechanism int getCapabilityMechanism() {
return (mCapabilities & type) > 0; return mCapabilityMechanism;
} }
/** /**
* @return true if the extension service tag is set, false otherwise. * @return The feature tags present in the OPTIONS response from the network.
*/
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> * <p>
* This will typically be the contact {@link Uri} available via {@link #getContactUri()} unless * Note: this is only populated if {@link #getCapabilityMechanism} is
* a different service {@link Uri} was associated with this capability using * {@link CAPABILITY_MECHANISM_OPTIONS}
* {@link Builder#add(long, 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(long)
*/ */
public @Nullable Uri getServiceUri(@CapabilityFlag long type) { public @NonNull List<String> getOptionsFeatureTags() {
Uri result = mServiceMap.getOrDefault(type, null); if (mCapabilityMechanism != CAPABILITY_MECHANISM_OPTIONS) {
// If the capability is capable, but does not have a service URI associated, use the default return Collections.emptyList();
// contact URI.
if (result == null) {
return isCapable(type) ? getContactUri() : null;
} }
return result; return Collections.unmodifiableList(mFeatureTags);
}
/**
* @return The tuple elements associated with the presence element portion of the PIDF document
* contained in the NOTIFY response from the network.
* <p>
* Note: this is only populated if {@link #getCapabilityMechanism} is
* {@link CAPABILITY_MECHANISM_PRESENCE}
*/
public @NonNull List<RcsContactPresenceTuple> getPresenceTuples() {
if (mCapabilityMechanism != CAPABILITY_MECHANISM_PRESENCE) {
return Collections.emptyList();
}
return Collections.unmodifiableList(mPresenceTuples);
}
/**
* Get the RcsContactPresenceTuple associated with the given service id.
* @param serviceId The service id to get the presence tuple.
* @return The RcsContactPresenceTuple which has the given service id.
*
* <p>
* Note: this is only populated if {@link #getCapabilityMechanism} is
* {@link CAPABILITY_MECHANISM_PRESENCE}
*/
public @Nullable RcsContactPresenceTuple getPresenceTuple(String serviceId) {
if (mCapabilityMechanism != CAPABILITY_MECHANISM_PRESENCE) {
return null;
}
for (RcsContactPresenceTuple tuple : mPresenceTuples) {
if (tuple.getServiceId().equals(serviceId)) {
return tuple;
}
}
return null;
}
/**
* @return the source of the data that was used to populate the capabilities of the requested
* contact.
*/
public @SourceType int getSourceType() {
return mSourceType;
}
/**
* @return the result of querying the capabilities of the requested contact.
*/
public @RequestResult int getRequestResult() {
return mRequestResult;
} }
/** /**