diff options
| author | 2020-11-03 02:22:29 +0000 | |
|---|---|---|
| committer | 2020-11-03 02:22:29 +0000 | |
| commit | adaf6fd8343ad7be9b065708bf5887e705396ced (patch) | |
| tree | eb3cb216610d248f26622c946b657cfbb893d34b | |
| parent | 0bfaac54ab1ebac38b5646f8f54db707d80721da (diff) | |
| parent | 827060593568f7503d9aab8920f7228c87971905 (diff) | |
Merge "[RCS UCE] Update the ImsService APIs and application APIs change."
19 files changed, 1176 insertions, 122 deletions
diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java index 94407f1dcd3a..8b6dac82b0eb 100644 --- a/telephony/java/android/telephony/ims/ImsRcsManager.java +++ b/telephony/java/android/telephony/ims/ImsRcsManager.java @@ -29,12 +29,10 @@ import android.os.RemoteException; import android.provider.Settings; import android.telephony.AccessNetworkConstants; import android.telephony.CarrierConfigManager; -import android.telephony.SubscriptionManager; import android.telephony.TelephonyFrameworkInitializer; import android.telephony.ims.aidl.IImsCapabilityCallback; import android.telephony.ims.aidl.IImsRcsController; import android.telephony.ims.feature.ImsFeature; -import android.telephony.ims.feature.RcsFeature; import android.telephony.ims.stub.ImsRegistrationImplBase; import android.util.Log; @@ -77,7 +75,7 @@ public class ImsRcsManager { "android.telephony.ims.action.SHOW_CAPABILITY_DISCOVERY_OPT_IN"; /** - * Receives RCS availability status updates from the ImsService. + * Receives RCS Feature availability status updates from the ImsService. * * @see #isAvailable(int) * @see #registerRcsAvailabilityCallback(Executor, AvailabilityCallback) @@ -101,8 +99,7 @@ public class ImsRcsManager { long callingIdentity = Binder.clearCallingIdentity(); try { - mExecutor.execute(() -> mLocalCallback.onAvailabilityChanged( - new RcsFeature.RcsImsCapabilities(config))); + mExecutor.execute(() -> mLocalCallback.onAvailabilityChanged(config)); } finally { restoreCallingIdentity(callingIdentity); } @@ -137,7 +134,7 @@ public class ImsRcsManager { * * @param capabilities The new availability of the capabilities. */ - public void onAvailabilityChanged(@NonNull RcsFeature.RcsImsCapabilities capabilities) { + public void onAvailabilityChanged(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { } /**@hide*/ @@ -394,7 +391,7 @@ public class ImsRcsManager { * @hide */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public boolean isCapable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability, + public boolean isCapable(@RcsUceAdapter.RcsImsCapabilityFlag int capability, @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) throws ImsException { IImsRcsController imsRcsController = getIImsRcsController(); if (imsRcsController == null) { @@ -428,7 +425,7 @@ public class ImsRcsManager { * @hide */ @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public boolean isAvailable(@RcsFeature.RcsImsCapabilities.RcsImsCapabilityFlag int capability) + public boolean isAvailable(@RcsUceAdapter.RcsImsCapabilityFlag int capability) throws ImsException { IImsRcsController imsRcsController = getIImsRcsController(); if (imsRcsController == null) { diff --git a/telephony/java/android/telephony/ims/RcsContactTerminatedReason.aidl b/telephony/java/android/telephony/ims/RcsContactTerminatedReason.aidl new file mode 100644 index 000000000000..cd1ee8400d3e --- /dev/null +++ b/telephony/java/android/telephony/ims/RcsContactTerminatedReason.aidl @@ -0,0 +1,20 @@ +/* + * Copyright (c) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + + +package android.telephony.ims; + +parcelable RcsContactTerminatedReason; diff --git a/telephony/java/android/telephony/ims/RcsContactTerminatedReason.java b/telephony/java/android/telephony/ims/RcsContactTerminatedReason.java new file mode 100644 index 000000000000..ee02564267c0 --- /dev/null +++ b/telephony/java/android/telephony/ims/RcsContactTerminatedReason.java @@ -0,0 +1,75 @@ +/* + * Copyright (C) 2020 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims; + +import android.annotation.NonNull; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; + +/** + * When the resource for the presence subscribe event has been terminated, the method + * SubscribeResponseCallback#onResourceTerminated wil be called with a list of + * RcsContactTerminatedReason. + * @hide + */ +public final class RcsContactTerminatedReason implements Parcelable { + private final Uri mContactUri; + private final String mReason; + + public RcsContactTerminatedReason(Uri contact, String reason) { + mContactUri = contact; + mReason = reason; + } + + private RcsContactTerminatedReason(Parcel in) { + mContactUri = in.readParcelable(Uri.class.getClassLoader()); + mReason = in.readString(); + } + + @Override + public void writeToParcel(@NonNull Parcel out, int flags) { + out.writeParcelable(mContactUri, flags); + out.writeString(mReason); + } + + @Override + public int describeContents() { + return 0; + } + + public static final @NonNull Creator<RcsContactTerminatedReason> CREATOR = + new Creator<RcsContactTerminatedReason>() { + @Override + public RcsContactTerminatedReason createFromParcel(Parcel in) { + return new RcsContactTerminatedReason(in); + } + + @Override + public RcsContactTerminatedReason[] newArray(int size) { + return new RcsContactTerminatedReason[size]; + } + }; + + public Uri getContactUri() { + return mContactUri; + } + + public String getReason() { + return mReason; + } +} diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java index 0c88ade4bb77..0aeaecc2af5e 100644 --- a/telephony/java/android/telephony/ims/RcsUceAdapter.java +++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java @@ -47,6 +47,30 @@ public class RcsUceAdapter { private static final String TAG = "RcsUceAdapter"; /** + * This carrier supports User Capability Exchange as, defined by the framework using + * SIP OPTIONS. If set, the RcsFeature should support capability exchange. If not set, this + * RcsFeature should not publish capabilities or service capability requests. + * @hide + */ + public static final int CAPABILITY_TYPE_OPTIONS_UCE = 1 << 0; + + /** + * This carrier supports User Capability Exchange as, defined by the framework using a + * presence server. If set, the RcsFeature should support capability exchange. If not set, this + * RcsFeature should not publish capabilities or service capability requests. + * @hide + */ + public static final int CAPABILITY_TYPE_PRESENCE_UCE = 1 << 1; + + /**@hide*/ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "CAPABILITY_TYPE_", value = { + CAPABILITY_TYPE_OPTIONS_UCE, + CAPABILITY_TYPE_PRESENCE_UCE + }) + public @interface RcsImsCapabilityFlag {} + + /** * An unknown error has caused the request to fail. * @hide */ @@ -106,11 +130,6 @@ public class RcsUceAdapter { * @hide */ public static final int ERROR_LOST_NETWORK = 12; - /** - * The request has failed because the same request has already been added to the queue. - * @hide - */ - public static final int ERROR_ALREADY_IN_QUEUE = 13; /**@hide*/ @Retention(RetentionPolicy.SOURCE) @@ -125,12 +144,90 @@ public class RcsUceAdapter { ERROR_REQUEST_TOO_LARGE, ERROR_REQUEST_TIMEOUT, ERROR_INSUFFICIENT_MEMORY, - ERROR_LOST_NETWORK, - ERROR_ALREADY_IN_QUEUE + ERROR_LOST_NETWORK }) public @interface ErrorCode {} /** + * A capability update has been requested due to the Entity Tag (ETag) expiring. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED = 0; + /** + * 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; + /** + * 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; + /** + * A capability update has been requested due to moving to eHRPD. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD = 3; + /** + * A capability update has been requested due to moving to HSPA+. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS = 4; + /** + * A capability update has been requested due to moving to 3G. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G = 5; + /** + * A capability update has been requested due to moving to 2G. + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_2G = 6; + /** + * A capability update has been requested due to moving to WLAN + * @hide + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_WLAN = 7; + /** + * 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; + /** + * A capability update has been requested due to moving to 5G NR with VoPS disabled. + * @hide + */ + 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 + */ + public static final int CAPABILITY_UPDATE_TRIGGER_MOVE_TO_NR5G_VOPS_ENABLED = 11; + + /**@hide*/ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "ERROR_", value = { + CAPABILITY_UPDATE_TRIGGER_ETAG_EXPIRED, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_DISABLED, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_LTE_VOPS_ENABLED, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_EHRPD, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_HSPAPLUS, + CAPABILITY_UPDATE_TRIGGER_MOVE_TO_3G, + 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 + }) + public @interface StackPublishTriggerType {} + + /** * The last publish has resulted in a "200 OK" response or the device is using SIP OPTIONS for * UCE. * @hide @@ -205,7 +302,7 @@ public class RcsUceAdapter { public void onPublishStateChanged(int publishState) { if (mLocalCallback == null) return; - long callingIdentity = Binder.clearCallingIdentity(); + final long callingIdentity = Binder.clearCallingIdentity(); try { mExecutor.execute(() -> mLocalCallback.onChanged(publishState)); } finally { @@ -238,38 +335,49 @@ public class RcsUceAdapter { } /** - * Provides a one-time callback for the response to a UCE request. After this callback is called - * by the framework, the reference to this callback will be discarded on the service side. + * A callback for the response to a UCE request. The method + * {@link CapabilitiesCallback#onCapabilitiesReceived} will be called zero or more times as the + * capabilities are received for each requested contact. + * <p> + * This request will take a varying amount of time depending on if the contacts requested are + * cached or if it requires a network query. The timeout time of these requests can vary + * depending on the network, however in poor cases it could take up to a minute for a request + * to timeout. In that time only a subset of capabilities may have been retrieved. + * <p> + * After {@link CapabilitiesCallback#onComplete} or {@link CapabilitiesCallback#onError} has + * been called, the reference to this callback will be discarded on the service side. * @see #requestCapabilities(Executor, List, CapabilitiesCallback) * @hide */ - public static class CapabilitiesCallback { + public interface CapabilitiesCallback { /** - * Notify this application that the pending capability request has returned successfully. + * Notify this application that the pending capability request has returned successfully + * for one or more of the requested contacts. * @param contactCapabilities List of capabilities associated with each contact requested. */ - public void onCapabilitiesReceived( - @NonNull List<RcsContactUceCapability> contactCapabilities) { + void onCapabilitiesReceived(@NonNull List<RcsContactUceCapability> contactCapabilities); - } + /** + * The pending request has completed successfully due to all requested contacts information + * being delivered. + */ + void onComplete(); /** * The pending request has resulted in an error and may need to be retried, depending on the * error code. * @param errorCode The reason for the framework being unable to process the request. */ - public void onError(@ErrorCode int errorCode) { - - } + void onError(@ErrorCode int errorCode); } private final Context mContext; private final int mSubId; /** - * Not to be instantiated directly, use - * {@link ImsRcsManager#getUceAdapter()} to instantiate this manager class. + * Not to be instantiated directly, use {@link ImsRcsManager#getUceAdapter()} to instantiate + * this manager class. * @hide */ RcsUceAdapter(Context context, int subId) { @@ -280,6 +388,9 @@ 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)} and ensuring * {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_OPTIONS_UCE} or @@ -302,7 +413,7 @@ public class RcsUceAdapter { @NonNull List<Uri> contactNumbers, @NonNull CapabilitiesCallback c) throws ImsException { if (c == null) { - throw new IllegalArgumentException("Must include a non-null AvailabilityCallback."); + throw new IllegalArgumentException("Must include a non-null CapabilitiesCallback."); } if (executor == null) { throw new IllegalArgumentException("Must include a non-null Executor."); @@ -321,7 +432,7 @@ public class RcsUceAdapter { IRcsUceControllerCallback internalCallback = new IRcsUceControllerCallback.Stub() { @Override public void onCapabilitiesReceived(List<RcsContactUceCapability> contactCapabilities) { - long callingIdentity = Binder.clearCallingIdentity(); + final long callingIdentity = Binder.clearCallingIdentity(); try { executor.execute(() -> c.onCapabilitiesReceived(contactCapabilities)); @@ -330,8 +441,17 @@ public class RcsUceAdapter { } } @Override + public void onComplete() { + final long callingIdentity = Binder.clearCallingIdentity(); + try { + executor.execute(() -> c.onComplete()); + } finally { + restoreCallingIdentity(callingIdentity); + } + } + @Override public void onError(int errorCode) { - long callingIdentity = Binder.clearCallingIdentity(); + final long callingIdentity = Binder.clearCallingIdentity(); try { executor.execute(() -> c.onError(errorCode)); } finally { @@ -351,6 +471,88 @@ public class RcsUceAdapter { } /** + * Ignore the device cache and perform a capability discovery for one contact, also called + * "availability fetch." + * <p> + * This will always perform a query to the network as long as requests are over the carrier + * availability fetch throttling threshold. If too many network requests are sent too quickly, + * #ERROR_TOO_MANY_REQUESTS will be returned. + * + * <p> + * Be sure to check the availability of this feature using + * {@link ImsRcsManager#isAvailable(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 contactNumber The contact of the capabilities is being requested for. + * @param c A one-time callback for when the request for capabilities completes or there is + * an error processing the request. + * @hide + */ + @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) + public void requestNetworkAvailability(@NonNull @CallbackExecutor Executor executor, + @NonNull Uri contactNumber, @NonNull CapabilitiesCallback c) throws ImsException { + if (executor == null) { + throw new IllegalArgumentException("Must include a non-null Executor."); + } + if (contactNumber == null) { + throw new IllegalArgumentException("Must include non-null contact number."); + } + if (c == null) { + throw new IllegalArgumentException("Must include a non-null CapabilitiesCallback."); + } + + IImsRcsController imsRcsController = getIImsRcsController(); + if (imsRcsController == null) { + Log.e(TAG, "requestNetworkAvailability: IImsRcsController is null"); + throw new ImsException("Cannot 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) { + final long callingIdentity = Binder.clearCallingIdentity(); + try { + executor.execute(() -> c.onError(errorCode)); + } finally { + restoreCallingIdentity(callingIdentity); + } + } + }; + + try { + imsRcsController.requestNetworkAvailability(mSubId, mContext.getOpPackageName(), + mContext.getAttributionTag(), contactNumber, internalCallback); + } catch (RemoteException e) { + Log.e(TAG, "Error calling IImsRcsController#requestNetworkAvailability", e); + throw new ImsException("Remote IMS Service is not available", + ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); + } + } + + /** * Gets the last publish result from the UCE service if the device is using an RCS presence * server. * @return The last publish result from the UCE service. If the device is using SIP OPTIONS, diff --git a/telephony/java/android/telephony/ims/aidl/ICapabilityExchangeEventListener.aidl b/telephony/java/android/telephony/ims/aidl/ICapabilityExchangeEventListener.aidl new file mode 100644 index 000000000000..a4ffbef9fa84 --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/ICapabilityExchangeEventListener.aidl @@ -0,0 +1,75 @@ +/* + * 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.net.Uri; +import android.telephony.ims.aidl.IOptionsRequestCallback; + +import java.util.List; + +/** + * Listener interface for the ImsService to use to notify the framework of UCE events. + * {@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); +} diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl index 6d25a09e079f..8e84e9373f65 100644 --- a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl @@ -47,6 +47,9 @@ interface IImsRcsController { // ImsUceAdapter specific void requestCapabilities(int subId, String callingPackage, String callingFeatureId, in List<Uri> contactNumbers, IRcsUceControllerCallback c); + void requestNetworkAvailability(int subId, String callingPackage, + String callingFeatureId, in Uri contactNumber, + IRcsUceControllerCallback c); int getUcePublishState(int subId); boolean isUceSettingEnabled(int subId, String callingPackage, String callingFeatureId); void setUceSettingEnabled(int subId, boolean isEnabled); diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl index 4b98b79f1095..b47e3c75b558 100644 --- a/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl +++ b/telephony/java/android/telephony/ims/aidl/IImsRcsFeature.aidl @@ -18,8 +18,12 @@ package android.telephony.ims.aidl; import android.net.Uri; import android.telephony.ims.RcsContactUceCapability; +import android.telephony.ims.aidl.ICapabilityExchangeEventListener; import android.telephony.ims.aidl.IImsCapabilityCallback; +import android.telephony.ims.aidl.IOptionsResponseCallback; +import android.telephony.ims.aidl.IPublishResponseCallback; import android.telephony.ims.aidl.IRcsFeatureListener; +import android.telephony.ims.aidl.ISubscribeResponseCallback; import android.telephony.ims.feature.CapabilityChangeRequest; import java.util.List; @@ -40,6 +44,12 @@ interface IImsRcsFeature { IImsCapabilityCallback c); oneway void queryCapabilityConfiguration(int capability, int radioTech, IImsCapabilityCallback c); + // RcsCapabilityExchangeImplBase specific api + oneway void setCapabilityExchangeEventListener(ICapabilityExchangeEventListener listener); + oneway void publishCapabilities(in String pidfXml, IPublishResponseCallback cb); + oneway void subscribeForCapabilities(in List<Uri> uris, ISubscribeResponseCallback cb); + oneway void sendOptionsCapabilityRequest(in Uri contactUri, + in List<String> myCapabilities, IOptionsResponseCallback cb); // RcsPresenceExchangeImplBase specific api oneway void requestCapabilities(in List<Uri> uris, int operationToken); oneway void updateCapabilities(in RcsContactUceCapability capabilities, int operationToken); @@ -50,4 +60,4 @@ interface IImsRcsFeature { in RcsContactUceCapability ownCapabilities, int operationToken); oneway void respondToCapabilityRequestWithError(in Uri contactUri, int code, in String reason, int operationToken); -}
\ No newline at end of file +} diff --git a/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl b/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl new file mode 100644 index 000000000000..d55670dd313b --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl @@ -0,0 +1,41 @@ +/* + * 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.telephony.ims.RcsContactUceCapability; + +/** + * Interface used by the framework to respond to OPTIONS requests. + * {@hide} + */ +oneway interface IOptionsRequestCallback { + /** + * Respond to a remote capability request from the contact specified with the capabilities + * of this device. + * @param ownCapabilities The capabilities of this device. + */ + void respondToCapabilityRequest(in RcsContactUceCapability ownCapabilities); + + /** + * 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. + */ + void respondToCapabilityRequestWithError(int code, String reason); +} diff --git a/telephony/java/android/telephony/ims/aidl/IOptionsResponseCallback.aidl b/telephony/java/android/telephony/ims/aidl/IOptionsResponseCallback.aidl new file mode 100644 index 000000000000..a8c8329fe55e --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/IOptionsResponseCallback.aidl @@ -0,0 +1,29 @@ +/* + * 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 java.util.List; + +/** + * Interface used by the framework to receive the response from the remote user + * through {@link RcsCapabilityExchangeImplBase#sendOptionsCapabilityRequest} + * {@hide} + */ +oneway interface IOptionsResponseCallback { + void onCommandError(int code); + void onNetworkResponse(int code, String reason, in List<String> theirCaps); +} diff --git a/telephony/java/android/telephony/ims/aidl/IPublishResponseCallback.aidl b/telephony/java/android/telephony/ims/aidl/IPublishResponseCallback.aidl new file mode 100644 index 000000000000..481e7f8b37b9 --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/IPublishResponseCallback.aidl @@ -0,0 +1,29 @@ +/* + * 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 java.util.List; + +/** + * Interface used by the framework to receive the response of the publish + * request through {@link RcsCapabilityExchangeImplBase#publishCapabilities} + * {@hide} + */ +oneway interface IPublishResponseCallback { + void onCommandError(int code); + void onNetworkResponse(int code, String reason); +} diff --git a/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl b/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl index 5975930d5cfa..0bd3e5ed354e 100644 --- a/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl +++ b/telephony/java/android/telephony/ims/aidl/IRcsUceControllerCallback.aidl @@ -25,5 +25,6 @@ import android.telephony.ims.RcsContactUceCapability; */ oneway interface IRcsUceControllerCallback { void onCapabilitiesReceived(in List<RcsContactUceCapability> contactCapabilities); + void onComplete(); void onError(int errorCode); } diff --git a/telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl b/telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl new file mode 100644 index 000000000000..4deaba1b7a49 --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl @@ -0,0 +1,36 @@ +/* + * 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.net.Uri; +import android.telephony.ims.RcsContactTerminatedReason; + +import java.util.List; +import java.util.Map; + +/** + * Interface used by the framework to receive the response of the subscribe + * request through {@link RcsCapabilityExchangeImplBase#subscribeForCapabilities} + * {@hide} + */ +oneway interface ISubscribeResponseCallback { + void onCommandError(int code); + void onNetworkResponse(int code, in String reason); + void onNotifyCapabilitiesUpdate(in List<String> pidfXmls); + void onResourceTerminated(in List<RcsContactTerminatedReason> uriTerminatedReason); + void onTerminated(in String reason, in String retryAfter); +} diff --git a/telephony/java/android/telephony/ims/aidl/RcsOptionsResponseAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/RcsOptionsResponseAidlWrapper.java new file mode 100644 index 000000000000..47a96af1cba1 --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/RcsOptionsResponseAidlWrapper.java @@ -0,0 +1,54 @@ +/* + * 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.os.RemoteException; +import android.telephony.ims.ImsException; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.OptionsResponseCallback; + +import java.util.List; + +/** + * Implementation of the callback OptionsResponseCallback by wrapping the internal AIDL from + * telephony. + * @hide + */ +public class RcsOptionsResponseAidlWrapper implements OptionsResponseCallback { + + private final IOptionsResponseCallback mResponseBinder; + + public RcsOptionsResponseAidlWrapper(IOptionsResponseCallback responseBinder) { + mResponseBinder = responseBinder; + } + + @Override + public void onCommandError(int code) { + try { + mResponseBinder.onCommandError(code); + } catch (RemoteException e) { + } + } + + @Override + public void onNetworkResponse(int code, String reason, List<String> theirCaps) + throws ImsException { + try { + mResponseBinder.onNetworkResponse(code, reason, theirCaps); + } catch (RemoteException e) { + } + } +} diff --git a/telephony/java/android/telephony/ims/aidl/RcsPublishResponseAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/RcsPublishResponseAidlWrapper.java new file mode 100644 index 000000000000..22985d0cf85c --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/RcsPublishResponseAidlWrapper.java @@ -0,0 +1,51 @@ +/* + * 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.os.RemoteException; +import android.telephony.ims.ImsException; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.PublishResponseCallback; + +/** + * Implementation of the callback PublishResponseCallback by wrapping the internal AIDL from + * telephony. + * @hide + */ +public class RcsPublishResponseAidlWrapper implements PublishResponseCallback { + + private final IPublishResponseCallback mResponseBinder; + + public RcsPublishResponseAidlWrapper(IPublishResponseCallback responseBinder) { + mResponseBinder = responseBinder; + } + + @Override + public void onCommandError(int code) { + try { + mResponseBinder.onCommandError(code); + } catch (RemoteException e) { + } + } + + @Override + public void onNetworkResponse(int code, String reason) throws ImsException { + try { + mResponseBinder.onNetworkResponse(code, reason); + } catch (RemoteException e) { + } + } +} diff --git a/telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java new file mode 100644 index 000000000000..37588ed98585 --- /dev/null +++ b/telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java @@ -0,0 +1,95 @@ +/* + * 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.net.Uri; +import android.os.RemoteException; +import android.telephony.ims.ImsException; +import android.telephony.ims.RcsContactTerminatedReason; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.SubscribeResponseCallback; +import android.util.Pair; + +import java.util.ArrayList; +import java.util.List; + +/** + * Implementation of the callback OptionsResponseCallback by wrapping the internal AIDL from + * telephony. + * @hide + */ +public class RcsSubscribeResponseAidlWrapper implements SubscribeResponseCallback { + + private final ISubscribeResponseCallback mResponseBinder; + + public RcsSubscribeResponseAidlWrapper(ISubscribeResponseCallback responseBinder) { + mResponseBinder = responseBinder; + } + + @Override + public void onCommandError(int code) { + try { + mResponseBinder.onCommandError(code); + } catch (RemoteException e) { + } + } + + @Override + public void onNetworkResponse(int code, String reason) throws ImsException { + try { + mResponseBinder.onNetworkResponse(code, reason); + } catch (RemoteException e) { + } + } + + @Override + public void onNotifyCapabilitiesUpdate(List<String> pidfXmls) throws ImsException { + try { + mResponseBinder.onNotifyCapabilitiesUpdate(pidfXmls); + } catch (RemoteException e) { + } + } + + @Override + public void onResourceTerminated(List<Pair<Uri, String>> uriTerminatedReason) + throws ImsException { + try { + mResponseBinder.onResourceTerminated(getTerminatedReasonList(uriTerminatedReason)); + } catch (RemoteException e) { + } + } + + private List<RcsContactTerminatedReason> getTerminatedReasonList( + List<Pair<Uri, String>> uriTerminatedReason) { + List<RcsContactTerminatedReason> uriTerminatedReasonList = new ArrayList<>(); + if (uriTerminatedReason != null) { + for (Pair<Uri, String> pair : uriTerminatedReason) { + RcsContactTerminatedReason reason = + new RcsContactTerminatedReason(pair.first, pair.second); + uriTerminatedReasonList.add(reason); + } + } + return uriTerminatedReasonList; + } + + @Override + public void onTerminated(String reason, String retryAfter) throws ImsException { + try { + mResponseBinder.onTerminated(reason, retryAfter); + } catch (RemoteException e) { + } + } +} diff --git a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java index 87a5094a95f3..87a6873d00b2 100644 --- a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java +++ b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java @@ -28,8 +28,8 @@ import java.util.List; import java.util.Set; /** - * Request to send to IMS provider, which will try to enable/disable capabilities that are added to - * the request. + * Used by the framework to enable and disable MMTEL and RCS capabilities. See + * MmTelFeature#changeEnabledCapabilities and RcsFeature#changeEnabledCapabilities. * {@hide} */ @SystemApi diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java index b8ae146784d4..5de2ddc578a1 100644 --- a/telephony/java/android/telephony/ims/feature/RcsFeature.java +++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java @@ -23,12 +23,22 @@ import android.annotation.SystemApi; import android.net.Uri; import android.os.RemoteException; import android.telephony.ims.RcsContactUceCapability; +import android.telephony.ims.RcsUceAdapter; +import android.telephony.ims.aidl.ICapabilityExchangeEventListener; import android.telephony.ims.aidl.IImsCapabilityCallback; import android.telephony.ims.aidl.IImsRcsFeature; +import android.telephony.ims.aidl.IOptionsResponseCallback; +import android.telephony.ims.aidl.IPublishResponseCallback; import android.telephony.ims.aidl.IRcsFeatureListener; +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.ImsRegistrationImplBase; -import android.telephony.ims.stub.RcsPresenceExchangeImplBase; -import android.telephony.ims.stub.RcsSipOptionsImplBase; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.OptionsResponseCallback; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.PublishResponseCallback; +import android.telephony.ims.stub.RcsCapabilityExchangeImplBase.SubscribeResponseCallback; import android.util.Log; import com.android.internal.telephony.util.TelephonyUtils; @@ -64,9 +74,14 @@ public class RcsFeature extends ImsFeature { mExecutor = executor; } + /** + * @deprecated This method is deprecated. Please call the method + * setCapabilityExchangeEventListener instead. + */ @Override + @Deprecated public void setListener(IRcsFeatureListener listener) { - mReference.setListener(listener); + Log.w(LOG_TAG, "The method setListener is deprecated"); } @Override @@ -106,44 +121,66 @@ public class RcsFeature extends ImsFeature { return executeMethodAsyncForResult(mReference::getFeatureState, "getFeatureState"); } + // RcsCapabilityExchangeImplBase specific APIs + @Override + public void setCapabilityExchangeEventListener( + @NonNull ICapabilityExchangeEventListener listener) throws RemoteException { + executeMethodAsync(() -> mReference.setCapabilityExchangeEventListener(listener), + "setCapabilityExchangeEventListener"); + } + + @Override + public void publishCapabilities(@NonNull String pidfXml, + @NonNull IPublishResponseCallback callback) throws RemoteException { + PublishResponseCallback callbackWrapper = new RcsPublishResponseAidlWrapper(callback); + executeMethodAsync(() -> mReference.getCapabilityExchangeImplBaseInternal() + .publishCapabilities(pidfXml, callbackWrapper), "publishCapabilities"); + } + + @Override + public void subscribeForCapabilities(@NonNull List<Uri> uris, + @NonNull ISubscribeResponseCallback callback) throws RemoteException { + SubscribeResponseCallback wrapper = new RcsSubscribeResponseAidlWrapper(callback); + executeMethodAsync(() -> mReference.getCapabilityExchangeImplBaseInternal() + .subscribeForCapabilities(uris, wrapper), "subscribeForCapabilities"); + } + + @Override + public void sendOptionsCapabilityRequest(@NonNull Uri contactUri, + @NonNull List<String> myCapabilities, @NonNull IOptionsResponseCallback callback) + throws RemoteException { + OptionsResponseCallback callbackWrapper = new RcsOptionsResponseAidlWrapper(callback); + executeMethodAsync(() -> mReference.getCapabilityExchangeImplBaseInternal() + .sendOptionsCapabilityRequest(contactUri, myCapabilities, callbackWrapper), + "sendOptionsCapabilityRequest"); + } + // RcsPresenceExchangeImplBase specific APIS @Override public void requestCapabilities(List<Uri> uris, int operationToken) throws RemoteException { - executeMethodAsync(() -> mReference.getPresenceExchangeInternal() - .requestCapabilities(uris, operationToken), "requestCapabilities"); + throw new RemoteException("Unsupported operation: requestCapabilities"); } @Override public void updateCapabilities(RcsContactUceCapability capabilities, int operationToken) throws RemoteException { - executeMethodAsync(() -> mReference.getPresenceExchangeInternal() - .updateCapabilities(capabilities, operationToken), - "updateCapabilities"); - + throw new RemoteException("Unsupported operation: updateCapabilities"); } // RcsSipOptionsImplBase specific APIS @Override public void sendCapabilityRequest(Uri contactUri, RcsContactUceCapability capabilities, int operationToken) throws RemoteException { - executeMethodAsync(() -> mReference.getOptionsExchangeInternal() - .sendCapabilityRequest(contactUri, capabilities, operationToken), - "sendCapabilityRequest"); - + throw new RemoteException("Unsupported operation: sendCapabilityRequest"); } @Override public void respondToCapabilityRequest(String contactUri, RcsContactUceCapability ownCapabilities, int operationToken) throws RemoteException { - executeMethodAsync(() -> mReference.getOptionsExchangeInternal() - .respondToCapabilityRequest(contactUri, ownCapabilities, - operationToken), "respondToCapabilityRequest"); - + throw new RemoteException("Unsupported operation: respondToCapabilityRequest"); } @Override public void respondToCapabilityRequestWithError(Uri contactUri, int code, String reason, int operationToken) throws RemoteException { - executeMethodAsync(() -> mReference.getOptionsExchangeInternal() - .respondToCapabilityRequestWithError(contactUri, code, reason, - operationToken), "respondToCapabilityRequestWithError"); + throw new RemoteException("Unsupported operation: respondToCapabilityRequestWithError"); } // Call the methods with a clean calling identity on the executor and wait indefinitely for @@ -182,8 +219,8 @@ public class RcsFeature extends ImsFeature { * Contains the capabilities defined and supported by a {@link RcsFeature} in the * form of a bitmask. The capabilities that are used in the RcsFeature are * defined as: - * {@link RcsImsCapabilityFlag#CAPABILITY_TYPE_OPTIONS_UCE} - * {@link RcsImsCapabilityFlag#CAPABILITY_TYPE_PRESENCE_UCE} + * {@link RcsUceAdatper.RcsImsCapabilityFlag#CAPABILITY_TYPE_OPTIONS_UCE} + * {@link RceUceAdapter.RcsImsCapabilityFlag#CAPABILITY_TYPE_PRESENCE_UCE} * * The enabled capabilities of this RcsFeature will be set by the framework * using {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)}. @@ -223,7 +260,7 @@ public class RcsFeature extends ImsFeature { */ public static final int CAPABILITY_TYPE_PRESENCE_UCE = 1 << 1; - public RcsImsCapabilities(@RcsImsCapabilityFlag int capabilities) { + public RcsImsCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { super(capabilities); } @@ -232,25 +269,24 @@ public class RcsFeature extends ImsFeature { } @Override - public void addCapabilities(@RcsImsCapabilityFlag int capabilities) { + public void addCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { super.addCapabilities(capabilities); } @Override - public void removeCapabilities(@RcsImsCapabilityFlag int capabilities) { + public void removeCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { super.removeCapabilities(capabilities); } @Override - public boolean isCapable(@RcsImsCapabilityFlag int capabilities) { + public boolean isCapable(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) { return super.isCapable(capabilities); } } private final RcsFeatureBinder mImsRcsBinder; - private IRcsFeatureListener mListenerBinder; - private RcsPresenceExchangeImplBase mPresExchange; - private RcsSipOptionsImplBase mSipOptions; + private RcsCapabilityExchangeImplBase mCapabilityExchangeImpl; + private ICapabilityExchangeEventListener mCapExchangeEventListener; /** * Create a new RcsFeature. @@ -314,7 +350,7 @@ public class RcsFeature extends ImsFeature { * @hide */ public boolean queryCapabilityConfiguration( - @RcsImsCapabilities.RcsImsCapabilityFlag int capability, + @RcsUceAdapter.RcsImsCapabilityFlag int capability, @ImsRegistrationImplBase.ImsRegistrationTech int radioTech) { // Base Implementation - Override to provide functionality return false; @@ -342,37 +378,22 @@ public class RcsFeature extends ImsFeature { } /** - * Retrieve the implementation of SIP OPTIONS for this {@link RcsFeature}. - * <p> - * Will only be requested by the framework if capability exchange via SIP OPTIONS is - * configured as capable during a - * {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)} - * operation and the RcsFeature sets the status of the capability to true using - * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. + * Retrieve the implementation of UCE for this {@link RcsFeature}, which can use either + * presence or OPTIONS for capability exchange. * - * @return An instance of {@link RcsSipOptionsImplBase} that implements SIP options exchange if - * it is supported by the device. - * @hide - */ - public @NonNull RcsSipOptionsImplBase getOptionsExchangeImpl() { - // Base Implementation, override to implement functionality - return new RcsSipOptionsImplBase(); - } - - /** - * Retrieve the implementation of UCE presence for this {@link RcsFeature}. - * Will only be requested by the framework if presence exchang is configured as capable during - * a {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)} + * Will only be requested by the framework if capability exchange is configured + * as capable during a + * {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)} * operation and the RcsFeature sets the status of the capability to true using * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. * - * @return An instance of {@link RcsPresenceExchangeImplBase} that implements presence + * @return An instance of {@link RcsCapabilityExchangeImplBase} that implements presence * exchange if it is supported by the device. * @hide */ - public @NonNull RcsPresenceExchangeImplBase getPresenceExchangeImpl() { - // Base Implementation, override to implement functionality. - return new RcsPresenceExchangeImplBase(); + public @NonNull RcsCapabilityExchangeImplBase createCapabilityExchangeImpl() { + // Base Implementation, override to implement functionality + return new RcsCapabilityExchangeImplBase(); } /**{@inheritDoc}*/ @@ -395,39 +416,20 @@ public class RcsFeature extends ImsFeature { return mImsRcsBinder; } - /**@hide*/ - public IRcsFeatureListener getListener() { - synchronized (mLock) { - return mListenerBinder; - } - } - - private void setListener(IRcsFeatureListener listener) { - synchronized (mLock) { - mListenerBinder = listener; - if (mListenerBinder != null) { - onFeatureReady(); - } - } - } - - private RcsPresenceExchangeImplBase getPresenceExchangeInternal() { - synchronized (mLock) { - if (mPresExchange == null) { - mPresExchange = getPresenceExchangeImpl(); - mPresExchange.initialize(this); - } - return mPresExchange; + private void setCapabilityExchangeEventListener(ICapabilityExchangeEventListener listener) { + mCapExchangeEventListener = listener; + if (mCapExchangeEventListener != null) { + onFeatureReady(); } } - private RcsSipOptionsImplBase getOptionsExchangeInternal() { + private RcsCapabilityExchangeImplBase getCapabilityExchangeImplBaseInternal() { synchronized (mLock) { - if (mSipOptions == null) { - mSipOptions = getOptionsExchangeImpl(); - mSipOptions.initialize(this); + if (mCapabilityExchangeImpl == null) { + mCapabilityExchangeImpl = createCapabilityExchangeImpl(); + mCapabilityExchangeImpl.setEventListener(mCapExchangeEventListener); } - return mSipOptions; + return mCapabilityExchangeImpl; } } } diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java index fda295a27111..0b13efb7b4b4 100644 --- a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java +++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchange.java @@ -87,12 +87,8 @@ public class RcsCapabilityExchange { /** @hide */ protected final IRcsFeatureListener getListener() throws ImsException { - IRcsFeatureListener listener = mFeature.getListener(); - if (listener == null) { - throw new ImsException("Connection to Framework has not been established, wait for " - + "onFeatureReady().", ImsException.CODE_ERROR_SERVICE_UNAVAILABLE); - } - return mFeature.getListener(); + throw new ImsException("This method is deprecated.", + ImsException.CODE_ERROR_UNSUPPORTED_OPERATION); } /** diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java new file mode 100644 index 000000000000..b5704bfb3569 --- /dev/null +++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java @@ -0,0 +1,338 @@ +/* + * 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.IntDef; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.net.Uri; +import android.telephony.ims.ImsException; +import android.telephony.ims.aidl.ICapabilityExchangeEventListener; +import android.util.Log; +import android.util.Pair; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.util.List; + +/** + * Base class for different types of Capability exchange. + * @hide + */ +public class RcsCapabilityExchangeImplBase { + + private static final String LOG_TAG = "RcsCapExchangeImplBase"; + + /** + * Service is unknown. + */ + public static final int COMMAND_CODE_SERVICE_UNKNOWN = 0; + + /** + * The command failed with an unknown error. + */ + public static final int COMMAND_CODE_GENERIC_FAILURE = 1; + + /** + * Invalid parameter(s). + */ + public static final int COMMAND_CODE_INVALID_PARAM = 2; + + /** + * Fetch error. + */ + public static final int COMMAND_CODE_FETCH_ERROR = 3; + + /** + * Request timed out. + */ + public static final int COMMAND_CODE_REQUEST_TIMEOUT = 4; + + /** + * Failure due to insufficient memory available. + */ + public static final int COMMAND_CODE_INSUFFICIENT_MEMORY = 5; + + /** + * 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; + + /** + * Contact or resource is not found. + */ + public static final int COMMAND_CODE_NOT_FOUND = 8; + + /** + * Service is not available. + */ + public static final int COMMAND_CODE_SERVICE_UNAVAILABLE = 9; + + /** + * Command resulted in no change in state, ignoring. + */ + public static final int COMMAND_CODE_NO_CHANGE = 10; + + /**@hide*/ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = "COMMAND_CODE_", value = { + COMMAND_CODE_SERVICE_UNKNOWN, + COMMAND_CODE_GENERIC_FAILURE, + COMMAND_CODE_INVALID_PARAM, + COMMAND_CODE_FETCH_ERROR, + COMMAND_CODE_REQUEST_TIMEOUT, + COMMAND_CODE_INSUFFICIENT_MEMORY, + COMMAND_CODE_LOST_NETWORK_CONNECTION, + COMMAND_CODE_NOT_SUPPORTED, + COMMAND_CODE_NOT_FOUND, + COMMAND_CODE_SERVICE_UNAVAILABLE, + COMMAND_CODE_NO_CHANGE + }) + public @interface CommandCode {} + + /** + * Interface used by the framework to receive the response of the publish request. + */ + public interface PublishResponseCallback { + /** + * Notify the framework that the command associated with this callback has failed. + * + * @param code The reason why the associated command has failed. + * @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 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. + * @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 onNetworkResponse(@IntRange(from = 100, to = 699) int code, + @NonNull String reason) throws ImsException; + } + + /** + * Interface used by the framework to respond to OPTIONS requests. + */ + public interface OptionsResponseCallback { + /** + * Notify the framework that the command associated with this callback has failed. + * + * @param code The reason why the associated command has failed. + * @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 onCommandError(@CommandCode int code) throws ImsException; + + /** + * Send the response of a SIP OPTIONS capability exchange to the framework. + * @param code The SIP response code that was sent by the network in response + * to the request sent by {@link #sendOptionsCapabilityRequest}. + * @param reason The optional SIP response reason sent by the network. + * 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 + * 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 onNetworkResponse(int code, @NonNull String reason, + @Nullable List<String> theirCaps) throws ImsException; + } + + /** + * Interface used by the framework to receive the response of the subscribe request. + */ + public interface SubscribeResponseCallback { + /** + * Notify the framework that the command associated with this callback has failed. + * + * @param code The reason why the associated command has failed. + * @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 onCommandError(@CommandCode int code) throws ImsException; + + /** + * Notify the framework of the response to the SUBSCRIBE request from + * {@link #subscribeForCapabilities(List<Uri>, SubscribeResponseCallback)}. + * + * @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. + * @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 onNetworkResponse(@IntRange(from = 100, to = 699) int code, + @NonNull String reason) throws ImsException; + + /** + * 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 + * 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. + */ + void onNotifyCapabilitiesUpdate(@NonNull List<String> pidfXmls) throws ImsException; + + /** + * A resource in the resource list for the presence subscribe event has been terminated. + * <p> + * This allows the framework to know that there will not be any capability information for + * a specific contact URI that they subscribed for. + */ + void onResourceTerminated( + @NonNull List<Pair<Uri, String>> uriTerminatedReason) throws ImsException; + + /** + * The subscription associated with a previous #requestCapabilities operation + * has been terminated. This will mostly be due to the subscription expiring, + * but may also happen due to an error. + * <p> + * This allows the framework to know that there will no longer be any + * capability updates for the requested operationToken. + */ + void onTerminated(String reason, String retryAfter) throws ImsException; + } + + + private ICapabilityExchangeEventListener mListener; + + /** + * Set the event listener to send the request to Framework. + */ + public void setEventListener(ICapabilityExchangeEventListener listener) { + mListener = listener; + } + + /** + * Get the event listener. + */ + public ICapabilityExchangeEventListener getEventListener() { + return mListener; + } + + /** + * The user capabilities of one or multiple contacts have been requested by the framework. + * <p> + * The response from the network to the SUBSCRIBE request must be sent back to the framework + * using {@link #onSubscribeNetworkResponse(int, String, int)}. As NOTIFY requests come in from + * the network, the requested contact’s capabilities should be sent back to the framework using + * {@link #onSubscribeNotifyRequest} and {@link onSubscribeResourceTerminated} + * should be called with the presence information for the contacts specified. + * <p> + * Once the subscription is terminated, {@link #onSubscriptionTerminated} must be called for + * the framework to finish listening for NOTIFY responses. + * @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. + */ + public void subscribeForCapabilities(@NonNull List<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. + * <p> + * If this operation succeeds, network response updates should be sent to the framework using + * {@link #onNetworkResponse(int, String)}. + * @param pidfXml The XML PIDF document containing the capabilities of this device to be sent + * to the carrier’s presence server. + * @param cb The callback of the publish request + */ + public void publishCapabilities(@NonNull String pidfXml, @NonNull PublishResponseCallback cb) { + // Stub - to be implemented by service + Log.w(LOG_TAG, "publishCapabilities called with no implementation."); + try { + cb.onCommandError(COMMAND_CODE_NOT_SUPPORTED); + } catch (ImsException e) { + // Do not do anything, this is a stub implementation. + } + } + + /** + * Push one's own capabilities to a remote user via the SIP OPTIONS presence exchange mechanism + * in order to receive the capabilities of the remote user in response. + * <p> + * The implementer must call {@link #onNetworkResponse} to send the response of this + * query back to the framework. + * @param contactUri The URI of the remote user that we wish to get the capabilities of. + * @param myCapabilities The capabilities of this device to send to the remote user. + * @param callback The callback of this request which is sent from the remote user. + */ + public void sendOptionsCapabilityRequest(@NonNull Uri contactUri, + @NonNull List<String> myCapabilities, @NonNull OptionsResponseCallback callback) { + // Stub - to be implemented by service + Log.w(LOG_TAG, "sendOptionsCapabilityRequest called with no implementation."); + try { + callback.onCommandError(COMMAND_CODE_NOT_SUPPORTED); + } catch (ImsException e) { + // Do not do anything, this is a stub implementation. + } + } +} |