Merge "[RCS UCE] Expose the RCS UCE publishing device's capabilities APIs" am: 5b51530d0d

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

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I9ccba700f145b722133b0e6929dca594ecef94b6
This commit is contained in:
James Lin
2021-01-13 00:41:12 +00:00
committed by Automerger Merge Worker
11 changed files with 613 additions and 204 deletions

View File

@@ -11570,7 +11570,32 @@ package android.telephony.ims {
}
public class RcsUceAdapter {
method @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void addOnPublishStateChangedListener(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.RcsUceAdapter.OnPublishStateChangedListener) 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.MODIFY_PHONE_STATE) public void setUceSettingEnabled(boolean) throws android.telephony.ims.ImsException;
field public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 1; // 0x1
field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G = 7; // 0x7
field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 6; // 0x6
field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD = 4; // 0x4
field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS = 5; // 0x5
field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN = 9; // 0x9
field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED = 2; // 0x2
field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED = 3; // 0x3
field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED = 10; // 0xa
field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED = 11; // 0xb
field public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN = 8; // 0x8
field public static final int CAPABILITY_UPDATE_TRIGGER_UNKNOWN = 0; // 0x0
field public static final int PUBLISH_STATE_NOT_PUBLISHED = 2; // 0x2
field public static final int PUBLISH_STATE_OK = 1; // 0x1
field public static final int PUBLISH_STATE_OTHER_ERROR = 6; // 0x6
field public static final int PUBLISH_STATE_RCS_PROVISION_ERROR = 4; // 0x4
field public static final int PUBLISH_STATE_REQUEST_TIMEOUT = 5; // 0x5
field public static final int PUBLISH_STATE_VOICE_PROVISION_ERROR = 3; // 0x3
}
public static interface RcsUceAdapter.OnPublishStateChangedListener {
method public void onPublishStateChange(int);
}
public final class RtpHeaderExtension implements android.os.Parcelable {
@@ -11777,16 +11802,24 @@ package android.telephony.ims.feature {
}
public class RcsFeature extends android.telephony.ims.feature.ImsFeature {
ctor public RcsFeature();
ctor @Deprecated public RcsFeature();
ctor public RcsFeature(@NonNull java.util.concurrent.Executor);
method public void changeEnabledCapabilities(@NonNull android.telephony.ims.feature.CapabilityChangeRequest, @NonNull android.telephony.ims.feature.ImsFeature.CapabilityCallbackProxy);
method @NonNull public android.telephony.ims.stub.RcsCapabilityExchangeImplBase createCapabilityExchangeImpl(@NonNull java.util.concurrent.Executor, @NonNull android.telephony.ims.stub.CapabilityExchangeEventListener);
method public void onFeatureReady();
method public void onFeatureRemoved();
method public void removeCapabilityExchangeImpl(@NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase);
}
}
package android.telephony.ims.stub {
public interface CapabilityExchangeEventListener {
method public void onRequestPublishCapabilities(int) throws android.telephony.ims.ImsException;
method public void onUnpublish() throws android.telephony.ims.ImsException;
}
public interface DelegateConnectionMessageCallback {
method public void onMessageReceived(@NonNull android.telephony.ims.SipMessage);
method public void onMessageSendFailure(@NonNull String, int);
@@ -11967,6 +12000,27 @@ package android.telephony.ims.stub {
method public int updateColr(int);
}
public class RcsCapabilityExchangeImplBase {
ctor public RcsCapabilityExchangeImplBase(@NonNull java.util.concurrent.Executor);
method public void publishCapabilities(@NonNull String, @NonNull android.telephony.ims.stub.RcsCapabilityExchangeImplBase.PublishResponseCallback);
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_INSUFFICIENT_MEMORY = 5; // 0x5
field public static final int COMMAND_CODE_INVALID_PARAM = 2; // 0x2
field public static final int COMMAND_CODE_LOST_NETWORK_CONNECTION = 6; // 0x6
field public static final int COMMAND_CODE_NOT_FOUND = 8; // 0x8
field public static final int COMMAND_CODE_NOT_SUPPORTED = 7; // 0x7
field public static final int COMMAND_CODE_NO_CHANGE = 10; // 0xa
field public static final int COMMAND_CODE_REQUEST_TIMEOUT = 4; // 0x4
field public static final int COMMAND_CODE_SERVICE_UNAVAILABLE = 9; // 0x9
field public static final int COMMAND_CODE_SERVICE_UNKNOWN = 0; // 0x0
}
public static interface RcsCapabilityExchangeImplBase.PublishResponseCallback {
method public void onCommandError(int) throws android.telephony.ims.ImsException;
method public void onNetworkResponse(@IntRange(from=100, to=699) int, @NonNull String) throws android.telephony.ims.ImsException;
}
public interface SipDelegate {
method public void closeDialog(@NonNull String);
method public void notifyMessageReceiveError(@NonNull String, int);

View File

@@ -34,7 +34,7 @@ import java.util.List;
* network during a SUBSCRIBE request. See RFC3863 for more information.
* @hide
*/
public class RcsContactPresenceTuple implements Parcelable {
public final 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";
@@ -61,7 +61,7 @@ public class RcsContactPresenceTuple implements Parcelable {
* 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 {
public static final class ServiceCapabilities implements Parcelable {
/** The service can simultaneously send and receive data. */
public static final String DUPLEX_MODE_FULL = "full";
@@ -88,7 +88,7 @@ public class RcsContactPresenceTuple implements Parcelable {
/**
* Builder to help construct {@link ServiceCapabilities} instances.
*/
public static class Builder {
public static final class Builder {
private ServiceCapabilities mCapabilities;
@@ -106,7 +106,7 @@ public class RcsContactPresenceTuple implements Parcelable {
* Add the supported duplex mode.
* @param mode The supported duplex mode
*/
public Builder addSupportedDuplexMode(@NonNull @DuplexMode String mode) {
public @NonNull Builder addSupportedDuplexMode(@NonNull @DuplexMode String mode) {
mCapabilities.mSupportedDuplexModeList.add(mode);
return this;
}
@@ -115,7 +115,7 @@ public class RcsContactPresenceTuple implements Parcelable {
* Add the unsupported duplex mode.
* @param mode The unsupported duplex mode
*/
public Builder addUnsupportedDuplexMode(@NonNull @DuplexMode String mode) {
public @NonNull Builder addUnsupportedDuplexMode(@NonNull @DuplexMode String mode) {
mCapabilities.mUnsupportedDuplexModeList.add(mode);
return this;
}
@@ -123,7 +123,7 @@ public class RcsContactPresenceTuple implements Parcelable {
/**
* @return the ServiceCapabilities instance.
*/
public ServiceCapabilities build() {
public @NonNull ServiceCapabilities build() {
return mCapabilities;
}
}
@@ -211,9 +211,9 @@ public class RcsContactPresenceTuple implements Parcelable {
/**
* Builder to help construct {@link RcsContactPresenceTuple} instances.
*/
public static class Builder {
public static final class Builder {
private RcsContactPresenceTuple mPresenceTuple;
private final RcsContactPresenceTuple mPresenceTuple;
/**
* Builds a RcsContactPresenceTuple instance.
@@ -230,7 +230,7 @@ public class RcsContactPresenceTuple implements Parcelable {
/**
* The optional SIP Contact URI associated with the PIDF tuple element.
*/
public Builder addContactUri(@NonNull Uri contactUri) {
public @NonNull Builder addContactUri(@NonNull Uri contactUri) {
mPresenceTuple.mContactUri = contactUri;
return this;
}
@@ -239,7 +239,7 @@ public class RcsContactPresenceTuple implements Parcelable {
* 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) {
public @NonNull Builder addTimeStamp(@NonNull String timestamp) {
mPresenceTuple.mTimestamp = timestamp;
return this;
}
@@ -248,7 +248,7 @@ public class RcsContactPresenceTuple implements Parcelable {
* An optional parameter containing the description element of the service-description. See
* OMA Presence SIMPLE specification v1.1
*/
public Builder addDescription(@NonNull String description) {
public @NonNull Builder addDescription(@NonNull String description) {
mPresenceTuple.mServiceDescription = description;
return this;
}
@@ -257,7 +257,7 @@ public class RcsContactPresenceTuple implements Parcelable {
* 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) {
public @NonNull Builder addServiceCapabilities(@NonNull ServiceCapabilities caps) {
mPresenceTuple.mServiceCapabilities = caps;
return this;
}
@@ -265,7 +265,7 @@ public class RcsContactPresenceTuple implements Parcelable {
/**
* @return the constructed instance.
*/
public RcsContactPresenceTuple build() {
public @NonNull RcsContactPresenceTuple build() {
return mPresenceTuple;
}
}

View File

@@ -144,7 +144,7 @@ public final class RcsContactUceCapability implements Parcelable {
* @param tag the supported feature tag
* @return this OptionBuilder
*/
public @NonNull OptionsBuilder addFeatureTag(String tag) {
public @NonNull OptionsBuilder addFeatureTag(@NonNull String tag) {
mCapabilities.mFeatureTags.add(tag);
return this;
}
@@ -154,7 +154,7 @@ public final class RcsContactUceCapability implements Parcelable {
* @param tags the list of the supported feature tags
* @return this OptionBuilder
*/
public @NonNull OptionsBuilder addFeatureTags(List<String> tags) {
public @NonNull OptionsBuilder addFeatureTags(@NonNull List<String> tags) {
mCapabilities.mFeatureTags.addAll(tags);
return this;
}
@@ -195,7 +195,7 @@ public final class RcsContactUceCapability implements Parcelable {
* @param tuple The {@link RcsContactPresenceTuple} to be added into.
* @return this PresenceBuilder
*/
public @NonNull PresenceBuilder addCapabilityTuple(RcsContactPresenceTuple tuple) {
public @NonNull PresenceBuilder addCapabilityTuple(@NonNull RcsContactPresenceTuple tuple) {
mCapabilities.mPresenceTuples.add(tuple);
return this;
}
@@ -205,7 +205,8 @@ public final class RcsContactUceCapability implements Parcelable {
* @param tuples The list of the {@link RcsContactPresenceTuple} to be added into.
* @return this PresenceBuilder
*/
public @NonNull PresenceBuilder addCapabilityTuples(List<RcsContactPresenceTuple> tuples) {
public @NonNull PresenceBuilder addCapabilityTuples(
@NonNull List<RcsContactPresenceTuple> tuples) {
mCapabilities.mPresenceTuples.addAll(tuples);
return this;
}
@@ -282,7 +283,7 @@ public final class RcsContactUceCapability implements Parcelable {
* @return The feature tags present in the OPTIONS response from the network.
* <p>
* Note: this is only populated if {@link #getCapabilityMechanism} is
* {@link CAPABILITY_MECHANISM_OPTIONS}
* {@link RcsContactUceCapability#CAPABILITY_MECHANISM_OPTIONS}
*/
public @NonNull List<String> getOptionsFeatureTags() {
if (mCapabilityMechanism != CAPABILITY_MECHANISM_OPTIONS) {
@@ -296,7 +297,7 @@ public final class RcsContactUceCapability implements Parcelable {
* contained in the NOTIFY response from the network.
* <p>
* Note: this is only populated if {@link #getCapabilityMechanism} is
* {@link CAPABILITY_MECHANISM_PRESENCE}
* {@link RcsContactUceCapability#CAPABILITY_MECHANISM_PRESENCE}
*/
public @NonNull List<RcsContactPresenceTuple> getPresenceTuples() {
if (mCapabilityMechanism != CAPABILITY_MECHANISM_PRESENCE) {
@@ -312,9 +313,9 @@ public final class RcsContactUceCapability implements Parcelable {
*
* <p>
* Note: this is only populated if {@link #getCapabilityMechanism} is
* {@link CAPABILITY_MECHANISM_PRESENCE}
* {@link RcsContactUceCapability#CAPABILITY_MECHANISM_PRESENCE}
*/
public @Nullable RcsContactPresenceTuple getPresenceTuple(String serviceId) {
public @Nullable RcsContactPresenceTuple getPresenceTuple(@NonNull String serviceId) {
if (mCapabilityMechanism != CAPABILITY_MECHANISM_PRESENCE) {
return null;
}

View File

@@ -36,7 +36,9 @@ import android.util.Log;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.Executor;
/**
@@ -110,7 +112,7 @@ public class RcsUceAdapter {
public static final int ERROR_FORBIDDEN = 6;
/**
* The contact URI requested is not provisioned for VoLTE or it is not known as an IMS
* The contact URI requested is not provisioned for voice or it is not known as an IMS
* subscriber to the carrier network.
* @hide
*/
@@ -128,26 +130,26 @@ public class RcsUceAdapter {
* The network did not respond to the capabilities request before the request timed out.
* @hide
*/
public static final int ERROR_REQUEST_TIMEOUT = 10;
public static final int ERROR_REQUEST_TIMEOUT = 9;
/**
* The request failed due to the service having insufficient memory.
* @hide
*/
public static final int ERROR_INSUFFICIENT_MEMORY = 11;
public static final int ERROR_INSUFFICIENT_MEMORY = 10;
/**
* The network was lost while trying to complete the request.
* @hide
*/
public static final int ERROR_LOST_NETWORK = 12;
public static final int ERROR_LOST_NETWORK = 11;
/**
* The network is temporarily unavailable or busy. Retries should only be done after the retry
* time returned in {@link CapabilitiesCallback#onError} has elapsed.
* @hide
*/
public static final int ERROR_SERVER_UNAVAILABLE = 13;
public static final int ERROR_SERVER_UNAVAILABLE = 12;
/**@hide*/
@Retention(RetentionPolicy.SOURCE)
@@ -167,70 +169,94 @@ public class RcsUceAdapter {
})
public @interface ErrorCode {}
/**
* A capability update has been requested but the reason is unknown.
* @hide
*/
@SystemApi
public static final int CAPABILITY_UPDATE_TRIGGER_UNKNOWN = 0;
/**
* A capability update has been requested due to the Entity Tag (ETag) expiring.
* @hide
*/
public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 0;
@SystemApi
public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 1;
/**
* A capability update has been requested due to moving to LTE with VoPS disabled.
* @hide
*/
public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED = 1;
@SystemApi
public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED = 2;
/**
* A capability update has been requested due to moving to LTE with VoPS enabled.
* @hide
*/
public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED = 2;
@SystemApi
public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED = 3;
/**
* A capability update has been requested due to moving to eHRPD.
* @hide
*/
public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD = 3;
@SystemApi
public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD = 4;
/**
* A capability update has been requested due to moving to HSPA+.
* @hide
*/
public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS = 4;
@SystemApi
public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS = 5;
/**
* A capability update has been requested due to moving to 3G.
* @hide
*/
public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 5;
@SystemApi
public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 6;
/**
* A capability update has been requested due to moving to 2G.
* @hide
*/
public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G = 6;
@SystemApi
public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G = 7;
/**
* A capability update has been requested due to moving to WLAN
* @hide
*/
public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN = 7;
@SystemApi
public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN = 8;
/**
* A capability update has been requested due to moving to IWLAN
* @hide
*/
public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN = 8;
/**
* A capability update has been requested but the reason is unknown.
* @hide
*/
public static final int CAPABILITY_UPDATE_TRIGGER_UNKNOWN = 9;
@SystemApi
public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN = 9;
/**
* A capability update has been requested due to moving to 5G NR with VoPS disabled.
* @hide
*/
@SystemApi
public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED = 10;
/**
* A capability update has been requested due to moving to 5G NR with VoPS enabled.
* @hide
*/
@SystemApi
public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED = 11;
/**@hide*/
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "ERROR_", value = {
CAPABILITY_UPDATE_TRIGGER_UNKNOWN,
CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED,
CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED,
CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED,
@@ -240,7 +266,6 @@ public class RcsUceAdapter {
CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G,
CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN,
CAPABILITY_UPDATE_TRIGGER_MOVE_TO_IWLAN,
CAPABILITY_UPDATE_TRIGGER_UNKNOWN,
CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_DISABLED,
CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED
})
@@ -251,32 +276,37 @@ public class RcsUceAdapter {
* UCE.
* @hide
*/
@SystemApi
public static final int PUBLISH_STATE_OK = 1;
/**
* The hasn't published its capabilities since boot or hasn't gotten any publish response yet.
* @hide
*/
@SystemApi
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.
* is related to the fact that the device is not provisioned for voice.
* @hide
*/
public static final int PUBLISH_STATE_VOLTE_PROVISION_ERROR = 3;
@SystemApi
public static final int PUBLISH_STATE_VOICE_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.
* @hide
*/
@SystemApi
public static final int PUBLISH_STATE_RCS_PROVISION_ERROR = 4;
/**
* The last publish resulted in a "408 Request Timeout" response.
* @hide
*/
@SystemApi
public static final int PUBLISH_STATE_REQUEST_TIMEOUT = 5;
/**
@@ -286,6 +316,7 @@ public class RcsUceAdapter {
* Device shall retry with exponential back-off.
* @hide
*/
@SystemApi
public static final int PUBLISH_STATE_OTHER_ERROR = 6;
/**@hide*/
@@ -293,7 +324,7 @@ public class RcsUceAdapter {
@IntDef(prefix = "PUBLISH_STATE_", value = {
PUBLISH_STATE_OK,
PUBLISH_STATE_NOT_PUBLISHED,
PUBLISH_STATE_VOLTE_PROVISION_ERROR,
PUBLISH_STATE_VOICE_PROVISION_ERROR,
PUBLISH_STATE_RCS_PROVISION_ERROR,
PUBLISH_STATE_REQUEST_TIMEOUT,
PUBLISH_STATE_OTHER_ERROR
@@ -301,55 +332,61 @@ public class RcsUceAdapter {
public @interface PublishState {}
/**
* An application can use {@link #registerPublishStateCallback} to register a
* {@link PublishStateCallback), which will notify the user when the publish state to the
* network changes.
* An application can use {@link #addOnPublishStateChangedListener} to register a
* {@link OnPublishStateChangedListener ), which will notify the user when the publish state to
* the network changes.
* @hide
*/
public static class PublishStateCallback {
private static class PublishStateBinder extends IRcsUcePublishStateCallback.Stub {
private final PublishStateCallback mLocalCallback;
private Executor mExecutor;
PublishStateBinder(PublishStateCallback c) {
mLocalCallback = c;
}
@Override
public void onPublishStateChanged(int publishState) {
if (mLocalCallback == null) return;
final long callingIdentity = Binder.clearCallingIdentity();
try {
mExecutor.execute(() -> mLocalCallback.onChanged(publishState));
} finally {
restoreCallingIdentity(callingIdentity);
}
}
private void setExecutor(Executor executor) {
mExecutor = executor;
}
}
private final PublishStateBinder mBinder = new PublishStateBinder(this);
/**@hide*/
public final IRcsUcePublishStateCallback getBinder() {
return mBinder;
}
private void setExecutor(Executor executor) {
mBinder.setExecutor(executor);
}
@SystemApi
public interface OnPublishStateChangedListener {
/**
* Notifies the callback when the publish state has changed.
* @param publishState The latest update to the publish state.
*/
public void onChanged(@PublishState int publishState) {
void onPublishStateChange(@PublishState int publishState);
}
/**
* An application can use {@link #addOnPublishStateChangedListener} to register a
* {@link OnPublishStateChangedListener ), which will notify the user when the publish state to
* the network changes.
* @hide
*/
public static class PublishStateCallbackAdapter {
private static class PublishStateBinder extends IRcsUcePublishStateCallback.Stub {
private final OnPublishStateChangedListener mPublishStateChangeListener;
private final Executor mExecutor;
PublishStateBinder(Executor executor, OnPublishStateChangedListener listener) {
mExecutor = executor;
mPublishStateChangeListener = listener;
}
@Override
public void onPublishStateChanged(int publishState) {
if (mPublishStateChangeListener == null) return;
final long callingIdentity = Binder.clearCallingIdentity();
try {
mExecutor.execute(() ->
mPublishStateChangeListener.onPublishStateChange(publishState));
} finally {
restoreCallingIdentity(callingIdentity);
}
}
}
private final PublishStateBinder mBinder;
public PublishStateCallbackAdapter(@NonNull Executor executor,
@NonNull OnPublishStateChangedListener listener) {
mBinder = new PublishStateBinder(executor, listener);
}
/**@hide*/
public final IRcsUcePublishStateCallback getBinder() {
return mBinder;
}
}
@@ -395,6 +432,8 @@ public class RcsUceAdapter {
private final Context mContext;
private final int mSubId;
private final Map<OnPublishStateChangedListener, PublishStateCallbackAdapter>
mPublishStateCallbacks;
/**
* Not to be instantiated directly, use {@link ImsRcsManager#getUceAdapter()} to instantiate
@@ -404,6 +443,7 @@ public class RcsUceAdapter {
RcsUceAdapter(Context context, int subId) {
mContext = context;
mSubId = subId;
mPublishStateCallbacks = new HashMap<>();
}
/**
@@ -588,6 +628,7 @@ public class RcsUceAdapter {
* becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public @PublishState int getUcePublishState() throws ImsException {
IImsRcsController imsRcsController = getIImsRcsController();
@@ -609,81 +650,90 @@ public class RcsUceAdapter {
}
/**
* Registers a {@link PublishStateCallback} with the system, which will provide publish state
* updates for the subscription specified in {@link ImsManager@getRcsManager(subid)}.
* Registers a {@link OnPublishStateChangedListener} with the system, which will provide publish
* state updates for the subscription specified in {@link ImsManager@getRcsManager(subid)}.
* <p>
* Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to subscription
* changed events and call {@link #unregisterPublishStateCallback} to clean up.
* <p>
* The registered {@link PublishStateCallback} will also receive a callback when it is
* The registered {@link OnPublishStateChangedListener} will also receive a callback when it is
* registered with the current publish state.
*
* @param executor The executor the listener callback events should be run on.
* @param c The {@link PublishStateCallback} to be added.
* @param listener The {@link OnPublishStateChangedListener} to be added.
* @throws ImsException if the subscription associated with this callback is valid, but
* the {@link ImsService} associated with the subscription is not available. This can happen if
* the service crashed, for example. See {@link ImsException#getCode()} for a more detailed
* reason.
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void registerPublishStateCallback(@NonNull @CallbackExecutor Executor executor,
@NonNull PublishStateCallback c) throws ImsException {
if (c == null) {
throw new IllegalArgumentException("Must include a non-null PublishStateCallback.");
}
public void addOnPublishStateChangedListener(@NonNull @CallbackExecutor Executor executor,
@NonNull OnPublishStateChangedListener listener) throws ImsException {
if (executor == null) {
throw new IllegalArgumentException("Must include a non-null Executor.");
}
if (listener == null) {
throw new IllegalArgumentException(
"Must include a non-null OnPublishStateChangedListener.");
}
IImsRcsController imsRcsController = getIImsRcsController();
if (imsRcsController == null) {
Log.e(TAG, "registerPublishStateCallback : IImsRcsController is null");
Log.e(TAG, "addOnPublishStateChangedListener : IImsRcsController is null");
throw new ImsException("Cannot find remote IMS service",
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
c.setExecutor(executor);
PublishStateCallbackAdapter stateCallback = addPublishStateCallback(executor, listener);
try {
imsRcsController.registerUcePublishStateCallback(mSubId, c.getBinder());
imsRcsController.registerUcePublishStateCallback(mSubId, stateCallback.getBinder());
} catch (ServiceSpecificException e) {
throw new ImsException(e.getMessage(), e.errorCode);
} catch (RemoteException e) {
Log.e(TAG, "Error calling IImsRcsController#registerUcePublishStateCallback", e);
throw new ImsException("Remote IMS Service is not available",
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
/**
* Removes an existing {@link PublishStateCallback}.
* Removes an existing {@link OnPublishStateChangedListener}.
* <p>
* When the subscription associated with this callback is removed
* (SIM removed, ESIM swap,etc...), this callback will automatically be removed. If this method
* is called for an inactive subscription, it will result in a no-op.
*
* @param c The callback to be unregistered.
* @param listener The callback to be unregistered.
* @throws ImsException if the subscription associated with this callback is valid, but
* the {@link ImsService} associated with the subscription is not available. This can happen if
* the service crashed, for example. See {@link ImsException#getCode()} for a more detailed
* reason.
* @hide
*/
@SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void unregisterPublishStateCallback(@NonNull PublishStateCallback c)
throws ImsException {
if (c == null) {
throw new IllegalArgumentException("Must include a non-null PublishStateCallback.");
public void removeOnPublishStateChangedListener(
@NonNull OnPublishStateChangedListener listener) throws ImsException {
if (listener == null) {
throw new IllegalArgumentException(
"Must include a non-null OnPublishStateChangedListener.");
}
IImsRcsController imsRcsController = getIImsRcsController();
if (imsRcsController == null) {
Log.e(TAG, "unregisterPublishStateCallback: IImsRcsController is null");
Log.e(TAG, "removeOnPublishStateChangedListener: IImsRcsController is null");
throw new ImsException("Cannot find remote IMS service",
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
PublishStateCallbackAdapter callback = removePublishStateCallback(listener);
if (callback == null) {
return;
}
try {
imsRcsController.unregisterUcePublishStateCallback(mSubId, c.getBinder());
imsRcsController.unregisterUcePublishStateCallback(mSubId, callback.getBinder());
} catch (android.os.ServiceSpecificException e) {
throw new ImsException(e.getMessage(), e.errorCode);
} catch (RemoteException e) {
@@ -763,6 +813,36 @@ public class RcsUceAdapter {
}
}
/**
* Add the {@link OnPublishStateChangedListener} to collection for tracking.
* @param executor The executor that will be used when the publish state is changed and the
* {@link OnPublishStateChangedListener} is called.
* @param listener The {@link OnPublishStateChangedListener} to call the publish state changed.
* @return The {@link PublishStateCallbackAdapter} to wrapper the
* {@link OnPublishStateChangedListener}
*/
private PublishStateCallbackAdapter addPublishStateCallback(@NonNull Executor executor,
@NonNull OnPublishStateChangedListener listener) {
PublishStateCallbackAdapter adapter = new PublishStateCallbackAdapter(executor, listener);
synchronized (mPublishStateCallbacks) {
mPublishStateCallbacks.put(listener, adapter);
}
return adapter;
}
/**
* Remove the existing {@link OnPublishStateChangedListener}.
* @param listener The {@link OnPublishStateChangedListener} to remove from the collection.
* @return The wrapper class {@link PublishStateCallbackAdapter} associated with the
* {@link OnPublishStateChangedListener}.
*/
private PublishStateCallbackAdapter removePublishStateCallback(
@NonNull OnPublishStateChangedListener listener) {
synchronized (mPublishStateCallbacks) {
return mPublishStateCallbacks.remove(listener);
}
}
private IImsRcsController getIImsRcsController() {
IBinder binder = TelephonyFrameworkInitializer
.getTelephonyServiceManager()

View File

@@ -0,0 +1,115 @@
/*
* 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.aidl;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.net.Uri;
import android.os.Binder;
import android.os.RemoteException;
import android.telephony.ims.RcsContactUceCapability;
import android.telephony.ims.stub.CapabilityExchangeEventListener;
import android.util.Log;
import java.util.List;
/**
* The ICapabilityExchangeEventListener wrapper class to store the listener which is registered by
* the framework. This wrapper class also delivers the request to the framework when receive the
* request from the network.
* @hide
*/
public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventListener {
private static final String LOG_TAG = "CapExchangeListener";
private final ICapabilityExchangeEventListener mListenerBinder;
public CapabilityExchangeAidlWrapper(@Nullable ICapabilityExchangeEventListener listener) {
mListenerBinder = listener;
}
/**
* Receives the request of publishing capabilities from the network and deliver this request
* to the framework via the registered capability exchange event listener.
*/
public void onRequestPublishCapabilities(int publishTriggerType) {
ICapabilityExchangeEventListener listener = mListenerBinder;
if (listener == null) {
return;
}
try {
listener.onRequestPublishCapabilities(publishTriggerType);
} catch (RemoteException e) {
Log.w(LOG_TAG, "request publish capabilities exception: " + e);
}
}
/**
* Receives the unpublish notification and deliver this callback to the framework.
*/
public void onUnpublish() {
ICapabilityExchangeEventListener listener = mListenerBinder;
if (listener == null) {
return;
}
try {
listener.onUnpublish();
} catch (RemoteException e) {
Log.w(LOG_TAG, "Unpublish exception: " + e);
}
}
/**
* Receives the callback of the remote capability request from the network and deliver this
* request to the framework.
*/
public void onRemoteCapabilityRequest(@NonNull Uri contactUri,
@NonNull List<String> remoteCapabilities, @NonNull OptionsRequestCallback callback) {
ICapabilityExchangeEventListener listener = mListenerBinder;
if (listener == null) {
return;
}
IOptionsRequestCallback internalCallback = new IOptionsRequestCallback.Stub() {
@Override
public void respondToCapabilityRequest(RcsContactUceCapability ownCapabilities) {
final long callingIdentity = Binder.clearCallingIdentity();
try {
callback.onRespondToCapabilityRequest(ownCapabilities);
} finally {
restoreCallingIdentity(callingIdentity);
}
}
@Override
public void respondToCapabilityRequestWithError(int code, String reason) {
final long callingIdentity = Binder.clearCallingIdentity();
try {
callback.onRespondToCapabilityRequestWithError(code, reason);
} finally {
restoreCallingIdentity(callingIdentity);
}
}
};
try {
listener.onRemoteCapabilityRequest(contactUri, remoteCapabilities, internalCallback);
} catch (RemoteException e) {
Log.w(LOG_TAG, "Remote capability request exception: " + e);
}
}
}

View File

@@ -22,54 +22,15 @@ import android.telephony.ims.aidl.IOptionsRequestCallback;
import java.util.List;
/**
* Listener interface for the ImsService to use to notify the framework of UCE events.
* Listener interface for the ImsService to use to notify the framework of UCE
* events.
*
* See CapabilityExchangeEventListener for more information.
* {@hide}
*/
oneway interface ICapabilityExchangeEventListener {
/**
* Trigger the framework to provide a capability update using
* {@link RcsCapabilityExchangeImplBase#publishCapabilities}.
* <p>
* This is typically used when trying to generate an initial PUBLISH for a new
* subscription to the network. The device will cache all presence publications
* after boot until this method is called the first time.
* @param publishTriggerType {@link StackPublishTriggerType} The reason for the
* capability update request.
* @throws ImsException If this {@link RcsPresenceExchangeImplBase} instance is
* not currently connected to the framework. This can happen if the
* {@link RcsFeature} is not {@link ImsFeature#STATE_READY} and the
* {@link RcsFeature} has not received the
* {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare
* cases when the Telephony stack has crashed.
*/
void onRequestPublishCapabilities(int publishTriggerType);
/**
* Notify the framework that the device's capabilities have been unpublished from the network.
*
* @throws ImsException If this {@link RcsPresenceExchangeImplBase} instance is not currently
* connected to the framework. This can happen if the {@link RcsFeature} is not
* {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the
* {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the
* Telephony stack has crashed.
*/
void onUnpublish();
/**
* Inform the framework of a query for this device's UCE capabilities.
* <p>
* The framework will respond via the
* {@link IOptionsRequestCallback#respondToCapabilityRequest} or
* {@link IOptionsRequestCallback#respondToCapabilityRequestWithError} method.
* @param contactUri The URI associated with the remote contact that is requesting capabilities.
* @param remoteCapabilities The remote contact's capability information.
* @throws ImsException If this {@link RcsSipOptionsImplBase} instance is not currently
* connected to the framework. This can happen if the {@link RcsFeature} is not
* {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received
* the {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when
* the Telephony stack has crashed.
*/
void onRemoteCapabilityRequest(in Uri contactUri,
in List<String> remoteCapabilities,
IOptionsRequestCallback cb);
in List<String> remoteCapabilities, IOptionsRequestCallback cb);
}

View File

@@ -33,7 +33,6 @@ oneway interface IOptionsRequestCallback {
/**
* Respond to a remote capability request from the contact specified with the
* specified error.
* @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.
*/

View File

@@ -336,7 +336,7 @@ public abstract class ImsFeature {
/**
* @hide
*/
public final void initialize(Context context, int slotId) {
public void initialize(Context context, int slotId) {
mContext = context;
mSlotId = slotId;
}

View File

@@ -21,9 +21,11 @@ import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.content.Context;
import android.net.Uri;
import android.os.RemoteException;
import android.telephony.ims.RcsUceAdapter;
import android.telephony.ims.aidl.CapabilityExchangeAidlWrapper;
import android.telephony.ims.aidl.ICapabilityExchangeEventListener;
import android.telephony.ims.aidl.IImsCapabilityCallback;
import android.telephony.ims.aidl.IImsRcsFeature;
@@ -33,6 +35,7 @@ import android.telephony.ims.aidl.ISubscribeResponseCallback;
import android.telephony.ims.aidl.RcsOptionsResponseAidlWrapper;
import android.telephony.ims.aidl.RcsPublishResponseAidlWrapper;
import android.telephony.ims.aidl.RcsSubscribeResponseAidlWrapper;
import android.telephony.ims.stub.CapabilityExchangeEventListener;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.telephony.ims.stub.RcsCapabilityExchangeImplBase;
import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.OptionsResponseCallback;
@@ -114,8 +117,10 @@ public class RcsFeature extends ImsFeature {
@Override
public void setCapabilityExchangeEventListener(
@Nullable ICapabilityExchangeEventListener listener) throws RemoteException {
executeMethodAsync(() -> mReference.setCapabilityExchangeEventListener(listener),
"setCapabilityExchangeEventListener");
CapabilityExchangeEventListener listenerWrapper =
new CapabilityExchangeAidlWrapper(listener);
executeMethodAsync(() -> mReference.setCapabilityExchangeEventListener(
mExecutor, listenerWrapper), "setCapabilityExchangeEventListener");
}
@Override
@@ -245,9 +250,10 @@ public class RcsFeature extends ImsFeature {
}
}
private final Executor mExecutor;
private final RcsFeatureBinder mImsRcsBinder;
private RcsCapabilityExchangeImplBase mCapabilityExchangeImpl;
private ICapabilityExchangeEventListener mCapExchangeEventListener;
private CapabilityExchangeEventListener mCapExchangeEventListener;
/**
* Create a new RcsFeature.
@@ -255,26 +261,45 @@ public class RcsFeature extends ImsFeature {
* Method stubs called from the framework will be called asynchronously. To specify the
* {@link Executor} that the methods stubs will be called, use
* {@link RcsFeature#RcsFeature(Executor)} instead.
*
* @deprecated Use {@link #RcsFeature(Executor)} to create the RcsFeature.
*/
@Deprecated
public RcsFeature() {
super();
mExecutor = Runnable::run;
// Run on the Binder threads that call them.
mImsRcsBinder = new RcsFeatureBinder(this, Runnable::run);
mImsRcsBinder = new RcsFeatureBinder(this, mExecutor);
}
/**
* Create a new RcsFeature using the Executor specified for methods being called by the
* framework.
* @param executor The executor for the framework to use when making calls to this service.
* @hide
* @param executor The executor for the framework to use when executing the methods overridden
* by the implementation of RcsFeature.
*/
public RcsFeature(@NonNull Executor executor) {
super();
if (executor == null) {
throw new IllegalArgumentException("executor can not be null.");
}
mExecutor = executor;
// Run on the Binder thread by default.
mImsRcsBinder = new RcsFeatureBinder(this, executor);
mImsRcsBinder = new RcsFeatureBinder(this, mExecutor);
}
/**
* Called when the RcsFeature is initialized.
*
* @param context The context that is used in the ImsService.
* @param slotId The slot ID associated with the RcsFeature.
* @hide
*/
@Override
public void initialize(Context context, int slotId) {
super.initialize(context, slotId);
// Notify that the RcsFeature is ready.
mExecutor.execute(() -> onFeatureReady());
}
/**
@@ -348,13 +373,26 @@ public class RcsFeature extends ImsFeature {
* operation and the RcsFeature sets the status of the capability to true using
* {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}.
*
* @return An instance of {@link RcsCapabilityExchangeImplBase} that implements presence
* @param executor The executor for the framework to use when request RCS resquests to this
* service.
* @param listener A {@link CapabilityExchangeEventListener} to send the capability exchange
* event to the framework.
* @return An instance of {@link RcsCapabilityExchangeImplBase} that implements capability
* exchange if it is supported by the device.
* @hide
*/
public @NonNull RcsCapabilityExchangeImplBase createCapabilityExchangeImpl() {
public @NonNull RcsCapabilityExchangeImplBase createCapabilityExchangeImpl(
@NonNull Executor executor, @NonNull CapabilityExchangeEventListener listener) {
// Base Implementation, override to implement functionality
return new RcsCapabilityExchangeImplBase();
return new RcsCapabilityExchangeImplBase(executor);
}
/**
* Remove the given CapabilityExchangeImplBase instance.
* @param capExchangeImpl The {@link RcsCapabilityExchangeImplBase} instance to be removed.
*/
public void removeCapabilityExchangeImpl(
@NonNull RcsCapabilityExchangeImplBase capExchangeImpl) {
// Override to implement the process of removing RcsCapabilityExchangeImplBase instance.
}
/**{@inheritDoc}*/
@@ -377,18 +415,58 @@ public class RcsFeature extends ImsFeature {
return mImsRcsBinder;
}
private void setCapabilityExchangeEventListener(ICapabilityExchangeEventListener listener) {
mCapExchangeEventListener = listener;
if (mCapExchangeEventListener != null) {
onFeatureReady();
/**
* Set the capability exchange listener.
* @param executor The executor for the framework to use when request RCS requests to this
* service.
* @param listener A {@link CapabilityExchangeEventListener} to send the capability exchange
* event to the framework.
*/
private void setCapabilityExchangeEventListener(@NonNull Executor executor,
@Nullable CapabilityExchangeEventListener listener) {
synchronized (mLock) {
mCapExchangeEventListener = listener;
if (mCapExchangeEventListener != null) {
initRcsCapabilityExchangeImplBase(executor, mCapExchangeEventListener);
} else {
// Remove the RcsCapabilityExchangeImplBase instance when the capability exchange
// instance has been removed in the framework.
if (mCapabilityExchangeImpl != null) {
removeCapabilityExchangeImpl(mCapabilityExchangeImpl);
}
mCapabilityExchangeImpl = null;
}
}
}
private RcsCapabilityExchangeImplBase getCapabilityExchangeImplBaseInternal() {
/**
* Initialize the RcsCapabilityExchangeImplBase instance if the capability exchange instance
* has already been created in the framework.
* @param executor The executor for the framework to use when request RCS requests to this
* service.
* @param listener A {@link CapabilityExchangeEventListener} to send the capability exchange
* event to the framework.
*/
private void initRcsCapabilityExchangeImplBase(@NonNull Executor executor,
@NonNull CapabilityExchangeEventListener listener) {
synchronized (mLock) {
// Remove the original instance
if (mCapabilityExchangeImpl != null) {
removeCapabilityExchangeImpl(mCapabilityExchangeImpl);
}
mCapabilityExchangeImpl = createCapabilityExchangeImpl(executor, listener);
}
}
/**
* @return the {@link RcsCapabilityExchangeImplBase} associated with the RcsFeature.
*/
private @NonNull RcsCapabilityExchangeImplBase getCapabilityExchangeImplBaseInternal() {
synchronized (mLock) {
// The method should not be called if the instance of RcsCapabilityExchangeImplBase has
// not been created yet.
if (mCapabilityExchangeImpl == null) {
mCapabilityExchangeImpl = createCapabilityExchangeImpl();
mCapabilityExchangeImpl.setEventListener(mCapExchangeEventListener);
throw new IllegalStateException("Session is not available.");
}
return mCapabilityExchangeImpl;
}

View File

@@ -0,0 +1,108 @@
/*
* 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.stub;
import android.annotation.NonNull;
import android.annotation.SystemApi;
import android.net.Uri;
import android.telephony.ims.ImsException;
import android.telephony.ims.RcsContactUceCapability;
import android.telephony.ims.RcsUceAdapter;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.RcsFeature;
import java.util.List;
/**
* The interface of the capabilities event listener for ImsService to notify the framework of the
* UCE request and status updated.
* @hide
*/
@SystemApi
public interface CapabilityExchangeEventListener {
/**
* Interface used by the framework to respond to OPTIONS requests.
* @hide
*/
interface OptionsRequestCallback {
/**
* Respond to a remote capability request from the contact specified with the
* capabilities of this device.
* @param ownCapabilities The capabilities of this device.
*/
void onRespondToCapabilityRequest(@NonNull RcsContactUceCapability ownCapabilities);
/**
* Respond to a remote capability request from the contact specified with the
* specified error.
* @param code The SIP response code to respond with.
* @param reason A non-null String containing the reason associated with the SIP code.
*/
void onRespondToCapabilityRequestWithError(int code, @NonNull String reason);
}
/**
* Trigger the framework to provide a capability update using
* {@link RcsCapabilityExchangeImplBase#publishCapabilities}.
* <p>
* This is typically used when trying to generate an initial PUBLISH for a new subscription to
* the network. The device will cache all presence publications after boot until this method is
* called the first time.
* @param publishTriggerType {@link RcsUceAdapter#StackPublishTriggerType} The reason for the
* capability update request.
* @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is not currently
* connected to the framework. This can happen if the {@link RcsFeature} is not
* {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the
* {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the
* Telephony stack has crashed.
*/
void onRequestPublishCapabilities(
@RcsUceAdapter.StackPublishTriggerType int publishTriggerType) throws ImsException;
/**
* Notify the framework that the device's capabilities have been unpublished
* from the network.
*
* @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is not currently
* connected to the framework. This can happen if the {@link RcsFeature} is not
* {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the
* {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare cases when the
* Telephony stack has crashed.
*/
void onUnpublish() throws ImsException;
/**
* Inform the framework of a query for this device's UCE capabilities.
* <p>
* The framework will respond via the
* {@link OptionsRequestCallback#onRespondToCapabilityRequest} or
* {@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 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
* {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received
* the {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare
* cases when the Telephony stack has crashed.
* @hide
*/
void onRemoteCapabilityRequest(@NonNull Uri contactUri,
@NonNull List<String> remoteCapabilities,
@NonNull OptionsRequestCallback callback) throws ImsException;
}

View File

@@ -20,20 +20,28 @@ import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.net.Uri;
import android.telephony.ims.ImsException;
import android.telephony.ims.aidl.ICapabilityExchangeEventListener;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.RcsFeature;
import android.util.Log;
import android.util.Pair;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.util.List;
import java.util.concurrent.Executor;
/**
* Base class for different types of Capability exchange.
* Extend this base class to implement RCS User Capability Exchange (UCE) for the AOSP platform
* using the vendor ImsService.
* <p>
* See RCC.07 for more details on UCE as well as how UCE should be implemented.
* @hide
*/
@SystemApi
public class RcsCapabilityExchangeImplBase {
private static final String LOG_TAG = "RcsCapExchangeImplBase";
@@ -70,13 +78,11 @@ public class RcsCapabilityExchangeImplBase {
/**
* Network connection is lost.
* @hide
*/
public static final int COMMAND_CODE_LOST_NETWORK_CONNECTION = 6;
/**
* Requested feature/resource is not supported.
* @hide
*/
public static final int COMMAND_CODE_NOT_SUPPORTED = 7;
@@ -117,7 +123,8 @@ public class RcsCapabilityExchangeImplBase {
*/
public interface PublishResponseCallback {
/**
* Notify the framework that the command associated with this callback has failed.
* Notify the framework that the command associated with the
* {@link #publishCapabilities(String, PublishResponseCallback)} has failed.
*
* @param code The reason why the associated command has failed.
* @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is
@@ -128,15 +135,15 @@ public class RcsCapabilityExchangeImplBase {
*/
void onCommandError(@CommandCode int code) throws ImsException;
/**
* Provide the framework with a subsequent network response update to
* {@link #publishCapabilities(String, PublishResponseCallback)}.
*
* @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 reason The optional reason response from the network. If there is a reason header
* included in the response, that should take precedence over the reason provided in the
* status line. If the network provided no reason with the code, the string should be empty.
* @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is
* not currently connected to the framework. This can happen if the {@link RcsFeature}
* is not {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received
@@ -149,6 +156,7 @@ public class RcsCapabilityExchangeImplBase {
/**
* Interface used by the framework to respond to OPTIONS requests.
* @hide
*/
public interface OptionsResponseCallback {
/**
@@ -171,7 +179,7 @@ public class RcsCapabilityExchangeImplBase {
* If none was sent, this should be an empty string.
* @param theirCaps the contact's UCE capabilities associated with the
* capability request.
* @throws ImsException If this {@link RcsSipOptionsImplBase} instance is not
* @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is not
* currently connected to the framework. This can happen if the
* {@link RcsFeature} is not {@link ImsFeature#STATE_READY} and the
* {@link RcsFeature} has not received the
@@ -184,6 +192,7 @@ public class RcsCapabilityExchangeImplBase {
/**
* Interface used by the framework to receive the response of the subscribe request.
* @hide
*/
public interface SubscribeResponseCallback {
/**
@@ -219,17 +228,16 @@ public class RcsCapabilityExchangeImplBase {
/**
* Provides the framework with latest XML PIDF documents included in the
* network response for the requested contacts' capabilities requested by the
* Framework using {@link #requestCapabilities(List, int)}. This should be
* Framework using {@link #requestCapabilities(List, int)}. This should be
* called every time a new NOTIFY event is received with new capability
* information.
*
* @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is
* not currently
* connected to the framework. This can happen if the {@link RcsFeature} is not
* {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received
* the {@link ImsFeature#onFeatureReady()} callback. This may also happen in
* rare cases when the
* Telephony stack has crashed.
* not currently connected to the framework.
* This can happen if the {@link RcsFeature} is not {@link ImsFeature#STATE_READY} and the
* {@link RcsFeature} {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not
* received the {@link ImsFeature#onFeatureReady()} callback. This may also happen in
* rare cases when the Telephony stack has crashed.
*/
void onNotifyCapabilitiesUpdate(@NonNull List<String> pidfXmls) throws ImsException;
@@ -250,24 +258,21 @@ public class RcsCapabilityExchangeImplBase {
* This allows the framework to know that there will no longer be any
* capability updates for the requested operationToken.
*/
void onTerminated(String reason, long retryAfterMilliseconds) throws ImsException;
void onTerminated(@NonNull String reason, long retryAfterMilliseconds) throws ImsException;
}
private ICapabilityExchangeEventListener mListener;
private final Executor mBinderExecutor;
/**
* Set the event listener to send the request to Framework.
* Create a new RcsCapabilityExchangeImplBase instance.
*
* @param executor The executor that remote calls from the framework will be called on.
*/
public void setEventListener(ICapabilityExchangeEventListener listener) {
mListener = listener;
}
/**
* Get the event listener.
*/
public ICapabilityExchangeEventListener getEventListener() {
return mListener;
public RcsCapabilityExchangeImplBase(@NonNull Executor executor) {
if (executor == null) {
throw new IllegalArgumentException("executor must not be null");
}
mBinderExecutor = executor;
}
/**
@@ -284,7 +289,10 @@ public class RcsCapabilityExchangeImplBase {
* @param uris A {@link List} of the {@link Uri}s that the framework is requesting the UCE
* capabilities for.
* @param cb The callback of the subscribe request.
* @hide
*/
// executor used is defined in the constructor.
@SuppressLint("ExecutorRegistration")
public void subscribeForCapabilities(@NonNull List<Uri> uris,
@NonNull SubscribeResponseCallback cb) {
// Stub - to be implemented by service
@@ -300,11 +308,13 @@ public class RcsCapabilityExchangeImplBase {
* The capabilities of this device have been updated and should be published to the network.
* <p>
* If this operation succeeds, network response updates should be sent to the framework using
* {@link #onNetworkResponse(int, String)}.
* {@link PublishResponseCallback#onNetworkResponse(int, String)}.
* @param pidfXml The XML PIDF document containing the capabilities of this device to be sent
* to the carriers presence server.
* @param cb The callback of the publish request
*/
// executor used is defined in the constructor.
@SuppressLint("ExecutorRegistration")
public void publishCapabilities(@NonNull String pidfXml, @NonNull PublishResponseCallback cb) {
// Stub - to be implemented by service
Log.w(LOG_TAG, "publishCapabilities called with no implementation.");
@@ -324,7 +334,10 @@ 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")
public void sendOptionsCapabilityRequest(@NonNull Uri contactUri,
@NonNull List<String> myCapabilities, @NonNull OptionsResponseCallback callback) {
// Stub - to be implemented by service