summaryrefslogtreecommitdiff
path: root/telephony/java/android
diff options
context:
space:
mode:
Diffstat (limited to 'telephony/java/android')
-rw-r--r--telephony/java/android/telephony/CarrierBandwidth.java28
-rw-r--r--telephony/java/android/telephony/CarrierConfigManager.java25
-rw-r--r--telephony/java/android/telephony/DataFailCause.java5
-rw-r--r--telephony/java/android/telephony/NetworkRegistrationInfo.java1
-rw-r--r--telephony/java/android/telephony/SignalThresholdInfo.java24
-rw-r--r--telephony/java/android/telephony/SubscriptionManager.java72
-rw-r--r--telephony/java/android/telephony/TelephonyManager.java19
-rw-r--r--telephony/java/android/telephony/data/DataCallResponse.java47
-rw-r--r--telephony/java/android/telephony/data/DataService.java19
-rw-r--r--telephony/java/android/telephony/data/IDataService.aidl3
-rw-r--r--telephony/java/android/telephony/data/IQualifiedNetworksService.aidl4
-rw-r--r--telephony/java/android/telephony/data/QualifiedNetworksService.java12
-rw-r--r--telephony/java/android/telephony/data/SliceInfo.aidl (renamed from telephony/java/android/telephony/data/ApnThrottleStatus.aidl)2
-rw-r--r--telephony/java/android/telephony/data/SliceInfo.java342
-rw-r--r--telephony/java/android/telephony/data/ThrottleStatus.aidl20
-rw-r--r--telephony/java/android/telephony/data/ThrottleStatus.java (renamed from telephony/java/android/telephony/data/ApnThrottleStatus.java)62
-rw-r--r--telephony/java/android/telephony/euicc/DownloadableSubscription.java52
-rw-r--r--telephony/java/android/telephony/ims/DelegateStateCallback.java5
-rw-r--r--telephony/java/android/telephony/ims/ImsRcsManager.java275
-rw-r--r--telephony/java/android/telephony/ims/ImsRegistrationAttributes.aidl19
-rw-r--r--telephony/java/android/telephony/ims/ImsRegistrationAttributes.java219
-rw-r--r--telephony/java/android/telephony/ims/ImsUtListener.java7
-rw-r--r--telephony/java/android/telephony/ims/ProvisioningManager.java21
-rw-r--r--telephony/java/android/telephony/ims/RcsContactPresenceTuple.java144
-rw-r--r--telephony/java/android/telephony/ims/RcsContactUceCapability.java48
-rw-r--r--telephony/java/android/telephony/ims/RcsUceAdapter.java49
-rw-r--r--telephony/java/android/telephony/ims/RegistrationManager.java68
-rw-r--r--telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java18
-rw-r--r--telephony/java/android/telephony/ims/SipDelegateManager.java5
-rw-r--r--telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java19
-rw-r--r--telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl4
-rw-r--r--telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl5
-rw-r--r--telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl3
-rw-r--r--telephony/java/android/telephony/ims/aidl/IPublishResponseCallback.aidl1
-rw-r--r--telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl1
-rw-r--r--telephony/java/android/telephony/ims/aidl/RcsPublishResponseAidlWrapper.java15
-rw-r--r--telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java18
-rw-r--r--telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java30
-rw-r--r--telephony/java/android/telephony/ims/feature/RcsFeature.java33
-rw-r--r--telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java61
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java42
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java35
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java82
-rw-r--r--telephony/java/android/telephony/ims/stub/ImsUtImplBase.java34
-rw-r--r--telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java167
45 files changed, 1773 insertions, 392 deletions
diff --git a/telephony/java/android/telephony/CarrierBandwidth.java b/telephony/java/android/telephony/CarrierBandwidth.java
index 17747a3919ee..b153fefce6e3 100644
--- a/telephony/java/android/telephony/CarrierBandwidth.java
+++ b/telephony/java/android/telephony/CarrierBandwidth.java
@@ -18,6 +18,7 @@ package android.telephony;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.RequiresFeature;
import android.annotation.SystemApi;
import android.os.Parcel;
import android.os.Parcelable;
@@ -102,7 +103,7 @@ public final class CarrierBandwidth implements Parcelable {
/**
* Retrieves the upstream bandwidth for the primary network in Kbps. This always only refers to
* the estimated first hop transport bandwidth.
- * This will be INVALID if the network is not connected
+ * This will be {@link #INVALID} if the network is not connected
*
* @return The estimated first hop upstream (device to network) bandwidth.
*/
@@ -113,7 +114,7 @@ public final class CarrierBandwidth implements Parcelable {
/**
* Retrieves the downstream bandwidth for the primary network in Kbps. This always only refers
* to the estimated first hop transport bandwidth.
- * This will be INVALID if the network is not connected
+ * This will be {@link #INVALID} if the network is not connected
*
* @return The estimated first hop downstream (network to device) bandwidth.
*/
@@ -124,10 +125,19 @@ public final class CarrierBandwidth implements Parcelable {
/**
* Retrieves the upstream bandwidth for the secondary network in Kbps. This always only refers
* to the estimated first hop transport bandwidth.
- * This will be INVALID if the network is not connected
+ * <p/>
+ * This will be {@link #INVALID} if either are the case:
+ * <ol>
+ * <li>The network is not connected</li>
+ * <li>The device does not support
+ * {@link android.telephony.TelephonyManager#CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE}.</li>
+ * </ol>
*
* @return The estimated first hop upstream (device to network) bandwidth.
*/
+ @RequiresFeature(
+ enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported",
+ value = TelephonyManager.CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE)
public int getSecondaryDownlinkCapacityKbps() {
return mSecondaryDownlinkCapacityKbps;
}
@@ -135,10 +145,18 @@ public final class CarrierBandwidth implements Parcelable {
/**
* Retrieves the downstream bandwidth for the secondary network in Kbps. This always only
* refers to the estimated first hop transport bandwidth.
- * This will be INVALID if the network is not connected
- *
+ * <p/>
+ * This will be {@link #INVALID} if either are the case:
+ * <ol>
+ * <li>The network is not connected</li>
+ * <li>The device does not support
+ * {@link android.telephony.TelephonyManager#CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE}.</li>
+ * </ol>
* @return The estimated first hop downstream (network to device) bandwidth.
*/
+ @RequiresFeature(
+ enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported",
+ value = TelephonyManager.CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE)
public int getSecondaryUplinkCapacityKbps() {
return mSecondaryUplinkCapacityKbps;
}
diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java
index f203402032d8..3b46371177d7 100644
--- a/telephony/java/android/telephony/CarrierConfigManager.java
+++ b/telephony/java/android/telephony/CarrierConfigManager.java
@@ -3937,6 +3937,20 @@ public class CarrierConfigManager {
public static final String KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL =
KEY_PREFIX + "enable_presence_group_subscribe_bool";
+ /**
+ * An integer key associated with the period of time in seconds the non-rcs capability
+ * information of each contact is cached on the device.
+ * <p>
+ * The rcs capability cache expiration sec is managed by
+ * {@code android.telephony.ims.ProvisioningManager} but non-rcs capability is managed by
+ * {@link CarrierConfigManager} since non-rcs capability will be provided via ACS or carrier
+ * config.
+ * <p>
+ * The default value is 2592000 secs (30 days), see RCC.07 Annex A.1.9.
+ */
+ public static final String KEY_NON_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC_INT =
+ KEY_PREFIX + "non_rcs_capabilities_cache_expiration_sec_int";
+
private Ims() {}
private static PersistableBundle getDefaults() {
@@ -3947,6 +3961,7 @@ public class CarrierConfigManager {
defaults.putBoolean(KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL, false);
defaults.putBoolean(KEY_RCS_BULK_CAPABILITY_EXCHANGE_BOOL, false);
defaults.putBoolean(KEY_ENABLE_PRESENCE_GROUP_SUBSCRIBE_BOOL, true);
+ defaults.putInt(KEY_NON_RCS_CAPABILITIES_CACHE_EXPIRATION_SEC_INT, 30 * 24 * 60 * 60);
return defaults;
}
}
@@ -4117,7 +4132,7 @@ public class CarrierConfigManager {
* Indicates whether RTT is supported while roaming.
*/
public static final String KEY_RTT_SUPPORTED_WHILE_ROAMING_BOOL =
- "rtt_supported_while_roaming";
+ "rtt_supported_while_roaming_bool";
/**
* Indicates if auto-configuration server is used for the RCS config
@@ -4125,6 +4140,13 @@ public class CarrierConfigManager {
*/
public static final String KEY_USE_ACS_FOR_RCS_BOOL = "use_acs_for_rcs_bool";
+ /**
+ * Indicates temporarily unmetered mobile data is supported by the carrier.
+ * @hide
+ */
+ public static final String KEY_NETWORK_TEMP_NOT_METERED_SUPPORTED_BOOL =
+ "network_temp_not_metered_supported_bool";
+
/** The default value for every variable. */
private final static PersistableBundle sDefaults;
@@ -4674,6 +4696,7 @@ public class CarrierConfigManager {
sDefaults.putString(KEY_CALL_COMPOSER_PICTURE_SERVER_URL_STRING, "");
sDefaults.putBoolean(KEY_USE_LOWER_MTU_VALUE_IF_BOTH_RECEIVED, false);
sDefaults.putBoolean(KEY_USE_ACS_FOR_RCS_BOOL, false);
+ sDefaults.putBoolean(KEY_NETWORK_TEMP_NOT_METERED_SUPPORTED_BOOL, false);
sDefaults.putInt(KEY_DEFAULT_RTT_MODE_INT, 0);
}
diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java
index d502da9fb9ec..99a77ae5d133 100644
--- a/telephony/java/android/telephony/DataFailCause.java
+++ b/telephony/java/android/telephony/DataFailCause.java
@@ -915,6 +915,8 @@ public final class DataFailCause {
public static final int IPV6_PREFIX_UNAVAILABLE = 0x8CA;
/** System preference change back to SRAT during handoff */
public static final int HANDOFF_PREFERENCE_CHANGED = 0x8CB;
+ /** Data call fail due to the slice not being allowed for the data call. */
+ public static final int SLICE_REJECTED = 0x8CC;
//IKE error notifications message as specified in 3GPP TS 24.302 (Section 8.1.2.2).
@@ -985,7 +987,7 @@ public final class DataFailCause {
* the authentication failed.
*/
public static final int IWLAN_IKEV2_AUTH_FAILURE = 0x4001;
- /** IKE message timeout, tunnel setup failed due to no response from EPDG */
+ /** IKE message timeout, tunnel setup failed due to no response from EPDG */
public static final int IWLAN_IKEV2_MSG_TIMEOUT = 0x4002;
/** IKE Certification validation failure */
public static final int IWLAN_IKEV2_CERT_INVALID = 0x4003;
@@ -1419,6 +1421,7 @@ public final class DataFailCause {
sFailCauseMap.put(VSNCP_RECONNECT_NOT_ALLOWED, "VSNCP_RECONNECT_NOT_ALLOWED");
sFailCauseMap.put(IPV6_PREFIX_UNAVAILABLE, "IPV6_PREFIX_UNAVAILABLE");
sFailCauseMap.put(HANDOFF_PREFERENCE_CHANGED, "HANDOFF_PREFERENCE_CHANGED");
+ sFailCauseMap.put(SLICE_REJECTED, "SLICE_REJECTED");
sFailCauseMap.put(IWLAN_PDN_CONNECTION_REJECTION, "IWLAN_PDN_CONNECTION_REJECTION");
sFailCauseMap.put(IWLAN_MAX_CONNECTION_REACHED, "IWLAN_MAX_CONNECTION_REACHED");
sFailCauseMap.put(IWLAN_SEMANTIC_ERROR_IN_THE_TFT_OPERATION,
diff --git a/telephony/java/android/telephony/NetworkRegistrationInfo.java b/telephony/java/android/telephony/NetworkRegistrationInfo.java
index 8507d8512a5c..706e3cb93a0f 100644
--- a/telephony/java/android/telephony/NetworkRegistrationInfo.java
+++ b/telephony/java/android/telephony/NetworkRegistrationInfo.java
@@ -344,6 +344,7 @@ public final class NetworkRegistrationInfo implements Parcelable {
// TODO: Instead of doing this, we should create a formal way for cloning cell identity.
// Cell identity is not an immutable object so we have to deep copy it.
mCellIdentity = CellIdentity.CREATOR.createFromParcel(p);
+ p.recycle();
}
if (nri.mVoiceSpecificInfo != null) {
diff --git a/telephony/java/android/telephony/SignalThresholdInfo.java b/telephony/java/android/telephony/SignalThresholdInfo.java
index 0059ad6c2426..ae7d20929d58 100644
--- a/telephony/java/android/telephony/SignalThresholdInfo.java
+++ b/telephony/java/android/telephony/SignalThresholdInfo.java
@@ -402,29 +402,27 @@ public final class SignalThresholdInfo implements Parcelable {
* @see #getThresholds() for more details on signal strength thresholds
*/
public @NonNull Builder setThresholds(@NonNull int[] thresholds) {
- Objects.requireNonNull(thresholds, "thresholds must not be null");
- if (thresholds.length < MINIMUM_NUMBER_OF_THRESHOLDS_ALLOWED
- || thresholds.length > MAXIMUM_NUMBER_OF_THRESHOLDS_ALLOWED) {
- throw new IllegalArgumentException(
- "thresholds length must between " + MINIMUM_NUMBER_OF_THRESHOLDS_ALLOWED
- + " and " + MAXIMUM_NUMBER_OF_THRESHOLDS_ALLOWED);
- }
- mThresholds = thresholds.clone();
- Arrays.sort(mThresholds);
- return this;
+ return setThresholds(thresholds, false /*isSystem*/);
}
/**
- * Set the signal strength thresholds for the corresponding signal measurement type without
- * the length limitation.
+ * Set the signal strength thresholds for the corresponding signal measurement type.
*
* @param thresholds array of integer as the signal threshold values
+ * @param isSystem true is the caller is system which does not have restrictions on
+ * the length of thresholds array.
* @return the builder to facilitate the chaining
*
* @hide
*/
- public @NonNull Builder setThresholdsUnlimited(@NonNull int[] thresholds) {
+ public @NonNull Builder setThresholds(@NonNull int[] thresholds, boolean isSystem) {
Objects.requireNonNull(thresholds, "thresholds must not be null");
+ if (!isSystem && (thresholds.length < MINIMUM_NUMBER_OF_THRESHOLDS_ALLOWED
+ || thresholds.length > MAXIMUM_NUMBER_OF_THRESHOLDS_ALLOWED)) {
+ throw new IllegalArgumentException(
+ "thresholds length must between " + MINIMUM_NUMBER_OF_THRESHOLDS_ALLOWED
+ + " and " + MAXIMUM_NUMBER_OF_THRESHOLDS_ALLOWED);
+ }
mThresholds = thresholds.clone();
Arrays.sort(mThresholds);
return this;
diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java
index 904232b54b8f..4e481b3ad837 100644
--- a/telephony/java/android/telephony/SubscriptionManager.java
+++ b/telephony/java/android/telephony/SubscriptionManager.java
@@ -2589,14 +2589,45 @@ public class SubscriptionManager {
* requested state until explicitly cleared, or the next reboot,
* whichever happens first.
* @throws SecurityException if the caller doesn't meet the requirements
- * outlined above.
+ * outlined above.
*/
public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered,
@DurationMillisLong long timeoutMillis) {
+ setSubscriptionOverrideUnmetered(subId, overrideUnmetered,
+ TelephonyManager.getAllNetworkTypes(), timeoutMillis);
+ }
+ /**
+ * Temporarily override the billing relationship plan between a carrier and
+ * a specific subscriber to be considered unmetered. This will be reflected
+ * to apps via {@link NetworkCapabilities#NET_CAPABILITY_NOT_METERED}.
+ * <p>
+ * This method is only accessible to the following narrow set of apps:
+ * <ul>
+ * <li>The carrier app for this subscriberId, as determined by
+ * {@link TelephonyManager#hasCarrierPrivileges()}.
+ * <li>The carrier app explicitly delegated access through
+ * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
+ * </ul>
+ *
+ * @param subId the subscriber this override applies to.
+ * @param overrideUnmetered set if the billing relationship should be
+ * considered unmetered.
+ * @param networkTypes the network types this override applies to.
+ * {@see TelephonyManager#getAllNetworkTypes()}
+ * @param timeoutMillis the timeout after which the requested override will
+ * be automatically cleared, or {@code 0} to leave in the
+ * requested state until explicitly cleared, or the next reboot,
+ * whichever happens first.
+ * @throws SecurityException if the caller doesn't meet the requirements
+ * outlined above.
+ */
+ public void setSubscriptionOverrideUnmetered(int subId, boolean overrideUnmetered,
+ @NonNull @Annotation.NetworkType int[] networkTypes,
+ @DurationMillisLong long timeoutMillis) {
final int overrideValue = overrideUnmetered ? SUBSCRIPTION_OVERRIDE_UNMETERED : 0;
getNetworkPolicyManager().setSubscriptionOverride(subId, SUBSCRIPTION_OVERRIDE_UNMETERED,
- overrideValue, timeoutMillis, mContext.getOpPackageName());
+ overrideValue, networkTypes, timeoutMillis, mContext.getOpPackageName());
}
/**
@@ -2621,13 +2652,46 @@ public class SubscriptionManager {
* requested state until explicitly cleared, or the next reboot,
* whichever happens first.
* @throws SecurityException if the caller doesn't meet the requirements
- * outlined above.
+ * outlined above.
+ */
+ public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested,
+ @DurationMillisLong long timeoutMillis) {
+ setSubscriptionOverrideCongested(subId, overrideCongested,
+ TelephonyManager.getAllNetworkTypes(), timeoutMillis);
+ }
+
+ /**
+ * Temporarily override the billing relationship plan between a carrier and
+ * a specific subscriber to be considered congested. This will cause the
+ * device to delay certain network requests when possible, such as developer
+ * jobs that are willing to run in a flexible time window.
+ * <p>
+ * This method is only accessible to the following narrow set of apps:
+ * <ul>
+ * <li>The carrier app for this subscriberId, as determined by
+ * {@link TelephonyManager#hasCarrierPrivileges()}.
+ * <li>The carrier app explicitly delegated access through
+ * {@link CarrierConfigManager#KEY_CONFIG_PLANS_PACKAGE_OVERRIDE_STRING}.
+ * </ul>
+ *
+ * @param subId the subscriber this override applies to.
+ * @param overrideCongested set if the subscription should be considered
+ * congested.
+ * @param networkTypes the network types this override applies to.
+ * {@see TelephonyManager#getAllNetworkTypes()}
+ * @param timeoutMillis the timeout after which the requested override will
+ * be automatically cleared, or {@code 0} to leave in the
+ * requested state until explicitly cleared, or the next reboot,
+ * whichever happens first.
+ * @throws SecurityException if the caller doesn't meet the requirements
+ * outlined above.
*/
public void setSubscriptionOverrideCongested(int subId, boolean overrideCongested,
+ @NonNull @Annotation.NetworkType int[] networkTypes,
@DurationMillisLong long timeoutMillis) {
final int overrideValue = overrideCongested ? SUBSCRIPTION_OVERRIDE_CONGESTED : 0;
getNetworkPolicyManager().setSubscriptionOverride(subId, SUBSCRIPTION_OVERRIDE_CONGESTED,
- overrideValue, timeoutMillis, mContext.getOpPackageName());
+ overrideValue, networkTypes, timeoutMillis, mContext.getOpPackageName());
}
/**
diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java
index 646744da5336..e8ace34793db 100644
--- a/telephony/java/android/telephony/TelephonyManager.java
+++ b/telephony/java/android/telephony/TelephonyManager.java
@@ -31,6 +31,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
import android.annotation.SdkConstant.SdkConstantType;
+import android.annotation.StringDef;
import android.annotation.SuppressAutoDoc;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
@@ -14344,9 +14345,22 @@ public class TelephonyManager {
return Collections.emptyList();
}
+ /**
+ * Indicates whether {@link CarrierBandwidth#getSecondaryDownlinkCapacityKbps()} and
+ * {@link CarrierBandwidth#getSecondaryUplinkCapacityKbps()} are visible. See comments
+ * on respective methods for more information.
+ *
+ * @hide
+ */
+ @SystemApi
+ public static final String CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE =
+ "CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE";
+
/** @hide */
- @IntDef(prefix = {"RADIO_INTERFACE_CAPABILITY_"},
- value = {})
+ @Retention(RetentionPolicy.SOURCE)
+ @StringDef(prefix = "CAPABILITY_", value = {
+ CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE,
+ })
public @interface RadioInterfaceCapability {}
/**
@@ -14359,6 +14373,7 @@ public class TelephonyManager {
*
* @hide
*/
+ @SystemApi
public boolean isRadioInterfaceCapabilitySupported(
@NonNull @RadioInterfaceCapability String capability) {
try {
diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java
index 8348502586a5..46ec4a39fd21 100644
--- a/telephony/java/android/telephony/data/DataCallResponse.java
+++ b/telephony/java/android/telephony/data/DataCallResponse.java
@@ -136,6 +136,7 @@ public final class DataCallResponse implements Parcelable {
private final int mPduSessionId;
private final Qos mDefaultQos;
private final List<QosSession> mQosSessions;
+ private final SliceInfo mSliceInfo;
/**
* @param cause Data call fail cause. {@link DataFailCause#NONE} indicates no error.
@@ -186,6 +187,7 @@ public final class DataCallResponse implements Parcelable {
mPduSessionId = PDU_SESSION_ID_NOT_SET;
mDefaultQos = null;
mQosSessions = new ArrayList<>();
+ mSliceInfo = null;
}
private DataCallResponse(@DataFailureCause int cause, long suggestedRetryTime, int id,
@@ -194,7 +196,8 @@ public final class DataCallResponse implements Parcelable {
@Nullable List<InetAddress> dnsAddresses, @Nullable List<InetAddress> gatewayAddresses,
@Nullable List<InetAddress> pcscfAddresses, int mtu, int mtuV4, int mtuV6,
@HandoverFailureMode int handoverFailureMode, int pduSessionId,
- @Nullable Qos defaultQos, @Nullable List<QosSession> qosSessions) {
+ @Nullable Qos defaultQos, @Nullable List<QosSession> qosSessions,
+ @Nullable SliceInfo sliceInfo) {
mCause = cause;
mSuggestedRetryTime = suggestedRetryTime;
mId = id;
@@ -216,6 +219,7 @@ public final class DataCallResponse implements Parcelable {
mPduSessionId = pduSessionId;
mDefaultQos = defaultQos;
mQosSessions = qosSessions;
+ mSliceInfo = sliceInfo;
}
/** @hide */
@@ -243,6 +247,7 @@ public final class DataCallResponse implements Parcelable {
mDefaultQos = source.readParcelable(Qos.class.getClassLoader());
mQosSessions = new ArrayList<>();
source.readList(mQosSessions, QosSession.class.getClassLoader());
+ mSliceInfo = source.readParcelable(SliceInfo.class.getClassLoader());
}
/**
@@ -368,7 +373,7 @@ public final class DataCallResponse implements Parcelable {
}
/**
- * @return default QOS of the data call received from the network
+ * @return default QOS of the data connection received from the network
*
* @hide
*/
@@ -379,16 +384,24 @@ public final class DataCallResponse implements Parcelable {
}
/**
- * @return All the dedicated bearer QOS sessions of the data call received from the network
+ * @return All the dedicated bearer QOS sessions of the data connection received from the
+ * network.
*
* @hide
*/
-
@NonNull
public List<QosSession> getQosSessions() {
return mQosSessions;
}
+ /**
+ * @return The slice info related to this data connection.
+ */
+ @Nullable
+ public SliceInfo getSliceInfo() {
+ return mSliceInfo;
+ }
+
@NonNull
@Override
public String toString() {
@@ -411,6 +424,7 @@ public final class DataCallResponse implements Parcelable {
.append(" pduSessionId=").append(getPduSessionId())
.append(" defaultQos=").append(mDefaultQos)
.append(" qosSessions=").append(mQosSessions)
+ .append(" sliceInfo=").append(mSliceInfo)
.append("}");
return sb.toString();
}
@@ -454,7 +468,8 @@ public final class DataCallResponse implements Parcelable {
&& mHandoverFailureMode == other.mHandoverFailureMode
&& mPduSessionId == other.mPduSessionId
&& isQosSame
- && isQosSessionsSame;
+ && isQosSessionsSame
+ && Objects.equals(mSliceInfo, other.mSliceInfo);
}
@Override
@@ -462,7 +477,7 @@ public final class DataCallResponse implements Parcelable {
return Objects.hash(mCause, mSuggestedRetryTime, mId, mLinkStatus, mProtocolType,
mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses, mPcscfAddresses,
mMtu, mMtuV4, mMtuV6, mHandoverFailureMode, mPduSessionId, mDefaultQos,
- mQosSessions);
+ mQosSessions, mSliceInfo);
}
@Override
@@ -493,6 +508,7 @@ public final class DataCallResponse implements Parcelable {
dest.writeParcelable((NrQos)mDefaultQos, flags);
}
dest.writeList(mQosSessions);
+ dest.writeParcelable(mSliceInfo, flags);
}
public static final @android.annotation.NonNull Parcelable.Creator<DataCallResponse> CREATOR =
@@ -576,6 +592,8 @@ public final class DataCallResponse implements Parcelable {
private List<QosSession> mQosSessions = new ArrayList<>();
+ private SliceInfo mSliceInfo;
+
/**
* Default constructor for Builder.
*/
@@ -799,6 +817,21 @@ public final class DataCallResponse implements Parcelable {
}
/**
+ * The Slice used for this data connection.
+ * <p/>
+ * If a handover occurs from EPDG to 5G,
+ * this is the {@link SliceInfo} used in {@link DataService#setupDataCall}.
+ *
+ * @param sliceInfo the slice info for the data call
+ *
+ * @return The same instance of the builder.
+ */
+ public @NonNull Builder setSliceInfo(@Nullable SliceInfo sliceInfo) {
+ mSliceInfo = sliceInfo;
+ return this;
+ }
+
+ /**
* Build the DataCallResponse.
*
* @return the DataCallResponse object.
@@ -807,7 +840,7 @@ public final class DataCallResponse implements Parcelable {
return new DataCallResponse(mCause, mSuggestedRetryTime, mId, mLinkStatus,
mProtocolType, mInterfaceName, mAddresses, mDnsAddresses, mGatewayAddresses,
mPcscfAddresses, mMtu, mMtuV4, mMtuV6, mHandoverFailureMode, mPduSessionId,
- mDefaultQos, mQosSessions);
+ mDefaultQos, mQosSessions, mSliceInfo);
}
}
}
diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java
index 2ec965101930..03c2ef9d9baa 100644
--- a/telephony/java/android/telephony/data/DataService.java
+++ b/telephony/java/android/telephony/data/DataService.java
@@ -194,13 +194,19 @@ public abstract class DataService extends Service {
* The standard range of values are 1-15 while 0 means no pdu session id
* was attached to this call. Reference: 3GPP TS 24.007 section
* 11.2.3.1b.
+ * @param sliceInfo used within the data connection when a handover occurs from EPDG to 5G.
+ * The value is null unless the access network is
+ * {@link android.telephony.AccessNetworkConstants.AccessNetworkType#NGRAN} and a
+ * handover is occurring from EPDG to 5G. If the slice passed is rejected, then
+ * {@link DataCallResponse#getCause()} is
+ * {@link android.telephony.DataFailCause#SLICE_REJECTED}.
* @param callback The result callback for this request.
*/
public void setupDataCall(int accessNetworkType, @NonNull DataProfile dataProfile,
boolean isRoaming, boolean allowRoaming,
@SetupDataReason int reason,
@Nullable LinkProperties linkProperties,
- @IntRange(from = 0, to = 15) int pduSessionId,
+ @IntRange(from = 0, to = 15) int pduSessionId, @Nullable SliceInfo sliceInfo,
@NonNull DataServiceCallback callback) {
/* Call the old version since the new version isn't supported */
setupDataCall(accessNetworkType, dataProfile, isRoaming, allowRoaming, reason,
@@ -392,10 +398,11 @@ public abstract class DataService extends Service {
public final int reason;
public final LinkProperties linkProperties;
public final int pduSessionId;
+ public final SliceInfo sliceInfo;
public final IDataServiceCallback callback;
SetupDataCallRequest(int accessNetworkType, DataProfile dataProfile, boolean isRoaming,
boolean allowRoaming, int reason, LinkProperties linkProperties,
- int pduSessionId, IDataServiceCallback callback) {
+ int pduSessionId, SliceInfo sliceInfo, IDataServiceCallback callback) {
this.accessNetworkType = accessNetworkType;
this.dataProfile = dataProfile;
this.isRoaming = isRoaming;
@@ -403,6 +410,7 @@ public abstract class DataService extends Service {
this.linkProperties = linkProperties;
this.reason = reason;
this.pduSessionId = pduSessionId;
+ this.sliceInfo = sliceInfo;
this.callback = callback;
}
}
@@ -513,6 +521,7 @@ public abstract class DataService extends Service {
setupDataCallRequest.dataProfile, setupDataCallRequest.isRoaming,
setupDataCallRequest.allowRoaming, setupDataCallRequest.reason,
setupDataCallRequest.linkProperties, setupDataCallRequest.pduSessionId,
+ setupDataCallRequest.sliceInfo,
(setupDataCallRequest.callback != null)
? new DataServiceCallback(setupDataCallRequest.callback)
: null);
@@ -676,10 +685,12 @@ public abstract class DataService extends Service {
@Override
public void setupDataCall(int slotIndex, int accessNetworkType, DataProfile dataProfile,
boolean isRoaming, boolean allowRoaming, int reason,
- LinkProperties linkProperties, int pduSessionId, IDataServiceCallback callback) {
+ LinkProperties linkProperties, int pduSessionId, SliceInfo sliceInfo,
+ IDataServiceCallback callback) {
mHandler.obtainMessage(DATA_SERVICE_REQUEST_SETUP_DATA_CALL, slotIndex, 0,
new SetupDataCallRequest(accessNetworkType, dataProfile, isRoaming,
- allowRoaming, reason, linkProperties, pduSessionId, callback))
+ allowRoaming, reason, linkProperties, pduSessionId, sliceInfo,
+ callback))
.sendToTarget();
}
diff --git a/telephony/java/android/telephony/data/IDataService.aidl b/telephony/java/android/telephony/data/IDataService.aidl
index 3f1f033d6f11..e0b9a1a9bb5a 100644
--- a/telephony/java/android/telephony/data/IDataService.aidl
+++ b/telephony/java/android/telephony/data/IDataService.aidl
@@ -19,6 +19,7 @@ package android.telephony.data;
import android.net.LinkProperties;
import android.telephony.data.DataProfile;
import android.telephony.data.IDataServiceCallback;
+import android.telephony.data.SliceInfo;
/**
* {@hide}
@@ -29,7 +30,7 @@ oneway interface IDataService
void removeDataServiceProvider(int slotId);
void setupDataCall(int slotId, int accessNetwork, in DataProfile dataProfile, boolean isRoaming,
boolean allowRoaming, int reason, in LinkProperties linkProperties,
- int pduSessionId, IDataServiceCallback callback);
+ int pduSessionId, in SliceInfo sliceInfo, IDataServiceCallback callback);
void deactivateDataCall(int slotId, int cid, int reason, IDataServiceCallback callback);
void setInitialAttachApn(int slotId, in DataProfile dataProfile, boolean isRoaming,
IDataServiceCallback callback);
diff --git a/telephony/java/android/telephony/data/IQualifiedNetworksService.aidl b/telephony/java/android/telephony/data/IQualifiedNetworksService.aidl
index 2904082616e7..ba2b62d14bec 100644
--- a/telephony/java/android/telephony/data/IQualifiedNetworksService.aidl
+++ b/telephony/java/android/telephony/data/IQualifiedNetworksService.aidl
@@ -17,7 +17,7 @@
package android.telephony.data;
import android.telephony.data.IQualifiedNetworksServiceCallback;
-import android.telephony.data.ApnThrottleStatus;
+import android.telephony.data.ThrottleStatus;
/**
* {@hide}
@@ -26,5 +26,5 @@ interface IQualifiedNetworksService
{
oneway void createNetworkAvailabilityProvider(int slotId, IQualifiedNetworksServiceCallback callback);
oneway void removeNetworkAvailabilityProvider(int slotId);
- oneway void reportApnThrottleStatusChanged(int slotId, in List<ApnThrottleStatus> statuses);
+ oneway void reportThrottleStatusChanged(int slotId, in List<ThrottleStatus> statuses);
}
diff --git a/telephony/java/android/telephony/data/QualifiedNetworksService.java b/telephony/java/android/telephony/data/QualifiedNetworksService.java
index 4af63b4cf981..4e85d8926f11 100644
--- a/telephony/java/android/telephony/data/QualifiedNetworksService.java
+++ b/telephony/java/android/telephony/data/QualifiedNetworksService.java
@@ -168,8 +168,8 @@ public abstract class QualifiedNetworksService extends Service {
*
* @param statuses the statuses that have changed
*/
- public void reportApnThrottleStatusChanged(@NonNull List<ApnThrottleStatus> statuses) {
- Log.d(TAG, "reportApnThrottleStatusChanged: statuses size=" + statuses.size());
+ public void reportThrottleStatusChanged(@NonNull List<ThrottleStatus> statuses) {
+ Log.d(TAG, "reportThrottleStatusChanged: statuses size=" + statuses.size());
}
/**
@@ -212,8 +212,8 @@ public abstract class QualifiedNetworksService extends Service {
break;
case QNS_APN_THROTTLE_STATUS_CHANGED:
if (provider != null) {
- List<ApnThrottleStatus> statuses = (List<ApnThrottleStatus>) message.obj;
- provider.reportApnThrottleStatusChanged(statuses);
+ List<ThrottleStatus> statuses = (List<ThrottleStatus>) message.obj;
+ provider.reportThrottleStatusChanged(statuses);
}
break;
@@ -307,8 +307,8 @@ public abstract class QualifiedNetworksService extends Service {
}
@Override
- public void reportApnThrottleStatusChanged(int slotIndex,
- List<ApnThrottleStatus> statuses) {
+ public void reportThrottleStatusChanged(int slotIndex,
+ List<ThrottleStatus> statuses) {
mHandler.obtainMessage(QNS_APN_THROTTLE_STATUS_CHANGED, slotIndex, 0, statuses)
.sendToTarget();
}
diff --git a/telephony/java/android/telephony/data/ApnThrottleStatus.aidl b/telephony/java/android/telephony/data/SliceInfo.aidl
index 46bc4abde159..286ea5e4f8c7 100644
--- a/telephony/java/android/telephony/data/ApnThrottleStatus.aidl
+++ b/telephony/java/android/telephony/data/SliceInfo.aidl
@@ -17,4 +17,4 @@
/** @hide */
package android.telephony.data;
-parcelable ApnThrottleStatus;
+parcelable SliceInfo;
diff --git a/telephony/java/android/telephony/data/SliceInfo.java b/telephony/java/android/telephony/data/SliceInfo.java
new file mode 100644
index 000000000000..51857a7b4908
--- /dev/null
+++ b/telephony/java/android/telephony/data/SliceInfo.java
@@ -0,0 +1,342 @@
+/*
+ * 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.data;
+
+import android.annotation.IntDef;
+import android.annotation.IntRange;
+import android.annotation.NonNull;
+import android.annotation.SuppressLint;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
+
+/**
+ * Represents a S-NSSAI as defined in 3GPP TS 24.501.
+ *
+ * @hide
+ */
+@SystemApi
+public final class SliceInfo implements Parcelable {
+ /**
+ * When set on a Slice Differentiator, this value indicates that there is no corresponding
+ * Slice.
+ */
+ public static final int SLICE_DIFFERENTIATOR_NO_SLICE = -1;
+
+ /**
+ * Indicates that the service type is not present.
+ */
+ public static final int SLICE_SERVICE_TYPE_NONE = 0;
+
+ /**
+ * Slice suitable for the handling of 5G enhanced Mobile Broadband.
+ */
+ public static final int SLICE_SERVICE_TYPE_EMBB = 1;
+
+ /**
+ * Slice suitable for the handling of ultra-reliable low latency communications.
+ */
+ public static final int SLICE_SERVICE_TYPE_URLLC = 2;
+
+ /**
+ * Slice suitable for the handling of massive IoT.
+ */
+ public static final int SLICE_SERVICE_TYPE_MIOT = 3;
+
+ /**
+ * The min acceptable value for a Slice Differentiator
+ */
+ @SuppressLint("MinMaxConstant")
+ public static final int MIN_SLICE_DIFFERENTIATOR = -1;
+
+ /**
+ * The max acceptable value for a Slice Differentiator
+ */
+ @SuppressLint("MinMaxConstant")
+ public static final int MAX_SLICE_DIFFERENTIATOR = 0xFFFFFE;
+
+ /** @hide */
+ @IntDef(prefix = { "SLICE_SERVICE_TYPE_" }, value = {
+ SLICE_SERVICE_TYPE_NONE,
+ SLICE_SERVICE_TYPE_EMBB,
+ SLICE_SERVICE_TYPE_URLLC,
+ SLICE_SERVICE_TYPE_MIOT,
+ })
+ @Retention(RetentionPolicy.SOURCE)
+ public @interface SliceServiceType {}
+
+
+ @SliceServiceType
+ private final int mSliceServiceType;
+ @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR)
+ private final int mSliceDifferentiator;
+ @SliceServiceType
+ private final int mMappedHplmnSliceServiceType;
+ @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR)
+ private final int mMappedHplmnSliceDifferentiator;
+
+ private SliceInfo(@SliceServiceType int sliceServiceType,
+ int sliceDifferentiator, int mappedHplmnSliceServiceType,
+ int mappedHplmnSliceDifferentiator) {
+ mSliceServiceType = sliceServiceType;
+ mSliceDifferentiator = sliceDifferentiator;
+ mMappedHplmnSliceDifferentiator = mappedHplmnSliceDifferentiator;
+ mMappedHplmnSliceServiceType = mappedHplmnSliceServiceType;
+ }
+
+ /**
+ * The type of service provided by the slice.
+ * <p/>
+ * see: 3GPP TS 24.501 Section 9.11.2.8.
+ */
+ @SliceServiceType
+ public int getSliceServiceType() {
+ return mSliceServiceType;
+ }
+
+ /**
+ * Identifies the slice from others with the same Slice Service Type.
+ * <p/>
+ * Returns {@link #SLICE_DIFFERENTIATOR_NO_SLICE} if {@link #getSliceServiceType} returns
+ * {@link #SLICE_SERVICE_TYPE_NONE}.
+ * <p/>
+ * see: 3GPP TS 24.501 Section 9.11.2.8.
+ */
+ @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR)
+ public int getSliceDifferentiator() {
+ return mSliceDifferentiator;
+ }
+
+ /**
+ * Corresponds to a Slice Info (S-NSSAI) of the HPLMN.
+ * <p/>
+ * see: 3GPP TS 24.501 Section 9.11.2.8.
+ */
+ @SliceServiceType
+ public int getMappedHplmnSliceServiceType() {
+ return mMappedHplmnSliceServiceType;
+ }
+
+ /**
+ * This Slice Differentiator corresponds to a {@link SliceInfo} (S-NSSAI) of the HPLMN;
+ * {@link #getSliceDifferentiator()} is mapped to this value.
+ * <p/>
+ * Returns {@link #SLICE_DIFFERENTIATOR_NO_SLICE} if either of the following are true:
+ * <ul>
+ * <li>{@link #getSliceDifferentiator()} returns {@link #SLICE_DIFFERENTIATOR_NO_SLICE}</li>
+ * <li>{@link #getMappedHplmnSliceServiceType()} returns {@link #SLICE_SERVICE_TYPE_NONE}</li>
+ * </ul>
+ * <p/>
+ * see: 3GPP TS 24.501 Section 9.11.2.8.
+ */
+ @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR)
+ public int getMappedHplmnSliceDifferentiator() {
+ return mMappedHplmnSliceDifferentiator;
+ }
+
+ private SliceInfo(@NonNull Parcel in) {
+ mSliceServiceType = in.readInt();
+ mSliceDifferentiator = in.readInt();
+ mMappedHplmnSliceServiceType = in.readInt();
+ mMappedHplmnSliceDifferentiator = in.readInt();
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mSliceServiceType);
+ dest.writeInt(mSliceDifferentiator);
+ dest.writeInt(mMappedHplmnSliceServiceType);
+ dest.writeInt(mMappedHplmnSliceDifferentiator);
+ }
+
+ public static final @android.annotation.NonNull Parcelable.Creator<SliceInfo> CREATOR =
+ new Parcelable.Creator<SliceInfo>() {
+ @Override
+ @NonNull
+ public SliceInfo createFromParcel(@NonNull Parcel source) {
+ return new SliceInfo(source);
+ }
+
+ @Override
+ @NonNull
+ public SliceInfo[] newArray(int size) {
+ return new SliceInfo[size];
+ }
+ };
+
+ @Override
+ public String toString() {
+ return "SliceInfo{"
+ + "mSliceServiceType=" + sliceServiceTypeToString(mSliceServiceType)
+ + ", mSliceDifferentiator=" + mSliceDifferentiator
+ + ", mMappedHplmnSliceServiceType="
+ + sliceServiceTypeToString(mMappedHplmnSliceServiceType)
+ + ", mMappedHplmnSliceDifferentiator=" + mMappedHplmnSliceDifferentiator
+ + '}';
+ }
+
+ private static String sliceServiceTypeToString(@SliceServiceType int sliceServiceType) {
+ switch(sliceServiceType) {
+ case SLICE_SERVICE_TYPE_NONE:
+ return "NONE";
+ case SLICE_SERVICE_TYPE_EMBB:
+ return "EMBB";
+ case SLICE_SERVICE_TYPE_URLLC:
+ return "URLLC";
+ case SLICE_SERVICE_TYPE_MIOT:
+ return "MIOT";
+ default:
+ return Integer.toString(sliceServiceType);
+ }
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ SliceInfo sliceInfo = (SliceInfo) o;
+ return mSliceServiceType == sliceInfo.mSliceServiceType
+ && mSliceDifferentiator == sliceInfo.mSliceDifferentiator
+ && mMappedHplmnSliceServiceType == sliceInfo.mMappedHplmnSliceServiceType
+ && mMappedHplmnSliceDifferentiator == sliceInfo.mMappedHplmnSliceDifferentiator;
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mSliceServiceType, mSliceDifferentiator, mMappedHplmnSliceServiceType,
+ mMappedHplmnSliceDifferentiator);
+ }
+
+ /**
+ * Provides a convenient way to set the fields of a {@link SliceInfo} when creating a
+ * new instance.
+ *
+ * <p>The example below shows how you might create a new {@code SliceInfo}:
+ *
+ * <pre><code>
+ *
+ * SliceInfo response = new SliceInfo.Builder()
+ * .setSliceServiceType(SLICE_SERVICE_TYPE_URLLC)
+ * .build();
+ * </code></pre>
+ */
+ public static final class Builder {
+ @SliceServiceType
+ private int mSliceServiceType = SLICE_SERVICE_TYPE_NONE;
+ @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR)
+ private int mSliceDifferentiator = SLICE_DIFFERENTIATOR_NO_SLICE;
+ @SliceServiceType
+ private int mMappedHplmnSliceServiceType = SLICE_SERVICE_TYPE_NONE;
+ @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR)
+ private int mMappedHplmnSliceDifferentiator = SLICE_DIFFERENTIATOR_NO_SLICE;
+
+ /**
+ * Default constructor for Builder.
+ */
+ public Builder() {
+ }
+
+ /**
+ * Set the Slice Service Type.
+ *
+ * @return The same instance of the builder.
+ */
+ @NonNull
+ public Builder setSliceServiceType(@SliceServiceType int mSliceServiceType) {
+ this.mSliceServiceType = mSliceServiceType;
+ return this;
+ }
+
+ /**
+ * Set the Slice Differentiator.
+ * <p/>
+ * A value of {@link #SLICE_DIFFERENTIATOR_NO_SLICE} indicates that there is no
+ * corresponding Slice.
+ *
+ * @throws IllegalArgumentException if the parameter is not between
+ * {@link #MIN_SLICE_DIFFERENTIATOR} and {@link #MAX_SLICE_DIFFERENTIATOR}.
+ *
+ * @return The same instance of the builder.
+ */
+ @NonNull
+ public Builder setSliceDifferentiator(
+ @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR)
+ int sliceDifferentiator) {
+ if (sliceDifferentiator < MIN_SLICE_DIFFERENTIATOR
+ || sliceDifferentiator > MAX_SLICE_DIFFERENTIATOR) {
+ throw new IllegalArgumentException("The slice diffentiator value is out of range");
+ }
+ this.mSliceDifferentiator = sliceDifferentiator;
+ return this;
+ }
+
+ /**
+ * Set the HPLMN Slice Service Type.
+ *
+ * @return The same instance of the builder.
+ */
+ @NonNull
+ public Builder setMappedHplmnSliceServiceType(
+ @SliceServiceType int mappedHplmnSliceServiceType) {
+ this.mMappedHplmnSliceServiceType = mappedHplmnSliceServiceType;
+ return this;
+ }
+
+ /**
+ * Set the HPLMN Slice Differentiator.
+ * <p/>
+ * A value of {@link #SLICE_DIFFERENTIATOR_NO_SLICE} indicates that there is no
+ * corresponding Slice of the HPLMN.
+ *
+ * @throws IllegalArgumentException if the parameter is not between
+ * {@link #MIN_SLICE_DIFFERENTIATOR} and {@link #MAX_SLICE_DIFFERENTIATOR}.
+ *
+ * @return The same instance of the builder.
+ */
+ @NonNull
+ public Builder setMappedHplmnSliceDifferentiator(
+ @IntRange(from = MIN_SLICE_DIFFERENTIATOR, to = MAX_SLICE_DIFFERENTIATOR)
+ int mappedHplmnSliceDifferentiator) {
+ if (mappedHplmnSliceDifferentiator < MIN_SLICE_DIFFERENTIATOR
+ || mappedHplmnSliceDifferentiator > MAX_SLICE_DIFFERENTIATOR) {
+ throw new IllegalArgumentException("The slice diffentiator value is out of range");
+ }
+ this.mMappedHplmnSliceDifferentiator = mappedHplmnSliceDifferentiator;
+ return this;
+ }
+
+ /**
+ * Build the {@link SliceInfo}.
+ *
+ * @return the {@link SliceInfo} object.
+ */
+ @NonNull
+ public SliceInfo build() {
+ return new SliceInfo(this.mSliceServiceType, this.mSliceDifferentiator,
+ this.mMappedHplmnSliceServiceType, this.mMappedHplmnSliceDifferentiator);
+ }
+ }
+}
diff --git a/telephony/java/android/telephony/data/ThrottleStatus.aidl b/telephony/java/android/telephony/data/ThrottleStatus.aidl
new file mode 100644
index 000000000000..f75f35709816
--- /dev/null
+++ b/telephony/java/android/telephony/data/ThrottleStatus.aidl
@@ -0,0 +1,20 @@
+/*
+ * Copyright 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.
+ */
+
+/** @hide */
+package android.telephony.data;
+
+parcelable ThrottleStatus;
diff --git a/telephony/java/android/telephony/data/ApnThrottleStatus.java b/telephony/java/android/telephony/data/ThrottleStatus.java
index 51461d17690a..0335c6868340 100644
--- a/telephony/java/android/telephony/data/ApnThrottleStatus.java
+++ b/telephony/java/android/telephony/data/ThrottleStatus.java
@@ -35,7 +35,7 @@ import java.util.Objects;
* @hide
*/
@SystemApi
-public final class ApnThrottleStatus implements Parcelable {
+public final class ThrottleStatus implements Parcelable {
/**
* The APN type is not throttled.
*/
@@ -43,14 +43,14 @@ public final class ApnThrottleStatus implements Parcelable {
/**
* The APN type is throttled until {@link android.os.SystemClock#elapsedRealtime()}
- * has reached {@link ApnThrottleStatus#getThrottleExpiryTimeMillis}
+ * has reached {@link ThrottleStatus#getThrottleExpiryTimeMillis}
*/
public static final int THROTTLE_TYPE_ELAPSED_TIME = 2;
/** {@hide} */
@IntDef(flag = true, prefix = {"THROTTLE_TYPE_"}, value = {
- ApnThrottleStatus.THROTTLE_TYPE_NONE,
- ApnThrottleStatus.THROTTLE_TYPE_ELAPSED_TIME,
+ ThrottleStatus.THROTTLE_TYPE_NONE,
+ ThrottleStatus.THROTTLE_TYPE_ELAPSED_TIME,
})
public @interface ThrottleType {
}
@@ -72,9 +72,9 @@ public final class ApnThrottleStatus implements Parcelable {
/** {@hide} */
@IntDef(flag = true, prefix = {"RETRY_TYPE_"}, value = {
- ApnThrottleStatus.RETRY_TYPE_NONE,
- ApnThrottleStatus.RETRY_TYPE_NEW_CONNECTION,
- ApnThrottleStatus.RETRY_TYPE_HANDOVER,
+ ThrottleStatus.RETRY_TYPE_NONE,
+ ThrottleStatus.RETRY_TYPE_NEW_CONNECTION,
+ ThrottleStatus.RETRY_TYPE_HANDOVER,
})
public @interface RetryType {
}
@@ -141,7 +141,7 @@ public final class ApnThrottleStatus implements Parcelable {
* {@link SystemClock#elapsedRealtime}.
*
* This value only applies when the throttle type is set to
- * {@link ApnThrottleStatus#THROTTLE_TYPE_ELAPSED_TIME}.
+ * {@link ThrottleStatus#THROTTLE_TYPE_ELAPSED_TIME}.
*
* A value of {@link Long#MAX_VALUE} implies that the APN type is throttled indefinitely.
*
@@ -152,7 +152,7 @@ public final class ApnThrottleStatus implements Parcelable {
return mThrottleExpiryTimeMillis;
}
- private ApnThrottleStatus(int slotIndex,
+ private ThrottleStatus(int slotIndex,
@AccessNetworkConstants.TransportType int transportType,
@Annotation.ApnType int apnTypes,
@ThrottleType int throttleType,
@@ -166,7 +166,7 @@ public final class ApnThrottleStatus implements Parcelable {
mRetryType = retryType;
}
- private ApnThrottleStatus(@NonNull Parcel source) {
+ private ThrottleStatus(@NonNull Parcel source) {
mSlotIndex = source.readInt();
mTransportType = source.readInt();
mApnType = source.readInt();
@@ -185,16 +185,16 @@ public final class ApnThrottleStatus implements Parcelable {
dest.writeInt(mThrottleType);
}
- public static final @NonNull Parcelable.Creator<ApnThrottleStatus> CREATOR =
- new Parcelable.Creator<ApnThrottleStatus>() {
+ public static final @NonNull Parcelable.Creator<ThrottleStatus> CREATOR =
+ new Parcelable.Creator<ThrottleStatus>() {
@Override
- public ApnThrottleStatus createFromParcel(@NonNull Parcel source) {
- return new ApnThrottleStatus(source);
+ public ThrottleStatus createFromParcel(@NonNull Parcel source) {
+ return new ThrottleStatus(source);
}
@Override
- public ApnThrottleStatus[] newArray(int size) {
- return new ApnThrottleStatus[size];
+ public ThrottleStatus[] newArray(int size) {
+ return new ThrottleStatus[size];
}
};
@@ -213,8 +213,8 @@ public final class ApnThrottleStatus implements Parcelable {
public boolean equals(Object obj) {
if (obj == null) {
return false;
- } else if (obj instanceof ApnThrottleStatus) {
- ApnThrottleStatus other = (ApnThrottleStatus) obj;
+ } else if (obj instanceof ThrottleStatus) {
+ ThrottleStatus other = (ThrottleStatus) obj;
return this.mSlotIndex == other.mSlotIndex
&& this.mApnType == other.mApnType
&& this.mRetryType == other.mRetryType
@@ -228,7 +228,7 @@ public final class ApnThrottleStatus implements Parcelable {
@Override
public String toString() {
- return "ApnThrottleStatus{"
+ return "ThrottleStatus{"
+ "mSlotIndex=" + mSlotIndex
+ ", mTransportType=" + mTransportType
+ ", mApnType=" + ApnSetting.getApnTypeString(mApnType)
@@ -239,18 +239,18 @@ public final class ApnThrottleStatus implements Parcelable {
}
/**
- * Provides a convenient way to set the fields of an {@link ApnThrottleStatus} when creating a
+ * Provides a convenient way to set the fields of an {@link ThrottleStatus} when creating a
* new instance.
*
- * <p>The example below shows how you might create a new {@code ApnThrottleStatus}:
+ * <p>The example below shows how you might create a new {@code ThrottleStatus}:
*
* <pre><code>
*
- * DataCallResponseApnThrottleStatus = new ApnThrottleStatus.Builder()
+ * ThrottleStatus = new ThrottleStatus.Builder()
* .setSlotIndex(1)
* .setApnType({@link ApnSetting#TYPE_EMERGENCY})
* .setNoThrottle()
- * .setRetryType({@link ApnThrottleStatus#RETRY_TYPE_NEW_CONNECTION})
+ * .setRetryType({@link ThrottleStatus#RETRY_TYPE_NEW_CONNECTION})
* .build();
* </code></pre>
*/
@@ -261,6 +261,10 @@ public final class ApnThrottleStatus implements Parcelable {
private long mThrottleExpiryTimeMillis;
private @RetryType int mRetryType;
private @ThrottleType int mThrottleType;
+
+ /**
+ * @hide
+ */
public static final long NO_THROTTLE_EXPIRY_TIME =
DataCallResponse.RETRY_DURATION_UNDEFINED;
@@ -312,7 +316,7 @@ public final class ApnThrottleStatus implements Parcelable {
* {@link SystemClock#elapsedRealtime}.
*
* When setting this value, the throttle type is set to
- * {@link ApnThrottleStatus#THROTTLE_TYPE_ELAPSED_TIME}.
+ * {@link ThrottleStatus#THROTTLE_TYPE_ELAPSED_TIME}.
*
* A value of {@link Long#MAX_VALUE} implies that the APN type is throttled indefinitely.
*
@@ -338,7 +342,7 @@ public final class ApnThrottleStatus implements Parcelable {
* Sets the status of the APN type as not being throttled.
*
* When setting this value, the throttle type is set to
- * {@link ApnThrottleStatus#THROTTLE_TYPE_NONE} and the expiry time is set to
+ * {@link ThrottleStatus#THROTTLE_TYPE_NONE} and the expiry time is set to
* {@link Builder#NO_THROTTLE_EXPIRY_TIME}.
*
* @return The same instance of the builder.
@@ -365,13 +369,13 @@ public final class ApnThrottleStatus implements Parcelable {
}
/**
- * Build the {@link ApnThrottleStatus}
+ * Build the {@link ThrottleStatus}
*
- * @return the {@link ApnThrottleStatus} object
+ * @return the {@link ThrottleStatus} object
*/
@NonNull
- public ApnThrottleStatus build() {
- return new ApnThrottleStatus(
+ public ThrottleStatus build() {
+ return new ThrottleStatus(
mSlotIndex,
mTransportType,
mApnType,
diff --git a/telephony/java/android/telephony/euicc/DownloadableSubscription.java b/telephony/java/android/telephony/euicc/DownloadableSubscription.java
index 52b31d7f9611..a5150b010f57 100644
--- a/telephony/java/android/telephony/euicc/DownloadableSubscription.java
+++ b/telephony/java/android/telephony/euicc/DownloadableSubscription.java
@@ -15,6 +15,7 @@
*/
package android.telephony.euicc;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.app.PendingIntent;
@@ -102,44 +103,81 @@ public final class DownloadableSubscription implements Parcelable {
this.accessRules = accessRules;
}
- /** @hide */
- @SystemApi
public static final class Builder {
@Nullable private String encodedActivationCode;
@Nullable private String confirmationCode;
@Nullable private String carrierName;
List<UiccAccessRule> accessRules;
+ /** @hide */
+ @SystemApi
public Builder() {}
- public Builder(DownloadableSubscription baseSubscription) {
+ public Builder(@NonNull DownloadableSubscription baseSubscription) {
encodedActivationCode = baseSubscription.getEncodedActivationCode();
confirmationCode = baseSubscription.getConfirmationCode();
carrierName = baseSubscription.getCarrierName();
accessRules = baseSubscription.getAccessRules();
}
+ public Builder(@NonNull String encodedActivationCode) {
+ this.encodedActivationCode = encodedActivationCode;
+ }
+
+ /**
+ * Builds a {@link DownloadableSubscription} object.
+ * @return a non-null {@link DownloadableSubscription} object.
+ */
+ @NonNull
public DownloadableSubscription build() {
return new DownloadableSubscription(encodedActivationCode, confirmationCode,
carrierName, accessRules);
}
- public Builder setEncodedActivationCode(String value) {
+ /**
+ * Sets the encoded activation code.
+ * @param value the activation code to use. An activation code can be parsed from a user
+ * scanned QR code. The format of activation code is defined in SGP.22. For
+ * example, "1$SMDP.GSMA.COM$04386-AGYFT-A74Y8-3F815$1.3.6.1.4.1.31746". For
+ * detail, see {@code com.android.euicc.data.ActivationCode}. Must not be null.
+ */
+ @NonNull
+ public Builder setEncodedActivationCode(@NonNull String value) {
encodedActivationCode = value;
return this;
}
- public Builder setConfirmationCode(String value) {
+ /**
+ * Sets the confirmation code.
+ * @param value the confirmation code to use to authenticate the carrier server got
+ * subscription download.
+ */
+ @NonNull
+ public Builder setConfirmationCode(@NonNull String value) {
confirmationCode = value;
return this;
}
- public Builder setCarrierName(String value) {
+ /**
+ * Sets the user-visible carrier name.
+ * @param value carrier name.
+ * @hide
+ */
+ @NonNull
+ @SystemApi
+ public Builder setCarrierName(@NonNull String value) {
carrierName = value;
return this;
}
- public Builder setAccessRules(List<UiccAccessRule> value) {
+ /**
+ * Sets the {@link UiccAccessRule}s dictating access to this subscription.
+ * @param value A list of {@link UiccAccessRule}s.
+ * @hide
+ */
+ @NonNull
+ @SystemApi
+ public Builder setAccessRules(@NonNull List<UiccAccessRule> value) {
accessRules = value;
return this;
}
diff --git a/telephony/java/android/telephony/ims/DelegateStateCallback.java b/telephony/java/android/telephony/ims/DelegateStateCallback.java
index fb659490d546..6bf992e64480 100644
--- a/telephony/java/android/telephony/ims/DelegateStateCallback.java
+++ b/telephony/java/android/telephony/ims/DelegateStateCallback.java
@@ -18,6 +18,7 @@ package android.telephony.ims;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.telephony.ims.stub.SipDelegate;
import android.telephony.ims.stub.SipTransportImplBase;
@@ -52,7 +53,9 @@ public interface DelegateStateCallback {
* implementing this feature elsewhere. If all features of this {@link SipDelegate} are
* denied, this method should still be called.
*/
- void onCreated(@NonNull SipDelegate delegate, @Nullable Set<FeatureTagState> deniedTags);
+ void onCreated(@NonNull SipDelegate delegate,
+ @SuppressLint("NullableCollection") // TODO(b/154763999): Mark deniedTags @Nonnull
+ @Nullable Set<FeatureTagState> deniedTags);
/**
* This must be called by the ImsService after the framework calls
diff --git a/telephony/java/android/telephony/ims/ImsRcsManager.java b/telephony/java/android/telephony/ims/ImsRcsManager.java
index bd623e055743..5f4e1e6f3148 100644
--- a/telephony/java/android/telephony/ims/ImsRcsManager.java
+++ b/telephony/java/android/telephony/ims/ImsRcsManager.java
@@ -21,6 +21,7 @@ import android.annotation.CallbackExecutor;
import android.annotation.NonNull;
import android.annotation.RequiresPermission;
import android.annotation.SdkConstant;
+import android.annotation.SystemApi;
import android.content.Context;
import android.content.Intent;
import android.os.Binder;
@@ -39,6 +40,8 @@ import android.util.Log;
import com.android.internal.telephony.IIntegerConsumer;
+import java.util.HashMap;
+import java.util.Map;
import java.util.concurrent.Executor;
import java.util.function.Consumer;
@@ -77,31 +80,49 @@ public class ImsRcsManager {
"android.telephony.ims.action.SHOW_CAPABILITY_DISCOVERY_OPT_IN";
/**
- * Receives RCS Feature availability status updates from the ImsService.
- *
- * @see #isAvailable(int)
- * @see #registerRcsAvailabilityCallback(Executor, AvailabilityCallback)
- * @see #unregisterRcsAvailabilityCallback(AvailabilityCallback)
+ * An application can use {@link #addOnAvailabilityChangedListener} to register a
+ * {@link OnAvailabilityChangedListener}, which will notify the user when the RCS feature
+ * availability status updates from the ImsService.
* @hide
*/
- public static class AvailabilityCallback {
+ @SystemApi
+ public interface OnAvailabilityChangedListener {
+ /**
+ * The availability of the feature's capabilities has changed to either available or
+ * unavailable.
+ * <p>
+ * If unavailable, the feature does not support the capability at the current time. This may
+ * be due to network or subscription provisioning changes, such as the IMS registration
+ * being lost, network type changing, or OMA-DM provisioning updates.
+ *
+ * @param capabilities The new availability of the capabilities.
+ */
+ void onAvailabilityChanged(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities);
+ }
- private static class CapabilityBinder extends IImsCapabilityCallback.Stub {
+ /**
+ * Receive the availability status changed from the ImsService and pass the status change to
+ * the associated {@link OnAvailabilityChangedListener}
+ */
+ private static class AvailabilityCallbackAdapter {
- private final AvailabilityCallback mLocalCallback;
- private Executor mExecutor;
+ private static class CapabilityBinder extends IImsCapabilityCallback.Stub {
+ private final OnAvailabilityChangedListener mOnAvailabilityChangedListener;
+ private final Executor mExecutor;
- CapabilityBinder(AvailabilityCallback c) {
- mLocalCallback = c;
+ CapabilityBinder(OnAvailabilityChangedListener listener, Executor executor) {
+ mExecutor = executor;
+ mOnAvailabilityChangedListener = listener;
}
@Override
public void onCapabilitiesStatusChanged(int config) {
- if (mLocalCallback == null) return;
+ if (mOnAvailabilityChangedListener == null) return;
long callingIdentity = Binder.clearCallingIdentity();
try {
- mExecutor.execute(() -> mLocalCallback.onAvailabilityChanged(config));
+ mExecutor.execute(() ->
+ mOnAvailabilityChangedListener.onAvailabilityChanged(config));
} finally {
restoreCallingIdentity(callingIdentity);
}
@@ -110,48 +131,34 @@ public class ImsRcsManager {
@Override
public void onQueryCapabilityConfiguration(int capability, int radioTech,
boolean isEnabled) {
- // This is not used for public interfaces.
+ // This is not used.
}
@Override
public void onChangeCapabilityConfigurationError(int capability, int radioTech,
@ImsFeature.ImsCapabilityError int reason) {
- // This is not used for public interfaces
- }
-
- private void setExecutor(Executor executor) {
- mExecutor = executor;
+ // This is not used.
}
}
- private final CapabilityBinder mBinder = new CapabilityBinder(this);
+ private final CapabilityBinder mBinder;
- /**
- * The availability of the feature's capabilities has changed to either available or
- * unavailable.
- * <p>
- * If unavailable, the feature does not support the capability at the current time. This may
- * be due to network or subscription provisioning changes, such as the IMS registration
- * being lost, network type changing, or OMA-DM provisioning updates.
- *
- * @param capabilities The new availability of the capabilities.
- */
- public void onAvailabilityChanged(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) {
+ AvailabilityCallbackAdapter(@NonNull Executor executor,
+ @NonNull OnAvailabilityChangedListener listener) {
+ mBinder = new CapabilityBinder(listener, executor);
}
/**@hide*/
public final IImsCapabilityCallback getBinder() {
return mBinder;
}
-
- private void setExecutor(Executor executor) {
- mBinder.setExecutor(executor);
- }
}
private final int mSubId;
private final Context mContext;
private final BinderCacheManager<IImsRcsController> mBinderCache;
+ private final Map<OnAvailabilityChangedListener, AvailabilityCallbackAdapter>
+ mAvailabilityChangedCallbacks;
/**
* Use {@link ImsManager#getImsRcsManager(int)} to create an instance of this class.
@@ -162,6 +169,7 @@ public class ImsRcsManager {
mSubId = subId;
mContext = context;
mBinderCache = binderCache;
+ mAvailabilityChangedCallbacks = new HashMap<>();
}
/**
@@ -174,10 +182,23 @@ public class ImsRcsManager {
}
/**
- * @hide
+ * Registers a {@link RegistrationManager.RegistrationCallback} with the system. When the
+ * callback is registered, it will initiate the callback c to be called with the current
+ * registration state.
+ *
+ * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
+ * READ_PRECISE_PHONE_STATE} or that the calling app has carrier privileges
+ * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}).
+ *
+ * @param executor The executor the callback events should be run on.
+ * @param c The {@link RegistrationManager.RegistrationCallback} to be added.
+ * @see #unregisterImsRegistrationCallback(RegistrationManager.RegistrationCallback)
+ * @throws ImsException if the subscription associated with this callback is valid, but
+ * the {@link ImsService} associated with the subscription is not available. This can happen if
+ * the service crashed, for example. See {@link ImsException#getCode()} for a more detailed
+ * reason.
*/
- // @Override add back to RegistrationManager interface once public.
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
public void registerImsRegistrationCallback(
@NonNull @CallbackExecutor Executor executor,
@NonNull RegistrationManager.RegistrationCallback c)
@@ -191,7 +212,7 @@ public class ImsRcsManager {
IImsRcsController imsRcsController = getIImsRcsController();
if (imsRcsController == null) {
- Log.e(TAG, "Register registration callback: IImsRcsController is null");
+ Log.w(TAG, "Register registration callback: IImsRcsController is null");
throw new ImsException("Cannot find remote IMS service",
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
@@ -207,10 +228,21 @@ public class ImsRcsManager {
}
/**
- * @hide
+ * Removes an existing {@link RegistrationManager.RegistrationCallback}.
+ *
+ * When the subscription associated with this callback is removed (SIM removed, ESIM swap,
+ * etc...), this callback will automatically be removed. If this method is called for an
+ * inactive subscription, it will result in a no-op.
+ *
+ * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
+ * READ_PRECISE_PHONE_STATE} or that the calling app has carrier privileges
+ * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}).
+ *
+ * @param c The {@link RegistrationManager.RegistrationCallback} to be removed.
+ * @see android.telephony.SubscriptionManager.OnSubscriptionsChangedListener
+ * @see #registerImsRegistrationCallback(Executor, RegistrationCallback)
*/
- // @Override add back to RegistrationManager interface once public.
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
public void unregisterImsRegistrationCallback(
@NonNull RegistrationManager.RegistrationCallback c) {
if (c == null) {
@@ -219,7 +251,7 @@ public class ImsRcsManager {
IImsRcsController imsRcsController = getIImsRcsController();
if (imsRcsController == null) {
- Log.e(TAG, "Unregister registration callback: IImsRcsController is null");
+ Log.w(TAG, "Unregister registration callback: IImsRcsController is null");
throw new IllegalStateException("Cannot find remote IMS service");
}
@@ -231,10 +263,21 @@ public class ImsRcsManager {
}
/**
- * @hide
+ * Gets the registration state of the IMS service.
+ *
+ * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
+ * READ_PRECISE_PHONE_STATE} or that the calling app has carrier privileges
+ * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}).
+ *
+ * @param executor The {@link Executor} that will be used to call the IMS registration state
+ * callback.
+ * @param stateCallback A callback called on the supplied {@link Executor} that will contain the
+ * registration state of the IMS service, which will be one of the
+ * following: {@link RegistrationManager#REGISTRATION_STATE_NOT_REGISTERED},
+ * {@link RegistrationManager#REGISTRATION_STATE_REGISTERING}, or
+ * {@link RegistrationManager#REGISTRATION_STATE_REGISTERED}.
*/
- // @Override add back to RegistrationManager interface once public.
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
public void getRegistrationState(@NonNull @CallbackExecutor Executor executor,
@NonNull @RegistrationManager.ImsRegistrationState Consumer<Integer> stateCallback) {
if (stateCallback == null) {
@@ -246,7 +289,7 @@ public class ImsRcsManager {
IImsRcsController imsRcsController = getIImsRcsController();
if (imsRcsController == null) {
- Log.e(TAG, "Get registration state error: IImsRcsController is null");
+ Log.w(TAG, "Get registration state error: IImsRcsController is null");
throw new IllegalStateException("Cannot find remote IMS service");
}
@@ -263,9 +306,20 @@ public class ImsRcsManager {
}
/**
- * @hide
+ * Gets the Transport Type associated with the current IMS registration.
+ *
+ * Requires Permission: {@link android.Manifest.permission#READ_PRECISE_PHONE_STATE
+ * READ_PRECISE_PHONE_STATE} or that the calling app has carrier privileges
+ * (see {@link android.telephony.TelephonyManager#hasCarrierPrivileges}).
+ *
+ * @param executor The {@link Executor} that will be used to call the transportTypeCallback.
+ * @param transportTypeCallback The transport type associated with the current IMS registration,
+ * which will be one of following:
+ * {@see AccessNetworkConstants#TRANSPORT_TYPE_WWAN},
+ * {@see AccessNetworkConstants#TRANSPORT_TYPE_WLAN}, or
+ * {@see AccessNetworkConstants#TRANSPORT_TYPE_INVALID}.
*/
- @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
+ @RequiresPermission(Manifest.permission.READ_PRECISE_PHONE_STATE)
public void getRegistrationTransportType(@NonNull @CallbackExecutor Executor executor,
@NonNull @AccessNetworkConstants.TransportType
Consumer<Integer> transportTypeCallback) {
@@ -278,7 +332,7 @@ public class ImsRcsManager {
IImsRcsController imsRcsController = getIImsRcsController();
if (imsRcsController == null) {
- Log.e(TAG, "Get registration transport type error: IImsRcsController is null");
+ Log.w(TAG, "Get registration transport type error: IImsRcsController is null");
throw new IllegalStateException("Cannot find remote IMS service");
}
@@ -296,31 +350,33 @@ public class ImsRcsManager {
}
/**
- * Registers an {@link AvailabilityCallback} with the system, which will provide RCS
+ * Add an {@link OnAvailabilityChangedListener} with the system, which will provide RCS
* availability updates for the subscription specified.
*
* Use {@link SubscriptionManager.OnSubscriptionsChangedListener} to listen to
* subscription changed events and call
- * {@link #unregisterRcsAvailabilityCallback(AvailabilityCallback)} to clean up after a
- * subscription is removed.
+ * {@link #removeOnAvailabilityChangedListener(OnAvailabilityChangedListener)} to clean up
+ * after a subscription is removed.
* <p>
- * When the callback is registered, it will initiate the callback c to be called with the
- * current capabilities.
+ * When the listener is registered, it will initiate the callback listener to be called with
+ * the current capabilities.
*
* @param executor The executor the callback events should be run on.
- * @param c The RCS {@link AvailabilityCallback} to be registered.
- * @see #unregisterRcsAvailabilityCallback(AvailabilityCallback)
+ * @param listener The RCS {@link OnAvailabilityChangedListener} to be registered.
+ * @see #removeOnAvailabilityChangedListener(OnAvailabilityChangedListener)
* @throws ImsException if the subscription associated with this instance of
* {@link ImsRcsManager} is valid, but the ImsService associated with the subscription is not
* available. This can happen if the ImsService has crashed, for example, or if the subscription
* becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
* @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public void registerRcsAvailabilityCallback(@NonNull @CallbackExecutor Executor executor,
- @NonNull AvailabilityCallback c) throws ImsException {
- if (c == null) {
- throw new IllegalArgumentException("Must include a non-null AvailabilityCallback.");
+ public void addOnAvailabilityChangedListener(@NonNull @CallbackExecutor Executor executor,
+ @NonNull OnAvailabilityChangedListener listener) throws ImsException {
+ if (listener == null) {
+ throw new IllegalArgumentException("Must include a non-null"
+ + "OnAvailabilityChangedListener.");
}
if (executor == null) {
throw new IllegalArgumentException("Must include a non-null Executor.");
@@ -328,56 +384,61 @@ public class ImsRcsManager {
IImsRcsController imsRcsController = getIImsRcsController();
if (imsRcsController == null) {
- Log.e(TAG, "Register availability callback: IImsRcsController is null");
+ Log.w(TAG, "Add availability changed listener: IImsRcsController is null");
throw new ImsException("Cannot find remote IMS service",
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
- c.setExecutor(executor);
+ AvailabilityCallbackAdapter adapter =
+ addAvailabilityChangedListenerToCollection(executor, listener);
try {
- imsRcsController.registerRcsAvailabilityCallback(mSubId, c.getBinder());
-
+ imsRcsController.registerRcsAvailabilityCallback(mSubId, adapter.getBinder());
} catch (ServiceSpecificException e) {
throw new ImsException(e.toString(), e.errorCode);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling IImsRcsController#registerRcsAvailabilityCallback", e);
+ Log.w(TAG, "Error calling IImsRcsController#registerRcsAvailabilityCallback", e);
throw new ImsException("Remote IMS Service is not available",
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
- /**
- * Removes an existing RCS {@link AvailabilityCallback}.
+ /**
+ * Removes an existing RCS {@link OnAvailabilityChangedListener}.
* <p>
* When the subscription associated with this callback is removed (SIM removed, ESIM swap,
* etc...), this callback will automatically be unregistered. If this method is called for an
* inactive subscription, it will result in a no-op.
- * @param c The RCS {@link AvailabilityCallback} to be removed.
- * @see #registerRcsAvailabilityCallback(Executor, AvailabilityCallback)
+ * @param listener The RCS {@link OnAvailabilityChangedListener} to be removed.
+ * @see #addOnAvailabilityChangedListener(Executor, OnAvailabilityChangedListener)
* @throws ImsException if the IMS service is not available when calling this method.
* See {@link ImsException#getCode()} for more information on the error codes.
* @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public void unregisterRcsAvailabilityCallback(@NonNull AvailabilityCallback c)
- throws ImsException {
- if (c == null) {
- throw new IllegalArgumentException("Must include a non-null AvailabilityCallback.");
+ public void removeOnAvailabilityChangedListener(
+ @NonNull OnAvailabilityChangedListener listener) {
+ if (listener == null) {
+ throw new IllegalArgumentException("Must include a non-null"
+ + "OnAvailabilityChangedListener.");
}
IImsRcsController imsRcsController = getIImsRcsController();
if (imsRcsController == null) {
- Log.e(TAG, "Unregister availability callback: IImsRcsController is null");
- throw new ImsException("Cannot find remote IMS service",
- ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ Log.w(TAG, "Remove availability changed listener: IImsRcsController is null");
+ return;
+ }
+
+ AvailabilityCallbackAdapter callback =
+ removeAvailabilityChangedListenerFromCollection(listener);
+ if (callback == null) {
+ return;
}
try {
- imsRcsController.unregisterRcsAvailabilityCallback(mSubId, c.getBinder());
+ imsRcsController.unregisterRcsAvailabilityCallback(mSubId, callback.getBinder());
} catch (RemoteException e) {
- Log.e(TAG, "Error calling IImsRcsController#unregisterRcsAvailabilityCallback", e);
- throw new ImsException("Remote IMS Service is not available",
- ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ Log.w(TAG, "Error calling IImsRcsController#unregisterRcsAvailabilityCallback", e);
}
}
@@ -388,25 +449,24 @@ public class ImsRcsManager {
* RCS capabilities provided over-the-top by applications.
*
* @param capability The RCS capability to query.
- * @param radioTech The radio tech that this capability failed for, defined as
- * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE} or
- * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN}.
+ * @param radioTech The radio technology type that we are querying.
* @return true if the RCS capability is capable for this subscription, false otherwise. This
* does not necessarily mean that we are registered for IMS and the capability is available, but
* rather the subscription is capable of this service over IMS.
- * @see #isAvailable(int)
+ * @see #isAvailable(int, int)
* @see android.telephony.CarrierConfigManager#KEY_USE_RCS_PRESENCE_BOOL
* @see android.telephony.CarrierConfigManager.Ims#KEY_ENABLE_PRESENCE_CAPABILITY_EXCHANGE_BOOL
* @throws ImsException if the IMS service is not available when calling this method.
* See {@link ImsException#getCode()} for more information on the error codes.
* @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public boolean isCapable(@RcsUceAdapter.RcsImsCapabilityFlag int capability,
@ImsRegistrationImplBase.ImsRegistrationTech int radioTech) throws ImsException {
IImsRcsController imsRcsController = getIImsRcsController();
if (imsRcsController == null) {
- Log.e(TAG, "isCapable: IImsRcsController is null");
+ Log.w(TAG, "isCapable: IImsRcsController is null");
throw new ImsException("Cannot find remote IMS service",
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
@@ -414,7 +474,7 @@ public class ImsRcsManager {
try {
return imsRcsController.isCapable(mSubId, capability, radioTech);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling IImsRcsController#isCapable", e);
+ Log.w(TAG, "Error calling IImsRcsController#isCapable", e);
throw new ImsException("Remote IMS Service is not available",
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
@@ -427,6 +487,7 @@ public class ImsRcsManager {
* RCS capabilities provided by over-the-top by applications.
*
* @param capability the RCS capability to query.
+ * @param radioTech The radio technology type that we are querying.
* @return true if the RCS capability is currently available for the associated subscription,
* false otherwise. If the capability is available, IMS is registered and the service is
* currently available over IMS.
@@ -435,25 +496,57 @@ public class ImsRcsManager {
* See {@link ImsException#getCode()} for more information on the error codes.
* @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public boolean isAvailable(@RcsUceAdapter.RcsImsCapabilityFlag int capability)
+ public boolean isAvailable(@RcsUceAdapter.RcsImsCapabilityFlag int capability,
+ @ImsRegistrationImplBase.ImsRegistrationTech int radioTech)
throws ImsException {
IImsRcsController imsRcsController = getIImsRcsController();
if (imsRcsController == null) {
- Log.e(TAG, "isAvailable: IImsRcsController is null");
+ Log.w(TAG, "isAvailable: IImsRcsController is null");
throw new ImsException("Cannot find remote IMS service",
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
try {
- return imsRcsController.isAvailable(mSubId, capability);
+ return imsRcsController.isAvailable(mSubId, capability, radioTech);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling IImsRcsController#isAvailable", e);
+ Log.w(TAG, "Error calling IImsRcsController#isAvailable", e);
throw new ImsException("Remote IMS Service is not available",
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
+ /**
+ * Add the {@link OnAvailabilityChangedListener} to collection for tracking.
+ * @param executor The executor that will be used when the publish state is changed and the
+ * {@link OnAvailabilityChangedListener} is called.
+ * @param listener The {@link OnAvailabilityChangedListener} to call the publish state changed.
+ * @return The {@link AvailabilityCallbackAdapter} to wrapper the
+ * {@link OnAvailabilityChangedListener}
+ */
+ private AvailabilityCallbackAdapter addAvailabilityChangedListenerToCollection(
+ @NonNull Executor executor, @NonNull OnAvailabilityChangedListener listener) {
+ AvailabilityCallbackAdapter adapter = new AvailabilityCallbackAdapter(executor, listener);
+ synchronized (mAvailabilityChangedCallbacks) {
+ mAvailabilityChangedCallbacks.put(listener, adapter);
+ }
+ return adapter;
+ }
+
+ /**
+ * Remove the existing {@link OnAvailabilityChangedListener} from the collection.
+ * @param listener The {@link OnAvailabilityChangedListener} to remove from the collection.
+ * @return The wrapper class {@link AvailabilityCallbackAdapter} associated with the
+ * {@link OnAvailabilityChangedListener}.
+ */
+ private AvailabilityCallbackAdapter removeAvailabilityChangedListenerFromCollection(
+ @NonNull OnAvailabilityChangedListener listener) {
+ synchronized (mAvailabilityChangedCallbacks) {
+ return mAvailabilityChangedCallbacks.remove(listener);
+ }
+ }
+
private IImsRcsController getIImsRcsController() {
IBinder binder = TelephonyFrameworkInitializer
.getTelephonyServiceManager()
diff --git a/telephony/java/android/telephony/ims/ImsRegistrationAttributes.aidl b/telephony/java/android/telephony/ims/ImsRegistrationAttributes.aidl
new file mode 100644
index 000000000000..0830ff2ff050
--- /dev/null
+++ b/telephony/java/android/telephony/ims/ImsRegistrationAttributes.aidl
@@ -0,0 +1,19 @@
+/*
+ * Copyright (c) 2021 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 ImsRegistrationAttributes;
diff --git a/telephony/java/android/telephony/ims/ImsRegistrationAttributes.java b/telephony/java/android/telephony/ims/ImsRegistrationAttributes.java
new file mode 100644
index 000000000000..a36f54953e63
--- /dev/null
+++ b/telephony/java/android/telephony/ims/ImsRegistrationAttributes.java
@@ -0,0 +1,219 @@
+/*
+ * Copyright (C) 2021 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.annotation.Nullable;
+import android.annotation.SystemApi;
+import android.os.Parcel;
+import android.os.Parcelable;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.ims.stub.ImsRegistrationImplBase;
+import android.util.ArraySet;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Objects;
+import java.util.Set;
+
+/**
+ * Contains the attributes associated with the current IMS registration.
+ */
+public final class ImsRegistrationAttributes implements Parcelable {
+
+ /**
+ * Builder for creating {@link ImsRegistrationAttributes} instances.
+ * @hide
+ */
+ @SystemApi
+ public static final class Builder {
+ private final int mRegistrationTech;
+ private Set<String> mFeatureTags = Collections.emptySet();
+
+ /**
+ * Build a new instance of {@link ImsRegistrationAttributes}.
+ *
+ * @param registrationTech The Radio Access Technology that IMS is registered on.
+ */
+ public Builder(@ImsRegistrationImplBase.ImsRegistrationTech int registrationTech) {
+ mRegistrationTech = registrationTech;
+ }
+
+ /**
+ * Optional IMS feature tags included in this IMS registration.
+ * @param tags A set of Strings containing the MMTEL and RCS feature tags associated with
+ * the IMS registration. This information is used for services such as the UCE
+ * service to ascertain the complete IMS registration state to ensure the SIP
+ * PUBLISH is accurate. The format of the set of feature tags must be one feature
+ * tag key and value per entry. Each feature tag will contain the feature tag name
+ * and string value (if applicable), even if they have the same feature tag name.
+ * For example,
+ * {@code +g.3gpp.icsi-ref="urn%3Aurn-7%3A3gpp-service.ims.icsi.oma.cpm.msg,
+ * urn%3Aurn-7%3A3gpp-service.ims.icsi.oma.cpm.session", +g.gsma.callcomposer} must
+ * be split into three feature tag entries:
+ * {@code {+g.3gpp.icsi-ref="urn%3Aurn-7%3A3gpp-service.ims.icsi.oma.cpm.msg",
+ * +g.3gpp.icsi-ref="urn%3Aurn-7%3A3gpp-service.ims.icsi.oma.cpm.session",
+ * +g.gsma.callcomposer}}.
+ */
+ public @NonNull Builder setFeatureTags(@NonNull Set<String> tags) {
+ if (tags == null) {
+ throw new IllegalArgumentException("feature tag set must not be null");
+ }
+ mFeatureTags = new ArraySet<>(tags);
+ return this;
+ }
+
+ /**
+ * @return A new instance created from this builder.
+ */
+ public @NonNull ImsRegistrationAttributes build() {
+ return new ImsRegistrationAttributes(mRegistrationTech,
+ RegistrationManager.getAccessType(mRegistrationTech),
+ 0 /* No attributes in AOSP */, mFeatureTags);
+ }
+
+ }
+
+ private final int mRegistrationTech;
+ private final int mTransportType;
+ private final int mImsAttributeFlags;
+ private final ArrayList<String> mFeatureTags;
+
+ /**
+ * Create a new {@link ImsRegistrationAttributes} instance.
+ *
+ * @param registrationTech The technology that IMS has been registered on.
+ * @param transportType The transport type that IMS has been registered on.
+ * @param imsAttributeFlags The attributes associated with the IMS registration.
+ * @param featureTags The feature tags included in the IMS registration.
+ * @see Builder
+ * @hide
+ */
+ public ImsRegistrationAttributes(
+ @ImsRegistrationImplBase.ImsRegistrationTech int registrationTech,
+ @AccessNetworkConstants.TransportType int transportType,
+ int imsAttributeFlags,
+ @Nullable Set<String> featureTags) {
+ mRegistrationTech = registrationTech;
+ mTransportType = transportType;
+ mImsAttributeFlags = imsAttributeFlags;
+ mFeatureTags = new ArrayList<>(featureTags);
+ }
+
+ /**@hide*/
+ public ImsRegistrationAttributes(Parcel source) {
+ mRegistrationTech = source.readInt();
+ mTransportType = source.readInt();
+ mImsAttributeFlags = source.readInt();
+ mFeatureTags = new ArrayList<>();
+ source.readList(mFeatureTags, null /*classloader*/);
+ }
+
+ /**
+ * @return The Radio Access Technology that the IMS registration has been registered over.
+ * @hide
+ */
+ @SystemApi
+ public @ImsRegistrationImplBase.ImsRegistrationTech int getRegistrationTechnology() {
+ return mRegistrationTech;
+ }
+
+ /**
+ * @return The access network transport type that IMS has been registered over.
+ */
+ public @AccessNetworkConstants.TransportType int getTransportType() {
+ return mTransportType;
+ }
+
+ /**
+ * @return A bit-mask containing attributes associated with the IMS registration.
+ */
+ public int getAttributeFlags() {
+ return mImsAttributeFlags;
+ }
+
+ /**
+ * Gets the Set of feature tags associated with the current IMS registration, if the IMS
+ * service supports supplying this information.
+ * <p>
+ * The format of the set of feature tags will be one feature tag key and value per entry and
+ * will potentially contain MMTEL and RCS feature tags, depending the configuration of the IMS
+ * service associated with the registration indications. Each feature tag will contain the
+ * feature tag name and string value (if applicable), even if they have the same feature tag
+ * name. For example, {@code +g.3gpp.icsi-ref="urn%3Aurn-7%3A3gpp-service.ims.icsi.oma.cpm.msg,
+ * urn%3Aurn-7%3A3gpp-service.ims.icsi.oma.cpm.session", +g.gsma.callcomposer} will be split
+ * into three feature tag entries:
+ * {@code {+g.3gpp.icsi-ref="urn%3Aurn-7%3A3gpp-service.ims.icsi.oma.cpm.msg",
+ * +g.3gpp.icsi-ref="urn%3Aurn-7%3A3gpp-service.ims.icsi.oma.cpm.session",
+ * +g.gsma.callcomposer}}.
+ * @return The Set of feature tags associated with the current IMS registration.
+ */
+ public @NonNull Set<String> getFeatureTags() {
+ if (mFeatureTags == null) {
+ return Collections.emptySet();
+ }
+ return new ArraySet<>(mFeatureTags);
+ }
+
+ @Override
+ public int describeContents() {
+ return 0;
+ }
+
+ @Override
+ public void writeToParcel(@NonNull Parcel dest, int flags) {
+ dest.writeInt(mRegistrationTech);
+ dest.writeInt(mTransportType);
+ dest.writeInt(mImsAttributeFlags);
+ dest.writeList(mFeatureTags);
+ }
+
+ public static final @NonNull Creator<ImsRegistrationAttributes> CREATOR =
+ new Creator<ImsRegistrationAttributes>() {
+ @Override
+ public ImsRegistrationAttributes createFromParcel(Parcel source) {
+ return new ImsRegistrationAttributes(source);
+ }
+
+ @Override
+ public ImsRegistrationAttributes[] newArray(int size) {
+ return new ImsRegistrationAttributes[size];
+ }
+ };
+
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) return true;
+ if (o == null || getClass() != o.getClass()) return false;
+ ImsRegistrationAttributes that = (ImsRegistrationAttributes) o;
+ return mRegistrationTech == that.mRegistrationTech
+ && mTransportType == that.mTransportType
+ && mImsAttributeFlags == that.mImsAttributeFlags
+ && Objects.equals(mFeatureTags, that.mFeatureTags);
+ }
+
+ @Override
+ public int hashCode() {
+ return Objects.hash(mRegistrationTech, mTransportType, mImsAttributeFlags, mFeatureTags);
+ }
+
+ @Override
+ public String toString() {
+ return "ImsRegistrationAttributes { transportType= " + mTransportType + ", attributeFlags="
+ + mImsAttributeFlags + ", featureTags=[" + mFeatureTags + "]}";
+ }
+}
diff --git a/telephony/java/android/telephony/ims/ImsUtListener.java b/telephony/java/android/telephony/ims/ImsUtListener.java
index baa0576cdf13..754814facb71 100644
--- a/telephony/java/android/telephony/ims/ImsUtListener.java
+++ b/telephony/java/android/telephony/ims/ImsUtListener.java
@@ -178,4 +178,11 @@ public class ImsUtListener {
public ImsUtListener(IImsUtListener serviceInterface) {
mServiceInterface = serviceInterface;
}
+
+ /**
+ * @hide
+ */
+ public IImsUtListener getListenerInterface() {
+ return mServiceInterface;
+ }
}
diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java
index f3c38bcba98a..08eec29d5ac2 100644
--- a/telephony/java/android/telephony/ims/ProvisioningManager.java
+++ b/telephony/java/android/telephony/ims/ProvisioningManager.java
@@ -25,6 +25,7 @@ import android.annotation.SdkConstant;
import android.annotation.StringDef;
import android.annotation.SystemApi;
import android.annotation.WorkerThread;
+import android.content.pm.PackageManager;
import android.os.Binder;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
@@ -1325,7 +1326,7 @@ public class ProvisioningManager {
* the RCS VoLTE single registration feature. Only default messaging application may receive
* the intent.
*
- * <p>Contains {@link #EXTRA_SUBSCRIPTION_INDEX} to specify the subscription index for which
+ * <p>Contains {@link #EXTRA_SUBSCRIPTION_ID} to specify the subscription index for which
* the intent is valid. and {@link #EXTRA_STATUS} to specify RCS VoLTE single registration
* status.
*/
@@ -1371,7 +1372,7 @@ public class ProvisioningManager {
* provisioning is done using autoconfiguration, then these parameters shall be
* sent in the HTTP get request to fetch the RCS provisioning. RCS client
* configuration must be provided by the application before registering for the
- * provisioning status events {@link #registerRcsProvisioningChangedCallback()}
+ * provisioning status events {@link #registerRcsProvisioningChangedCallback}
* @param rcc RCS client configuration {@link RcsClientConfiguration}
*/
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
@@ -1387,13 +1388,15 @@ public class ProvisioningManager {
}
/**
- * Returns a flag to indicate if the device software and the carrier
- * have the capability to support RCS Volte single IMS registration.
- * @return true if this single registration is capable, false otherwise
+ * Returns a flag to indicate whether or not the device supports IMS single registration for
+ * MMTEL and RCS features as well as if the carrier has provisioned the feature.
+ * @return true if IMS single registration is capable at this time, or false otherwise
* @throws ImsException If the remote ImsService is not available for
* any reason or the subscription associated with this instance is no
* longer active. See {@link ImsException#getCode()} for more
* information.
+ * @see PackageManager#FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION for whether or not this
+ * device supports IMS single registration.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public boolean isRcsVolteSingleRegistrationCapable() throws ImsException {
@@ -1430,7 +1433,7 @@ public class ProvisioningManager {
* available. This can happen if the service crashed, for example.
* It shall also throw this exception when the RCS client parameters for the
* application are not valid. In that case application must set the client
- * params (See {@link #setRcsClientConfiguration()}) and re register the
+ * params (See {@link #setRcsClientConfiguration}) and re register the
* callback.
* See {@link ImsException#getCode()} for a more detailed reason.
*/
@@ -1458,9 +1461,9 @@ public class ProvisioningManager {
* will result in a no-op.
* @param callback The existing {@link RcsProvisioningCallback} to be
* removed.
- * @see #registerRcsProvisioningChangedCallback(RcsClientConfiguration,
- * Executor, RcsProvisioningCallback) @throws IllegalArgumentException
- * if the subscription associated with this callback is invalid.
+ * @see #registerRcsProvisioningChangedCallback
+ * @throws IllegalArgumentException if the subscription associated with this callback is
+ * invalid.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public void unregisterRcsProvisioningChangedCallback(
diff --git a/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java b/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java
index 519d0164b0d6..5eb75e762fc9 100644
--- a/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java
+++ b/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java
@@ -19,6 +19,7 @@ package android.telephony.ims;
import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.StringDef;
+import android.annotation.SystemApi;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
@@ -34,14 +35,135 @@ import java.util.List;
* network during a SUBSCRIBE request. See RFC3863 for more information.
* @hide
*/
+@SystemApi
public final class RcsContactPresenceTuple implements Parcelable {
- /** The service id of the MMTEL */
+ /**
+ * The service ID used to indicate that MMTEL service is available.
+ * <p>
+ * See the GSMA RCC.07 specification for more information.
+ */
public static final String SERVICE_ID_MMTEL = "org.3gpp.urn:urn-7:3gpp-service.ims.icsi.mmtel";
- /** The service id of the Call Composer */
+ /**
+ * The service ID used to indicate that the chat(v1.0) is available.
+ * <p>
+ * See the GSMA RCC.07 specification for more information.
+ */
+ public static final String SERVICE_ID_CHAT_V1 = "org.openmobilealliance:IM-session";
+
+ /**
+ * The service ID used to indicate that the chat(v2.0) is available.
+ * <p>
+ * See the GSMA RCC.07 specification for more information.
+ */
+ public static final String SERVICE_ID_CHAT_V2 = "org.openmobilealliance:ChatSession";
+
+ /**
+ * The service ID used to indicate that the File Transfer is available.
+ * <p>
+ * See the GSMA RCC.07 specification for more information.
+ */
+ public static final String SERVICE_ID_FT = "org.openmobilealliance:File-Transfer-HTTP";
+
+ /**
+ * The service ID used to indicate that the File Transfer over SMS is available.
+ * <p>
+ * See the GSMA RCC.07 specification for more information.
+ */
+ public static final String SERVICE_ID_FT_OVER_SMS =
+ "org.3gpp.urn:urn-7:3gpp-application.ims.iari.rcs.ftsms";
+
+ /**
+ * The service ID used to indicate that the Geolocation Push is available.
+ * <p>
+ * See the GSMA RCC.07 specification for more information.
+ */
+ public static final String SERVICE_ID_GEO_PUSH =
+ "org.3gpp.urn:urn-7:3gpp-application.ims.iari.rcs.geopush";
+
+ /**
+ * The service ID used to indicate that the Geolocation Push via SMS is available.
+ * <p>
+ * See the GSMA RCC.07 specification for more information.
+ */
+ public static final String SERVICE_ID_GEO_PUSH_VIA_SMS =
+ "org.3gpp.urn:urn-7:3gpp-application.ims.iari.rcs.geosms";
+
+ /**
+ * The service ID used to indicate that the Call Composer is available.
+ * <p>
+ * See the GSMA RCC.07 specification for more information.
+ */
public static final String SERVICE_ID_CALL_COMPOSER =
- "org.3gpp.urn:urn-7:3gppservice.ims.icsi.gsma.callcomposer";
+ "org.3gpp.urn:urn-7:3gpp-service.ims.icsi.gsma.callcomposer";
+
+ /**
+ * The service ID used to indicate that the Post Call is available.
+ * <p>
+ * See the GSMA RCC.07 specification for more information.
+ */
+ public static final String SERVICE_ID_POST_CALL =
+ "org.3gpp.urn:urn-7:3gpp-service.ims.icsi.gsma.callunanswered";
+
+ /**
+ * The service ID used to indicate that the Shared Map is available.
+ * <p>
+ * See the GSMA RCC.07 specification for more information.
+ */
+ public static final String SERVICE_ID_SHARED_MAP =
+ "org.3gpp.urn:urn-7:3gpp-service.ims.icsi.gsma.sharedmap";
+
+ /**
+ * The service ID used to indicate that the Shared Sketch is available.
+ * <p>
+ * See the GSMA RCC.07 specification for more information.
+ */
+ public static final String SERVICE_ID_SHARED_SKETCH =
+ "org.3gpp.urn:urn-7:3gpp-service.ims.icsi.gsma.sharedsketch";
+
+ /**
+ * The service ID used to indicate that the Chatbot using Session is available.
+ * <p>
+ * See the GSMA RCC.07 specification for more information.
+ */
+ public static final String SERVICE_ID_CHATBOT =
+ "org.3gpp.urn:urn-7:3gpp-application.ims.iari.rcs.chatbot";
+
+ /**
+ * The service ID used to indicate that the Standalone Messaging is available.
+ * <p>
+ * See the GSMA RCC.07 specification for more information.
+ */
+ public static final String SERVICE_ID_CHATBOT_STANDALONE =
+ " org.3gpp.urn:urn-7:3gpp-application.ims.iari.rcs.chatbot.sa";
+
+ /**
+ * The service ID used to indicate that the Chatbot Role is available.
+ * <p>
+ * See the GSMA RCC.07 specification for more information.
+ */
+ public static final String SERVICE_ID_CHATBOT_ROLE = "org.gsma.rcs.isbot";
+
+ /** @hide */
+ @Retention(RetentionPolicy.SOURCE)
+ @StringDef(prefix = "SERVICE_ID_", value = {
+ SERVICE_ID_MMTEL,
+ SERVICE_ID_CHAT_V1,
+ SERVICE_ID_CHAT_V2,
+ SERVICE_ID_FT,
+ SERVICE_ID_FT_OVER_SMS,
+ SERVICE_ID_GEO_PUSH,
+ SERVICE_ID_GEO_PUSH_VIA_SMS,
+ SERVICE_ID_CALL_COMPOSER,
+ SERVICE_ID_POST_CALL,
+ SERVICE_ID_SHARED_MAP,
+ SERVICE_ID_SHARED_SKETCH,
+ SERVICE_ID_CHATBOT,
+ SERVICE_ID_CHATBOT_STANDALONE,
+ SERVICE_ID_CHATBOT_ROLE
+ })
+ public @interface ServiceId {}
/** The service capabilities is available. */
public static final String TUPLE_BASIC_STATUS_OPEN = "open";
@@ -149,6 +271,7 @@ public final class RcsContactPresenceTuple implements Parcelable {
in.readStringList(mSupportedDuplexModeList);
in.readStringList(mUnsupportedDuplexModeList);
}
+
@Override
public void writeToParcel(@NonNull Parcel out, int flags) {
out.writeBoolean(mIsAudioCapable);
@@ -217,12 +340,14 @@ public final class RcsContactPresenceTuple implements Parcelable {
/**
* Builds a RcsContactPresenceTuple instance.
+ * @param status The status associated with the service capability. See RFC3865 for more
+ * information.
* @param serviceId The OMA Presence service-id associated with this capability. See the
* OMA Presence SIMPLE specification v1.1, section 10.5.1.
* @param serviceVersion The OMA Presence version associated with the service capability.
* See the OMA Presence SIMPLE specification v1.1, section 10.5.1.
*/
- public Builder(@NonNull @BasicStatus String status, @NonNull String serviceId,
+ public Builder(@NonNull @BasicStatus String status, @NonNull @ServiceId String serviceId,
@NonNull String serviceVersion) {
mPresenceTuple = new RcsContactPresenceTuple(status, serviceId, serviceVersion);
}
@@ -230,16 +355,17 @@ public final class RcsContactPresenceTuple implements Parcelable {
/**
* The optional SIP Contact URI associated with the PIDF tuple element.
*/
- public @NonNull Builder addContactUri(@NonNull Uri contactUri) {
+ public @NonNull Builder setContactUri(@NonNull Uri contactUri) {
mPresenceTuple.mContactUri = contactUri;
return this;
}
/**
* The optional timestamp indicating the data and time of the status change of this tuple.
- * See RFC3863, section 4.1.7 for more information on the expected format.
+ * Per RFC3863 section 4.1.7, the timestamp is formatted as an IMPP datetime format
+ * string per RFC3339.
*/
- public @NonNull Builder addTimeStamp(@NonNull String timestamp) {
+ public @NonNull Builder setTimestamp(@NonNull String timestamp) {
mPresenceTuple.mTimestamp = timestamp;
return this;
}
@@ -248,7 +374,7 @@ public final class RcsContactPresenceTuple implements Parcelable {
* An optional parameter containing the description element of the service-description. See
* OMA Presence SIMPLE specification v1.1
*/
- public @NonNull Builder addDescription(@NonNull String description) {
+ public @NonNull Builder setServiceDescription(@NonNull String description) {
mPresenceTuple.mServiceDescription = description;
return this;
}
@@ -257,7 +383,7 @@ public final class RcsContactPresenceTuple implements Parcelable {
* An optional parameter containing the service capabilities of the presence tuple if they
* are present in the servcaps element.
*/
- public @NonNull Builder addServiceCapabilities(@NonNull ServiceCapabilities caps) {
+ public @NonNull Builder setServiceCapabilities(@NonNull ServiceCapabilities caps) {
mPresenceTuple.mServiceCapabilities = caps;
return this;
}
diff --git a/telephony/java/android/telephony/ims/RcsContactUceCapability.java b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
index d4715bfeeb3e..fe855023f5d0 100644
--- a/telephony/java/android/telephony/ims/RcsContactUceCapability.java
+++ b/telephony/java/android/telephony/ims/RcsContactUceCapability.java
@@ -19,6 +19,7 @@ package android.telephony.ims;
import android.annotation.IntDef;
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.annotation.SystemApi;
import android.net.Uri;
import android.os.Parcel;
import android.os.Parcelable;
@@ -33,6 +34,7 @@ import java.util.List;
* Contains the User Capability Exchange capabilities corresponding to a contact's URI.
* @hide
*/
+@SystemApi
public final class RcsContactUceCapability implements Parcelable {
/** Contains presence information associated with the contact */
@@ -70,52 +72,46 @@ public final class RcsContactUceCapability implements Parcelable {
public @interface SourceType {}
/**
+ * Capability information for the requested contact has expired and can not be refreshed due to
+ * a temporary network error. This is a temporary error and the capabilities of the contact
+ * should be queried again at a later time.
+ */
+ public static final int REQUEST_RESULT_UNKNOWN = 0;
+
+ /**
* The requested contact was found to be offline when queried. This is only applicable to
* contact capabilities that were queried via OPTIONS requests and the network returned a
* 408/480 response.
*/
- public static final int REQUEST_RESULT_NOT_ONLINE = 0;
+ public static final int REQUEST_RESULT_NOT_ONLINE = 1;
/**
* Capability information for the requested contact was not found. The contact should not be
* considered an RCS user.
*/
- public static final int REQUEST_RESULT_NOT_FOUND = 1;
+ public static final int REQUEST_RESULT_NOT_FOUND = 2;
/**
* Capability information for the requested contact was found successfully.
*/
- public static final int REQUEST_RESULT_FOUND = 2;
-
- /**
- * Capability information for the requested contact has expired and can not be refreshed due to
- * a temporary network error. This is a temporary error and the capabilities of the contact
- * should be queried again at a later time.
- */
- public static final int REQUEST_RESULT_UNKNOWN = 3;
+ public static final int REQUEST_RESULT_FOUND = 3;
/** @hide */
@Retention(RetentionPolicy.SOURCE)
@IntDef(prefix = "REQUEST_RESULT_", value = {
+ REQUEST_RESULT_UNKNOWN,
REQUEST_RESULT_NOT_ONLINE,
REQUEST_RESULT_NOT_FOUND,
- REQUEST_RESULT_FOUND,
- REQUEST_RESULT_UNKNOWN
+ REQUEST_RESULT_FOUND
})
public @interface RequestResult {}
/**
- * The base class of {@link OptionsBuilder} and {@link PresenceBuilder}
- */
- public static abstract class RcsUcsCapabilityBuilder {
- public abstract @NonNull RcsContactUceCapability build();
- }
-
- /**
* Builder to help construct {@link RcsContactUceCapability} instances when capabilities were
* queried through SIP OPTIONS.
+ * @hide
*/
- public static class OptionsBuilder extends RcsUcsCapabilityBuilder {
+ public static final class OptionsBuilder {
private final RcsContactUceCapability mCapabilities;
@@ -162,7 +158,6 @@ public final class RcsContactUceCapability implements Parcelable {
/**
* @return the constructed instance.
*/
- @Override
public @NonNull RcsContactUceCapability build() {
return mCapabilities;
}
@@ -172,7 +167,7 @@ public final class RcsContactUceCapability implements Parcelable {
* Builder to help construct {@link RcsContactUceCapability} instances when capabilities were
* queried through a presence server.
*/
- public static class PresenceBuilder extends RcsUcsCapabilityBuilder {
+ public static final class PresenceBuilder {
private final RcsContactUceCapability mCapabilities;
@@ -214,7 +209,6 @@ public final class RcsContactUceCapability implements Parcelable {
/**
* @return the RcsContactUceCapability instance.
*/
- @Override
public @NonNull RcsContactUceCapability build() {
return mCapabilities;
}
@@ -284,6 +278,7 @@ public final class RcsContactUceCapability implements Parcelable {
* <p>
* Note: this is only populated if {@link #getCapabilityMechanism} is
* {@link RcsContactUceCapability#CAPABILITY_MECHANISM_OPTIONS}
+ * @hide
*/
public @NonNull List<String> getOptionsFeatureTags() {
if (mCapabilityMechanism != CAPABILITY_MECHANISM_OPTIONS) {
@@ -299,7 +294,7 @@ public final class RcsContactUceCapability implements Parcelable {
* Note: this is only populated if {@link #getCapabilityMechanism} is
* {@link RcsContactUceCapability#CAPABILITY_MECHANISM_PRESENCE}
*/
- public @NonNull List<RcsContactPresenceTuple> getPresenceTuples() {
+ public @NonNull List<RcsContactPresenceTuple> getCapabilityTuples() {
if (mCapabilityMechanism != CAPABILITY_MECHANISM_PRESENCE) {
return Collections.emptyList();
}
@@ -309,13 +304,14 @@ public final class RcsContactUceCapability implements Parcelable {
/**
* Get the RcsContactPresenceTuple associated with the given service id.
* @param serviceId The service id to get the presence tuple.
- * @return The RcsContactPresenceTuple which has the given service id.
+ * @return The RcsContactPresenceTuple which has the given service id or {@code null} if the
+ * service id does not exist in the list of presence tuples returned from the network.
*
* <p>
* Note: this is only populated if {@link #getCapabilityMechanism} is
* {@link RcsContactUceCapability#CAPABILITY_MECHANISM_PRESENCE}
*/
- public @Nullable RcsContactPresenceTuple getPresenceTuple(@NonNull String serviceId) {
+ public @Nullable RcsContactPresenceTuple getCapabilityTuple(@NonNull String serviceId) {
if (mCapabilityMechanism != CAPABILITY_MECHANISM_PRESENCE) {
return null;
}
diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java
index 6c31466c2a89..070fd799d6cc 100644
--- a/telephony/java/android/telephony/ims/RcsUceAdapter.java
+++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java
@@ -63,6 +63,7 @@ public class RcsUceAdapter {
* RcsFeature should not publish capabilities or service capability requests.
* @hide
*/
+ @SystemApi
public static final int CAPABILITY_TYPE_PRESENCE_UCE = 1 << 1;
/**@hide*/
@@ -77,12 +78,14 @@ public class RcsUceAdapter {
* An unknown error has caused the request to fail.
* @hide
*/
+ @SystemApi
public static final int ERROR_GENERIC_FAILURE = 1;
/**
* The carrier network does not have UCE support enabled for this subscriber.
* @hide
*/
+ @SystemApi
public static final int ERROR_NOT_ENABLED = 2;
/**
@@ -90,12 +93,14 @@ public class RcsUceAdapter {
* 1x only currently).
* @hide
*/
+ @SystemApi
public static final int ERROR_NOT_AVAILABLE = 3;
/**
* The network has responded with SIP 403 error and a reason "User not registered."
* @hide
*/
+ @SystemApi
public static final int ERROR_NOT_REGISTERED = 4;
/**
@@ -103,12 +108,14 @@ public class RcsUceAdapter {
* presence" for this subscriber.
* @hide
*/
+ @SystemApi
public static final int ERROR_NOT_AUTHORIZED = 5;
/**
* The network has responded to this request with a SIP 403 error and no reason.
* @hide
*/
+ @SystemApi
public static final int ERROR_FORBIDDEN = 6;
/**
@@ -116,6 +123,7 @@ public class RcsUceAdapter {
* subscriber to the carrier network.
* @hide
*/
+ @SystemApi
public static final int ERROR_NOT_FOUND = 7;
/**
@@ -123,6 +131,7 @@ public class RcsUceAdapter {
* with a lower number of contact numbers. The number varies per carrier.
* @hide
*/
+ @SystemApi
// TODO: Try to integrate this into the API so that the service will split based on carrier.
public static final int ERROR_REQUEST_TOO_LARGE = 8;
@@ -130,18 +139,21 @@ public class RcsUceAdapter {
* The network did not respond to the capabilities request before the request timed out.
* @hide
*/
+ @SystemApi
public static final int ERROR_REQUEST_TIMEOUT = 9;
/**
* The request failed due to the service having insufficient memory.
* @hide
*/
+ @SystemApi
public static final int ERROR_INSUFFICIENT_MEMORY = 10;
/**
* The network was lost while trying to complete the request.
* @hide
*/
+ @SystemApi
public static final int ERROR_LOST_NETWORK = 11;
/**
@@ -149,6 +161,7 @@ public class RcsUceAdapter {
* time returned in {@link CapabilitiesCallback#onError} has elapsed.
* @hide
*/
+ @SystemApi
public static final int ERROR_SERVER_UNAVAILABLE = 12;
/**@hide*/
@@ -405,6 +418,7 @@ public class RcsUceAdapter {
* @see #requestCapabilities(Executor, List, CapabilitiesCallback)
* @hide
*/
+ @SystemApi
public interface CapabilitiesCallback {
/**
@@ -424,10 +438,10 @@ public class RcsUceAdapter {
* 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.
- * @param retryAfterMilliseconds The time in milliseconds the requesting application should
+ * @param retryIntervalMillis The time in milliseconds the requesting application should
* wait before retrying, if non-zero.
*/
- void onError(@ErrorCode int errorCode, long retryAfterMilliseconds);
+ void onError(@ErrorCode int errorCode, long retryIntervalMillis);
}
private final Context mContext;
@@ -458,9 +472,9 @@ public class RcsUceAdapter {
* {@link RcsFeature.RcsImsCapabilities#CAPABILITY_TYPE_PRESENCE_UCE} is enabled or else
* this operation will fail with {@link #ERROR_NOT_AVAILABLE} or {@link #ERROR_NOT_ENABLED}.
*
+ * @param contactNumbers A list of numbers that the capabilities are being requested for.
* @param executor The executor that will be used when the request is completed and the
* {@link CapabilitiesCallback} is called.
- * @param contactNumbers A list of numbers that the capabilities are being requested for.
* @param c A one-time callback for when the request for capabilities completes or there is an
* error processing the request.
* @throws ImsException if the subscription associated with this instance of
@@ -469,9 +483,10 @@ public class RcsUceAdapter {
* becomes inactive. See {@link ImsException#getCode()} for more information on the error codes.
* @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
- public void requestCapabilities(@NonNull @CallbackExecutor Executor executor,
- @NonNull List<Uri> contactNumbers,
+ public void requestCapabilities(@NonNull List<Uri> contactNumbers,
+ @NonNull @CallbackExecutor Executor executor,
@NonNull CapabilitiesCallback c) throws ImsException {
if (c == null) {
throw new IllegalArgumentException("Must include a non-null CapabilitiesCallback.");
@@ -495,8 +510,7 @@ public class RcsUceAdapter {
public void onCapabilitiesReceived(List<RcsContactUceCapability> contactCapabilities) {
final long callingIdentity = Binder.clearCallingIdentity();
try {
- executor.execute(() ->
- c.onCapabilitiesReceived(contactCapabilities));
+ executor.execute(() -> c.onCapabilitiesReceived(contactCapabilities));
} finally {
restoreCallingIdentity(callingIdentity);
}
@@ -550,13 +564,17 @@ public class RcsUceAdapter {
* {@link #ERROR_NOT_AVAILABLE} or {@link #ERROR_NOT_ENABLED}.
*
* @param contactNumber The contact of the capabilities is being requested for.
+ * @param executor The executor that will be used when the request is completed and the
+ * {@link CapabilitiesCallback} is called.
* @param c A one-time callback for when the request for capabilities completes or there is
* an error processing the request.
* @hide
*/
+ @SystemApi
@RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE)
- public void requestNetworkAvailability(@NonNull @CallbackExecutor Executor executor,
- @NonNull Uri contactNumber, @NonNull CapabilitiesCallback c) throws ImsException {
+ public void requestAvailability(@NonNull Uri contactNumber,
+ @NonNull @CallbackExecutor Executor executor,
+ @NonNull CapabilitiesCallback c) throws ImsException {
if (executor == null) {
throw new IllegalArgumentException("Must include a non-null Executor.");
}
@@ -569,7 +587,7 @@ public class RcsUceAdapter {
IImsRcsController imsRcsController = getIImsRcsController();
if (imsRcsController == null) {
- Log.e(TAG, "requestNetworkAvailability: IImsRcsController is null");
+ Log.e(TAG, "requestAvailability: IImsRcsController is null");
throw new ImsException("Cannot find remote IMS service",
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
@@ -579,8 +597,7 @@ public class RcsUceAdapter {
public void onCapabilitiesReceived(List<RcsContactUceCapability> contactCapabilities) {
final long callingIdentity = Binder.clearCallingIdentity();
try {
- executor.execute(() ->
- c.onCapabilitiesReceived(contactCapabilities));
+ executor.execute(() -> c.onCapabilitiesReceived(contactCapabilities));
} finally {
restoreCallingIdentity(callingIdentity);
}
@@ -606,12 +623,12 @@ public class RcsUceAdapter {
};
try {
- imsRcsController.requestNetworkAvailability(mSubId, mContext.getOpPackageName(),
+ imsRcsController.requestAvailability(mSubId, mContext.getOpPackageName(),
mContext.getAttributionTag(), contactNumber, internalCallback);
} catch (ServiceSpecificException e) {
throw new ImsException(e.toString(), e.errorCode);
} catch (RemoteException e) {
- Log.e(TAG, "Error calling IImsRcsController#requestNetworkAvailability", e);
+ Log.e(TAG, "Error calling IImsRcsController#requestAvailability", e);
throw new ImsException("Remote IMS Service is not available",
ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
@@ -683,7 +700,7 @@ public class RcsUceAdapter {
if (imsRcsController == null) {
Log.e(TAG, "addOnPublishStateChangedListener : IImsRcsController is null");
throw new ImsException("Cannot find remote IMS service",
- ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
PublishStateCallbackAdapter stateCallback = addPublishStateCallback(executor, listener);
@@ -694,7 +711,7 @@ public class RcsUceAdapter {
} catch (RemoteException e) {
Log.e(TAG, "Error calling IImsRcsController#registerUcePublishStateCallback", e);
throw new ImsException("Remote IMS Service is not available",
- ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
diff --git a/telephony/java/android/telephony/ims/RegistrationManager.java b/telephony/java/android/telephony/ims/RegistrationManager.java
index 2c75368b86bf..c49121f4dc5d 100644
--- a/telephony/java/android/telephony/ims/RegistrationManager.java
+++ b/telephony/java/android/telephony/ims/RegistrationManager.java
@@ -71,7 +71,6 @@ public interface RegistrationManager {
*/
int REGISTRATION_STATE_REGISTERED = 2;
-
/**@hide*/
// Translate ImsRegistrationImplBase API to new AccessNetworkConstant because WLAN
// and WWAN are more accurate constants.
@@ -79,7 +78,8 @@ public interface RegistrationManager {
new HashMap<Integer, Integer>() {{
// Map NONE to -1 to make sure that we handle the REGISTRATION_TECH_NONE
// case, since it is defined.
- put(ImsRegistrationImplBase.REGISTRATION_TECH_NONE, -1);
+ put(ImsRegistrationImplBase.REGISTRATION_TECH_NONE,
+ AccessNetworkConstants.TRANSPORT_TYPE_INVALID);
put(ImsRegistrationImplBase.REGISTRATION_TECH_LTE,
AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
put(ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN,
@@ -103,6 +103,20 @@ public interface RegistrationManager {
}
/**
+ * @param regtech The registration technology.
+ * @return The Access Network type from registration technology.
+ * @hide
+ */
+ static int getAccessType(int regtech) {
+ if (!RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.containsKey(regtech)) {
+ Log.w("RegistrationManager", "getAccessType - invalid regType returned: "
+ + regtech);
+ return AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
+ }
+ return RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(regtech);
+ }
+
+ /**
* Callback class for receiving IMS network Registration callback events.
* @see #registerImsRegistrationCallback(Executor, RegistrationCallback)
* @see #unregisterImsRegistrationCallback(RegistrationCallback)
@@ -119,26 +133,24 @@ public interface RegistrationManager {
}
@Override
- public void onRegistered(int imsRadioTech) {
+ public void onRegistered(ImsRegistrationAttributes attr) {
if (mLocalCallback == null) return;
long callingIdentity = Binder.clearCallingIdentity();
try {
- mExecutor.execute(() ->
- mLocalCallback.onRegistered(getAccessType(imsRadioTech)));
+ mExecutor.execute(() -> mLocalCallback.onRegistered(attr));
} finally {
restoreCallingIdentity(callingIdentity);
}
}
@Override
- public void onRegistering(int imsRadioTech) {
+ public void onRegistering(ImsRegistrationAttributes attr) {
if (mLocalCallback == null) return;
long callingIdentity = Binder.clearCallingIdentity();
try {
- mExecutor.execute(() ->
- mLocalCallback.onRegistering(getAccessType(imsRadioTech)));
+ mExecutor.execute(() -> mLocalCallback.onRegistering(attr));
} finally {
restoreCallingIdentity(callingIdentity);
}
@@ -183,15 +195,6 @@ public interface RegistrationManager {
private void setExecutor(Executor executor) {
mExecutor = executor;
}
-
- private static int getAccessType(int regType) {
- if (!RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.containsKey(regType)) {
- Log.w("RegistrationManager", "RegistrationBinder - invalid regType returned: "
- + regType);
- return -1;
- }
- return RegistrationManager.IMS_REG_TO_ACCESS_TYPE_MAP.get(regType);
- }
}
private final RegistrationBinder mBinder = new RegistrationBinder(this);
@@ -200,19 +203,42 @@ public interface RegistrationManager {
* Notifies the framework when the IMS Provider is registered to the IMS network.
*
* @param imsTransportType the radio access technology.
+ * @deprecated Use {@link #onRegistered(ImsRegistrationAttributes)} instead.
*/
public void onRegistered(@AccessNetworkConstants.TransportType int imsTransportType) {
}
/**
+ * Notifies the framework when the IMS Provider is registered to the IMS network
+ * with corresponding attributes.
+ *
+ * @param attributes The attributes associated with this IMS registration.
+ */
+ public void onRegistered(@NonNull ImsRegistrationAttributes attributes) {
+ // Default impl to keep backwards compatibility with old implementations
+ onRegistered(attributes.getTransportType());
+ }
+
+ /**
* Notifies the framework when the IMS Provider is trying to register the IMS network.
*
* @param imsTransportType the radio access technology.
+ * @deprecated Use {@link #onRegistering(ImsRegistrationAttributes)} instead.
*/
public void onRegistering(@AccessNetworkConstants.TransportType int imsTransportType) {
}
/**
+ * Notifies the framework when the IMS Provider is trying to register the IMS network.
+ *
+ * @param attributes The attributes associated with this IMS registration.
+ */
+ public void onRegistering(@NonNull ImsRegistrationAttributes attributes) {
+ // Default impl to keep backwards compatibility with old implementations
+ onRegistering(attributes.getTransportType());
+ }
+
+ /**
* Notifies the framework when the IMS Provider is unregistered from the IMS network.
*
* @param info the {@link ImsReasonInfo} associated with why registration was disconnected.
@@ -298,10 +324,10 @@ public interface RegistrationManager {
* @param executor The {@link Executor} that will be used to call the IMS registration state
* callback.
* @param stateCallback A callback called on the supplied {@link Executor} that will contain the
- * registration state of the IMS service, which will be one of the
- * following: {@link #REGISTRATION_STATE_NOT_REGISTERED},
- * {@link #REGISTRATION_STATE_REGISTERING}, or
- * {@link #REGISTRATION_STATE_REGISTERED}.
+ * registration state of the IMS service, which will be one of the
+ * following: {@link #REGISTRATION_STATE_NOT_REGISTERED},
+ * {@link #REGISTRATION_STATE_REGISTERING}, or
+ * {@link #REGISTRATION_STATE_REGISTERED}.
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
void getRegistrationState(@NonNull @CallbackExecutor Executor executor,
diff --git a/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java b/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java
index eddbb1002f20..8762b6a712f2 100644
--- a/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java
+++ b/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java
@@ -280,6 +280,12 @@ public final class SipDelegateImsConfiguration implements Parcelable {
"sip_config_path_header_string";
/**
+ * The SIP User-Agent header value used by the IMS stack during IMS registration.
+ */
+ public static final String KEY_SIP_CONFIG_USER_AGENT_HEADER_STRING =
+ "sip_config_sip_user_agent_header_string";
+
+ /**
* SIP User part string in contact header
*/
public static final String KEY_SIP_CONFIG_URI_USER_PART_STRING =
@@ -292,12 +298,20 @@ public final class SipDelegateImsConfiguration implements Parcelable {
"sip_config_p_access_network_info_header_string";
/**
- * SIP P-last-access-network-info header string
+ * The SIP P-last-access-network-info header value, populated for networks that require this
+ * information to be provided in outgoing SIP messages.
*/
public static final String KEY_SIP_CONFIG_P_LAST_ACCESS_NETWORK_INFO_HEADER_STRING =
"sip_config_p_last_access_network_info_header_string";
/**
+ * The Cellular-Network-Info header value (See 3GPP 24.229, section 7.2.15), populated for
+ * networks that require this information to be provided as part of outgoing SIP messages.
+ */
+ public static final String KEY_SIP_CONFIG_CELLULAR_NETWORK_INFO_HEADER_STRING =
+ "sip_config_cellular_network_info_header_string";
+
+ /**
* SIP P-associated-uri header string
*/
public static final String KEY_SIP_CONFIG_P_ASSOCIATED_URI_HEADER_STRING =
@@ -320,9 +334,11 @@ public final class SipDelegateImsConfiguration implements Parcelable {
KEY_SIP_CONFIG_SERVICE_ROUTE_HEADER_STRING,
KEY_SIP_CONFIG_SECURITY_VERIFY_HEADER_STRING,
KEY_SIP_CONFIG_PATH_HEADER_STRING,
+ KEY_SIP_CONFIG_USER_AGENT_HEADER_STRING,
KEY_SIP_CONFIG_URI_USER_PART_STRING,
KEY_SIP_CONFIG_P_ACCESS_NETWORK_INFO_HEADER_STRING,
KEY_SIP_CONFIG_P_LAST_ACCESS_NETWORK_INFO_HEADER_STRING,
+ KEY_SIP_CONFIG_CELLULAR_NETWORK_INFO_HEADER_STRING,
KEY_SIP_CONFIG_P_ASSOCIATED_URI_HEADER_STRING
})
@Retention(RetentionPolicy.SOURCE)
diff --git a/telephony/java/android/telephony/ims/SipDelegateManager.java b/telephony/java/android/telephony/ims/SipDelegateManager.java
index 2e9eb94605a5..04421c9a2449 100644
--- a/telephony/java/android/telephony/ims/SipDelegateManager.java
+++ b/telephony/java/android/telephony/ims/SipDelegateManager.java
@@ -24,6 +24,7 @@ import android.annotation.Nullable;
import android.annotation.RequiresPermission;
import android.annotation.SystemApi;
import android.content.Context;
+import android.content.pm.PackageManager;
import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.telephony.BinderCacheManager;
@@ -47,6 +48,9 @@ import java.util.concurrent.Executor;
* This allows multiple IMS applications to forward SIP messages to/from their application for the
* purposes of providing a single IMS registration to the carrier's IMS network from potentially
* many IMS stacks implementing a subset of the supported MMTEL/RCS features.
+ * <p>
+ * This API is only supported if the device supports the
+ * {@link PackageManager#FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION} feature.
* @hide
*/
@SystemApi
@@ -269,6 +273,7 @@ public class SipDelegateManager {
* {@link ImsException#getCode()} for more information.
*
* @see CarrierConfigManager.Ims#KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL
+ * @see PackageManager#FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION
*/
@RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE)
public boolean isSupported() throws ImsException {
diff --git a/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java
index 4435640e008c..a217d1321342 100644
--- a/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java
+++ b/telephony/java/android/telephony/ims/aidl/CapabilityExchangeAidlWrapper.java
@@ -21,6 +21,7 @@ import android.annotation.Nullable;
import android.net.Uri;
import android.os.Binder;
import android.os.RemoteException;
+import android.telephony.ims.ImsException;
import android.telephony.ims.RcsContactUceCapability;
import android.telephony.ims.stub.CapabilityExchangeEventListener;
import android.util.Log;
@@ -47,7 +48,7 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis
* Receives the request of publishing capabilities from the network and deliver this request
* to the framework via the registered capability exchange event listener.
*/
- public void onRequestPublishCapabilities(int publishTriggerType) {
+ public void onRequestPublishCapabilities(int publishTriggerType) throws ImsException {
ICapabilityExchangeEventListener listener = mListenerBinder;
if (listener == null) {
return;
@@ -56,13 +57,15 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis
listener.onRequestPublishCapabilities(publishTriggerType);
} catch (RemoteException e) {
Log.w(LOG_TAG, "request publish capabilities exception: " + e);
+ throw new ImsException("Remote is not available",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
/**
* Receives the unpublish notification and deliver this callback to the framework.
*/
- public void onUnpublish() {
+ public void onUnpublish() throws ImsException {
ICapabilityExchangeEventListener listener = mListenerBinder;
if (listener == null) {
return;
@@ -71,6 +74,8 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis
listener.onUnpublish();
} catch (RemoteException e) {
Log.w(LOG_TAG, "Unpublish exception: " + e);
+ throw new ImsException("Remote is not available",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
@@ -79,7 +84,8 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis
* request to the framework.
*/
public void onRemoteCapabilityRequest(@NonNull Uri contactUri,
- @NonNull List<String> remoteCapabilities, @NonNull OptionsRequestCallback callback) {
+ @NonNull List<String> remoteCapabilities, @NonNull OptionsRequestCallback callback)
+ throws ImsException {
ICapabilityExchangeEventListener listener = mListenerBinder;
if (listener == null) {
return;
@@ -87,10 +93,11 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis
IOptionsRequestCallback internalCallback = new IOptionsRequestCallback.Stub() {
@Override
- public void respondToCapabilityRequest(RcsContactUceCapability ownCapabilities) {
+ public void respondToCapabilityRequest(RcsContactUceCapability ownCapabilities,
+ boolean isBlocked) {
final long callingIdentity = Binder.clearCallingIdentity();
try {
- callback.onRespondToCapabilityRequest(ownCapabilities);
+ callback.onRespondToCapabilityRequest(ownCapabilities, isBlocked);
} finally {
restoreCallingIdentity(callingIdentity);
}
@@ -110,6 +117,8 @@ public class CapabilityExchangeAidlWrapper implements CapabilityExchangeEventLis
listener.onRemoteCapabilityRequest(contactUri, remoteCapabilities, internalCallback);
} catch (RemoteException e) {
Log.w(LOG_TAG, "Remote capability request exception: " + e);
+ throw new ImsException("Remote is not available",
+ ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
}
diff --git a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
index 36349895c35b..8931a78709ed 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRcsController.aidl
@@ -47,12 +47,12 @@ interface IImsRcsController {
void registerRcsAvailabilityCallback(int subId, IImsCapabilityCallback c);
void unregisterRcsAvailabilityCallback(int subId, IImsCapabilityCallback c);
boolean isCapable(int subId, int capability, int radioTech);
- boolean isAvailable(int subId, int capability);
+ boolean isAvailable(int subId, int capability, int radioTech);
// ImsUceAdapter specific
void requestCapabilities(int subId, String callingPackage, String callingFeatureId,
in List<Uri> contactNumbers, IRcsUceControllerCallback c);
- void requestNetworkAvailability(int subId, String callingPackage,
+ void requestAvailability(int subId, String callingPackage,
String callingFeatureId, in Uri contactNumber,
IRcsUceControllerCallback c);
int getUcePublishState(int subId);
diff --git a/telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl b/telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl
index 749b1916962e..179407c983e5 100644
--- a/telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IImsRegistrationCallback.aidl
@@ -21,6 +21,7 @@ import android.net.Uri;
import android.telephony.ims.stub.ImsFeatureConfiguration;
import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsRegistrationAttributes;
/**
* See {@link ImsManager#RegistrationCallback} for more information.
@@ -28,8 +29,8 @@ import android.telephony.ims.ImsReasonInfo;
* {@hide}
*/
oneway interface IImsRegistrationCallback {
- void onRegistered(int imsRadioTech);
- void onRegistering(int imsRadioTech);
+ void onRegistered(in ImsRegistrationAttributes attr);
+ void onRegistering(in ImsRegistrationAttributes attr);
void onDeregistered(in ImsReasonInfo info);
void onTechnologyChangeFailed(int imsRadioTech, in ImsReasonInfo info);
void onSubscriberAssociatedUriChanged(in Uri[] uris);
diff --git a/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl b/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl
index d4d5301f38fa..8eecbca7e6a7 100644
--- a/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IOptionsRequestCallback.aidl
@@ -27,8 +27,9 @@ 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.
+ * @param isBlocked True if the user has blocked the number sending this request.
*/
- void respondToCapabilityRequest(in RcsContactUceCapability ownCapabilities);
+ void respondToCapabilityRequest(in RcsContactUceCapability ownCapabilities, boolean isBlocked);
/**
* Respond to a remote capability request from the contact specified with the
diff --git a/telephony/java/android/telephony/ims/aidl/IPublishResponseCallback.aidl b/telephony/java/android/telephony/ims/aidl/IPublishResponseCallback.aidl
index 481e7f8b37b9..b99d8a7d6d38 100644
--- a/telephony/java/android/telephony/ims/aidl/IPublishResponseCallback.aidl
+++ b/telephony/java/android/telephony/ims/aidl/IPublishResponseCallback.aidl
@@ -26,4 +26,5 @@ import java.util.List;
oneway interface IPublishResponseCallback {
void onCommandError(int code);
void onNetworkResponse(int code, String reason);
+ void onNetworkRespHeader(int code, String reasonPhrase, int reasonHeaderCause, String reasonHeaderText);
}
diff --git a/telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl b/telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl
index a14199365b07..8cc8020df29a 100644
--- a/telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl
+++ b/telephony/java/android/telephony/ims/aidl/ISubscribeResponseCallback.aidl
@@ -30,6 +30,7 @@ import java.util.Map;
oneway interface ISubscribeResponseCallback {
void onCommandError(int code);
void onNetworkResponse(int code, in String reason);
+ void onNetworkRespHeader(int code, String reasonPhrase, int reasonHeaderCause, String reasonHeaderText);
void onNotifyCapabilitiesUpdate(in List<String> pidfXmls);
void onResourceTerminated(in List<RcsContactTerminatedReason> uriTerminatedReason);
void onTerminated(in String reason, long retryAfterMilliseconds);
diff --git a/telephony/java/android/telephony/ims/aidl/RcsPublishResponseAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/RcsPublishResponseAidlWrapper.java
index 22985d0cf85c..65415ea441b5 100644
--- a/telephony/java/android/telephony/ims/aidl/RcsPublishResponseAidlWrapper.java
+++ b/telephony/java/android/telephony/ims/aidl/RcsPublishResponseAidlWrapper.java
@@ -34,10 +34,11 @@ public class RcsPublishResponseAidlWrapper implements PublishResponseCallback {
}
@Override
- public void onCommandError(int code) {
+ public void onCommandError(int code) throws ImsException {
try {
mResponseBinder.onCommandError(code);
} catch (RemoteException e) {
+ throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
@@ -46,6 +47,18 @@ public class RcsPublishResponseAidlWrapper implements PublishResponseCallback {
try {
mResponseBinder.onNetworkResponse(code, reason);
} catch (RemoteException e) {
+ throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+ }
+
+ @Override
+ public void onNetworkResponse(int code, String reasonPhrase, int reasonHeaderCause,
+ String reasonHeaderText) throws ImsException {
+ try {
+ mResponseBinder.onNetworkRespHeader(code, reasonPhrase, reasonHeaderCause,
+ reasonHeaderText);
+ } catch (RemoteException e) {
+ throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
}
diff --git a/telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java
index 1fb339c0cf89..11118c0617c2 100644
--- a/telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java
+++ b/telephony/java/android/telephony/ims/aidl/RcsSubscribeResponseAidlWrapper.java
@@ -40,10 +40,11 @@ public class RcsSubscribeResponseAidlWrapper implements SubscribeResponseCallbac
}
@Override
- public void onCommandError(int code) {
+ public void onCommandError(int code) throws ImsException {
try {
mResponseBinder.onCommandError(code);
} catch (RemoteException e) {
+ throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
@@ -52,6 +53,18 @@ public class RcsSubscribeResponseAidlWrapper implements SubscribeResponseCallbac
try {
mResponseBinder.onNetworkResponse(code, reason);
} catch (RemoteException e) {
+ throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
+ }
+ }
+
+ @Override
+ public void onNetworkResponse(int code, String reasonPhrase, int reasonHeaderCause,
+ String reasonHeaderText) throws ImsException {
+ try {
+ mResponseBinder.onNetworkRespHeader(code, reasonPhrase, reasonHeaderCause,
+ reasonHeaderText);
+ } catch (RemoteException e) {
+ throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
@@ -60,6 +73,7 @@ public class RcsSubscribeResponseAidlWrapper implements SubscribeResponseCallbac
try {
mResponseBinder.onNotifyCapabilitiesUpdate(pidfXmls);
} catch (RemoteException e) {
+ throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
@@ -69,6 +83,7 @@ public class RcsSubscribeResponseAidlWrapper implements SubscribeResponseCallbac
try {
mResponseBinder.onResourceTerminated(getTerminatedReasonList(uriTerminatedReason));
} catch (RemoteException e) {
+ throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
@@ -90,6 +105,7 @@ public class RcsSubscribeResponseAidlWrapper implements SubscribeResponseCallbac
try {
mResponseBinder.onTerminated(reason, retryAfterMilliseconds);
} catch (RemoteException e) {
+ throw new ImsException(e.getMessage(), ImsException.CODE_ERROR_SERVICE_UNAVAILABLE);
}
}
}
diff --git a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
index 87a6873d00b2..47c56e13f829 100644
--- a/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
+++ b/telephony/java/android/telephony/ims/feature/CapabilityChangeRequest.java
@@ -36,12 +36,9 @@ import java.util.Set;
public final class CapabilityChangeRequest implements Parcelable {
/**
- * Contains a feature capability, defined as
- * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE},
- * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO},
- * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT}, or
- * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS},
- * along with an associated technology, defined as
+ * Contains a MMTEL feature capability {@link MmTelFeature.MmTelCapabilities} and RCS feature
+ * capability {@link RcsFeature.RcsImsCapabilities}, along with an associated technology,
+ * defined as
* {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE} or
* {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN}
*/
@@ -49,7 +46,7 @@ public final class CapabilityChangeRequest implements Parcelable {
private final int mCapability;
private final int radioTech;
- public CapabilityPair(@MmTelFeature.MmTelCapabilities.MmTelCapability int capability,
+ public CapabilityPair(int capability,
@ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
this.mCapability = capability;
this.radioTech = radioTech;
@@ -80,13 +77,10 @@ public final class CapabilityChangeRequest implements Parcelable {
}
/**
- * @return The stored capability, defined as
- * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE},
- * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO},
- * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT}, or
- * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS}
+ * @return The stored capability, defined as {@link MmTelFeature.MmTelCapabilities} and
+ * {@link RcsFeature.RcsImsCapabilities}
*/
- public @MmTelFeature.MmTelCapabilities.MmTelCapability int getCapability() {
+ public int getCapability() {
return mCapability;
}
@@ -123,12 +117,11 @@ public final class CapabilityChangeRequest implements Parcelable {
* Add one or many capabilities to the request to be enabled.
*
* @param capabilities A bitfield of capabilities to enable, valid values are defined in
- * {@link MmTelFeature.MmTelCapabilities.MmTelCapability}.
+ * {@link MmTelFeature.MmTelCapabilities} and {@link RcsFeature.RcsImsCapabilities}.
* @param radioTech the radio tech that these capabilities should be enabled for, valid
* values are in {@link ImsRegistrationImplBase.ImsRegistrationTech}.
*/
- public void addCapabilitiesToEnableForTech(
- @MmTelFeature.MmTelCapabilities.MmTelCapability int capabilities,
+ public void addCapabilitiesToEnableForTech(int capabilities,
@ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
addAllCapabilities(mCapabilitiesToEnable, capabilities, radioTech);
}
@@ -136,12 +129,11 @@ public final class CapabilityChangeRequest implements Parcelable {
/**
* Add one or many capabilities to the request to be disabled.
* @param capabilities A bitfield of capabilities to diable, valid values are defined in
- * {@link MmTelFeature.MmTelCapabilities.MmTelCapability}.
+ * {@link MmTelFeature.MmTelCapabilities} and {@link RcsFeature.RcsImsCapabilities}.
* @param radioTech the radio tech that these capabilities should be disabled for, valid
* values are in {@link ImsRegistrationImplBase.ImsRegistrationTech}.
*/
- public void addCapabilitiesToDisableForTech(
- @MmTelFeature.MmTelCapabilities.MmTelCapability int capabilities,
+ public void addCapabilitiesToDisableForTech(int capabilities,
@ImsRegistrationImplBase.ImsRegistrationTech int radioTech) {
addAllCapabilities(mCapabilitiesToDisable, capabilities, radioTech);
}
diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java
index 22df921c4214..85703f8de5e5 100644
--- a/telephony/java/android/telephony/ims/feature/RcsFeature.java
+++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java
@@ -194,7 +194,6 @@ public class RcsFeature extends ImsFeature {
* of the capability and notify the capability status as true using
* {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. This will signal to the
* framework that the capability is available for usage.
- * @hide
*/
public static class RcsImsCapabilities extends Capabilities {
/** @hide*/
@@ -226,12 +225,21 @@ public class RcsFeature extends ImsFeature {
*/
public static final int CAPABILITY_TYPE_PRESENCE_UCE = 1 << 1;
+ /**
+ * Create a new {@link RcsImsCapabilities} instance with the provided capabilities.
+ * @param capabilities The capabilities that are supported for RCS in the form of a
+ * bitfield.
+ */
public RcsImsCapabilities(@RcsUceAdapter.RcsImsCapabilityFlag int capabilities) {
super(capabilities);
}
- private RcsImsCapabilities(Capabilities c) {
- super(c.getMask());
+ /**
+ * Create a new {@link RcsImsCapabilities} instance with the provided capabilities.
+ * @param capabilities The capabilities instance that are supported for RCS
+ */
+ private RcsImsCapabilities(Capabilities capabilities) {
+ super(capabilities.getMask());
}
@Override
@@ -307,7 +315,7 @@ public class RcsFeature extends ImsFeature {
* set, the {@link RcsFeature} has brought up the capability and is ready for framework
* requests. To change the status of the capabilities
* {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)} should be called.
- * @hide
+ * @return A copy of the current RcsFeature capability status.
*/
@Override
public @NonNull final RcsImsCapabilities queryCapabilityStatus() {
@@ -318,13 +326,13 @@ public class RcsFeature extends ImsFeature {
* Notify the framework that the capabilities status has changed. If a capability is enabled,
* this signals to the framework that the capability has been initialized and is ready.
* Call {@link #queryCapabilityStatus()} to return the current capability status.
- * @hide
+ * @param capabilities The current capability status of the RcsFeature.
*/
- public final void notifyCapabilitiesStatusChanged(@NonNull RcsImsCapabilities c) {
- if (c == null) {
+ public final void notifyCapabilitiesStatusChanged(@NonNull RcsImsCapabilities capabilities) {
+ if (capabilities == null) {
throw new IllegalArgumentException("RcsImsCapabilities must be non-null!");
}
- super.notifyCapabilitiesStatusChanged(c);
+ super.notifyCapabilitiesStatusChanged(capabilities);
}
/**
@@ -333,7 +341,9 @@ public class RcsFeature extends ImsFeature {
* {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)} to
* enable or disable capability A, this method should return the correct configuration for
* capability A afterwards (until it has changed).
- * @hide
+ * @param capability The capability that we are querying the configuration for.
+ * @param radioTech The radio technology type that we are querying.
+ * @return true if the capability is enabled, false otherwise.
*/
public boolean queryCapabilityConfiguration(
@RcsUceAdapter.RcsImsCapabilityFlag int capability,
@@ -355,11 +365,12 @@ public class RcsFeature extends ImsFeature {
* If for some reason one or more of these capabilities can not be enabled/disabled,
* {@link CapabilityCallbackProxy#onChangeCapabilityConfigurationError(int, int, int)} should
* be called for each capability change that resulted in an error.
- * @hide
+ * @param request The request to change the capability.
+ * @param callback To notify the framework that the result of the capability changes.
*/
@Override
public void changeEnabledCapabilities(@NonNull CapabilityChangeRequest request,
- @NonNull CapabilityCallbackProxy c) {
+ @NonNull CapabilityCallbackProxy callback) {
// Base Implementation - Override to provide functionality
}
diff --git a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
index d9734a7475c0..4967e5da7c9a 100644
--- a/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
+++ b/telephony/java/android/telephony/ims/stub/CapabilityExchangeEventListener.java
@@ -16,32 +16,58 @@
package android.telephony.ims.stub;
+import android.annotation.IntRange;
import android.annotation.NonNull;
import android.annotation.SystemApi;
+import android.net.Uri;
import android.telephony.ims.ImsException;
import android.telephony.ims.RcsContactUceCapability;
import android.telephony.ims.RcsUceAdapter;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.RcsFeature;
+import android.util.Log;
+
+import java.util.List;
/**
- * The interface of the capabilities event listener for ImsService to notify the framework of the
- * UCE request and status updated.
+ * The interface that is used by the framework to listen to events from the vendor RCS stack
+ * regarding capabilities exchange using presence server and OPTIONS.
* @hide
*/
@SystemApi
public interface CapabilityExchangeEventListener {
/**
* Interface used by the framework to respond to OPTIONS requests.
- * @hide
*/
interface OptionsRequestCallback {
/**
* Respond to a remote capability request from the contact specified with the
* capabilities of this device.
* @param ownCapabilities The capabilities of this device.
+ * @hide
*/
- void onRespondToCapabilityRequest(@NonNull RcsContactUceCapability ownCapabilities);
+ default void onRespondToCapabilityRequest(
+ @NonNull RcsContactUceCapability ownCapabilities) {}
+
+ /**
+ * Respond to a remote capability request from the contact specified with the
+ * capabilities of this device.
+ * @param ownCapabilities The capabilities of this device.
+ * @param isBlocked Whether or not the user has blocked the number requesting the
+ * capabilities of this device. If true, the device should respond to the OPTIONS
+ * request with a 200 OK response and no capabilities.
+ */
+ default void onRespondToCapabilityRequest(@NonNull RcsContactUceCapability ownCapabilities,
+ boolean isBlocked) {
+ Log.w("CapabilityExchangeEventListener", "implement "
+ + "onRespondToCapabilityRequest(RcsContactUceCapability, boolean) instead!");
+ // Fall back to old implementation
+ if (isBlocked) {
+ onRespondToCapabilityRequestWithError(200, "OK");
+ } else {
+ onRespondToCapabilityRequest(ownCapabilities);
+ }
+ }
/**
* Respond to a remote capability request from the contact specified with the
@@ -49,7 +75,8 @@ public interface CapabilityExchangeEventListener {
* @param code The SIP response code to respond with.
* @param reason A non-null String containing the reason associated with the SIP code.
*/
- void onRespondToCapabilityRequestWithError(int code, @NonNull String reason);
+ void onRespondToCapabilityRequestWithError(@IntRange(from = 100, to = 699) int code,
+ @NonNull String reason);
}
/**
@@ -59,8 +86,7 @@ public interface CapabilityExchangeEventListener {
* This is typically used when trying to generate an initial PUBLISH for a new subscription to
* the network. The device will cache all presence publications after boot until this method is
* called the first time.
- * @param publishTriggerType {@link RcsUceAdapter#StackPublishTriggerType} The reason for the
- * capability update request.
+ * @param publishTriggerType The reason for the capability update request.
* @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is not currently
* connected to the framework. This can happen if the {@link RcsFeature} is not
* {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received the
@@ -81,4 +107,25 @@ public interface CapabilityExchangeEventListener {
* Telephony stack has crashed.
*/
void onUnpublish() throws ImsException;
+
+ /**
+ * Inform the framework of an OPTIONS query from a remote device for this device's UCE
+ * capabilities.
+ * <p>
+ * The framework will respond via the
+ * {@link OptionsRequestCallback#onRespondToCapabilityRequest} or
+ * {@link OptionsRequestCallback#onRespondToCapabilityRequestWithError}.
+ * @param contactUri The URI associated with the remote contact that is
+ * requesting capabilities.
+ * @param remoteCapabilities The remote contact's capability information.
+ * @param callback The callback of this request which is sent from the remote user.
+ * @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is not
+ * currently connected to the framework. This can happen if the {@link RcsFeature} is not
+ * {@link ImsFeature#STATE_READY} and the {@link RcsFeature} has not received
+ * the {@link ImsFeature#onFeatureReady()} callback. This may also happen in rare
+ * cases when the Telephony stack has crashed.
+ */
+ void onRemoteCapabilityRequest(@NonNull Uri contactUri,
+ @NonNull List<String> remoteCapabilities,
+ @NonNull OptionsRequestCallback callback) throws ImsException;
}
diff --git a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
index 06c35eaec6dd..5f8e93d02a00 100644
--- a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java
@@ -23,6 +23,8 @@ import android.util.Log;
import com.android.ims.internal.IImsEcbm;
import com.android.ims.internal.IImsEcbmListener;
+import java.util.Objects;
+
/**
* Base implementation of ImsEcbm, which implements stub versions of the methods
* in the IImsEcbm AIDL. Override the methods that your implementation of ImsEcbm supports.
@@ -36,11 +38,31 @@ import com.android.ims.internal.IImsEcbmListener;
public class ImsEcbmImplBase {
private static final String TAG = "ImsEcbmImplBase";
+ private final Object mLock = new Object();
private IImsEcbmListener mListener;
- private IImsEcbm mImsEcbm = new IImsEcbm.Stub() {
+ private final IImsEcbm mImsEcbm = new IImsEcbm.Stub() {
@Override
public void setListener(IImsEcbmListener listener) {
- mListener = listener;
+ synchronized (mLock) {
+ if (mListener != null && !mListener.asBinder().isBinderAlive()) {
+ Log.w(TAG, "setListener: discarding dead Binder");
+ mListener = null;
+ }
+ if (mListener != null && listener != null && Objects.equals(
+ mListener.asBinder(), listener.asBinder())) {
+ return;
+ }
+ if (listener == null) {
+ mListener = null;
+ } else if (listener != null && mListener == null) {
+ mListener = listener;
+ } else {
+ // Fail fast here instead of silently overwriting the listener to another
+ // listener due to another connection connecting.
+ throw new IllegalStateException("ImsEcbmImplBase: Listener already set by "
+ + "another connection.");
+ }
+ }
}
@Override
@@ -69,9 +91,13 @@ public class ImsEcbmImplBase {
*/
public final void enteredEcbm() {
Log.d(TAG, "Entered ECBM.");
- if (mListener != null) {
+ IImsEcbmListener listener;
+ synchronized (mLock) {
+ listener = mListener;
+ }
+ if (listener != null) {
try {
- mListener.enteredECBM();
+ listener.enteredECBM();
} catch (RemoteException e) {
throw new RuntimeException(e);
}
@@ -85,9 +111,13 @@ public class ImsEcbmImplBase {
*/
public final void exitedEcbm() {
Log.d(TAG, "Exited ECBM.");
- if (mListener != null) {
+ IImsEcbmListener listener;
+ synchronized (mLock) {
+ listener = mListener;
+ }
+ if (listener != null) {
try {
- mListener.exitedECBM();
+ listener.exitedECBM();
} catch (RemoteException e) {
throw new RuntimeException(e);
}
diff --git a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
index d002903a11b6..8e961acc7b36 100644
--- a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java
@@ -25,6 +25,7 @@ import com.android.ims.internal.IImsExternalCallStateListener;
import com.android.ims.internal.IImsMultiEndpoint;
import java.util.List;
+import java.util.Objects;
/**
* Base implementation of ImsMultiEndpoint, which implements stub versions of the methods
@@ -41,10 +42,32 @@ public class ImsMultiEndpointImplBase {
private static final String TAG = "MultiEndpointImplBase";
private IImsExternalCallStateListener mListener;
- private IImsMultiEndpoint mImsMultiEndpoint = new IImsMultiEndpoint.Stub() {
+ private final Object mLock = new Object();
+ private final IImsMultiEndpoint mImsMultiEndpoint = new IImsMultiEndpoint.Stub() {
+
@Override
public void setListener(IImsExternalCallStateListener listener) throws RemoteException {
- mListener = listener;
+ synchronized (mLock) {
+ if (mListener != null && !mListener.asBinder().isBinderAlive()) {
+ Log.w(TAG, "setListener: discarding dead Binder");
+ mListener = null;
+ }
+ if (mListener != null && listener != null && Objects.equals(
+ mListener.asBinder(), listener.asBinder())) {
+ return;
+ }
+
+ if (listener == null) {
+ mListener = null;
+ } else if (listener != null && mListener == null) {
+ mListener = listener;
+ } else {
+ // Fail fast here instead of silently overwriting the listener to another
+ // listener due to another connection connecting.
+ throw new IllegalStateException("ImsMultiEndpointImplBase: Listener already"
+ + " set by another connection.");
+ }
+ }
}
@Override
@@ -65,9 +88,13 @@ public class ImsMultiEndpointImplBase {
*/
public final void onImsExternalCallStateUpdate(List<ImsExternalCallState> externalCallDialogs) {
Log.d(TAG, "ims external call state update triggered.");
- if (mListener != null) {
+ IImsExternalCallStateListener listener;
+ synchronized (mLock) {
+ listener = mListener;
+ }
+ if (listener != null) {
try {
- mListener.onImsExternalCallStateUpdate(externalCallDialogs);
+ listener.onImsExternalCallStateUpdate(externalCallDialogs);
} catch (RemoteException e) {
throw new RuntimeException(e);
}
diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
index 088a7e26a9d0..23032f0c4d38 100644
--- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java
@@ -18,17 +18,18 @@ package android.telephony.ims.stub;
import android.annotation.IntDef;
import android.annotation.IntRange;
+import android.annotation.NonNull;
import android.annotation.Nullable;
import android.annotation.SystemApi;
import android.net.Uri;
import android.os.RemoteException;
import android.telephony.ims.ImsReasonInfo;
+import android.telephony.ims.ImsRegistrationAttributes;
import android.telephony.ims.RegistrationManager;
import android.telephony.ims.aidl.IImsRegistration;
import android.telephony.ims.aidl.IImsRegistrationCallback;
import android.util.Log;
-import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.telephony.util.RemoteCallbackListExt;
import com.android.internal.util.ArrayUtils;
@@ -83,7 +84,10 @@ public class ImsRegistrationImplBase {
@Override
public @ImsRegistrationTech int getRegistrationTechnology() throws RemoteException {
- return getConnectionType();
+ synchronized (mLock) {
+ return (mRegistrationAttributes == null) ? REGISTRATION_TECH_NONE
+ : mRegistrationAttributes.getRegistrationTechnology();
+ }
}
@Override
@@ -116,8 +120,7 @@ public class ImsRegistrationImplBase {
new RemoteCallbackListExt<>();
private final Object mLock = new Object();
// Locked on mLock
- private @ImsRegistrationTech
- int mConnectionType = REGISTRATION_TECH_NONE;
+ private ImsRegistrationAttributes mRegistrationAttributes;
// Locked on mLock
private int mRegistrationState = REGISTRATION_STATE_UNKNOWN;
// Locked on mLock, create unspecified disconnect cause.
@@ -195,17 +198,24 @@ public class ImsRegistrationImplBase {
/**
* Notify the framework that the device is connected to the IMS network.
*
- * @param imsRadioTech the radio access technology. Valid values are defined as
- * {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}.
+ * @param imsRadioTech the radio access technology.
*/
public final void onRegistered(@ImsRegistrationTech int imsRadioTech) {
- updateToState(imsRadioTech, RegistrationManager.REGISTRATION_STATE_REGISTERED);
+ onRegistered(new ImsRegistrationAttributes.Builder(imsRadioTech).build());
+ }
+
+ /**
+ * Notify the framework that the device is connected to the IMS network.
+ *
+ * @param attributes The attributes associated with the IMS registration.
+ */
+ public final void onRegistered(@NonNull ImsRegistrationAttributes attributes) {
+ updateToState(attributes, RegistrationManager.REGISTRATION_STATE_REGISTERED);
mCallbacks.broadcastAction((c) -> {
try {
- c.onRegistered(imsRadioTech);
+ c.onRegistered(attributes);
} catch (RemoteException e) {
- Log.w(LOG_TAG, e + " " + "onRegistrationConnected() - Skipping " +
- "callback.");
+ Log.w(LOG_TAG, e + "onRegistered(int, Set) - Skipping callback.");
}
});
}
@@ -213,17 +223,24 @@ public class ImsRegistrationImplBase {
/**
* Notify the framework that the device is trying to connect the IMS network.
*
- * @param imsRadioTech the radio access technology. Valid values are defined as
- * {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}.
+ * @param imsRadioTech the radio access technology.
*/
public final void onRegistering(@ImsRegistrationTech int imsRadioTech) {
- updateToState(imsRadioTech, RegistrationManager.REGISTRATION_STATE_REGISTERING);
+ onRegistering(new ImsRegistrationAttributes.Builder(imsRadioTech).build());
+ }
+
+ /**
+ * Notify the framework that the device is trying to connect the IMS network.
+ *
+ * @param attributes The attributes associated with the IMS registration.
+ */
+ public final void onRegistering(@NonNull ImsRegistrationAttributes attributes) {
+ updateToState(attributes, RegistrationManager.REGISTRATION_STATE_REGISTERING);
mCallbacks.broadcastAction((c) -> {
try {
- c.onRegistering(imsRadioTech);
+ c.onRegistering(attributes);
} catch (RemoteException e) {
- Log.w(LOG_TAG, e + " " + "onRegistrationProcessing() - Skipping " +
- "callback.");
+ Log.w(LOG_TAG, e + "onRegistering(int, Set) - Skipping callback.");
}
});
}
@@ -252,8 +269,7 @@ public class ImsRegistrationImplBase {
try {
c.onDeregistered(reasonInfo);
} catch (RemoteException e) {
- Log.w(LOG_TAG, e + " " + "onRegistrationDisconnected() - Skipping " +
- "callback.");
+ Log.w(LOG_TAG, e + "onDeregistered() - Skipping callback.");
}
});
}
@@ -272,8 +288,7 @@ public class ImsRegistrationImplBase {
try {
c.onTechnologyChangeFailed(imsRadioTech, reasonInfo);
} catch (RemoteException e) {
- Log.w(LOG_TAG, e + " " + "onRegistrationChangeFailed() - Skipping " +
- "callback.");
+ Log.w(LOG_TAG, e + "onTechnologyChangeFailed() - Skipping callback.");
}
});
}
@@ -297,14 +312,13 @@ public class ImsRegistrationImplBase {
try {
callback.onSubscriberAssociatedUriChanged(uris);
} catch (RemoteException e) {
- Log.w(LOG_TAG, e + " " + "onSubscriberAssociatedUriChanged() - Skipping "
- + "callback.");
+ Log.w(LOG_TAG, e + "onSubscriberAssociatedUriChanged() - Skipping callback.");
}
}
- private void updateToState(@ImsRegistrationTech int connType, int newState) {
+ private void updateToState(ImsRegistrationAttributes attributes, int newState) {
synchronized (mLock) {
- mConnectionType = connType;
+ mRegistrationAttributes = attributes;
mRegistrationState = newState;
mLastDisconnectCause = null;
}
@@ -316,7 +330,7 @@ public class ImsRegistrationImplBase {
mUrisSet = false;
mUris = null;
- updateToState(REGISTRATION_TECH_NONE,
+ updateToState(new ImsRegistrationAttributes.Builder(REGISTRATION_TECH_NONE).build(),
RegistrationManager.REGISTRATION_STATE_NOT_REGISTERED);
if (info != null) {
mLastDisconnectCause = info;
@@ -328,29 +342,19 @@ public class ImsRegistrationImplBase {
}
/**
- * @return the current registration connection type. Valid values are
- * {@link #REGISTRATION_TECH_LTE} and {@link #REGISTRATION_TECH_IWLAN}
- * @hide
- */
- @VisibleForTesting
- public final @ImsRegistrationTech int getConnectionType() {
- synchronized (mLock) {
- return mConnectionType;
- }
- }
-
- /**
* @param c the newly registered callback that will be updated with the current registration
* state.
*/
private void updateNewCallbackWithState(IImsRegistrationCallback c)
throws RemoteException {
int state;
+ ImsRegistrationAttributes attributes;
ImsReasonInfo disconnectInfo;
boolean urisSet;
Uri[] uris;
synchronized (mLock) {
state = mRegistrationState;
+ attributes = mRegistrationAttributes;
disconnectInfo = mLastDisconnectCause;
urisSet = mUrisSet;
uris = mUris;
@@ -361,11 +365,11 @@ public class ImsRegistrationImplBase {
break;
}
case RegistrationManager.REGISTRATION_STATE_REGISTERING: {
- c.onRegistering(getConnectionType());
+ c.onRegistering(attributes);
break;
}
case RegistrationManager.REGISTRATION_STATE_REGISTERED: {
- c.onRegistered(getConnectionType());
+ c.onRegistered(attributes);
break;
}
case REGISTRATION_STATE_UNKNOWN: {
diff --git a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
index f5219d5b49e8..83b89aa8e814 100644
--- a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java
@@ -23,12 +23,14 @@ import android.annotation.SystemApi;
import android.os.Bundle;
import android.os.RemoteException;
import android.telephony.ims.ImsUtListener;
+import android.util.Log;
import com.android.ims.internal.IImsUt;
import com.android.ims.internal.IImsUtListener;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
+import java.util.Objects;
/**
* Base implementation of IMS UT interface, which implements stubs. Override these methods to
@@ -40,6 +42,7 @@ import java.lang.annotation.RetentionPolicy;
// will break other implementations of ImsUt maintained by other ImsServices.
@SystemApi
public class ImsUtImplBase {
+ private static final String TAG = "ImsUtImplBase";
/**
* Bar all incoming calls. (See 3GPP TS 24.611)
* @hide
@@ -116,7 +119,10 @@ public class ImsUtImplBase {
*/
public static final int INVALID_RESULT = -1;
- private IImsUt.Stub mServiceImpl = new IImsUt.Stub() {
+ private final IImsUt.Stub mServiceImpl = new IImsUt.Stub() {
+ private final Object mLock = new Object();
+ private ImsUtListener mUtListener;
+
@Override
public void close() throws RemoteException {
ImsUtImplBase.this.close();
@@ -202,7 +208,31 @@ public class ImsUtImplBase {
@Override
public void setListener(IImsUtListener listener) throws RemoteException {
- ImsUtImplBase.this.setListener(new ImsUtListener(listener));
+ synchronized (mLock) {
+ if (mUtListener != null
+ && !mUtListener.getListenerInterface().asBinder().isBinderAlive()) {
+ Log.w(TAG, "setListener: discarding dead Binder");
+ mUtListener = null;
+ }
+ if (mUtListener != null && listener != null && Objects.equals(
+ mUtListener.getListenerInterface().asBinder(), listener.asBinder())) {
+ return;
+ }
+
+ if (listener == null) {
+ mUtListener = null;
+ } else if (listener != null && mUtListener == null) {
+ mUtListener = new ImsUtListener(listener);
+ } else {
+ // This is a limitation of the current API surface, there can only be one
+ // listener connected. Fail fast instead of silently overwriting the other
+ // listener.
+ throw new IllegalStateException("ImsUtImplBase#setListener: listener already "
+ + "set by another connected interface!");
+ }
+ }
+
+ ImsUtImplBase.this.setListener(mUtListener);
}
@Override
diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
index c84e23c38e97..908869beb607 100644
--- a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
+++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java
@@ -19,11 +19,11 @@ package android.telephony.ims.stub;
import android.annotation.IntDef;
import android.annotation.IntRange;
import android.annotation.NonNull;
-import android.annotation.Nullable;
import android.annotation.SuppressLint;
import android.annotation.SystemApi;
import android.net.Uri;
import android.telephony.ims.ImsException;
+import android.telephony.ims.RcsUceAdapter;
import android.telephony.ims.feature.ImsFeature;
import android.telephony.ims.feature.RcsFeature;
import android.util.Log;
@@ -139,24 +139,52 @@ public class RcsCapabilityExchangeImplBase {
* 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
+ * If this network response also contains a “Reason” header, then the
+ * {@link #onNetworkResponse(int, String, int, String)} method should be used instead.
+ *
+ * @param sipCode The SIP response code sent from the network for the operation
* token specified.
* @param reason The optional reason response from the network. If there is a reason header
* included in the response, that should take precedence over the reason provided in the
- * status line. If the network provided no reason with the code, the string should be empty.
+ * status line. If the network provided no reason with the sip 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,
+ void onNetworkResponse(@IntRange(from = 100, to = 699) int sipCode,
@NonNull String reason) throws ImsException;
+
+ /**
+ * Provide the framework with a subsequent network response update to
+ * {@link #publishCapabilities(String, PublishResponseCallback)} that also
+ * includes a reason provided in the “reason” header. See RFC3326 for more
+ * information.
+ *
+ * @param sipCode The SIP response code sent from the network.
+ * @param reasonPhrase The optional reason response from the network. If the
+ * network provided no reason with the sip code, the string should be empty.
+ * @param reasonHeaderCause The “cause” parameter of the “reason” header
+ * included in the SIP message.
+ * @param reasonHeaderText The “text” parameter of the “reason” header
+ * included in the SIP message.
+ * @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 sipCode,
+ @NonNull String reasonPhrase,
+ @IntRange(from = 100, to = 699) int reasonHeaderCause,
+ @NonNull String reasonHeaderText) throws ImsException;
}
/**
* Interface used by the framework to respond to OPTIONS requests.
- * @hide
*/
public interface OptionsResponseCallback {
/**
@@ -173,7 +201,7 @@ public class RcsCapabilityExchangeImplBase {
/**
* 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
+ * @param sipCode 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.
@@ -186,17 +214,20 @@ public class RcsCapabilityExchangeImplBase {
* {@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;
+ void onNetworkResponse(int sipCode, @NonNull String reason,
+ @NonNull List<String> theirCaps) throws ImsException;
}
/**
* Interface used by the framework to receive the response of the subscribe request.
- * @hide
*/
public interface SubscribeResponseCallback {
/**
* Notify the framework that the command associated with this callback has failed.
+ * <p>
+ * Must only be called when there was an error generating a SUBSCRIBE request due to an
+ * IMS stack error. This is a terminating event, so no other callback event will be
+ * expected after this callback.
*
* @param code The reason why the associated command has failed.
* @throws ImsException If this {@link RcsCapabilityExchangeImplBase} instance is
@@ -210,28 +241,68 @@ public class RcsCapabilityExchangeImplBase {
/**
* Notify the framework of the response to the SUBSCRIBE request from
- * {@link #subscribeForCapabilities(List<Uri>, SubscribeResponseCallback)}.
+ * {@link #subscribeForCapabilities(List, SubscribeResponseCallback)}.
+ * <p>
+ * If the carrier network responds to the SUBSCRIBE request with a 2XX response, then the
+ * framework will expect the IMS stack to call {@link #onNotifyCapabilitiesUpdate},
+ * {@link #onResourceTerminated}, and {@link #onTerminated} as required for the
+ * subsequent NOTIFY responses to the subscription.
+ *
+ * If this network response also contains a “Reason” header, then the
+ * {@link #onNetworkResponse(int, String, int, String)} method should be used instead.
*
- * @param code The SIP response code sent from the network for the operation
+ * @param sipCode 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.
+ * provided no reason with the sip 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,
+ void onNetworkResponse(@IntRange(from = 100, to = 699) int sipCode,
@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
+ * Notify the framework of the response to the SUBSCRIBE request from
+ * {@link #subscribeForCapabilities(List, SubscribeResponseCallback)} that also
+ * includes a reason provided in the “reason” header. See RFC3326 for more
* information.
*
+ * @param sipCode The SIP response code sent from the network,
+ * @param reasonPhrase The optional reason response from the network. If the
+ * network provided no reason with the sip code, the string should be empty.
+ * @param reasonHeaderCause The “cause” parameter of the “reason” header
+ * included in the SIP message.
+ * @param reasonHeaderText The “text” parameter of the “reason” header
+ * included in the SIP message.
+ * @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 sipCode,
+ @NonNull String reasonPhrase,
+ @IntRange(from = 100, to = 699) int reasonHeaderCause,
+ @NonNull String reasonHeaderText) throws ImsException;
+
+ /**
+ * Notify the framework of the latest XML PIDF documents included in the network response
+ * for the requested contacts' capabilities requested by the Framework using
+ * {@link RcsUceAdapter#requestCapabilities(List, Executor,
+ * RcsUceAdapter.CapabilitiesCallback)}.
+ * <p>
+ * The expected format for the PIDF XML is defined in RFC3861. Each XML document must be a
+ * "application/pidf+xml" object and start with a root <presence> element. For NOTIFY
+ * responses that contain RLMI information and potentially multiple PIDF XMLs, each
+ * PIDF XML should be separated and added as a separate item in the List. This should be
+ * called every time a new NOTIFY event is received with new capability information.
+ *
+ * @param pidfXmls The list of the PIDF XML data for the contact URIs that it subscribed
+ * for.
* @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
@@ -242,21 +313,43 @@ public class RcsCapabilityExchangeImplBase {
void onNotifyCapabilitiesUpdate(@NonNull List<String> pidfXmls) throws ImsException;
/**
- * A resource in the resource list for the presence subscribe event has been terminated.
+ * Notify the framework that a resource in the RLMI XML contained in the NOTIFY response
+ * for the ongoing SUBSCRIBE dialog 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.
+ * This will be used to notify the framework that a contact URI that the IMS stack has
+ * subscribed to on the Resource List Server has been terminated as well as the reason why.
+ * Usually this means that there will not be any capability information for the contact URI
+ * that they subscribed for. See RFC 4662 for more information.
+ *
+ * @param uriTerminatedReason The contact URIs which have been terminated. Each pair in the
+ * list is the contact URI and its terminated reason.
+ * @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} {@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 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.
+ * The subscription associated with a previous
+ * {@link RcsUceAdapter#requestCapabilities(List, Executor,
+ * RcsUceAdapter.CapabilitiesCallback)}
+ * operation has been terminated. This will mostly be due to the network sending a final
+ * NOTIFY response due to the subscription expiring, but this may also happen due to a
+ * network error.
+ *
+ * @param reason The reason for the request being unable to process.
+ * @param retryAfterMilliseconds The time in milliseconds the requesting application should
+ * wait before retrying, if non-zero.
+ * @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} {@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 onTerminated(@NonNull String reason, long retryAfterMilliseconds) throws ImsException;
}
@@ -278,18 +371,23 @@ public class RcsCapabilityExchangeImplBase {
/**
* The user capabilities of one or multiple contacts have been requested by the framework.
* <p>
+ * The implementer must follow up this call with an
+ * {@link SubscribeResponseCallback#onCommandError} call to indicate this operation has failed.
* The response from the network to the SUBSCRIBE request must be sent back to the framework
- * using {@link #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}
+ * using {@link SubscribeResponseCallback#onNetworkResponse(int, String)}.
+ * As NOTIFY requests come in from the network, the requested contact’s capabilities should be
+ * sent back to the framework using
+ * {@link SubscribeResponseCallback#onNotifyCapabilitiesUpdate(List<String>}) and
+ * {@link SubscribeResponseCallback#onResourceTerminated(List<Pair<Uri, String>>)}
* should be called with the presence information for the contacts specified.
* <p>
- * Once the subscription is terminated, {@link #onSubscriptionTerminated} must be called for
- * the framework to finish listening for NOTIFY responses.
+ * Once the subscription is terminated,
+ * {@link SubscribeResponseCallback#onTerminated(String, long)} must be called for the
+ * framework to finish listening for NOTIFY responses.
+ *
* @param uris A {@link List} of the {@link Uri}s that the framework is requesting the UCE
* capabilities for.
* @param cb The callback of the subscribe request.
- * @hide
*/
// executor used is defined in the constructor.
@SuppressLint("ExecutorRegistration")
@@ -329,12 +427,11 @@ public class RcsCapabilityExchangeImplBase {
* 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.
+ * The implementer must use {@link OptionsResponseCallback} to send the response of
+ * this query from the network 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.
- * @hide
*/
// executor used is defined in the constructor.
@SuppressLint("ExecutorRegistration")