Merge "[RCS UCE] Update the ImsService APIs and application APIs change."

This commit is contained in:
James Lin
2020-11-03 02:22:29 +00:00
committed by Gerrit Code Review
19 changed files with 1176 additions and 122 deletions

View File

@@ -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) {

View File

@@ -0,0 +1,20 @@
/*
* Copyright (c) 2020 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package android.telephony.ims;
parcelable RcsContactTerminatedReason;

View File

@@ -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;
}
}

View File

@@ -46,6 +46,30 @@ import java.util.concurrent.Executor;
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,11 +144,89 @@ 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.
@@ -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 {
@@ -350,6 +470,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.

View File

@@ -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);
}

View File

@@ -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);

View File

@@ -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);
}
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -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);
}

View File

@@ -25,5 +25,6 @@ import android.telephony.ims.RcsContactUceCapability;
*/
oneway interface IRcsUceControllerCallback {
void onCapabilitiesReceived(in List<RcsContactUceCapability> contactCapabilities);
void onComplete();
void onError(int errorCode);
}

View File

@@ -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);
}

View File

@@ -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) {
}
}
}

View File

@@ -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) {
}
}
}

View File

@@ -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) {
}
}
}

View File

@@ -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

View File

@@ -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
* Retrieve the implementation of UCE for this {@link RcsFeature}, which can use either
* presence or OPTIONS for capability exchange.
*
* 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 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)}
* 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 setCapabilityExchangeEventListener(ICapabilityExchangeEventListener listener) {
mCapExchangeEventListener = listener;
if (mCapExchangeEventListener != null) {
onFeatureReady();
}
}
private void setListener(IRcsFeatureListener listener) {
private RcsCapabilityExchangeImplBase getCapabilityExchangeImplBaseInternal() {
synchronized (mLock) {
mListenerBinder = listener;
if (mListenerBinder != null) {
onFeatureReady();
if (mCapabilityExchangeImpl == null) {
mCapabilityExchangeImpl = createCapabilityExchangeImpl();
mCapabilityExchangeImpl.setEventListener(mCapExchangeEventListener);
}
}
}
private RcsPresenceExchangeImplBase getPresenceExchangeInternal() {
synchronized (mLock) {
if (mPresExchange == null) {
mPresExchange = getPresenceExchangeImpl();
mPresExchange.initialize(this);
}
return mPresExchange;
}
}
private RcsSipOptionsImplBase getOptionsExchangeInternal() {
synchronized (mLock) {
if (mSipOptions == null) {
mSipOptions = getOptionsExchangeImpl();
mSipOptions.initialize(this);
}
return mSipOptions;
return mCapabilityExchangeImpl;
}
}
}

View File

@@ -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);
}
/**

View File

@@ -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 contacts 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 carriers 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.
}
}
}