blob: 51a3d72c57f244120425033f72d9a0e3d2d40e7c [file] [log] [blame]
/*
* 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.annotation.SystemApi;
import android.net.Uri;
import android.os.Build;
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.HashSet;
import java.util.List;
import java.util.Set;
/**
* Contains the User Capability Exchange capabilities corresponding to a contact's URI.
* @hide
*/
@SystemApi
public final class RcsContactUceCapability implements Parcelable {
/** Contains presence information associated with the contact */
public static final int CAPABILITY_MECHANISM_PRESENCE = 1;
/** Contains OPTIONS information associated with the contact */
public static final int CAPABILITY_MECHANISM_OPTIONS = 2;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "CAPABILITY_MECHANISM_", value = {
CAPABILITY_MECHANISM_PRESENCE,
CAPABILITY_MECHANISM_OPTIONS
})
public @interface CapabilityMechanism {}
/**
* The capabilities of this contact were requested recently enough to still be considered in
* the availability window.
*/
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 {}
/**
* 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 = 0;
/**
* 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 = 1;
/**
* 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 = 2;
/**
* Capability information for the requested contact was found successfully.
*/
public static final int REQUEST_RESULT_FOUND = 3;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "REQUEST_RESULT_", value = {
REQUEST_RESULT_UNKNOWN,
REQUEST_RESULT_NOT_ONLINE,
REQUEST_RESULT_NOT_FOUND,
REQUEST_RESULT_FOUND
})
public @interface RequestResult {}
/**
* Builder to help construct {@link RcsContactUceCapability} instances when capabilities were
* queried through SIP OPTIONS.
*/
public static final class OptionsBuilder {
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 OptionsBuilder(@NonNull Uri contact) {
mCapabilities = new RcsContactUceCapability(contact, CAPABILITY_MECHANISM_OPTIONS,
SOURCE_TYPE_NETWORK);
}
/**
* 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.
* @hide
*/
public OptionsBuilder(@NonNull Uri contact, @SourceType int sourceType) {
mCapabilities = new RcsContactUceCapability(contact, CAPABILITY_MECHANISM_OPTIONS,
sourceType);
}
/**
* Set the result of the capabilities request.
* @param requestResult the request result
* @return this OptionBuilder
*/
public @NonNull OptionsBuilder setRequestResult(@RequestResult int requestResult) {
mCapabilities.mRequestResult = requestResult;
return this;
}
/**
* Add the feature tag into the capabilities instance.
* @param tag the supported feature tag
* @return this OptionBuilder
*/
public @NonNull OptionsBuilder addFeatureTag(@NonNull String tag) {
mCapabilities.mFeatureTags.add(tag);
return this;
}
/**
* Add the list of feature tag into the capabilities instance.
* @param tags the list of the supported feature tags
* @return this OptionBuilder
*/
public @NonNull OptionsBuilder addFeatureTags(@NonNull Set<String> tags) {
mCapabilities.mFeatureTags.addAll(tags);
return this;
}
/**
* @return the constructed instance.
*/
public @NonNull RcsContactUceCapability build() {
return mCapabilities;
}
}
/**
* Builder to help construct {@link RcsContactUceCapability} instances when capabilities were
* queried through a presence server.
*/
public static final class PresenceBuilder {
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(@NonNull 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(
@NonNull List<RcsContactPresenceTuple> tuples) {
mCapabilities.mPresenceTuples.addAll(tuples);
return this;
}
/**
* Set the entity URI related to the contact whose capabilities were requested.
* @param entityUri the 'pres' URL of the PRESENTITY publishing presence document.
*/
public @NonNull PresenceBuilder setEntityUri(@NonNull Uri entityUri) {
mCapabilities.mEntityUri = entityUri;
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 Uri mEntityUri;
private final Set<String> mFeatureTags = new HashSet<>();
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) {
mContactUri = in.readParcelable(Uri.class.getClassLoader(), android.net.Uri.class);
mCapabilityMechanism = in.readInt();
mSourceType = in.readInt();
mRequestResult = in.readInt();
mEntityUri = in.readParcelable(Uri.class.getClassLoader(), android.net.Uri.class);
List<String> featureTagList = new ArrayList<>();
in.readStringList(featureTagList);
mFeatureTags.addAll(featureTagList);
in.readParcelableList(mPresenceTuples, RcsContactPresenceTuple.class.getClassLoader(), android.telephony.ims.RcsContactPresenceTuple.class);
}
@Override
public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeParcelable(mContactUri, flags);
out.writeInt(mCapabilityMechanism);
out.writeInt(mSourceType);
out.writeInt(mRequestResult);
out.writeParcelable(mEntityUri, flags);
out.writeStringList(new ArrayList<>(mFeatureTags));
out.writeParcelableList(mPresenceTuples, flags);
}
@Override
public int describeContents() {
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];
}
};
/**
* @return The mechanism used to get the capabilities.
*/
public @CapabilityMechanism int getCapabilityMechanism() {
return mCapabilityMechanism;
}
/**
* @return The feature tags present in the OPTIONS response from the network.
* <p>
* Note: this is only populated if {@link #getCapabilityMechanism} is
* {@link RcsContactUceCapability#CAPABILITY_MECHANISM_OPTIONS}
*/
public @NonNull Set<String> getFeatureTags() {
if (mCapabilityMechanism != CAPABILITY_MECHANISM_OPTIONS) {
return Collections.emptySet();
}
return Collections.unmodifiableSet(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 RcsContactUceCapability#CAPABILITY_MECHANISM_PRESENCE}
*/
public @NonNull List<RcsContactPresenceTuple> getCapabilityTuples() {
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 or {@code null} if the
* service id does not exist in the list of presence tuples returned from the network.
*
* <p>
* Note: this is only populated if {@link #getCapabilityMechanism} is
* {@link RcsContactUceCapability#CAPABILITY_MECHANISM_PRESENCE}
*/
public @Nullable RcsContactPresenceTuple getCapabilityTuple(@NonNull String serviceId) {
if (mCapabilityMechanism != CAPABILITY_MECHANISM_PRESENCE) {
return null;
}
for (RcsContactPresenceTuple tuple : mPresenceTuples) {
if (tuple.getServiceId() != null && 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;
}
/**
* Retrieve the contact URI requested by the applications.
* @return the URI representing the contact associated with the capabilities.
*/
public @NonNull Uri getContactUri() {
return mContactUri;
}
/**
* Retrieve the entity URI of the contact whose presence information is being requested for.
* @return the URI representing the 'pres' URL of the PRESENTITY publishing presence document
* or {@code null} if the entity uri does not exist in the presence document.
*/
public @Nullable Uri getEntityUri() {
return mEntityUri;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder("RcsContactUceCapability");
if (mCapabilityMechanism == CAPABILITY_MECHANISM_PRESENCE) {
builder.append("(presence) {");
} else if (mCapabilityMechanism == CAPABILITY_MECHANISM_OPTIONS) {
builder.append("(options) {");
} else {
builder.append("(?) {");
}
if (Build.IS_ENG) {
builder.append("uri=");
builder.append(mContactUri);
} else {
builder.append("uri (isNull)=");
builder.append(mContactUri != null ? "XXX" : "null");
}
builder.append(", sourceType=");
builder.append(mSourceType);
builder.append(", requestResult=");
builder.append(mRequestResult);
if (Build.IS_ENG) {
builder.append("entity uri=");
builder.append(mEntityUri != null ? mEntityUri : "null");
} else {
builder.append("entity uri (isNull)=");
builder.append(mEntityUri != null ? "XXX" : "null");
}
if (mCapabilityMechanism == CAPABILITY_MECHANISM_PRESENCE) {
builder.append(", presenceTuples={");
builder.append(mPresenceTuples);
builder.append("}");
} else if (mCapabilityMechanism == CAPABILITY_MECHANISM_OPTIONS) {
builder.append(", featureTags={");
builder.append(mFeatureTags);
builder.append("}");
}
return builder.toString();
}
}