Merge "Update the RCS UCE APIs." am: 6c165b2da9

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

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I5f8c85066e7636c78bd06f97e2a88a2167fe8f33
This commit is contained in:
James Lin
2021-03-11 06:50:55 +00:00
committed by Automerger Merge Worker
5 changed files with 198 additions and 14 deletions

View File

@@ -11567,7 +11567,7 @@ package android.telephony.ims {
method @NonNull public String getServiceId(); method @NonNull public String getServiceId();
method @NonNull public String getServiceVersion(); method @NonNull public String getServiceVersion();
method @NonNull public String getStatus(); method @NonNull public String getStatus();
method @Nullable public String getTimestamp(); method @Nullable public java.time.Instant getTime();
method public void writeToParcel(@NonNull android.os.Parcel, int); method public void writeToParcel(@NonNull android.os.Parcel, int);
field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.RcsContactPresenceTuple> CREATOR; field @NonNull public static final android.os.Parcelable.Creator<android.telephony.ims.RcsContactPresenceTuple> CREATOR;
field public static final String SERVICE_ID_CALL_COMPOSER = "org.3gpp.urn:urn-7:3gpp-service.ims.icsi.gsma.callcomposer"; field public static final String SERVICE_ID_CALL_COMPOSER = "org.3gpp.urn:urn-7:3gpp-service.ims.icsi.gsma.callcomposer";
@@ -11594,7 +11594,7 @@ package android.telephony.ims {
method @NonNull public android.telephony.ims.RcsContactPresenceTuple.Builder setContactUri(@NonNull android.net.Uri); method @NonNull public android.telephony.ims.RcsContactPresenceTuple.Builder setContactUri(@NonNull android.net.Uri);
method @NonNull public android.telephony.ims.RcsContactPresenceTuple.Builder setServiceCapabilities(@NonNull android.telephony.ims.RcsContactPresenceTuple.ServiceCapabilities); method @NonNull public android.telephony.ims.RcsContactPresenceTuple.Builder setServiceCapabilities(@NonNull android.telephony.ims.RcsContactPresenceTuple.ServiceCapabilities);
method @NonNull public android.telephony.ims.RcsContactPresenceTuple.Builder setServiceDescription(@NonNull String); method @NonNull public android.telephony.ims.RcsContactPresenceTuple.Builder setServiceDescription(@NonNull String);
method @NonNull public android.telephony.ims.RcsContactPresenceTuple.Builder setTimestamp(@NonNull String); method @NonNull public android.telephony.ims.RcsContactPresenceTuple.Builder setTime(@NonNull java.time.Instant);
} }
public static final class RcsContactPresenceTuple.ServiceCapabilities implements android.os.Parcelable { public static final class RcsContactPresenceTuple.ServiceCapabilities implements android.os.Parcelable {
@@ -11650,7 +11650,7 @@ package android.telephony.ims {
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getUcePublishState() throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int getUcePublishState() throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void removeOnPublishStateChangedListener(@NonNull android.telephony.ims.RcsUceAdapter.OnPublishStateChangedListener) throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void removeOnPublishStateChangedListener(@NonNull android.telephony.ims.RcsUceAdapter.OnPublishStateChangedListener) throws android.telephony.ims.ImsException;
method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, android.Manifest.permission.READ_CONTACTS}) public void requestAvailability(@NonNull android.net.Uri, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RcsUceAdapter.CapabilitiesCallback) throws android.telephony.ims.ImsException; method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, android.Manifest.permission.READ_CONTACTS}) public void requestAvailability(@NonNull android.net.Uri, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RcsUceAdapter.CapabilitiesCallback) throws android.telephony.ims.ImsException;
method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, android.Manifest.permission.READ_CONTACTS}) public void requestCapabilities(@NonNull java.util.List<android.net.Uri>, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RcsUceAdapter.CapabilitiesCallback) throws android.telephony.ims.ImsException; method @RequiresPermission(allOf={android.Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, android.Manifest.permission.READ_CONTACTS}) public void requestCapabilities(@NonNull java.util.Collection<android.net.Uri>, @NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RcsUceAdapter.CapabilitiesCallback) throws android.telephony.ims.ImsException;
method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException; method @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException;
field public static final int CAPABILITY_TYPE_PRESENCE_UCE = 2; // 0x2 field public static final int CAPABILITY_TYPE_PRESENCE_UCE = 2; // 0x2
field public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 1; // 0x1 field public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 1; // 0x1
@@ -12127,7 +12127,7 @@ package android.telephony.ims.stub {
ctor public RcsCapabilityExchangeImplBase(@NonNull java.util.concurrent.Executor); ctor public RcsCapabilityExchangeImplBase(@NonNull java.util.concurrent.Executor);
method public void publishCapabilities(@NonNull String, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.PublishResponseCallback); 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<java.lang.String>, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.OptionsResponseCallback); method public void sendOptionsCapabilityRequest(@NonNull android.net.Uri, @NonNull java.util.List<java.lang.String>, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.OptionsResponseCallback);
method public void subscribeForCapabilities(@NonNull java.util.List<android.net.Uri>, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.SubscribeResponseCallback); method public void subscribeForCapabilities(@NonNull java.util.Collection<android.net.Uri>, @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_FETCH_ERROR = 3; // 0x3
field public static final int COMMAND_CODE_GENERIC_FAILURE = 1; // 0x1 field public static final int COMMAND_CODE_GENERIC_FAILURE = 1; // 0x1
field public static final int COMMAND_CODE_INSUFFICIENT_MEMORY = 5; // 0x5 field public static final int COMMAND_CODE_INSUFFICIENT_MEMORY = 5; // 0x5

View File

@@ -23,9 +23,14 @@ import android.annotation.SystemApi;
import android.net.Uri; import android.net.Uri;
import android.os.Parcel; import android.os.Parcel;
import android.os.Parcelable; import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@@ -38,6 +43,8 @@ import java.util.List;
@SystemApi @SystemApi
public final class RcsContactPresenceTuple implements Parcelable { public final class RcsContactPresenceTuple implements Parcelable {
private static final String LOG_TAG = "RcsContactPresenceTuple";
/** /**
* The service ID used to indicate that MMTEL service is available. * The service ID used to indicate that MMTEL service is available.
* <p> * <p>
@@ -353,7 +360,8 @@ public final class RcsContactPresenceTuple implements Parcelable {
} }
/** /**
* The optional SIP Contact URI associated with the PIDF tuple element. * The optional SIP Contact URI associated with the PIDF tuple element if the network
* expects the user to use the URI instead of the contact URI to contact it.
*/ */
public @NonNull Builder setContactUri(@NonNull Uri contactUri) { public @NonNull Builder setContactUri(@NonNull Uri contactUri) {
mPresenceTuple.mContactUri = contactUri; mPresenceTuple.mContactUri = contactUri;
@@ -364,8 +372,24 @@ public final class RcsContactPresenceTuple implements Parcelable {
* The optional timestamp indicating the data and time of the status change of this tuple. * The optional timestamp indicating the data and time of the status change of this tuple.
* Per RFC3863 section 4.1.7, the timestamp is formatted as an IMPP datetime format * Per RFC3863 section 4.1.7, the timestamp is formatted as an IMPP datetime format
* string per RFC3339. * string per RFC3339.
* @hide
*/ */
public @NonNull Builder setTimestamp(@NonNull String timestamp) { public @NonNull Builder setTimestamp(@NonNull String timestamp) {
try {
mPresenceTuple.mTimestamp =
DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(timestamp, Instant::from);
} catch (DateTimeParseException e) {
Log.d(LOG_TAG, "Parse timestamp failed " + e);
}
return this;
}
/**
* The optional timestamp indicating the data and time of the status change of this tuple.
* Per RFC3863 section 4.1.7, the timestamp is formatted as an IMPP datetime format
* string per RFC3339.
*/
public @NonNull Builder setTime(@NonNull Instant timestamp) {
mPresenceTuple.mTimestamp = timestamp; mPresenceTuple.mTimestamp = timestamp;
return this; return this;
} }
@@ -397,7 +421,7 @@ public final class RcsContactPresenceTuple implements Parcelable {
} }
private Uri mContactUri; private Uri mContactUri;
private String mTimestamp; private Instant mTimestamp;
private @BasicStatus String mStatus; private @BasicStatus String mStatus;
// The service information in the service-description element. // The service information in the service-description element.
@@ -416,7 +440,7 @@ public final class RcsContactPresenceTuple implements Parcelable {
private RcsContactPresenceTuple(Parcel in) { private RcsContactPresenceTuple(Parcel in) {
mContactUri = in.readParcelable(Uri.class.getClassLoader()); mContactUri = in.readParcelable(Uri.class.getClassLoader());
mTimestamp = in.readString(); mTimestamp = convertStringFormatTimeToInstant(in.readString());
mStatus = in.readString(); mStatus = in.readString();
mServiceId = in.readString(); mServiceId = in.readString();
mServiceVersion = in.readString(); mServiceVersion = in.readString();
@@ -427,7 +451,7 @@ public final class RcsContactPresenceTuple implements Parcelable {
@Override @Override
public void writeToParcel(@NonNull Parcel out, int flags) { public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeParcelable(mContactUri, flags); out.writeParcelable(mContactUri, flags);
out.writeString(mTimestamp); out.writeString(convertInstantToStringFormat(mTimestamp));
out.writeString(mStatus); out.writeString(mStatus);
out.writeString(mServiceId); out.writeString(mServiceId);
out.writeString(mServiceVersion); out.writeString(mServiceVersion);
@@ -453,6 +477,26 @@ public final class RcsContactPresenceTuple implements Parcelable {
} }
}; };
// Convert the Instant to the string format
private String convertInstantToStringFormat(Instant instant) {
if (instant == null) {
return "";
}
return instant.toString();
}
// Convert the time string format to Instant
private @Nullable Instant convertStringFormatTimeToInstant(String timestamp) {
if (TextUtils.isEmpty(timestamp)) {
return null;
}
try {
return DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(timestamp, Instant::from);
} catch (DateTimeParseException e) {
return null;
}
}
/** @return the status of the tuple element. */ /** @return the status of the tuple element. */
public @NonNull @BasicStatus String getStatus() { public @NonNull @BasicStatus String getStatus() {
return mStatus; return mStatus;
@@ -473,8 +517,16 @@ public final class RcsContactPresenceTuple implements Parcelable {
return mContactUri; return mContactUri;
} }
/** @return the timestamp element contained in the tuple if it exists */ /**
* @return the timestamp element contained in the tuple if it exists
* @hide
*/
public @Nullable String getTimestamp() { public @Nullable String getTimestamp() {
return (mTimestamp == null) ? null : mTimestamp.toString();
}
/** @return the timestamp element contained in the tuple if it exists */
public @Nullable Instant getTime() {
return mTimestamp; return mTimestamp;
} }

View File

@@ -339,6 +339,7 @@ public final class RcsContactUceCapability implements Parcelable {
} }
/** /**
* Retrieve the contact URI requested by the applications.
* @return the URI representing the contact associated with the capabilities. * @return the URI representing the contact associated with the capabilities.
*/ */
public @NonNull Uri getContactUri() { public @NonNull Uri getContactUri() {

View File

@@ -36,6 +36,8 @@ import android.util.Log;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap; import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -430,13 +432,15 @@ public class RcsUceAdapter {
/** /**
* The pending request has completed successfully due to all requested contacts information * The pending request has completed successfully due to all requested contacts information
* being delivered. * being delivered. The callback {@link #onCapabilitiesReceived(List)}
* for each contacts is required to be called before {@link #onComplete} is called.
*/ */
void onComplete(); void onComplete();
/** /**
* The pending request has resulted in an error and may need to be retried, depending on the * The pending request has resulted in an error and may need to be retried, depending on the
* error code. * error code. The callback {@link #onCapabilitiesReceived(List)}
* for each contacts is required to be called before {@link #onError} is called.
* @param errorCode The reason for the framework being unable to process the request. * @param errorCode The reason for the framework being unable to process the request.
* @param retryIntervalMillis The time in milliseconds the requesting application should * @param retryIntervalMillis The time in milliseconds the requesting application should
* wait before retrying, if non-zero. * wait before retrying, if non-zero.
@@ -483,7 +487,6 @@ public class RcsUceAdapter {
* becomes inactive. See {@link ImsException#getCode()} for more information on the error codes. * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
* @hide * @hide
*/ */
@SystemApi
@RequiresPermission(allOf = {Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, @RequiresPermission(allOf = {Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE,
Manifest.permission.READ_CONTACTS}) Manifest.permission.READ_CONTACTS})
public void requestCapabilities(@NonNull List<Uri> contactNumbers, public void requestCapabilities(@NonNull List<Uri> contactNumbers,
@@ -548,6 +551,94 @@ public class RcsUceAdapter {
} }
} }
/**
* Request the User Capability Exchange capabilities for one or more contacts.
* <p>
* This will return the cached capabilities of the contact and will not perform a capability
* poll on the network unless there are contacts being queried with stale information.
* <p>
* Be sure to check the availability of this feature using
* {@link ImsRcsManager#isAvailable(int, 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 contactNumbers A list of numbers that the capabilities are being requested for.
* @param executor The executor that will be used when the request is completed and the
* {@link CapabilitiesCallback} is called.
* @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.
* @hide
*/
@SystemApi
@RequiresPermission(allOf = {Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE,
Manifest.permission.READ_CONTACTS})
public void requestCapabilities(@NonNull Collection<Uri> contactNumbers,
@NonNull @CallbackExecutor Executor executor,
@NonNull CapabilitiesCallback c) throws ImsException {
if (c == null) {
throw new IllegalArgumentException("Must include a non-null CapabilitiesCallback.");
}
if (executor == null) {
throw new IllegalArgumentException("Must include a non-null Executor.");
}
if (contactNumbers == null) {
throw new IllegalArgumentException("Must include non-null contact number list.");
}
IImsRcsController imsRcsController = getIImsRcsController();
if (imsRcsController == null) {
Log.e(TAG, "requestCapabilities: IImsRcsController is null");
throw new ImsException("Can not find remote IMS service",
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
IRcsUceControllerCallback internalCallback = new IRcsUceControllerCallback.Stub() {
@Override
public void onCapabilitiesReceived(List<RcsContactUceCapability> contactCapabilities) {
final long callingIdentity = Binder.clearCallingIdentity();
try {
executor.execute(() -> c.onCapabilitiesReceived(contactCapabilities));
} finally {
restoreCallingIdentity(callingIdentity);
}
}
@Override
public void onComplete() {
final long callingIdentity = Binder.clearCallingIdentity();
try {
executor.execute(() -> c.onComplete());
} finally {
restoreCallingIdentity(callingIdentity);
}
}
@Override
public void onError(int errorCode, long retryAfterMilliseconds) {
final long callingIdentity = Binder.clearCallingIdentity();
try {
executor.execute(() -> c.onError(errorCode, retryAfterMilliseconds));
} finally {
restoreCallingIdentity(callingIdentity);
}
}
};
try {
imsRcsController.requestCapabilities(mSubId, mContext.getOpPackageName(),
mContext.getAttributionTag(), new ArrayList(contactNumbers), internalCallback);
} catch (ServiceSpecificException e) {
throw new ImsException(e.toString(), e.errorCode);
} catch (RemoteException e) {
Log.e(TAG, "Error calling IImsRcsController#requestCapabilities", e);
throw new ImsException("Remote IMS Service is not available",
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
/** /**
* Ignore the device cache and perform a capability discovery for one contact, also called * Ignore the device cache and perform a capability discovery for one contact, also called
* "availability fetch." * "availability fetch."
@@ -569,6 +660,10 @@ public class RcsUceAdapter {
* {@link CapabilitiesCallback} is called. * {@link CapabilitiesCallback} is called.
* @param c A one-time callback for when the request for capabilities completes or there is * @param c A one-time callback for when the request for capabilities completes or there is
* an error processing the request. * 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.
* @hide * @hide
*/ */
@SystemApi @SystemApi

View File

@@ -31,6 +31,7 @@ import android.util.Pair;
import java.lang.annotation.Retention; import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.concurrent.Executor; import java.util.concurrent.Executor;
@@ -241,7 +242,7 @@ public class RcsCapabilityExchangeImplBase {
/** /**
* Notify the framework of the response to the SUBSCRIBE request from * Notify the framework of the response to the SUBSCRIBE request from
* {@link #subscribeForCapabilities(List, SubscribeResponseCallback)}. * {@link #subscribeForCapabilities(Collection, SubscribeResponseCallback)}.
* <p> * <p>
* If the carrier network responds to the SUBSCRIBE request with a 2XX response, then the * If the carrier network responds to the SUBSCRIBE request with a 2XX response, then the
* framework will expect the IMS stack to call {@link #onNotifyCapabilitiesUpdate}, * framework will expect the IMS stack to call {@link #onNotifyCapabilitiesUpdate},
@@ -266,7 +267,7 @@ public class RcsCapabilityExchangeImplBase {
/** /**
* Notify the framework of the response to the SUBSCRIBE request from * Notify the framework of the response to the SUBSCRIBE request from
* {@link #subscribeForCapabilities(List, SubscribeResponseCallback)} that also * {@link #subscribeForCapabilities(Collection, SubscribeResponseCallback)} that also
* includes a reason provided in the “reason” header. See RFC3326 for more * includes a reason provided in the “reason” header. See RFC3326 for more
* information. * information.
* *
@@ -388,6 +389,7 @@ public class RcsCapabilityExchangeImplBase {
* @param uris A {@link List} of the {@link Uri}s that the framework is requesting the UCE * @param uris A {@link List} of the {@link Uri}s that the framework is requesting the UCE
* capabilities for. * capabilities for.
* @param cb The callback of the subscribe request. * @param cb The callback of the subscribe request.
* @hide
*/ */
// executor used is defined in the constructor. // executor used is defined in the constructor.
@SuppressLint("ExecutorRegistration") @SuppressLint("ExecutorRegistration")
@@ -402,6 +404,40 @@ public class RcsCapabilityExchangeImplBase {
} }
} }
/**
* The user capabilities of one or multiple contacts have been requested by the framework.
* <p>
* The implementer must follow up this call with an
* {@link SubscribeResponseCallback#onCommandError} call to indicate this operation has failed.
* The response from the network to the SUBSCRIBE request must be sent back to the framework
* using {@link SubscribeResponseCallback#onNetworkResponse(int, String)}.
* As NOTIFY requests come in from the network, the requested contacts capabilities should be
* sent back to the framework using
* {@link SubscribeResponseCallback#onNotifyCapabilitiesUpdate(List<String>}) and
* {@link SubscribeResponseCallback#onResourceTerminated(List<Pair<Uri, String>>)}
* should be called with the presence information for the contacts specified.
* <p>
* Once the subscription is terminated,
* {@link SubscribeResponseCallback#onTerminated(String, long)} must be called for the
* framework to finish listening for NOTIFY responses.
*
* @param uris A {@link Collection} of the {@link Uri}s that the framework is requesting the
* UCE capabilities for.
* @param cb The callback of the subscribe request.
*/
// executor used is defined in the constructor.
@SuppressLint("ExecutorRegistration")
public void subscribeForCapabilities(@NonNull Collection<Uri> uris,
@NonNull SubscribeResponseCallback cb) {
// Stub - to be implemented by service
Log.w(LOG_TAG, "subscribeForCapabilities called with no implementation.");
try {
cb.onCommandError(COMMAND_CODE_NOT_SUPPORTED);
} catch (ImsException e) {
// Do not do anything, this is a stub implementation.
}
}
/** /**
* The capabilities of this device have been updated and should be published to the network. * The capabilities of this device have been updated and should be published to the network.
* <p> * <p>