diff options
Diffstat (limited to 'telephony/java/android')
36 files changed, 1329 insertions, 583 deletions
diff --git a/telephony/java/android/telephony/Annotation.java b/telephony/java/android/telephony/Annotation.java index 99f2e5ee0755..4a53a8023792 100644 --- a/telephony/java/android/telephony/Annotation.java +++ b/telephony/java/android/telephony/Annotation.java @@ -111,6 +111,7 @@ public class Annotation { public @interface NetworkType { } + // TODO(b/180542000): remove and replace references with @ApnSetting.ApnType @IntDef(flag = true, prefix = {"TYPE_"}, value = { ApnSetting.TYPE_DEFAULT, ApnSetting.TYPE_MMS, @@ -124,6 +125,7 @@ public class Annotation { ApnSetting.TYPE_EMERGENCY, ApnSetting.TYPE_MCX, ApnSetting.TYPE_XCAP, + // ApnSetting.TYPE_ENTERPRISE }) @Retention(RetentionPolicy.SOURCE) public @interface ApnType { diff --git a/telephony/java/android/telephony/CarrierBandwidth.java b/telephony/java/android/telephony/CarrierBandwidth.java index b153fefce6e3..9e1dee0162b9 100644 --- a/telephony/java/android/telephony/CarrierBandwidth.java +++ b/telephony/java/android/telephony/CarrierBandwidth.java @@ -101,7 +101,7 @@ public final class CarrierBandwidth implements Parcelable { } /** - * Retrieves the upstream bandwidth for the primary network in Kbps. This always only refers to + * Retrieves the upstream bandwidth for the primary network in kbps. This always only refers to * the estimated first hop transport bandwidth. * This will be {@link #INVALID} if the network is not connected * @@ -112,7 +112,7 @@ public final class CarrierBandwidth implements Parcelable { } /** - * Retrieves the downstream bandwidth for the primary network in Kbps. This always only refers + * Retrieves the downstream bandwidth for the primary network in kbps. This always only refers * to the estimated first hop transport bandwidth. * This will be {@link #INVALID} if the network is not connected * @@ -123,7 +123,7 @@ public final class CarrierBandwidth implements Parcelable { } /** - * Retrieves the upstream bandwidth for the secondary network in Kbps. This always only refers + * Retrieves the upstream bandwidth for the secondary network in kbps. This always only refers * to the estimated first hop transport bandwidth. * <p/> * This will be {@link #INVALID} if either are the case: @@ -143,7 +143,7 @@ public final class CarrierBandwidth implements Parcelable { } /** - * Retrieves the downstream bandwidth for the secondary network in Kbps. This always only + * Retrieves the downstream bandwidth for the secondary network in kbps. This always only * refers to the estimated first hop transport bandwidth. * <p/> * This will be {@link #INVALID} if either are the case: diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 9e01d0a3250d..217570e1401c 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -17,6 +17,7 @@ package android.telephony; import android.Manifest; +import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.RequiresPermission; @@ -32,11 +33,17 @@ import android.os.RemoteException; import android.service.carrier.CarrierService; import android.telecom.TelecomManager; import android.telephony.ims.ImsReasonInfo; +import android.telephony.ims.ImsRegistrationAttributes; import android.telephony.ims.ImsSsData; +import android.telephony.ims.SipDelegateManager; +import android.telephony.ims.feature.MmTelFeature; +import android.telephony.ims.feature.RcsFeature; import com.android.internal.telephony.ICarrierConfigLoader; import com.android.telephony.Rlog; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; import java.util.concurrent.TimeUnit; /** @@ -103,6 +110,32 @@ public class CarrierConfigManager { */ public static final int USSD_OVER_IMS_ONLY = 3; + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = { "CARRIER_NR_AVAILABILITY_" }, value = { + CARRIER_NR_AVAILABILITY_NONE, + CARRIER_NR_AVAILABILITY_NSA, + CARRIER_NR_AVAILABILITY_SA, + }) + public @interface DeviceNrCapability {} + + /** + * Indicates CARRIER_NR_AVAILABILITY_NONE determine that the carrier does not enable 5G NR. + */ + public static final int CARRIER_NR_AVAILABILITY_NONE = 0; + + /** + * Indicates CARRIER_NR_AVAILABILITY_NSA determine that the carrier enable the non-standalone + * (NSA) mode of 5G NR. + */ + public static final int CARRIER_NR_AVAILABILITY_NSA = 1 << 0; + + /** + * Indicates CARRIER_NR_AVAILABILITY_SA determine that the carrier enable the standalone (SA) + * mode of 5G NR. + */ + public static final int CARRIER_NR_AVAILABILITY_SA = 1 << 1; + private final Context mContext; /** @@ -1774,10 +1807,23 @@ public class CarrierConfigManager { "show_precise_failed_cause_bool"; /** - * Boolean to decide whether NR is enabled. - * @hide + * Bit-field integer to determine whether the carrier enable the non-standalone (NSA) mode of + * 5G NR, standalone (SA) mode of 5G NR + * + * <UL> + * <LI>CARRIER_NR_AVAILABILITY_NONE: non-NR = 0 </LI> + * <LI>CARRIER_NR_AVAILABILITY_NSA: NSA = 1 << 0</LI> + * <LI>CARRIER_NR_AVAILABILITY_SA: SA = 1 << 1</LI> + * </UL> + * <p> The value of this key must be bitwise OR of + * {@link #CARRIER_NR_AVAILABILITY_NONE}, {@link #CARRIER_NR_AVAILABILITY_NSA}, + * {@link #CARRIER_NR_AVAILABILITY_SA}. + * + * <p> For example, if both NSA and SA are used, the value of key is 3 (1 << 0 | 1 << 1). + * If the carrier doesn't support 5G NR, the value of key is 0 (non-NR). + * If the key is invalid or not configured, a default value 3 (NSA|SA = 3) will apply. */ - public static final String KEY_NR_ENABLED_BOOL = "nr_enabled_bool"; + public static final String KEY_CARRIER_NR_AVAILABILITY_INT = "carrier_nr_availability_int"; /** * Boolean to decide whether LTE is enabled. @@ -1881,9 +1927,8 @@ public class CarrierConfigManager { * "APN_1, ERROR_CODE_1 : CARRIER_ACTION_IDX_1, CARRIER_ACTION_IDX_2...", * "APN_1, ERROR_CODE_2 : CARRIER_ACTION_IDX_1 " * } - * Where {@code APN_1} is a string defined in - * com.android.internal.telephony.PhoneConstants - * Example: "default" + * Where {@code APN_1} is an integer defined in {@link android.telephony.data.ApnSetting} + * (e.g. {@link android.telephony.data.ApnSetting#TYPE_DEFAULT} * * {@code ERROR_CODE_1} is an integer defined in android.telephony.DataFailCause * Example: @@ -3912,6 +3957,43 @@ public class CarrierConfigManager { KEY_PREFIX + "enable_presence_publish_bool"; /** + * Each string in this array contains a mapping between the service-id and version portion + * of the service-description element and the associated IMS feature tag(s) that are + * associated with each element (see RCC.07 Table 7). + * <p> + * Each string contains 3 parts, which define the mapping between service-description and + * feature tag(s) that must be present in the IMS REGISTER for the RCS service to be + * published as part of the RCS PUBLISH procedure: + * [service-id]|[version]|[desc]|[feature_tag];[feature_tag];... + * <ul> + * <li>[service-id]: the service-id element associated with the RCS capability.</li> + * <li>[version]: The version element associated with that service-id</li> + * <li>[desc]: The optional desecription element associated with that service-id</li> + * <li>[feature_tag];[feature_tag]: The list of all feature tags associated with this + * capability that MUST ALL be present in the IMS registration for this this + * capability to be published to the network.</li> + * </ul> + * <p> + * Features managed by the framework will be considered capable when the ImsService reports + * that those services are capable via the + * {@link MmTelFeature#notifyCapabilitiesStatusChanged(MmTelFeature.MmTelCapabilities)} or + * {@link RcsFeature#notifyCapabilitiesStatusChanged(RcsFeature.RcsImsCapabilities)} APIs. + * For RCS services not managed by the framework, the capability of these services are + * determined by looking at the feature tags associated with the IMS registration using the + * {@link ImsRegistrationAttributes} API and mapping them to the service-description map. + * <p> + * The framework contains a default value of this key, which is based off of RCC.07 + * specification. Capabilities based of carrier extensions may be added to this list on a + * carrier-by-carrier basis as required in order to support additional services in the + * PUBLISH. If this list contains a service-id and version that overlaps with the default, + * it will override the framework default. + * @hide + */ + @SystemApi + public static final String KEY_PUBLISH_SERVICE_DESC_FEATURE_TAG_MAP_OVERRIDE_STRING_ARRAY = + KEY_PREFIX + "publish_service_desc_feature_tag_map_override_string_array"; + + /** * Flag indicating whether or not this carrier supports the exchange of phone numbers with * the carrier's RCS presence server in order to retrieve the RCS capabilities of requested * contacts used in the RCS User Capability Exchange (UCE) procedure. See RCC.71, section 3 @@ -3970,6 +4052,8 @@ public class CarrierConfigManager { defaults.putInt(KEY_WIFI_OFF_DEFERRING_TIME_MILLIS_INT, 4000); defaults.putBoolean(KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL, false); defaults.putBoolean(KEY_ENABLE_PRESENCE_PUBLISH_BOOL, false); + defaults.putStringArray(KEY_PUBLISH_SERVICE_DESC_FEATURE_TAG_MAP_OVERRIDE_STRING_ARRAY, + new String[] {}); 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); @@ -4561,7 +4645,8 @@ public class CarrierConfigManager { sDefaults.putString(KEY_SHOW_CARRIER_DATA_ICON_PATTERN_STRING, ""); sDefaults.putBoolean(KEY_HIDE_LTE_PLUS_DATA_ICON_BOOL, true); sDefaults.putInt(KEY_LTE_PLUS_THRESHOLD_BANDWIDTH_KHZ_INT, 20000); - sDefaults.putBoolean(KEY_NR_ENABLED_BOOL, true); + sDefaults.putInt(KEY_CARRIER_NR_AVAILABILITY_INT, + CARRIER_NR_AVAILABILITY_NSA | CARRIER_NR_AVAILABILITY_SA); sDefaults.putBoolean(KEY_LTE_ENABLED_BOOL, true); sDefaults.putBoolean(KEY_SUPPORT_TDSCDMA_BOOL, false); sDefaults.putStringArray(KEY_SUPPORT_TDSCDMA_ROAMING_NETWORKS_STRING_ARRAY, null); @@ -4725,7 +4810,7 @@ public class CarrierConfigManager { sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_ORIGINATOR_STRING_ARRAY, new String[0]); sDefaults.putStringArray(KEY_APN_PRIORITY_STRING_ARRAY, new String[] { - "default:0", "mms:2", "supl:2", "dun:2", "hipri:3", "fota:2", + "default:0", "enterprise:1", "mms:2", "supl:2", "dun:2", "hipri:3", "fota:2", "ims:2", "cbs:2", "ia:2", "emergency:2", "mcx:3", "xcap:3" }); sDefaults.putStringArray(KEY_MISSED_INCOMING_CALL_SMS_PATTERN_STRING_ARRAY, new String[0]); diff --git a/telephony/java/android/telephony/CellIdentity.java b/telephony/java/android/telephony/CellIdentity.java index 1e5ce05ff28a..518fabc09838 100644 --- a/telephony/java/android/telephony/CellIdentity.java +++ b/telephony/java/android/telephony/CellIdentity.java @@ -37,7 +37,7 @@ import java.util.UUID; public abstract class CellIdentity implements Parcelable { /** @hide */ - public static final int INVALID_CHANNEL_NUMBER = -1; + public static final int INVALID_CHANNEL_NUMBER = Integer.MAX_VALUE; /** * parameters for validation diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java index 99a77ae5d133..c8ed82cd2a3f 100644 --- a/telephony/java/android/telephony/DataFailCause.java +++ b/telephony/java/android/telephony/DataFailCause.java @@ -917,6 +917,10 @@ public final class DataFailCause { 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; + /** No matching rule available for the request, and match-all rule is not allowed for it. */ + public static final int MATCH_ALL_RULE_NOT_ALLOWED = 0x8CD; + /** If connection failed for all matching URSP rules. */ + public static final int ALL_MATCHING_RULES_FAILED = 0x8CE; //IKE error notifications message as specified in 3GPP TS 24.302 (Section 8.1.2.2). diff --git a/telephony/java/android/telephony/PhysicalChannelConfig.java b/telephony/java/android/telephony/PhysicalChannelConfig.java index 9fb098ea8758..dfe269cbb0d9 100644 --- a/telephony/java/android/telephony/PhysicalChannelConfig.java +++ b/telephony/java/android/telephony/PhysicalChannelConfig.java @@ -50,7 +50,7 @@ public final class PhysicalChannelConfig implements Parcelable { public static final int CONNECTION_UNKNOWN = -1; /** Channel number is unknown. */ - public static final int CHANNEL_NUMBER_UNKNOWN = -1; + public static final int CHANNEL_NUMBER_UNKNOWN = Integer.MAX_VALUE; /** Physical Cell Id is unknown. */ public static final int PHYSICAL_CELL_ID_UNKNOWN = -1; diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index 4e481b3ad837..85fe14ef8062 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -907,7 +907,8 @@ public class SubscriptionManager { * Indicate which network type is allowed. By default it's enabled. * @hide */ - public static final String ALLOWED_NETWORK_TYPES = SimInfo.COLUMN_ALLOWED_NETWORK_TYPES; + public static final String ALLOWED_NETWORK_TYPES = + SimInfo.COLUMN_ALLOWED_NETWORK_TYPES_FOR_REASONS; /** * Broadcast Action: The user has changed one of the default subs related to diff --git a/telephony/java/android/telephony/TelephonyDisplayInfo.java b/telephony/java/android/telephony/TelephonyDisplayInfo.java index 1fcb504e7895..877827578760 100644 --- a/telephony/java/android/telephony/TelephonyDisplayInfo.java +++ b/telephony/java/android/telephony/TelephonyDisplayInfo.java @@ -30,8 +30,8 @@ import java.util.Objects; * necessarily a precise or accurate representation of the current state and should be treated * accordingly. * To be notified of changes in TelephonyDisplayInfo, use - * {@link TelephonyManager#registerPhoneStateListener} with a {@link PhoneStateListener} - * that implements {@link PhoneStateListener.DisplayInfoChangedListener}. + * {@link TelephonyManager#registerTelephonyCallback} with a {@link TelephonyCallback} + * that implements {@link TelephonyCallback.DisplayInfoListener}. * Override the onDisplayInfoChanged() method to handle the broadcast. */ public final class TelephonyDisplayInfo implements Parcelable { diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 403d1d01903c..e77ee365b4d3 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -1585,177 +1585,157 @@ public class TelephonyManager { "android.telephony.extra.PHONE_IN_ECM_STATE"; /** - * <p>Broadcast Action: when data connections get redirected with validation failure. - * intended for sim/account status checks and only sent to the specified carrier app - * The intent will have the following extra values:</p> + * Broadcast action sent when a data connection is redirected with validation failure. + * + * This action is intended for sim/account status checks and only sent to the carrier apps + * specified in the carrier config for the subscription ID that's attached to this intent. + * + * The intent will have the following extra values: * <ul> - * <li>{@link #EXTRA_APN_TYPE}</li><dd>A string with the apn type.</dd> - * <li>{@link #EXTRA_APN_TYPE_INT}</li><dd>A integer with the apn type.</dd> - * <li>{@link #EXTRA_REDIRECTION_URL}</li><dd>redirection url string</dd> - * <li>subId</li><dd>Sub Id which associated the data connection failure.</dd> + * <li>{@link #EXTRA_APN_TYPE}</li><dd>An integer indicating the apn type.</dd> + * <li>{@link #EXTRA_REDIRECTION_URL}</li><dd>A string indicating the redirection url</dd> + * <li>{@link SubscriptionManager#EXTRA_SUBSCRIPTION_INDEX}</li> + * <dd>The subscription ID on which the validation failure happened.</dd> * </ul> * <p class="note">This is a protected intent that can only be sent by the system.</p> - * @hide */ - @SuppressLint("ActionValue") + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CARRIER_SIGNAL_REDIRECTED = - "com.android.internal.telephony.CARRIER_SIGNAL_REDIRECTED"; + "android.telephony.action.CARRIER_SIGNAL_REDIRECTED"; /** - * <p>Broadcast Action: when data connections setup fails. - * intended for sim/account status checks and only sent to the specified carrier app - * The intent will have the following extra values:</p> + * Broadcast action sent when a data connection setup fails. + * + * This action is intended for sim/account status checks and only sent to the carrier apps + * specified in the carrier config for the subscription ID that's attached to this intent. + * + * The intent will have the following extra values: * <ul> - * <li>{@link #EXTRA_APN_TYPE}</li><dd>A string with the apn type.</dd> - * <li>{@link #EXTRA_APN_TYPE_INT}</li><dd>A integer with the apn type.</dd> - * <li>{@link #EXTRA_ERROR_CODE}</li><dd>A integer with dataFailCause.</dd> - * <li>subId</li><dd>Sub Id which associated the data connection failure.</dd> + * <li>{@link #EXTRA_APN_TYPE}</li><dd>An integer indicating the apn type.</dd> + * <li>{@link #EXTRA_DATA_FAIL_CAUSE}</li><dd>A integer indicating the data fail cause.</dd> + * <li>{@link SubscriptionManager#EXTRA_SUBSCRIPTION_INDEX}</li> + * <dd>The subscription ID on which the data setup failure happened.</dd> * </ul> * <p class="note">This is a protected intent that can only be sent by the system. </p> - * @hide */ - @SuppressLint("ActionValue") + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED = - "com.android.internal.telephony.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED"; + "android.telephony.action.CARRIER_SIGNAL_REQUEST_NETWORK_FAILED"; /** - * <p>Broadcast Action: when pco value is available. - * intended for sim/account status checks and only sent to the specified carrier app + * Broadcast action sent when a PCO value becomes available from the modem. + * + * This action is intended for sim/account status checks and only sent to the carrier apps + * specified in the carrier config for the subscription ID that's attached to this intent. + * * The intent will have the following extra values:</p> * <ul> - * <li>{@link #EXTRA_APN_TYPE}</li><dd>A string with the apn type.</dd> - * <li>{@link #EXTRA_APN_TYPE_INT}</li><dd>A integer with the apn type.</dd> - * <li>{@link #EXTRA_APN_PROTOCOL}</li><dd>A string with the protocol of the apn connection - * (IP,IPV6, IPV4V6)</dd> - * <li>{@link #EXTRA_APN_PROTOCOL_INT}</li><dd>A integer with the protocol of the apn - * connection (IP,IPV6, IPV4V6)</dd> - * <li>{@link #EXTRA_PCO_ID}</li><dd>An integer indicating the pco id for the data.</dd> - * <li>{@link #EXTRA_PCO_VALUE}</li><dd>A byte array of pco data read from modem.</dd> - * <li>subId</li><dd>Sub Id which associated the data connection.</dd> + * <li>{@link #EXTRA_APN_TYPE}</li><dd>An integer indicating the apn type.</dd> + * <li>{@link #EXTRA_APN_PROTOCOL}</li><dd>An integer indicating the protocol of the apn + * connection</dd> + * <li>{@link #EXTRA_PCO_ID}</li><dd>An integer indicating the PCO id for the data.</dd> + * <li>{@link #EXTRA_PCO_VALUE}</li><dd>A byte array of PCO data read from modem.</dd> + * <li>{@link SubscriptionManager#EXTRA_SUBSCRIPTION_INDEX}</li> + * <dd>The subscription ID for which the PCO info was received.</dd> * </ul> * <p class="note">This is a protected intent that can only be sent by the system. </p> - * @hide */ - @SuppressLint("ActionValue") + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CARRIER_SIGNAL_PCO_VALUE = - "com.android.internal.telephony.CARRIER_SIGNAL_PCO_VALUE"; + "android.telephony.action.CARRIER_SIGNAL_PCO_VALUE"; /** - * <p>Broadcast Action: when system default network available/unavailable with - * carrier-disabled mobile data. Intended for carrier apps to set/reset carrier actions when - * other network becomes system default network, Wi-Fi for example. + * Broadcast action sent when the availability of the system default network changes. + * + * @see ConnectivityManager#registerDefaultNetworkCallback(ConnectivityManager.NetworkCallback) + * + * This action is intended for carrier apps to set/reset carrier actions. It is only sent to the + * carrier apps specified in the carrier config for the subscription ID attached to this intent. + * * The intent will have the following extra values:</p> * <ul> * <li>{@link #EXTRA_DEFAULT_NETWORK_AVAILABLE}</li> - * <dd>A boolean indicates default network available.</dd> - * <li>subId</li><dd>Sub Id which associated the default data.</dd> + * <dd>{@code true} if the default network is now available, {@code false} otherwise.</dd> + * <li>{@link SubscriptionManager#EXTRA_SUBSCRIPTION_INDEX}</li> + * <dd>The subscription ID on which the default network availability changed.</dd> * </ul> * <p class="note">This is a protected intent that can only be sent by the system. </p> - * @hide */ - @SuppressLint("ActionValue") + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE = - "com.android.internal.telephony.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE"; + "android.telephony.action.CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE"; /** - * <p>Broadcast Action: when framework reset all carrier actions on sim load or absent. - * intended for carrier apps clean up (clear UI e.g.) and only sent to the specified carrier app + * Broadcast action sent when carrier apps should reset their internal state. + * + * Sent when certain events such as turning on/off mobile data, removing the SIM, etc. require + * carrier apps to reset their state. + * + * This action is intended to signal carrier apps to perform cleanup operations. It is only sent + * to the carrier apps specified in the carrier config for the subscription ID attached to + * this intent. + * * The intent will have the following extra values:</p> * <ul> - * <li>subId</li><dd>Sub Id which associated the data connection failure.</dd> + * <li>{@link SubscriptionManager#EXTRA_SUBSCRIPTION_INDEX}</li> + * <dd>The subscription ID for which state should be reset.</dd> * </ul> * <p class="note">This is a protected intent that can only be sent by the system.</p> - * @hide */ - @SuppressLint("ActionValue") + @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_CARRIER_SIGNAL_RESET = - "com.android.internal.telephony.CARRIER_SIGNAL_RESET"; - - // CARRIER_SIGNAL_ACTION extra keys - /** - * An string extra of redirected url upon {@link #ACTION_CARRIER_SIGNAL_REDIRECTED}. - * @hide - */ - @SuppressLint("ActionValue") - public static final String EXTRA_REDIRECTION_URL = "redirectionUrl"; + "android.telephony.action.CARRIER_SIGNAL_RESET"; /** - * An integer extra of error code upon {@link #ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED}. - * Check {@link DataFailCause} for all possible values. - * @hide + * String extra containing the redirection URL sent with + * {@link #ACTION_CARRIER_SIGNAL_REDIRECTED}. */ - @SuppressLint("ActionValue") - public static final String EXTRA_ERROR_CODE = "errorCode"; + public static final String EXTRA_REDIRECTION_URL = "android.telephony.extra.REDIRECTION_URL"; /** - * An string extra of corresponding apn type upon - * {@link #ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED}, - * {@link #ACTION_CARRIER_SIGNAL_REDIRECTED} and - * {@link #ACTION_CARRIER_SIGNAL_PCO_VALUE} broadcasts. - * @deprecated This is kept for backward compatibility reason. Use {@link #EXTRA_APN_TYPE_INT} - * instead. + * An integer extra containing the data fail cause. * - * @hide + * Sent with {@link #ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED}. See {@link DataFailCause} + * for a list of possible values. */ - @Deprecated - @SuppressLint("ActionValue") - public static final String EXTRA_APN_TYPE = "apnType"; + public static final String EXTRA_DATA_FAIL_CAUSE = "android.telephony.extra.DATA_FAIL_CAUSE"; /** - * An string integer of corresponding apn type upon - * {@link #ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED}, - * {@link #ACTION_CARRIER_SIGNAL_REDIRECTED} and - * {@link #ACTION_CARRIER_SIGNAL_PCO_VALUE} broadcasts. - * Check {@link ApnSetting} TYPE_* for its values. - * @hide - */ - @SuppressLint("ActionValue") - public static final String EXTRA_APN_TYPE_INT = "apnTypeInt"; - - /** - * An string extra with the protocol of the apn connection (IP,IPV6, IPV4V6) upon - * {@link #ACTION_CARRIER_SIGNAL_PCO_VALUE} broadcasts. - * @deprecated This is kept for backward compatibility reason. - * Use {@link #EXTRA_APN_PROTOCOL_INT} instead. + * An integer extra containing the APN type. * - * @hide + * Sent with the {@link #ACTION_CARRIER_SIGNAL_REQUEST_NETWORK_FAILED}, + * {@link #ACTION_CARRIER_SIGNAL_REDIRECTED}, and {@link #ACTION_CARRIER_SIGNAL_PCO_VALUE} + * broadcasts. + * See the {@code TYPE_} constants in {@link ApnSetting} for a list of possible values. */ - @Deprecated - @SuppressLint("ActionValue") - public static final String EXTRA_APN_PROTOCOL = "apnProto"; + public static final String EXTRA_APN_TYPE = "android.telephony.extra.APN_TYPE"; /** - * An integer extra with the protocol of the apn connection (IP,IPV6, IPV4V6) upon - * {@link #ACTION_CARRIER_SIGNAL_PCO_VALUE} broadcasts. - * Check {@link ApnSetting} PROTOCOL_* for its values. - * @hide + * An integer extra containing the protocol of the apn connection. + * + * Sent with the {@link #ACTION_CARRIER_SIGNAL_PCO_VALUE} broadcast. + * See the {@code PROTOCOL_*} constants in {@link ApnSetting} for a list of possible values. */ - @SuppressLint("ActionValue") - public static final String EXTRA_APN_PROTOCOL_INT = "apnProtoInt"; + public static final String EXTRA_APN_PROTOCOL = "android.telephony.extra.APN_PROTOCOL"; /** - * An integer extra indicating the pco id for the data upon - * {@link #ACTION_CARRIER_SIGNAL_PCO_VALUE} broadcasts. - * @hide + * An integer extra indicating the ID for the PCO data. + * Sent with the {@link #ACTION_CARRIER_SIGNAL_PCO_VALUE} broadcast. */ - @SuppressLint("ActionValue") - public static final String EXTRA_PCO_ID = "pcoId"; + public static final String EXTRA_PCO_ID = "android.telephony.extra.PCO_ID"; /** - * An extra of byte array of pco data read from modem upon - * {@link #ACTION_CARRIER_SIGNAL_PCO_VALUE} broadcasts. - * @hide + * A byte array extra containing PCO data read from the modem. + * Sent with the {@link #ACTION_CARRIER_SIGNAL_PCO_VALUE} broadcast. */ - @SuppressLint("ActionValue") - public static final String EXTRA_PCO_VALUE = "pcoValue"; + public static final String EXTRA_PCO_VALUE = "android.telephony.extra.PCO_VALUE"; /** - * An boolean extra indicating default network available upon - * {@link #ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE} broadcasts. - * @hide + * A boolean extra indicating the availability of the default network. + * Sent with the {@link #ACTION_CARRIER_SIGNAL_DEFAULT_NETWORK_AVAILABLE} broadcast. */ - @SuppressLint("ActionValue") - public static final String EXTRA_DEFAULT_NETWORK_AVAILABLE = "defaultNetworkAvailable"; + public static final String EXTRA_DEFAULT_NETWORK_AVAILABLE = + "android.telephony.extra.DEFAULT_NETWORK_AVAILABLE"; /** * <p>Broadcast Action: The emergency call state is changed. @@ -5600,28 +5580,25 @@ public class TelephonyManager { * instability. If a process has registered too many listeners without unregistering them, it * may encounter an {@link IllegalStateException} when trying to register more listeners. * - * @param listener The {@link PhoneStateListener} object to register (or unregister) - * @param events The telephony state(s) of interest to the listener, as a bitwise-OR combination - * of {@link PhoneStateListener} LISTEN_ flags. - * @deprecated Use {@link #registerPhoneStateListener(Executor, PhoneStateListener)}. + * @param listener The {@link PhoneStateListener} object to register + * (or unregister) + * @param events The telephony state(s) of interest to the listener, + * as a bitwise-OR combination of {@link PhoneStateListener} + * LISTEN_ flags. + * @deprecated Use {@link #registerTelephonyCallback(Executor, TelephonyCallback)}. */ @Deprecated public void listen(PhoneStateListener listener, int events) { - if (!listener.isExecutorSet()) { - throw new IllegalStateException("PhoneStateListener should be created on a thread " - + "with Looper.myLooper() != null"); - } - boolean notifyNow = getITelephony() != null; - mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class); - if (mTelephonyRegistryMgr != null) { - if (events != PhoneStateListener.LISTEN_NONE) { - mTelephonyRegistryMgr.registerPhoneStateListenerWithEvents(mSubId, - getOpPackageName(), getAttributionTag(), listener, events, notifyNow); - } else { - unregisterPhoneStateListener(listener); - } + if (mContext == null) return; + boolean notifyNow = (getITelephony() != null); + TelephonyRegistryManager telephonyRegistry = + (TelephonyRegistryManager) + mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); + if (telephonyRegistry != null) { + telephonyRegistry.listenFromListener(mSubId, getOpPackageName(), + getAttributionTag(), listener, events, notifyNow); } else { - throw new IllegalStateException("telephony service is null."); + Rlog.w(TAG, "telephony registry not ready."); } } @@ -7755,21 +7732,13 @@ public class TelephonyManager { * * @return the preferred network type. * @hide - * @deprecated Use {@link #getPreferredNetworkTypeBitmask} instead. + * @deprecated Use {@link #getAllowedNetworkTypesBitmask} instead. */ @Deprecated @RequiresPermission((android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE)) @UnsupportedAppUsage public @PrefNetworkMode int getPreferredNetworkType(int subId) { - try { - ITelephony telephony = getITelephony(); - if (telephony != null) { - return telephony.getPreferredNetworkType(subId); - } - } catch (RemoteException ex) { - Rlog.e(TAG, "getPreferredNetworkType RemoteException", ex); - } - return -1; + return RadioAccessFamily.getNetworkTypeFromRaf((int) getAllowedNetworkTypesBitmask()); } /** @@ -7785,24 +7754,47 @@ public class TelephonyManager { * @return The bitmask of preferred network types. * * @hide + * @deprecated Use {@link #getAllowedNetworkTypesBitmask} instead. */ + @Deprecated @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @SystemApi public @NetworkTypeBitMask long getPreferredNetworkTypeBitmask() { + return getAllowedNetworkTypesBitmask(); + } + + /** + * Get the allowed network type bitmask. + * Note that the device can only register on the network of {@link NetworkTypeBitmask} + * (except for emergency call cases). + * + * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the + * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()} + * + * <p>Requires Permission: + * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE} + * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). + * + * @return The bitmask of allowed network types. + * + * @hide + */ + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @SystemApi + public @NetworkTypeBitMask long getAllowedNetworkTypesBitmask() { try { ITelephony telephony = getITelephony(); if (telephony != null) { - return (long) RadioAccessFamily.getRafFromNetworkType( - telephony.getPreferredNetworkType(getSubId())); + return (long) telephony.getAllowedNetworkTypesBitmask(getSubId()); } } catch (RemoteException ex) { - Rlog.e(TAG, "getPreferredNetworkTypeBitmask RemoteException", ex); + Rlog.e(TAG, "getAllowedNetworkTypesBitmask RemoteException", ex); } return 0; } /** - * Get the allowed network types. + * Get the allowed network types by carriers. * * <p>Requires Permission: * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE} @@ -7810,14 +7802,17 @@ public class TelephonyManager { * * @return the allowed network type bitmask * @hide + * @deprecated Use {@link #getAllowedNetworkTypesForReason} instead. */ @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @SystemApi + @Deprecated public @NetworkTypeBitMask long getAllowedNetworkTypes() { try { ITelephony telephony = getITelephony(); if (telephony != null) { - return telephony.getAllowedNetworkTypes(getSubId()); + return telephony.getAllowedNetworkTypesForReason(getSubId(), + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER); } } catch (RemoteException ex) { Rlog.e(TAG, "getAllowedNetworkTypes RemoteException", ex); @@ -8039,7 +8034,7 @@ public class TelephonyManager { return false; } - /** + /** * Get the network selection mode. * * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the @@ -8136,7 +8131,7 @@ public class TelephonyManager { * @param networkType the preferred network type * @return true on success; false on any failure. * @hide - * @deprecated Use {@link #setPreferredNetworkTypeBitmask} instead. + * @deprecated Use {@link #setAllowedNetworkTypesForReason} instead. */ @Deprecated @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553) @@ -8144,7 +8139,9 @@ public class TelephonyManager { try { ITelephony telephony = getITelephony(); if (telephony != null) { - return telephony.setPreferredNetworkType(subId, networkType); + return telephony.setAllowedNetworkTypesForReason(subId, + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, + RadioAccessFamily.getRafFromNetworkType(networkType)); } } catch (RemoteException ex) { Rlog.e(TAG, "setPreferredNetworkType RemoteException", ex); @@ -8171,16 +8168,17 @@ public class TelephonyManager { * @param networkTypeBitmask The bitmask of preferred network types. * @return true on success; false on any failure. * @hide + * @deprecated Use {@link #setAllowedNetworkTypesForReason} instead. */ + @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @SystemApi public boolean setPreferredNetworkTypeBitmask(@NetworkTypeBitMask long networkTypeBitmask) { try { ITelephony telephony = getITelephony(); if (telephony != null) { - return telephony.setPreferredNetworkType( - getSubId(), RadioAccessFamily.getNetworkTypeFromRaf( - (int) networkTypeBitmask)); + return telephony.setAllowedNetworkTypesForReason(getSubId(), + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER, networkTypeBitmask); } } catch (RemoteException ex) { Rlog.e(TAG, "setPreferredNetworkTypeBitmask RemoteException", ex); @@ -8201,7 +8199,9 @@ public class TelephonyManager { * @param allowedNetworkTypes The bitmask of allowed network types. * @return true on success; false on any failure. * @hide + * @deprecated Use {@link #setAllowedNetworkTypesForReason} instead. */ + @Deprecated @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @RequiresFeature( enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported", @@ -8211,7 +8211,8 @@ public class TelephonyManager { try { ITelephony telephony = getITelephony(); if (telephony != null) { - return telephony.setAllowedNetworkTypes(getSubId(), allowedNetworkTypes); + return telephony.setAllowedNetworkTypesForReason(getSubId(), + TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER, allowedNetworkTypes); } } catch (RemoteException ex) { Rlog.e(TAG, "setAllowedNetworkTypes RemoteException", ex); @@ -8221,27 +8222,53 @@ public class TelephonyManager { /** @hide */ @IntDef({ - ALLOWED_NETWORK_TYPES_REASON_POWER + ALLOWED_NETWORK_TYPES_REASON_USER, + ALLOWED_NETWORK_TYPES_REASON_POWER, + ALLOWED_NETWORK_TYPES_REASON_CARRIER }) @Retention(RetentionPolicy.SOURCE) - public @interface AllowedNetworkTypesReason{} + public @interface AllowedNetworkTypesReason { + } + + /** + * To indicate allowed network type change is requested by user. + * + * @hide + */ + @SystemApi + public static final int ALLOWED_NETWORK_TYPES_REASON_USER = 0; /** * To indicate allowed network type change is requested by power manager. * Power Manger configuration won't affect the settings configured through - * {@link setAllowedNetworkTypes} and will result in allowing network types that are in both + * other reasons and will result in allowing network types that are in both + * configurations (i.e intersection of both sets). + * + * @hide + */ + @SystemApi + public static final int ALLOWED_NETWORK_TYPES_REASON_POWER = 1; + + /** + * To indicate allowed network type change is requested by carrier. + * Carrier configuration won't affect the settings configured through + * other reasons and will result in allowing network types that are in both * configurations (i.e intersection of both sets). + * * @hide */ - public static final int ALLOWED_NETWORK_TYPES_REASON_POWER = 0; + @SystemApi + public static final int ALLOWED_NETWORK_TYPES_REASON_CARRIER = 2; /** * Set the allowed network types of the device and * provide the reason triggering the allowed network change. * This can be called for following reasons * <ol> + * <li>Allowed network types control by USER {@link #ALLOWED_NETWORK_TYPES_REASON_USER} * <li>Allowed network types control by power manager * {@link #ALLOWED_NETWORK_TYPES_REASON_POWER} + * <li>Allowed network types control by carrier {@link #ALLOWED_NETWORK_TYPES_REASON_CARRIER} * </ol> * This API will result in allowing an intersection of allowed network types for all reasons, * including the configuration done through other reasons. @@ -8257,15 +8284,17 @@ public class TelephonyManager { * @throws IllegalArgumentException if invalid AllowedNetworkTypesReason is passed. * @hide */ + @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) @RequiresFeature( enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported", value = TelephonyManager.CAPABILITY_ALLOWED_NETWORK_TYPES_USED) public void setAllowedNetworkTypesForReason(@AllowedNetworkTypesReason int reason, @NetworkTypeBitMask long allowedNetworkTypes) { - if (reason != ALLOWED_NETWORK_TYPES_REASON_POWER) { + if (!isValidAllowedNetworkTypesReason(reason)) { throw new IllegalArgumentException("invalid AllowedNetworkTypesReason."); } + try { ITelephony telephony = getITelephony(); if (telephony != null) { @@ -8284,28 +8313,29 @@ public class TelephonyManager { * Get the allowed network types for certain reason. * * {@link #getAllowedNetworkTypesForReason} returns allowed network type for a - * specific reason. For effective allowed network types configured on device, - * query {@link getEffectiveAllowedNetworkTypes} + * specific reason. * * <p>Requires Permission: * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE} * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). - *s + * * @param reason the reason the allowed network type change is taking place * @return the allowed network type bitmask - * @throws IllegalStateException if the Telephony process is not currently available. + * @throws IllegalStateException if the Telephony process is not currently available. * @throws IllegalArgumentException if invalid AllowedNetworkTypesReason is passed. * @hide */ + @SystemApi @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) @RequiresFeature( enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported", value = TelephonyManager.CAPABILITY_ALLOWED_NETWORK_TYPES_USED) public @NetworkTypeBitMask long getAllowedNetworkTypesForReason( @AllowedNetworkTypesReason int reason) { - if (reason != ALLOWED_NETWORK_TYPES_REASON_POWER) { + if (!isValidAllowedNetworkTypesReason(reason)) { throw new IllegalArgumentException("invalid AllowedNetworkTypesReason."); } + try { ITelephony telephony = getITelephony(); if (telephony != null) { @@ -8319,44 +8349,27 @@ public class TelephonyManager { } return -1; } - /** - * Get bit mask of all network types. - * - * @return bit mask of all network types + * Verifies that the reason provided is valid. * @hide */ - public static @NetworkTypeBitMask long getAllNetworkTypesBitmask() { - return NETWORK_STANDARDS_FAMILY_BITMASK_3GPP | NETWORK_STANDARDS_FAMILY_BITMASK_3GPP2; + public static boolean isValidAllowedNetworkTypesReason(@AllowedNetworkTypesReason int reason) { + switch (reason) { + case TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_USER: + case TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_POWER: + case TelephonyManager.ALLOWED_NETWORK_TYPES_REASON_CARRIER: + return true; + } + return false; } - /** - * Get the allowed network types configured on the device. - * This API will return an intersection of allowed network types for all reasons, - * including the configuration done through setAllowedNetworkTypes - * - * <p>Requires Permission: - * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE} - * or that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). + * Get bit mask of all network types. * - * @return the allowed network type bitmask - * @throws IllegalStateException if the Telephony process is not currently available. + * @return bit mask of all network types * @hide */ - @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public @NetworkTypeBitMask long getEffectiveAllowedNetworkTypes() { - try { - ITelephony telephony = getITelephony(); - if (telephony != null) { - return telephony.getEffectiveAllowedNetworkTypes(getSubId()); - } else { - throw new IllegalStateException("telephony service is null."); - } - } catch (RemoteException ex) { - Rlog.e(TAG, "getEffectiveAllowedNetworkTypes RemoteException", ex); - ex.rethrowFromSystemServer(); - } - return -1; + public static @NetworkTypeBitMask long getAllNetworkTypesBitmask() { + return NETWORK_STANDARDS_FAMILY_BITMASK_3GPP | NETWORK_STANDARDS_FAMILY_BITMASK_3GPP2; } /** @@ -14098,6 +14111,10 @@ public class TelephonyManager { /** * Enable/Disable E-UTRA-NR Dual Connectivity. * + * This api is supported only if + * {@link android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported} + * ({@link TelephonyManager#CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE}) + * returns true. * @param nrDualConnectivityState expected NR dual connectivity state * This can be passed following states * <ol> @@ -14107,12 +14124,14 @@ public class TelephonyManager { * {@link #NR_DUAL_CONNECTIVITY_DISABLE_IMMEDIATE} * </ol> * @return operation result. - * <p>Requires Permission: - * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE} * @throws IllegalStateException if the Telephony process is not currently available. * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + @RequiresFeature( + enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported", + value = TelephonyManager.CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE) public @EnableNrDualConnectivityResult int setNrDualConnectivityState( @NrDualConnectivityState int nrDualConnectivityState) { try { @@ -14132,15 +14151,21 @@ public class TelephonyManager { /** * Is E-UTRA-NR Dual Connectivity enabled. + * This api is supported only if + * {@link android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported} + * ({@link TelephonyManager#CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE}) + * returns true. * @return true if dual connectivity is enabled else false. Enabled state does not mean dual * connectivity is active. It means the device is allowed to connect to both primary and * secondary cell. - * <p>Requires Permission: - * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE READ_PRIVILEGED_PHONE_STATE} * @throws IllegalStateException if the Telephony process is not currently available. * @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @RequiresFeature( + enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported", + value = TelephonyManager.CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE) public boolean isNrDualConnectivityEnabled() { try { ITelephony telephony = getITelephony(); @@ -14392,11 +14417,23 @@ public class TelephonyManager { public static final String CAPABILITY_ALLOWED_NETWORK_TYPES_USED = "CAPABILITY_ALLOWED_NETWORK_TYPES_USED"; + /** + * Indicates whether {@link #setNrDualConnectivityState()} and + * {@link #isNrDualConnectivityEnabled()} ()} are available. See comments + * on respective methods for more information. + * + * @hide + */ + @SystemApi + public static final String CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE = + "CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE"; + /** @hide */ @Retention(RetentionPolicy.SOURCE) @StringDef(prefix = "CAPABILITY_", value = { CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE, CAPABILITY_ALLOWED_NETWORK_TYPES_USED, + CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE }) public @interface RadioInterfaceCapability {} @@ -14532,6 +14569,75 @@ public class TelephonyManager { return THERMAL_MITIGATION_RESULT_UNKNOWN_ERROR; } + /** + * Registers a callback object to receive notification of changes in specified telephony states. + * <p> + * To register a callback, pass a {@link TelephonyCallback} which implements + * interfaces of events. For example, + * FakeServiceStateCallback extends {@link TelephonyCallback} implements + * {@link TelephonyCallback.ServiceStateListener}. + * + * At registration, and when a specified telephony state changes, the telephony manager invokes + * the appropriate callback method on the callback object and passes the current (updated) + * values. + * <p> + * + * If this TelephonyManager object has been created with {@link #createForSubscriptionId}, + * applies to the given subId. Otherwise, applies to + * {@link SubscriptionManager#getDefaultSubscriptionId()}. To register events for multiple + * subIds, pass a separate callback object to each TelephonyManager object created with + * {@link #createForSubscriptionId}. + * + * Note: if you call this method while in the middle of a binder transaction, you <b>must</b> + * call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A + * {@link SecurityException} will be thrown otherwise. + * + * This API should be used sparingly -- large numbers of callbacks will cause system + * instability. If a process has registered too many callbacks without unregistering them, it + * may encounter an {@link IllegalStateException} when trying to register more callbacks. + * + * @param executor The executor of where the callback will execute. + * @param callback The {@link TelephonyCallback} object to register. + */ + public void registerTelephonyCallback(@NonNull @CallbackExecutor Executor executor, + @NonNull TelephonyCallback callback) { + if (executor == null || callback == null) { + throw new IllegalArgumentException("TelephonyCallback and executor must be non-null"); + } + mTelephonyRegistryMgr = (TelephonyRegistryManager) + mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); + if (mTelephonyRegistryMgr != null) { + mTelephonyRegistryMgr.registerTelephonyCallback(executor, mSubId, getOpPackageName(), + getAttributionTag(), callback, getITelephony() != null); + } else { + throw new IllegalStateException("telephony service is null."); + } + } + + /** + * Unregister an existing {@link TelephonyCallback}. + * + * @param callback The {@link TelephonyCallback} object to unregister. + */ + public void unregisterTelephonyCallback(@NonNull TelephonyCallback callback) { + + if (mContext == null) { + throw new IllegalStateException("telephony service is null."); + } + + if (callback.callback == null) { + return; + } + + mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class); + if (mTelephonyRegistryMgr != null) { + mTelephonyRegistryMgr.unregisterTelephonyCallback(mSubId, getOpPackageName(), + getAttributionTag(), callback, getITelephony() != null); + } else { + throw new IllegalStateException("telephony service is null."); + } + } + /** @hide */ @Retention(RetentionPolicy.SOURCE) @IntDef(prefix = {"GBA_FAILURE_REASON_"}, value = { @@ -14630,17 +14736,26 @@ public class TelephonyManager { * <li>Generate the ks_NAF/ ks_Ext_NAF to be returned via the callback.</li> * </ol> * - * <p> Requires Permission: MODIFY_PHONE_STATE or that the calling app has carrier - * privileges (see {@link #hasCarrierPrivileges}). + * <p> Requires Permission: + * <ul> + * <li>{@link android.Manifest.permission#MODIFY_PHONE_STATE},</li> + * <li>{@link android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION},</li> + * <li>or that the caller has carrier privileges (see + * {@link TelephonyManager#hasCarrierPrivileges()}).</li> + * </ul> * @param appType icc application type, like {@link #APPTYPE_USIM} or {@link * #APPTYPE_ISIM} or {@link#APPTYPE_UNKNOWN} - * @param nafId Network Application Function(NAF) fully qualified domain name and - * the selected GBA mode. It shall contain two parts delimited by "@" sign. The first - * part is the constant string "3GPP-bootstrapping" (GBA_ME), - * "3GPP-bootstrapping-uicc" (GBA_ U), or "3GPP-bootstrapping-digest" (GBA_Digest), - * and the latter part shall be the FQDN of the NAF (e.g. - * "3GPP-bootstrapping@naf1.operator.com" or "3GPP-bootstrapping-uicc@naf1.operator.com", - * or "3GPP-bootstrapping-digest@naf1.operator.com"). + * @param nafId A URI to specify Network Application Function(NAF) fully qualified domain + * name (FQDN) and the selected GBA mode. The authority of the URI must contain two parts + * delimited by "@" sign. The first part is the constant string "3GPP-bootstrapping" (GBA_ME), + * "3GPP-bootstrapping-uicc" (GBA_ U), or "3GPP-bootstrapping-digest" (GBA_Digest). + * The second part shall be the FQDN of the NAF. The scheme of the URI is not actually used + * for the authentication, which may be set the same as the resource that the application is + * going to access. For example, the nafId can be + * "https://3GPP-bootstrapping@naf1.operator.com", + * "https://3GPP-bootstrapping-uicc@naf1.operator.com", + * "https://3GPP-bootstrapping-digest@naf1.operator.com", + * "ftps://3GPP-bootstrapping-digest@naf1.operator.com". * @param securityProtocol Security protocol identifier between UE and NAF. See * 3GPP TS 33.220 Annex H. Application can use * {@link UaSecurityProtocolIdentifier#createDefaultUaSpId}, @@ -14658,7 +14773,8 @@ public class TelephonyManager { */ @SystemApi @WorkerThread - @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + @RequiresPermission(anyOf = {android.Manifest.permission.MODIFY_PHONE_STATE, + Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public void bootstrapAuthenticationRequest( @UiccAppTypeExt int appType, @NonNull Uri nafId, @NonNull UaSecurityProtocolIdentifier securityProtocol, @@ -14702,73 +14818,6 @@ public class TelephonyManager { } /** - * Registers a listener object to receive notification of changes in specified telephony states. - * <p> - * To register a listener, pass a {@link PhoneStateListener} which implements - * interfaces of events. For example, - * FakeServiceStateChangedListener extends {@link PhoneStateListener} implements - * {@link PhoneStateListener.ServiceStateChangedListener}. - * - * At registration, and when a specified telephony state changes, the telephony manager invokes - * the appropriate callback method on the listener object and passes the current (updated) - * values. - * <p> - * - * If this TelephonyManager object has been created with {@link #createForSubscriptionId}, - * applies to the given subId. Otherwise, applies to - * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}. To listen events for multiple subIds, - * pass a separate listener object to each TelephonyManager object created with - * {@link #createForSubscriptionId}. Only {@link PhoneStateListener.CallStateChangedListener} - * can be used to receive changes for all subIds through - * {@link SubscriptionManager#DEFAULT_SUBSCRIPTION_ID}. - * - * Note: if you call this method while in the middle of a binder transaction, you <b>must</b> - * call {@link android.os.Binder#clearCallingIdentity()} before calling this method. A - * {@link SecurityException} will be thrown otherwise. - * - * This API should be used sparingly -- large numbers of listeners will cause system - * instability. If a process has registered too many listeners without unregistering them, it - * may encounter an {@link IllegalStateException} when trying to register more listeners. - * - * @param executor The executor of where the callback will execute. - * @param listener The {@link PhoneStateListener} object to register. - */ - public void registerPhoneStateListener(@NonNull @CallbackExecutor Executor executor, - @NonNull PhoneStateListener listener) { - if (executor == null || listener == null) { - throw new IllegalArgumentException("PhoneStateListener and executor must be non-null"); - } - mTelephonyRegistryMgr = (TelephonyRegistryManager) - mContext.getSystemService(Context.TELEPHONY_REGISTRY_SERVICE); - if (mTelephonyRegistryMgr != null) { - mTelephonyRegistryMgr.registerPhoneStateListener(executor, mSubId, - getOpPackageName(), getAttributionTag(), listener, getITelephony() != null); - } else { - throw new IllegalStateException("telephony service is null."); - } - } - - /** - * Unregister an existing {@link PhoneStateListener}. - * - * @param listener The {@link PhoneStateListener} object to unregister. - */ - public void unregisterPhoneStateListener(@NonNull PhoneStateListener listener) { - - if (mContext == null) { - throw new IllegalStateException("telephony service is null."); - } - - mTelephonyRegistryMgr = mContext.getSystemService(TelephonyRegistryManager.class); - if (mTelephonyRegistryMgr != null) { - mTelephonyRegistryMgr.unregisterPhoneStateListener(mSubId, getOpPackageName(), - getAttributionTag(), listener, getITelephony() != null); - } else { - throw new IllegalStateException("telephony service is null."); - } - } - - /** * The network type is valid or not. * * @param networkType The network type {@link NetworkType}. @@ -14878,7 +14927,9 @@ public class TelephonyManager { public static final int PREPARE_UNATTENDED_REBOOT_PIN_REQUIRED = 1; /** - * The unattended reboot was not prepared due to generic error. + * The unattended reboot was not prepared due to a non-recoverable error. After this error, + * the client that manages the unattended reboot should not try to invoke the API again + * until the next power cycle. * @hide */ @SystemApi diff --git a/telephony/java/android/telephony/data/ApnSetting.java b/telephony/java/android/telephony/data/ApnSetting.java index ff9329ef9742..b503733f8de9 100644 --- a/telephony/java/android/telephony/data/ApnSetting.java +++ b/telephony/java/android/telephony/data/ApnSetting.java @@ -18,6 +18,8 @@ package android.telephony.data; import android.annotation.IntDef; import android.annotation.NonNull; import android.annotation.Nullable; +import android.annotation.StringDef; +import android.annotation.SystemApi; import android.content.ContentValues; import android.database.Cursor; import android.hardware.radio.V1_5.ApnTypes; @@ -26,7 +28,6 @@ import android.os.Parcel; import android.os.Parcelable; import android.provider.Telephony; import android.provider.Telephony.Carriers; -import android.telephony.Annotation.ApnType; import android.telephony.Annotation.NetworkType; import android.telephony.ServiceState; import android.telephony.TelephonyManager; @@ -113,6 +114,31 @@ public class ApnSetting implements Parcelable { public static final int TYPE_MCX = ApnTypes.MCX; /** APN type for XCAP. */ public static final int TYPE_XCAP = ApnTypes.XCAP; + /** + * APN type for ENTERPRISE. + * @hide + */ + public static final int TYPE_ENTERPRISE = TYPE_XCAP << 1; + + /** @hide */ + @IntDef(flag = true, prefix = {"TYPE_"}, value = { + TYPE_DEFAULT, + TYPE_MMS, + TYPE_SUPL, + TYPE_DUN, + TYPE_HIPRI, + TYPE_FOTA, + TYPE_IMS, + TYPE_CBS, + TYPE_IA, + TYPE_EMERGENCY, + TYPE_MCX, + TYPE_XCAP, + TYPE_ENTERPRISE, + }) + @Retention(RetentionPolicy.SOURCE) + public @interface ApnType { + } // Possible values for authentication types. /** No authentication type. */ @@ -133,6 +159,26 @@ public class ApnSetting implements Parcelable { @Retention(RetentionPolicy.SOURCE) public @interface Skip464XlatStatus {} + /** @hide */ + @StringDef(value = { + TYPE_ALL_STRING, + TYPE_CBS_STRING, + TYPE_DEFAULT_STRING, + TYPE_DUN_STRING, + TYPE_EMERGENCY_STRING, + TYPE_FOTA_STRING, + TYPE_HIPRI_STRING, + TYPE_IA_STRING, + TYPE_IMS_STRING, + TYPE_MCX_STRING, + TYPE_MMS_STRING, + TYPE_SUPL_STRING, + TYPE_XCAP_STRING, + TYPE_ENTERPRISE_STRING, + }, prefix = "TYPE_", suffix = "_STRING") + @Retention(RetentionPolicy.SOURCE) + public @interface ApnTypeString {} + /** * APN types for data connections. These are usage categories for an APN * entry. One APN entry may support multiple APN types, eg, a single APN @@ -140,101 +186,141 @@ public class ApnSetting implements Parcelable { * connections.<br/> * APN_TYPE_ALL is a special type to indicate that this APN entry can * service all data connections. - * <p> - * Note: The goal is to deprecate this. Due to the Carrier Table being used - * directly, this isn't feasible right now. * * @hide */ + @SystemApi public static final String TYPE_ALL_STRING = "*"; /** * APN type for default data traffic * + * Note: String representations of APN types are intended for system apps to communicate with + * modem components or carriers. Non-system apps should use the integer variants instead. * @hide */ + @SystemApi public static final String TYPE_DEFAULT_STRING = "default"; /** - * APN type for MMS traffic + * APN type for MMS (Multimedia Messaging Service) traffic. * + * Note: String representations of APN types are intended for system apps to communicate with + * modem components or carriers. Non-system apps should use the integer variants instead. * @hide */ + @SystemApi public static final String TYPE_MMS_STRING = "mms"; /** - * APN type for SUPL assisted GPS + * APN type for SUPL (Secure User Plane Location) assisted GPS. * + * Note: String representations of APN types are intended for system apps to communicate with + * modem components or carriers. Non-system apps should use the integer variants instead. * @hide */ + @SystemApi public static final String TYPE_SUPL_STRING = "supl"; /** - * APN type for DUN traffic + * APN type for DUN (Dial-up networking) traffic * + * Note: String representations of APN types are intended for system apps to communicate with + * modem components or carriers. Non-system apps should use the integer variants instead. * @hide */ + @SystemApi public static final String TYPE_DUN_STRING = "dun"; /** - * APN type for HiPri traffic + * APN type for high-priority traffic * + * Note: String representations of APN types are intended for system apps to communicate with + * modem components or carriers. Non-system apps should use the integer variants instead. * @hide */ + @SystemApi public static final String TYPE_HIPRI_STRING = "hipri"; /** - * APN type for FOTA + * APN type for FOTA (Firmware over-the-air) traffic. * + * Note: String representations of APN types are intended for system apps to communicate with + * modem components or carriers. Non-system apps should use the integer variants instead. * @hide */ + @SystemApi public static final String TYPE_FOTA_STRING = "fota"; /** - * APN type for IMS + * APN type for IMS (IP Multimedia Subsystem) traffic. * + * Note: String representations of APN types are intended for system apps to communicate with + * modem components or carriers. Non-system apps should use the integer variants instead. * @hide */ + @SystemApi public static final String TYPE_IMS_STRING = "ims"; /** - * APN type for CBS + * APN type for CBS (Carrier Branded Services) traffic. * + * Note: String representations of APN types are intended for system apps to communicate with + * modem components or carriers. Non-system apps should use the integer variants instead. * @hide */ + @SystemApi public static final String TYPE_CBS_STRING = "cbs"; /** - * APN type for IA Initial Attach APN + * APN type for the IA (Initial Attach) APN * + * Note: String representations of APN types are intended for system apps to communicate with + * modem components or carriers. Non-system apps should use the integer variants instead. * @hide */ + @SystemApi public static final String TYPE_IA_STRING = "ia"; /** * APN type for Emergency PDN. This is not an IA apn, but is used * for access to carrier services in an emergency call situation. * + * Note: String representations of APN types are intended for system apps to communicate with + * modem components or carriers. Non-system apps should use the integer variants instead. * @hide */ + @SystemApi public static final String TYPE_EMERGENCY_STRING = "emergency"; /** - * APN type for Mission Critical Services + * APN type for Mission Critical Services. * + * Note: String representations of APN types are intended for system apps to communicate with + * modem components or carriers. Non-system apps should use the integer variants instead. * @hide */ + @SystemApi public static final String TYPE_MCX_STRING = "mcx"; /** - * APN type for XCAP + * APN type for XCAP (XML Configuration Access Protocol) traffic. * + * Note: String representations of APN types are intended for system apps to communicate with + * modem components or carriers. Non-system apps should use the integer variants instead. * @hide */ + @SystemApi public static final String TYPE_XCAP_STRING = "xcap"; + /** + * APN type for ENTERPRISE traffic. + * @hide + */ + public static final String TYPE_ENTERPRISE_STRING = "enterprise"; + /** @hide */ @IntDef(prefix = { "AUTH_TYPE_" }, value = { @@ -314,6 +400,7 @@ public class ApnSetting implements Parcelable { APN_TYPE_STRING_MAP.put(TYPE_EMERGENCY_STRING, TYPE_EMERGENCY); APN_TYPE_STRING_MAP.put(TYPE_MCX_STRING, TYPE_MCX); APN_TYPE_STRING_MAP.put(TYPE_XCAP_STRING, TYPE_XCAP); + APN_TYPE_STRING_MAP.put(TYPE_ENTERPRISE_STRING, TYPE_ENTERPRISE); APN_TYPE_INT_MAP = new ArrayMap<>(); APN_TYPE_INT_MAP.put(TYPE_DEFAULT, TYPE_DEFAULT_STRING); @@ -328,6 +415,7 @@ public class ApnSetting implements Parcelable { APN_TYPE_INT_MAP.put(TYPE_EMERGENCY, TYPE_EMERGENCY_STRING); APN_TYPE_INT_MAP.put(TYPE_MCX, TYPE_MCX_STRING); APN_TYPE_INT_MAP.put(TYPE_XCAP, TYPE_XCAP_STRING); + APN_TYPE_INT_MAP.put(TYPE_ENTERPRISE, TYPE_ENTERPRISE_STRING); PROTOCOL_STRING_MAP = new ArrayMap<>(); PROTOCOL_STRING_MAP.put("IP", PROTOCOL_IP); @@ -1426,16 +1514,43 @@ public class ApnSetting implements Parcelable { } /** - * @param apnType APN type - * @return APN type in string format + * Converts the integer representation of APN type to its string representation. + * + * @param apnType APN type as an integer + * @return String representation of the APN type, or an empty string if the provided integer is + * not a valid APN type. * @hide */ - public static String getApnTypeString(int apnType) { + @SystemApi + public static @NonNull @ApnTypeString String getApnTypeString(@ApnType int apnType) { if (apnType == TYPE_ALL) { return "*"; } String apnTypeString = APN_TYPE_INT_MAP.get(apnType); - return apnTypeString == null ? "Unknown" : apnTypeString; + return apnTypeString == null ? "" : apnTypeString; + } + + /** + * Same as {@link #getApnTypeString(int)}, but returns "Unknown" instead of an empty string + * when provided with an invalid int for compatibility purposes. + * @hide + */ + public static @NonNull String getApnTypeStringInternal(@ApnType int apnType) { + String result = getApnTypeString(apnType); + return TextUtils.isEmpty(result) ? "Unknown" : result; + } + + /** + * Converts the string representation of an APN type to its integer representation. + * + * @param apnType APN type as a string + * @return Integer representation of the APN type, or 0 if the provided string is not a valid + * APN type. + * @hide + */ + @SystemApi + public static @ApnType int getApnTypeInt(@NonNull @ApnTypeString String apnType) { + return APN_TYPE_STRING_MAP.getOrDefault(apnType.toLowerCase(), 0); } /** @@ -2079,7 +2194,7 @@ public class ApnSetting implements Parcelable { public ApnSetting build() { if ((mApnTypeBitmask & (TYPE_DEFAULT | TYPE_MMS | TYPE_SUPL | TYPE_DUN | TYPE_HIPRI | TYPE_FOTA | TYPE_IMS | TYPE_CBS | TYPE_IA | TYPE_EMERGENCY | TYPE_MCX - | TYPE_XCAP)) == 0 + | TYPE_XCAP | TYPE_ENTERPRISE)) == 0 || TextUtils.isEmpty(mApnName) || TextUtils.isEmpty(mEntryName)) { return null; } diff --git a/telephony/java/android/telephony/data/DataCallResponse.java b/telephony/java/android/telephony/data/DataCallResponse.java index 46940dc6a0a5..a5e5ab01810f 100644 --- a/telephony/java/android/telephony/data/DataCallResponse.java +++ b/telephony/java/android/telephony/data/DataCallResponse.java @@ -136,8 +136,9 @@ public final class DataCallResponse implements Parcelable { private final @HandoverFailureMode int mHandoverFailureMode; private final int mPduSessionId; private final Qos mDefaultQos; - private final List<QosSession> mQosSessions; + private final List<QosBearerSession> mQosBearerSessions; private final SliceInfo mSliceInfo; + private final List<TrafficDescriptor> mTrafficDescriptors; /** * @param cause Data call fail cause. {@link DataFailCause#NONE} indicates no error. @@ -187,8 +188,9 @@ public final class DataCallResponse implements Parcelable { mHandoverFailureMode = HANDOVER_FAILURE_MODE_LEGACY; mPduSessionId = PDU_SESSION_ID_NOT_SET; mDefaultQos = null; - mQosSessions = new ArrayList<>(); + mQosBearerSessions = new ArrayList<>(); mSliceInfo = null; + mTrafficDescriptors = new ArrayList<>(); } private DataCallResponse(@DataFailureCause int cause, long suggestedRetryTime, int id, @@ -197,8 +199,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 SliceInfo sliceInfo) { + @Nullable Qos defaultQos, @Nullable List<QosBearerSession> qosBearerSessions, + @Nullable SliceInfo sliceInfo, @Nullable List<TrafficDescriptor> trafficDescriptors) { mCause = cause; mSuggestedRetryTime = suggestedRetryTime; mId = id; @@ -219,8 +221,11 @@ public final class DataCallResponse implements Parcelable { mHandoverFailureMode = handoverFailureMode; mPduSessionId = pduSessionId; mDefaultQos = defaultQos; - mQosSessions = qosSessions; + mQosBearerSessions = (qosBearerSessions == null) + ? new ArrayList<>() : new ArrayList<>(qosBearerSessions); mSliceInfo = sliceInfo; + mTrafficDescriptors = (trafficDescriptors == null) + ? new ArrayList<>() : new ArrayList<>(trafficDescriptors); } /** @hide */ @@ -246,9 +251,11 @@ public final class DataCallResponse implements Parcelable { mHandoverFailureMode = source.readInt(); mPduSessionId = source.readInt(); mDefaultQos = source.readParcelable(Qos.class.getClassLoader()); - mQosSessions = new ArrayList<>(); - source.readList(mQosSessions, QosSession.class.getClassLoader()); + mQosBearerSessions = new ArrayList<>(); + source.readList(mQosBearerSessions, QosBearerSession.class.getClassLoader()); mSliceInfo = source.readParcelable(SliceInfo.class.getClassLoader()); + mTrafficDescriptors = new ArrayList<>(); + source.readList(mTrafficDescriptors, TrafficDescriptor.class.getClassLoader()); } /** @@ -380,7 +387,6 @@ public final class DataCallResponse implements Parcelable { * * @hide */ - @Nullable public Qos getDefaultQos() { return mDefaultQos; @@ -393,8 +399,8 @@ public final class DataCallResponse implements Parcelable { * @hide */ @NonNull - public List<QosSession> getQosSessions() { - return mQosSessions; + public List<QosBearerSession> getQosBearerSessions() { + return mQosBearerSessions; } /** @@ -405,6 +411,14 @@ public final class DataCallResponse implements Parcelable { return mSliceInfo; } + /** + * @return The traffic descriptors related to this data connection. + */ + @NonNull + public List<TrafficDescriptor> getTrafficDescriptors() { + return mTrafficDescriptors; + } + @NonNull @Override public String toString() { @@ -426,8 +440,9 @@ public final class DataCallResponse implements Parcelable { .append(" handoverFailureMode=").append(getHandoverFailureMode()) .append(" pduSessionId=").append(getPduSessionId()) .append(" defaultQos=").append(mDefaultQos) - .append(" qosSessions=").append(mQosSessions) + .append(" qosBearerSessions=").append(mQosBearerSessions) .append(" sliceInfo=").append(mSliceInfo) + .append(" trafficDescriptors=").append(mTrafficDescriptors) .append("}"); return sb.toString(); } @@ -442,14 +457,21 @@ public final class DataCallResponse implements Parcelable { DataCallResponse other = (DataCallResponse) o; - final boolean isQosSame = (mDefaultQos == null || other.mDefaultQos == null) ? - mDefaultQos == other.mDefaultQos : - mDefaultQos.equals(other.mDefaultQos); + final boolean isQosSame = (mDefaultQos == null || other.mDefaultQos == null) + ? mDefaultQos == other.mDefaultQos + : mDefaultQos.equals(other.mDefaultQos); - final boolean isQosSessionsSame = (mQosSessions == null || mQosSessions == null) ? - mQosSessions == other.mQosSessions : - mQosSessions.size() == other.mQosSessions.size() - && mQosSessions.containsAll(other.mQosSessions); + final boolean isQosBearerSessionsSame = + (mQosBearerSessions == null || other.mQosBearerSessions == null) + ? mQosBearerSessions == other.mQosBearerSessions + : mQosBearerSessions.size() == other.mQosBearerSessions.size() + && mQosBearerSessions.containsAll(other.mQosBearerSessions); + + final boolean isTrafficDescriptorsSame = + (mTrafficDescriptors == null || other.mTrafficDescriptors == null) + ? mTrafficDescriptors == other.mTrafficDescriptors + : mTrafficDescriptors.size() == other.mTrafficDescriptors.size() + && mTrafficDescriptors.containsAll(other.mTrafficDescriptors); return mCause == other.mCause && mSuggestedRetryTime == other.mSuggestedRetryTime @@ -471,8 +493,9 @@ public final class DataCallResponse implements Parcelable { && mHandoverFailureMode == other.mHandoverFailureMode && mPduSessionId == other.mPduSessionId && isQosSame - && isQosSessionsSame - && Objects.equals(mSliceInfo, other.mSliceInfo); + && isQosBearerSessionsSame + && Objects.equals(mSliceInfo, other.mSliceInfo) + && isTrafficDescriptorsSame; } @Override @@ -480,7 +503,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, mSliceInfo); + mQosBearerSessions, mSliceInfo, mTrafficDescriptors); } @Override @@ -510,8 +533,9 @@ public final class DataCallResponse implements Parcelable { } else { dest.writeParcelable((NrQos)mDefaultQos, flags); } - dest.writeList(mQosSessions); + dest.writeList(mQosBearerSessions); dest.writeParcelable(mSliceInfo, flags); + dest.writeList(mTrafficDescriptors); } public static final @android.annotation.NonNull Parcelable.Creator<DataCallResponse> CREATOR = @@ -593,10 +617,12 @@ public final class DataCallResponse implements Parcelable { private Qos mDefaultQos; - private List<QosSession> mQosSessions = new ArrayList<>(); + private List<QosBearerSession> mQosBearerSessions = new ArrayList<>(); private SliceInfo mSliceInfo; + private List<TrafficDescriptor> mTrafficDescriptors = new ArrayList<>(); + /** * Default constructor for Builder. */ @@ -807,15 +833,16 @@ public final class DataCallResponse implements Parcelable { /** * Set the dedicated bearer QOS sessions for this data connection. * - * @param qosSessions Dedicated bearer QOS (Quality Of Service) sessions received + * @param qosBearerSessions Dedicated bearer QOS (Quality Of Service) sessions received * from network. * * @return The same instance of the builder. * * @hide */ - public @NonNull Builder setQosSessions(@NonNull List<QosSession> qosSessions) { - mQosSessions = qosSessions; + public @NonNull Builder setQosBearerSessions( + @NonNull List<QosBearerSession> qosBearerSessions) { + mQosBearerSessions = qosBearerSessions; return this; } @@ -835,6 +862,24 @@ public final class DataCallResponse implements Parcelable { } /** + * The traffic descriptors for this data connection, as defined in 3GPP TS 24.526 + * Section 5.2. They are used for URSP traffic matching as described in 3GPP TS 24.526 + * Section 4.2.2. They includes an optional DNN, which, if present, must be used for traffic + * matching; it does not specify the end point to be used for the data call. The end point + * is specified by {@link DataProfile}, which must be used as the end point if one is not + * specified through URSP rules. + * + * @param trafficDescriptors the traffic descriptors for the data call. + * + * @return The same instance of the builder. + */ + public @NonNull Builder setTrafficDescriptors( + @NonNull List<TrafficDescriptor> trafficDescriptors) { + mTrafficDescriptors = trafficDescriptors; + return this; + } + + /** * Build the DataCallResponse. * * @return the DataCallResponse object. @@ -843,7 +888,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, mSliceInfo); + mDefaultQos, mQosBearerSessions, mSliceInfo, mTrafficDescriptors); } } } diff --git a/telephony/java/android/telephony/data/DataService.java b/telephony/java/android/telephony/data/DataService.java index 03c2ef9d9baa..f5f29c65b7cd 100644 --- a/telephony/java/android/telephony/data/DataService.java +++ b/telephony/java/android/telephony/data/DataService.java @@ -200,6 +200,17 @@ public abstract class DataService extends Service { * 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 trafficDescriptor {@link TrafficDescriptor} for which data connection needs to be + * established. It is used for URSP traffic matching as described in 3GPP TS 24.526 + * Section 4.2.2. It includes an optional DNN which, if present, must be used for + * traffic matching; it does not specify the end point to be used for the data call. + * @param matchAllRuleAllowed Indicates if using default match-all URSP rule for this + * request is allowed. If false, this request must not use the match-all URSP rule + * and if a non-match-all rule is not found (or if URSP rules are not available) then + * {@link DataCallResponse#getCause()} is + * {@link android.telephony.DataFailCause#MATCH_ALL_RULE_NOT_ALLOWED}. This is needed + * as some requests need to have a hard failure if the intention cannot be met, + * for example, a zero-rating slice. * @param callback The result callback for this request. */ public void setupDataCall(int accessNetworkType, @NonNull DataProfile dataProfile, @@ -207,6 +218,7 @@ public abstract class DataService extends Service { @SetupDataReason int reason, @Nullable LinkProperties linkProperties, @IntRange(from = 0, to = 15) int pduSessionId, @Nullable SliceInfo sliceInfo, + @Nullable TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed, @NonNull DataServiceCallback callback) { /* Call the old version since the new version isn't supported */ setupDataCall(accessNetworkType, dataProfile, isRoaming, allowRoaming, reason, @@ -283,6 +295,8 @@ public abstract class DataService extends Service { * * @param cid The identifier of the data call which is provided in {@link DataCallResponse} * @param callback The result callback for this request. + * + * @hide */ public void startHandover(int cid, @NonNull DataServiceCallback callback) { // The default implementation is to return unsupported. @@ -303,6 +317,8 @@ public abstract class DataService extends Service { * * @param cid The identifier of the data call which is provided in {@link DataCallResponse} * @param callback The result callback for this request. + * + * @hide */ public void cancelHandover(int cid, @NonNull DataServiceCallback callback) { // The default implementation is to return unsupported. @@ -399,10 +415,13 @@ public abstract class DataService extends Service { public final LinkProperties linkProperties; public final int pduSessionId; public final SliceInfo sliceInfo; + public final TrafficDescriptor trafficDescriptor; + public final boolean matchAllRuleAllowed; public final IDataServiceCallback callback; SetupDataCallRequest(int accessNetworkType, DataProfile dataProfile, boolean isRoaming, - boolean allowRoaming, int reason, LinkProperties linkProperties, - int pduSessionId, SliceInfo sliceInfo, IDataServiceCallback callback) { + boolean allowRoaming, int reason, LinkProperties linkProperties, int pduSessionId, + SliceInfo sliceInfo, TrafficDescriptor trafficDescriptor, + boolean matchAllRuleAllowed, IDataServiceCallback callback) { this.accessNetworkType = accessNetworkType; this.dataProfile = dataProfile; this.isRoaming = isRoaming; @@ -411,6 +430,8 @@ public abstract class DataService extends Service { this.reason = reason; this.pduSessionId = pduSessionId; this.sliceInfo = sliceInfo; + this.trafficDescriptor = trafficDescriptor; + this.matchAllRuleAllowed = matchAllRuleAllowed; this.callback = callback; } } @@ -521,7 +542,8 @@ public abstract class DataService extends Service { setupDataCallRequest.dataProfile, setupDataCallRequest.isRoaming, setupDataCallRequest.allowRoaming, setupDataCallRequest.reason, setupDataCallRequest.linkProperties, setupDataCallRequest.pduSessionId, - setupDataCallRequest.sliceInfo, + setupDataCallRequest.sliceInfo, setupDataCallRequest.trafficDescriptor, + setupDataCallRequest.matchAllRuleAllowed, (setupDataCallRequest.callback != null) ? new DataServiceCallback(setupDataCallRequest.callback) : null); @@ -686,11 +708,12 @@ public abstract class DataService extends Service { public void setupDataCall(int slotIndex, int accessNetworkType, DataProfile dataProfile, boolean isRoaming, boolean allowRoaming, int reason, LinkProperties linkProperties, int pduSessionId, SliceInfo sliceInfo, + TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed, IDataServiceCallback callback) { mHandler.obtainMessage(DATA_SERVICE_REQUEST_SETUP_DATA_CALL, slotIndex, 0, new SetupDataCallRequest(accessNetworkType, dataProfile, isRoaming, allowRoaming, reason, linkProperties, pduSessionId, sliceInfo, - callback)) + trafficDescriptor, matchAllRuleAllowed, callback)) .sendToTarget(); } diff --git a/telephony/java/android/telephony/data/DataServiceCallback.java b/telephony/java/android/telephony/data/DataServiceCallback.java index f56c19b78a16..363e47a6d242 100644 --- a/telephony/java/android/telephony/data/DataServiceCallback.java +++ b/telephony/java/android/telephony/data/DataServiceCallback.java @@ -191,6 +191,8 @@ public class DataServiceCallback { * Called to indicate result for the request {@link DataService#startHandover}. * * @param result The result code. Must be one of the {@link ResultCode} + * + * @hide */ public void onHandoverStarted(@ResultCode int result) { if (mCallback != null) { @@ -209,6 +211,8 @@ public class DataServiceCallback { * Called to indicate result for the request {@link DataService#cancelHandover}. * * @param result The result code. Must be one of the {@link ResultCode} + * + * @hide */ public void onHandoverCancelled(@ResultCode int result) { if (mCallback != null) { @@ -250,15 +254,15 @@ public class DataServiceCallback { } /** - * The APN is throttled for the duration specified in - * {@link DataCallResponse#getRetryDurationMillis}. Calling this method unthrottles that - * APN. + * Unthrottles the APN on the current transport. There is no matching "APN throttle" method. + * Instead, the APN is throttled for the time specified in + * {@link DataCallResponse#getRetryDurationMillis}. * <p/> * see: {@link DataCallResponse#getRetryDurationMillis} * * @param apn Access Point Name defined by the carrier. */ - public void onApnUnthrottled(@NonNull String apn) { + public void onApnUnthrottled(final @NonNull String apn) { if (mCallback != null) { try { if (DBG) Rlog.d(TAG, "onApnUnthrottled"); diff --git a/telephony/java/android/telephony/data/EpsBearerQosSessionAttributes.java b/telephony/java/android/telephony/data/EpsBearerQosSessionAttributes.java index 041edc00c4d2..406c38bf60ef 100644 --- a/telephony/java/android/telephony/data/EpsBearerQosSessionAttributes.java +++ b/telephony/java/android/telephony/data/EpsBearerQosSessionAttributes.java @@ -184,16 +184,6 @@ public final class EpsBearerQosSessionAttributes implements Parcelable, QosSessi mRemoteAddresses = Collections.unmodifiableList(remoteAddresses); } - /** - * Creates attributes based off of a parcel - * @param in the parcel - * @return the attributes - */ - @NonNull - public static EpsBearerQosSessionAttributes create(@NonNull final Parcel in) { - return new EpsBearerQosSessionAttributes(in); - } - @Override public int describeContents() { return 0; diff --git a/telephony/java/android/telephony/data/EpsQos.java b/telephony/java/android/telephony/data/EpsQos.java index ad43068b2f11..22c8b0a0a74f 100644 --- a/telephony/java/android/telephony/data/EpsQos.java +++ b/telephony/java/android/telephony/data/EpsQos.java @@ -48,6 +48,10 @@ public final class EpsQos extends Qos implements Parcelable { qosClassId = source.readInt(); } + public int getQci() { + return qosClassId; + } + public static @NonNull EpsQos createFromParcelBody(@NonNull Parcel in) { return new EpsQos(in); } diff --git a/telephony/java/android/telephony/data/IDataService.aidl b/telephony/java/android/telephony/data/IDataService.aidl index e0b9a1a9bb5a..81f5fd3b69a9 100644 --- a/telephony/java/android/telephony/data/IDataService.aidl +++ b/telephony/java/android/telephony/data/IDataService.aidl @@ -20,6 +20,7 @@ import android.net.LinkProperties; import android.telephony.data.DataProfile; import android.telephony.data.IDataServiceCallback; import android.telephony.data.SliceInfo; +import android.telephony.data.TrafficDescriptor; /** * {@hide} @@ -30,7 +31,9 @@ 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, in SliceInfo sliceInfo, IDataServiceCallback callback); + int pduSessionId, in SliceInfo sliceInfo, + in TrafficDescriptor trafficDescriptor, boolean matchAllRuleAllowed, + 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/Qos.java b/telephony/java/android/telephony/data/Qos.java index c8bb91e28bf2..c286c6217450 100644 --- a/telephony/java/android/telephony/data/Qos.java +++ b/telephony/java/android/telephony/data/Qos.java @@ -56,7 +56,15 @@ public abstract class Qos { this.uplink = new QosBandwidth(uplink.maxBitrateKbps, uplink.guaranteedBitrateKbps); } - static class QosBandwidth implements Parcelable { + public QosBandwidth getDownlinkBandwidth() { + return downlink; + } + + public QosBandwidth getUplinkBandwidth() { + return uplink; + } + + public static class QosBandwidth implements Parcelable { int maxBitrateKbps; int guaranteedBitrateKbps; @@ -73,6 +81,14 @@ public abstract class Qos { guaranteedBitrateKbps = source.readInt(); } + public int getMaxBitrateKbps() { + return maxBitrateKbps; + } + + public int getGuaranteedBitrateKbps() { + return guaranteedBitrateKbps; + } + @Override public void writeToParcel(Parcel dest, int flags) { dest.writeInt(maxBitrateKbps); diff --git a/telephony/java/android/telephony/data/QosFilter.java b/telephony/java/android/telephony/data/QosBearerFilter.java index 69277445634d..6c1c653f13d0 100644 --- a/telephony/java/android/telephony/data/QosFilter.java +++ b/telephony/java/android/telephony/data/QosBearerFilter.java @@ -38,7 +38,7 @@ import java.util.Objects; * * @hide */ -public final class QosFilter implements Parcelable { +public final class QosBearerFilter implements Parcelable { private List<LinkAddress> localAddresses; private List<LinkAddress> remoteAddresses; @@ -74,7 +74,7 @@ public final class QosFilter implements Parcelable { @IntDef(prefix = "QOS_FILTER_DIRECTION_", value = {QOS_FILTER_DIRECTION_DOWNLINK, QOS_FILTER_DIRECTION_UPLINK, QOS_FILTER_DIRECTION_BIDIRECTIONAL}) - public @interface QosFilterDirection {} + public @interface QosBearerFilterDirection {} public static final int QOS_FILTER_DIRECTION_DOWNLINK = android.hardware.radio.V1_6.QosFilterDirection.DOWNLINK; @@ -83,7 +83,7 @@ public final class QosFilter implements Parcelable { public static final int QOS_FILTER_DIRECTION_BIDIRECTIONAL = android.hardware.radio.V1_6.QosFilterDirection.BIDIRECTIONAL; - @QosFilterDirection + @QosBearerFilterDirection private int filterDirection; /** @@ -92,7 +92,7 @@ public final class QosFilter implements Parcelable { */ private int precedence; - QosFilter() { + QosBearerFilter() { localAddresses = new ArrayList<>(); remoteAddresses = new ArrayList<>(); localPort = new PortRange(); @@ -101,7 +101,7 @@ public final class QosFilter implements Parcelable { filterDirection = QOS_FILTER_DIRECTION_BIDIRECTIONAL; } - public QosFilter(List<LinkAddress> localAddresses, List<LinkAddress> remoteAddresses, + public QosBearerFilter(List<LinkAddress> localAddresses, List<LinkAddress> remoteAddresses, PortRange localPort, PortRange remotePort, int protocol, int tos, long flowLabel, long spi, int direction, int precedence) { this.localAddresses = localAddresses; @@ -116,10 +116,30 @@ public final class QosFilter implements Parcelable { this.precedence = precedence; } + public List<LinkAddress> getLocalAddresses() { + return localAddresses; + } + + public List<LinkAddress> getRemoteAddresses() { + return remoteAddresses; + } + + public PortRange getLocalPortRange() { + return localPort; + } + + public PortRange getRemotePortRange() { + return remotePort; + } + + public int getPrecedence() { + return precedence; + } + /** @hide */ - public static @NonNull QosFilter create( + public static @NonNull QosBearerFilter create( @NonNull android.hardware.radio.V1_6.QosFilter qosFilter) { - QosFilter ret = new QosFilter(); + QosBearerFilter ret = new QosBearerFilter(); String[] localAddresses = qosFilter.localAddresses.stream().toArray(String[]::new); if (localAddresses != null) { @@ -202,6 +222,14 @@ public final class QosFilter implements Parcelable { this.end = end; } + public int getStart() { + return start; + } + + public int getEnd() { + return end; + } + @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeInt(start); @@ -254,7 +282,7 @@ public final class QosFilter implements Parcelable { @Override public String toString() { - return "QosFilter {" + return "QosBearerFilter {" + " localAddresses=" + localAddresses + " remoteAddresses=" + remoteAddresses + " localPort=" + localPort @@ -278,11 +306,11 @@ public final class QosFilter implements Parcelable { public boolean equals(Object o) { if (this == o) return true; - if (o == null || !(o instanceof QosFilter)) { + if (o == null || !(o instanceof QosBearerFilter)) { return false; } - QosFilter other = (QosFilter) o; + QosBearerFilter other = (QosBearerFilter) o; return localAddresses.size() == other.localAddresses.size() && localAddresses.containsAll(other.localAddresses) @@ -324,7 +352,7 @@ public final class QosFilter implements Parcelable { LinkAddress.LIFETIME_UNKNOWN, LinkAddress.LIFETIME_UNKNOWN); } - private QosFilter(Parcel source) { + private QosBearerFilter(Parcel source) { localAddresses = new ArrayList<>(); source.readList(localAddresses, LinkAddress.class.getClassLoader()); remoteAddresses = new ArrayList<>(); @@ -358,16 +386,16 @@ public final class QosFilter implements Parcelable { return 0; } - public static final @NonNull Parcelable.Creator<QosFilter> CREATOR = - new Parcelable.Creator<QosFilter>() { + public static final @NonNull Parcelable.Creator<QosBearerFilter> CREATOR = + new Parcelable.Creator<QosBearerFilter>() { @Override - public QosFilter createFromParcel(Parcel source) { - return new QosFilter(source); + public QosBearerFilter createFromParcel(Parcel source) { + return new QosBearerFilter(source); } @Override - public QosFilter[] newArray(int size) { - return new QosFilter[size]; + public QosBearerFilter[] newArray(int size) { + return new QosBearerFilter[size]; } }; } diff --git a/telephony/java/android/telephony/data/QosBearerSession.java b/telephony/java/android/telephony/data/QosBearerSession.java new file mode 100644 index 000000000000..30effc9273d7 --- /dev/null +++ b/telephony/java/android/telephony/data/QosBearerSession.java @@ -0,0 +1,137 @@ +/** + * 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. + */ + +package android.telephony.data; + +import android.annotation.NonNull; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; + + +/** + * Class that stores information specific to QOS session. + * + * @hide + */ +public final class QosBearerSession implements Parcelable{ + + final int qosBearerSessionId; + final Qos qos; + final List<QosBearerFilter> qosBearerFilterList; + + public QosBearerSession(int qosBearerSessionId, @NonNull Qos qos, @NonNull List<QosBearerFilter> qosBearerFilterList) { + this.qosBearerSessionId = qosBearerSessionId; + this.qos = qos; + this.qosBearerFilterList = qosBearerFilterList; + } + + private QosBearerSession(Parcel source) { + qosBearerSessionId = source.readInt(); + qos = source.readParcelable(Qos.class.getClassLoader()); + qosBearerFilterList = new ArrayList<>(); + source.readList(qosBearerFilterList, QosBearerFilter.class.getClassLoader()); + } + + public int getQosBearerSessionId() { + return qosBearerSessionId; + } + + public Qos getQos() { + return qos; + } + + public List<QosBearerFilter> getQosBearerFilterList() { + return qosBearerFilterList; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeInt(qosBearerSessionId); + if (qos.getType() == Qos.QOS_TYPE_EPS) { + dest.writeParcelable((EpsQos)qos, flags); + } else { + dest.writeParcelable((NrQos)qos, flags); + } + dest.writeList(qosBearerFilterList); + } + + public static @NonNull QosBearerSession create( + @NonNull android.hardware.radio.V1_6.QosSession qosSession) { + List<QosBearerFilter> qosBearerFilters = new ArrayList<>(); + + if (qosSession.qosFilters != null) { + for (android.hardware.radio.V1_6.QosFilter filter : qosSession.qosFilters) { + qosBearerFilters.add(QosBearerFilter.create(filter)); + } + } + + return new QosBearerSession( + qosSession.qosSessionId, + Qos.create(qosSession.qos), + qosBearerFilters); + } + + @Override + public int describeContents() { + return 0; + } + + @Override + public String toString() { + return "QosBearerSession {" + + " qosBearerSessionId=" + qosBearerSessionId + + " qos=" + qos + + " qosBearerFilterList=" + qosBearerFilterList + "}"; + } + + @Override + public int hashCode() { + return Objects.hash(qosBearerSessionId, qos, qosBearerFilterList); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + + if (o == null || !(o instanceof QosBearerSession)) { + return false; + } + + QosBearerSession other = (QosBearerSession) o; + return this.qosBearerSessionId == other.qosBearerSessionId + && this.qos.equals(other.qos) + && this.qosBearerFilterList.size() == other.qosBearerFilterList.size() + && this.qosBearerFilterList.containsAll(other.qosBearerFilterList); + } + + + public static final @NonNull Parcelable.Creator<QosBearerSession> CREATOR = + new Parcelable.Creator<QosBearerSession>() { + @Override + public QosBearerSession createFromParcel(Parcel source) { + return new QosBearerSession(source); + } + + @Override + public QosBearerSession[] newArray(int size) { + return new QosBearerSession[size]; + } + }; +} diff --git a/telephony/java/android/telephony/data/QosSession.java b/telephony/java/android/telephony/data/QosSession.java deleted file mode 100644 index f07b6a9f6725..000000000000 --- a/telephony/java/android/telephony/data/QosSession.java +++ /dev/null @@ -1,125 +0,0 @@ -/** - * 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. - */ - -package android.telephony.data; - -import android.annotation.NonNull; -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - - -/** - * Class that stores information specific to QOS session. - * - * @hide - */ -public final class QosSession implements Parcelable{ - - final int qosSessionId; - final Qos qos; - final List<QosFilter> qosFilterList; - - public QosSession(int qosSessionId, @NonNull Qos qos, @NonNull List<QosFilter> qosFilterList) { - this.qosSessionId = qosSessionId; - this.qos = qos; - this.qosFilterList = qosFilterList; - } - - private QosSession(Parcel source) { - qosSessionId = source.readInt(); - qos = source.readParcelable(Qos.class.getClassLoader()); - qosFilterList = new ArrayList<>(); - source.readList(qosFilterList, QosFilter.class.getClassLoader()); - } - - @Override - public void writeToParcel(@NonNull Parcel dest, int flags) { - dest.writeInt(qosSessionId); - if (qos.getType() == Qos.QOS_TYPE_EPS) { - dest.writeParcelable((EpsQos)qos, flags); - } else { - dest.writeParcelable((NrQos)qos, flags); - } - dest.writeList(qosFilterList); - } - - public static @NonNull QosSession create( - @NonNull android.hardware.radio.V1_6.QosSession qosSession) { - List<QosFilter> qosFilters = new ArrayList<>(); - - if (qosSession.qosFilters != null) { - for (android.hardware.radio.V1_6.QosFilter filter : qosSession.qosFilters) { - qosFilters.add(QosFilter.create(filter)); - } - } - - return new QosSession( - qosSession.qosSessionId, - Qos.create(qosSession.qos), - qosFilters); - } - - @Override - public int describeContents() { - return 0; - } - - @Override - public String toString() { - return "QosSession {" - + " qosSessionId=" + qosSessionId - + " qos=" + qos - + " qosFilterList=" + qosFilterList + "}"; - } - - @Override - public int hashCode() { - return Objects.hash(qosSessionId, qos, qosFilterList); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - - if (o == null || !(o instanceof QosSession)) { - return false; - } - - QosSession other = (QosSession) o; - return this.qosSessionId == other.qosSessionId - && this.qos.equals(other.qos) - && this.qosFilterList.size() == other.qosFilterList.size() - && this.qosFilterList.containsAll(other.qosFilterList); - } - - - public static final @NonNull Parcelable.Creator<QosSession> CREATOR = - new Parcelable.Creator<QosSession>() { - @Override - public QosSession createFromParcel(Parcel source) { - return new QosSession(source); - } - - @Override - public QosSession[] newArray(int size) { - return new QosSession[size]; - } - }; -} diff --git a/telephony/java/android/telephony/data/TrafficDescriptor.aidl b/telephony/java/android/telephony/data/TrafficDescriptor.aidl new file mode 100644 index 000000000000..a9c7604a91b6 --- /dev/null +++ b/telephony/java/android/telephony/data/TrafficDescriptor.aidl @@ -0,0 +1,20 @@ +/* + * 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. + */ + +/** @hide */ +package android.telephony.data; + +parcelable TrafficDescriptor; diff --git a/telephony/java/android/telephony/data/TrafficDescriptor.java b/telephony/java/android/telephony/data/TrafficDescriptor.java new file mode 100644 index 000000000000..480379d641b6 --- /dev/null +++ b/telephony/java/android/telephony/data/TrafficDescriptor.java @@ -0,0 +1,111 @@ +/* + * 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.data; + +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.os.Parcel; +import android.os.Parcelable; + +import java.util.Objects; + +/** + * A traffic descriptor, as defined in 3GPP TS 24.526 Section 5.2. It is used for URSP traffic + * matching as described in 3GPP TS 24.526 Section 4.2.2. It includes an optional DNN, which, + * if present, must be used for traffic matching; it does not specify the end point to be used for + * the data call. + * @hide + */ +@SystemApi +public final class TrafficDescriptor implements Parcelable { + private final String mDnn; + private final String mOsAppId; + + private TrafficDescriptor(@NonNull Parcel in) { + mDnn = in.readString(); + mOsAppId = in.readString(); + } + + /** + * Create a traffic descriptor, as defined in 3GPP TS 24.526 Section 5.2 + * @param dnn optional DNN, which must be used for traffic matching, if present + * @param osAppId OsId + osAppId of the traffic descriptor + */ + public TrafficDescriptor(@Nullable String dnn, @Nullable String osAppId) { + mDnn = dnn; + mOsAppId = osAppId; + } + + /** + * DNN stands for Data Network Name and represents an APN as defined in 3GPP TS 23.003. + * @return the DNN of this traffic descriptor. + */ + public @Nullable String getDnn() { + return mDnn; + } + + /** + * OsAppId represents the OsId + OsAppId as defined in 3GPP TS 24.526 Section 5.2. + * @return the OS App ID of this traffic descriptor. + */ + public @Nullable String getOsAppId() { + return mOsAppId; + } + + @Override + public int describeContents() { + return 0; + } + + @NonNull @Override + public String toString() { + return "TrafficDescriptor={mDnn=" + mDnn + ", mOsAppId=" + mOsAppId + "}"; + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeString(mDnn); + dest.writeString(mOsAppId); + } + + public static final @NonNull Parcelable.Creator<TrafficDescriptor> CREATOR = + new Parcelable.Creator<TrafficDescriptor>() { + @Override + public @NonNull TrafficDescriptor createFromParcel(@NonNull Parcel source) { + return new TrafficDescriptor(source); + } + + @Override + public @NonNull TrafficDescriptor[] newArray(int size) { + return new TrafficDescriptor[size]; + } + }; + + @Override + public boolean equals(@Nullable Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + TrafficDescriptor that = (TrafficDescriptor) o; + return Objects.equals(mDnn, that.mDnn) && Objects.equals(mOsAppId, that.mOsAppId); + } + + @Override + public int hashCode() { + return Objects.hash(mDnn, mOsAppId); + } +} diff --git a/telephony/java/android/telephony/ims/ProvisioningManager.java b/telephony/java/android/telephony/ims/ProvisioningManager.java index 08eec29d5ac2..1e80ab7a405c 100644 --- a/telephony/java/android/telephony/ims/ProvisioningManager.java +++ b/telephony/java/android/telephony/ims/ProvisioningManager.java @@ -32,6 +32,7 @@ import android.os.ServiceSpecificException; import android.telephony.CarrierConfigManager; import android.telephony.SubscriptionManager; import android.telephony.TelephonyFrameworkInitializer; +import android.telephony.TelephonyManager; import android.telephony.ims.aidl.IImsConfigCallback; import android.telephony.ims.aidl.IRcsConfigCallback; import android.telephony.ims.feature.MmTelFeature; @@ -992,6 +993,16 @@ public class ProvisioningManager { } } + @Override + public void onPreProvisioningReceived(byte[] configXml) { + final long identity = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> mLocalCallback.onPreProvisioningReceived(configXml)); + } finally { + Binder.restoreCallingIdentity(identity); + } + } + private void setExecutor(Executor executor) { mExecutor = executor; } @@ -1004,8 +1015,9 @@ public class ProvisioningManager { * due to various triggers defined in GSMA RCC.14 for ACS(auto configuration * server) or other operator defined triggers. If RCS provisioning is already * completed at the time of callback registration, then this method shall be - * invoked with the current configuration - * @param configXml The RCS configurationXML received OTA. + * invoked with the current configuration. + * @param configXml The RCS configuration XML received by OTA. It is defined + * by GSMA RCC.07. */ public void onConfigurationChanged(@NonNull byte[] configXml) {} @@ -1036,6 +1048,20 @@ public class ProvisioningManager { */ public void onRemoved() {} + /** + * Some carriers using ACS (auto configuration server) may send a carrier-specific + * pre-provisioning configuration XML if the user has not been provisioned for RCS + * services yet. When this provisioning XML is received, the framework will move + * into a "not provisioned" state for RCS. In order for provisioning to proceed, + * the application must parse this configuration XML and perform the carrier specific + * opt-in flow for RCS services. If the user accepts, {@link #triggerRcsReconfiguration} + * must be called in order for the device to move out of this state and try to fetch + * the RCS provisioning information. + * + * @param configXml the pre-provisioning config in carrier specified format. + */ + public void onPreProvisioningReceived(@NonNull byte[] configXml) {} + /**@hide*/ public final IRcsConfigCallback getBinder() { return mBinder; @@ -1300,7 +1326,7 @@ public class ProvisioningManager { * provisioning. * <p> * Requires Permission: Manifest.permission.MODIFY_PHONE_STATE or that the calling app has - * carrier privileges (see {@link #hasCarrierPrivileges}). + * carrier privileges (see {@link TelephonyManager#hasCarrierPrivileges}). * @param config The XML file to be read. ASCII/UTF8 encoded text if not compressed. * @param isCompressed The XML file is compressed in gzip format and must be decompressed * before being read. @@ -1330,7 +1356,7 @@ public class ProvisioningManager { * the intent is valid. and {@link #EXTRA_STATUS} to specify RCS VoLTE single registration * status. */ - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) @SdkConstant(SdkConstant.SdkConstantType.BROADCAST_INTENT_ACTION) public static final String ACTION_RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE = "android.telephony.ims.action.RCS_SINGLE_REGISTRATION_CAPABILITY_UPDATE"; @@ -1372,10 +1398,12 @@ 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 #registerRcsProvisioningCallback()} + * When the IMS/RCS service receives the RCS client configuration, it will detect + * the change in the configuration, and trigger the auto-configuration as needed. * @param rcc RCS client configuration {@link RcsClientConfiguration} */ - @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) + @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void setRcsClientConfiguration( @NonNull RcsClientConfiguration rcc) throws ImsException { try { @@ -1390,6 +1418,14 @@ public class ProvisioningManager { /** * 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. + * + * <p> Requires Permission: + * <ul> + * <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li> + * <li>{@link android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION},</li> + * <li>or that the caller has carrier privileges (see + * {@link TelephonyManager#hasCarrierPrivileges()}).</li> + * </ul> * @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 @@ -1398,7 +1434,8 @@ public class ProvisioningManager { * @see PackageManager#FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION for whether or not this * device supports IMS single registration. */ - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public boolean isRcsVolteSingleRegistrationCapable() throws ImsException { try { return getITelephony().isRcsVolteSingleRegistrationCapable(mSubId); @@ -1408,42 +1445,50 @@ public class ProvisioningManager { } /** - * Registers a new {@link RcsProvisioningCallback} to listen to changes to - * RCS provisioning xml. - * - * <p>RCS application must be the default messaging application and must - * have already registered its {@link RcsClientConfiguration} by using - * {@link #setRcsClientConfiguration} before it registers the provisioning - * callback. If ProvisioningManager has a valid RCS configuration at the - * time of callback registration and a reconfiguration is not required - * due to RCS client parameters change, then the callback shall be invoked - * immediately with the xml. - * When the subscription associated with this callback is removed (SIM removed, - * ESIM swap,etc...), this callback will automatically be removed. - * - * @param executor The {@link Executor} to call the callback methods on - * @param callback The rcs provisioning callback to be registered. - * @see #unregisterRcsProvisioningChangedCallback(RcsProvisioningCallback) - * @see SubscriptionManager.OnSubscriptionsChangedListener - * @throws IllegalArgumentException if the subscription associated with this - * callback is not active (SIM is not inserted, ESIM inactive) or the - * subscription is invalid. - * @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. - * 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 - * callback. - * See {@link ImsException#getCode()} for a more detailed reason. - */ - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public void registerRcsProvisioningChangedCallback( + * Registers a new {@link RcsProvisioningCallback} to listen to changes to + * RCS provisioning xml. + * + * <p>RCS application must be the default messaging application and must + * have already registered its {@link RcsClientConfiguration} by using + * {@link #setRcsClientConfiguration} before it registers the provisioning + * callback. If ProvisioningManager has a valid RCS configuration at the + * time of callback registration and a reconfiguration is not required + * due to RCS client parameters change, then the callback shall be invoked + * immediately with the xml. + * When the subscription associated with this callback is removed (SIM removed, + * ESIM swap,etc...), this callback will automatically be removed. + * <p> Requires Permission: + * <ul> + * <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li> + * <li>{@link android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION},</li> + * <li>or that the caller has carrier privileges (see + * {@link TelephonyManager#hasCarrierPrivileges()}).</li> + * </ul> + * + * @param executor The {@link Executor} to call the callback methods on + * @param callback The rcs provisioning callback to be registered. + * @see #unregisterRcsProvisioningCallback(RcsProvisioningCallback) + * @see SubscriptionManager.OnSubscriptionsChangedListener + * @throws IllegalArgumentException if the subscription associated with this + * callback is not active (SIM is not inserted, ESIM inactive) or the + * subscription is invalid. + * @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. + * 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 + * callback. + * See {@link ImsException#getCode()} for a more detailed reason. + */ + @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) + public void registerRcsProvisioningCallback( @NonNull @CallbackExecutor Executor executor, @NonNull RcsProvisioningCallback callback) throws ImsException { callback.setExecutor(executor); try { - getITelephony().registerRcsProvisioningChangedCallback(mSubId, callback.getBinder()); + getITelephony().registerRcsProvisioningCallback(mSubId, callback.getBinder()); } catch (ServiceSpecificException e) { throw new ImsException(e.getMessage(), e.errorCode); } catch (RemoteException | IllegalStateException e) { @@ -1459,17 +1504,26 @@ public class ProvisioningManager { * 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. + * <p> Requires Permission: + * <ul> + * <li>{@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE},</li> + * <li>{@link android.Manifest.permission#PERFORM_IMS_SINGLE_REGISTRATION},</li> + * <li>or that the caller has carrier privileges (see + * {@link TelephonyManager#hasCarrierPrivileges()}).</li> + * </ul> + * * @param callback The existing {@link RcsProvisioningCallback} to be * removed. - * @see #registerRcsProvisioningChangedCallback - * @throws IllegalArgumentException if the subscription associated with this callback is - * invalid. + * @see #registerRcsProvisioningCallback(Executor, RcsProvisioningCallback) + * @throws IllegalArgumentException if the subscription associated with + * this callback is invalid. */ - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) - public void unregisterRcsProvisioningChangedCallback( + @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) + public void unregisterRcsProvisioningCallback( @NonNull RcsProvisioningCallback callback) { try { - getITelephony().unregisterRcsProvisioningChangedCallback( + getITelephony().unregisterRcsProvisioningCallback( mSubId, callback.getBinder()); } catch (RemoteException e) { throw e.rethrowAsRuntimeException(); @@ -1479,8 +1533,16 @@ public class ProvisioningManager { /** * Reconfiguration triggered by the RCS application. Most likely cause * is the 403 forbidden to a HTTP request. - */ - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + * + * <p>When this api is called, the RCS configuration for the associated + * subscription will be removed, and the application which has registered + * {@link RcsProvisioningCallback} may expect to receive + * {@link RcsProvisioningCallback#onConfigurationReset}, then + * {@link RcsProvisioningCallback#onConfigurationChanged} when the new + * RCS configuration is received and notified by + * {@link #notifyRcsAutoConfigurationReceived} + */ + @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void triggerRcsReconfiguration() { try { getITelephony().triggerRcsReconfiguration(mSubId); diff --git a/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java b/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java index 5eb75e762fc9..9c28c36521f5 100644 --- a/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java +++ b/telephony/java/android/telephony/ims/RcsContactPresenceTuple.java @@ -21,11 +21,16 @@ import android.annotation.Nullable; import android.annotation.StringDef; import android.annotation.SystemApi; import android.net.Uri; +import android.os.Build; import android.os.Parcel; import android.os.Parcelable; +import android.text.TextUtils; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.time.Instant; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; import java.util.ArrayList; import java.util.Collections; import java.util.List; @@ -38,6 +43,17 @@ import java.util.List; @SystemApi public final class RcsContactPresenceTuple implements Parcelable { + private static final String LOG_TAG = "RcsContactPresenceTuple"; + + /** + * The service ID used to indicate that service discovery via presence is available. + * <p> + * See RCC.07 v5.0 specification for more information. + * @hide + */ + public static final String SERVICE_ID_PRESENCE = + "org.3gpp.urn:urn-7:3gpp-application.ims.iari.rcse.dp"; + /** * The service ID used to indicate that MMTEL service is available. * <p> @@ -329,6 +345,13 @@ public final class RcsContactPresenceTuple implements Parcelable { public @NonNull @DuplexMode List<String> getUnsupportedDuplexModes() { return Collections.unmodifiableList(mUnsupportedDuplexModeList); } + + @Override + public String toString() { + return "servCaps{" + "a=" + mIsAudioCapable + ", v=" + mIsVideoCapable + + ", supported=" + mSupportedDuplexModeList + ", unsupported=" + + mUnsupportedDuplexModeList + '}'; + } } /** @@ -353,7 +376,8 @@ public final class RcsContactPresenceTuple implements Parcelable { } /** - * The optional SIP Contact URI associated with the PIDF tuple element. + * The optional SIP Contact URI associated with the PIDF tuple element if the network + * expects the user to use the URI instead of the contact URI to contact it. */ public @NonNull Builder setContactUri(@NonNull Uri contactUri) { mPresenceTuple.mContactUri = contactUri; @@ -365,7 +389,7 @@ public final class RcsContactPresenceTuple implements Parcelable { * Per RFC3863 section 4.1.7, the timestamp is formatted as an IMPP datetime format * string per RFC3339. */ - public @NonNull Builder setTimestamp(@NonNull String timestamp) { + public @NonNull Builder setTime(@NonNull Instant timestamp) { mPresenceTuple.mTimestamp = timestamp; return this; } @@ -397,7 +421,7 @@ public final class RcsContactPresenceTuple implements Parcelable { } private Uri mContactUri; - private String mTimestamp; + private Instant mTimestamp; private @BasicStatus String mStatus; // The service information in the service-description element. @@ -416,7 +440,7 @@ public final class RcsContactPresenceTuple implements Parcelable { private RcsContactPresenceTuple(Parcel in) { mContactUri = in.readParcelable(Uri.class.getClassLoader()); - mTimestamp = in.readString(); + mTimestamp = convertStringFormatTimeToInstant(in.readString()); mStatus = in.readString(); mServiceId = in.readString(); mServiceVersion = in.readString(); @@ -427,7 +451,7 @@ public final class RcsContactPresenceTuple implements Parcelable { @Override public void writeToParcel(@NonNull Parcel out, int flags) { out.writeParcelable(mContactUri, flags); - out.writeString(mTimestamp); + out.writeString(convertInstantToStringFormat(mTimestamp)); out.writeString(mStatus); out.writeString(mServiceId); out.writeString(mServiceVersion); @@ -453,6 +477,26 @@ public final class RcsContactPresenceTuple implements Parcelable { } }; + // Convert the Instant to the string format + private String convertInstantToStringFormat(Instant instant) { + if (instant == null) { + return ""; + } + return instant.toString(); + } + + // Convert the time string format to Instant + private @Nullable Instant convertStringFormatTimeToInstant(String timestamp) { + if (TextUtils.isEmpty(timestamp)) { + return null; + } + try { + return DateTimeFormatter.ISO_OFFSET_DATE_TIME.parse(timestamp, Instant::from); + } catch (DateTimeParseException e) { + return null; + } + } + /** @return the status of the tuple element. */ public @NonNull @BasicStatus String getStatus() { return mStatus; @@ -474,7 +518,7 @@ public final class RcsContactPresenceTuple implements Parcelable { } /** @return the timestamp element contained in the tuple if it exists */ - public @Nullable String getTimestamp() { + public @Nullable Instant getTime() { return mTimestamp; } @@ -487,4 +531,36 @@ public final class RcsContactPresenceTuple implements Parcelable { public @Nullable ServiceCapabilities getServiceCapabilities() { return mServiceCapabilities; } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder("{"); + if (Build.IS_ENG) { + builder.append("u="); + builder.append(mContactUri); + } else { + builder.append("u="); + builder.append(mContactUri != null ? "XXX" : "null"); + } + builder.append(", id="); + builder.append(mServiceId); + builder.append(", v="); + builder.append(mServiceVersion); + builder.append(", s="); + builder.append(mStatus); + if (mTimestamp != null) { + builder.append(", timestamp="); + builder.append(mTimestamp); + } + if (mServiceDescription != null) { + builder.append(", servDesc="); + builder.append(mServiceDescription); + } + if (mServiceCapabilities != null) { + builder.append(", servCaps="); + builder.append(mServiceCapabilities); + } + builder.append("}"); + return builder.toString(); + } } diff --git a/telephony/java/android/telephony/ims/RcsContactUceCapability.java b/telephony/java/android/telephony/ims/RcsContactUceCapability.java index fe855023f5d0..52d0f036788c 100644 --- a/telephony/java/android/telephony/ims/RcsContactUceCapability.java +++ b/telephony/java/android/telephony/ims/RcsContactUceCapability.java @@ -21,6 +21,7 @@ import android.annotation.NonNull; import android.annotation.Nullable; import android.annotation.SystemApi; import android.net.Uri; +import android.os.Build; import android.os.Parcel; import android.os.Parcelable; @@ -339,9 +340,45 @@ public final class RcsContactUceCapability implements Parcelable { } /** + * Retrieve the contact URI requested by the applications. * @return the URI representing the contact associated with the capabilities. */ public @NonNull Uri getContactUri() { return mContactUri; } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder("RcsContactUceCapability"); + if (mCapabilityMechanism == CAPABILITY_MECHANISM_PRESENCE) { + builder.append("(presence) {"); + } else if (mCapabilityMechanism == CAPABILITY_MECHANISM_OPTIONS) { + builder.append("(options) {"); + } else { + builder.append("(?) {"); + } + if (Build.IS_ENG) { + builder.append("uri="); + builder.append(mContactUri); + } else { + builder.append("uri (isNull)="); + builder.append(mContactUri != null ? "XXX" : "null"); + } + builder.append(", sourceType="); + builder.append(mSourceType); + builder.append(", requestResult="); + builder.append(mRequestResult); + + if (mCapabilityMechanism == CAPABILITY_MECHANISM_PRESENCE) { + builder.append(", presenceTuples={"); + builder.append(mPresenceTuples); + builder.append("}"); + } else if (mCapabilityMechanism == CAPABILITY_MECHANISM_OPTIONS) { + builder.append(", featureTags={"); + builder.append(mFeatureTags); + builder.append("}"); + } + + return builder.toString(); + } } diff --git a/telephony/java/android/telephony/ims/RcsUceAdapter.java b/telephony/java/android/telephony/ims/RcsUceAdapter.java index ce8bd7d8c28e..dd9102699529 100644 --- a/telephony/java/android/telephony/ims/RcsUceAdapter.java +++ b/telephony/java/android/telephony/ims/RcsUceAdapter.java @@ -36,6 +36,8 @@ import android.util.Log; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -430,7 +432,8 @@ public class RcsUceAdapter { /** * The pending request has completed successfully due to all requested contacts information - * being delivered. + * being delivered. The callback {@link #onCapabilitiesReceived(List)} + * for each contacts is required to be called before {@link #onComplete} is called. */ void onComplete(); @@ -486,7 +489,7 @@ public class RcsUceAdapter { @SystemApi @RequiresPermission(allOf = {Manifest.permission.ACCESS_RCS_USER_CAPABILITY_EXCHANGE, Manifest.permission.READ_CONTACTS}) - public void requestCapabilities(@NonNull List<Uri> contactNumbers, + public void requestCapabilities(@NonNull Collection<Uri> contactNumbers, @NonNull @CallbackExecutor Executor executor, @NonNull CapabilitiesCallback c) throws ImsException { if (c == null) { @@ -538,7 +541,7 @@ public class RcsUceAdapter { try { imsRcsController.requestCapabilities(mSubId, mContext.getOpPackageName(), - mContext.getAttributionTag(), contactNumbers, internalCallback); + mContext.getAttributionTag(), new ArrayList(contactNumbers), internalCallback); } catch (ServiceSpecificException e) { throw new ImsException(e.toString(), e.errorCode); } catch (RemoteException e) { @@ -569,6 +572,10 @@ public class RcsUceAdapter { * {@link CapabilitiesCallback} is called. * @param c A one-time callback for when the request for capabilities completes or there is * an error processing the request. + * @throws ImsException if the subscription associated with this instance of + * {@link RcsUceAdapter} is valid, but the ImsService associated with the subscription is not + * available. This can happen if the ImsService has crashed, for example, or if the subscription + * becomes inactive. See {@link ImsException#getCode()} for more information on the error codes. * @hide */ @SystemApi diff --git a/telephony/java/android/telephony/ims/SipDelegateManager.java b/telephony/java/android/telephony/ims/SipDelegateManager.java index 04421c9a2449..399b6dc88cef 100644 --- a/telephony/java/android/telephony/ims/SipDelegateManager.java +++ b/telephony/java/android/telephony/ims/SipDelegateManager.java @@ -28,7 +28,6 @@ import android.content.pm.PackageManager; import android.os.RemoteException; import android.os.ServiceSpecificException; import android.telephony.BinderCacheManager; -import android.telephony.CarrierConfigManager; import android.telephony.ims.aidl.IImsRcsController; import android.telephony.ims.aidl.SipDelegateConnectionAidlWrapper; import android.telephony.ims.stub.DelegateConnectionMessageCallback; @@ -275,7 +274,8 @@ public class SipDelegateManager { * @see CarrierConfigManager.Ims#KEY_IMS_SINGLE_REGISTRATION_REQUIRED_BOOL * @see PackageManager#FEATURE_TELEPHONY_IMS_SINGLE_REGISTRATION */ - @RequiresPermission(Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @RequiresPermission(anyOf = {Manifest.permission.READ_PRIVILEGED_PHONE_STATE, + Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION}) public boolean isSupported() throws ImsException { try { IImsRcsController controller = mBinderCache.getBinder(); @@ -317,7 +317,7 @@ public class SipDelegateManager { * @throws ImsException Thrown if there was a problem communicating with the ImsService * associated with this SipDelegateManager. See {@link ImsException#getCode()}. */ - @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) + @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void createSipDelegate(@NonNull DelegateRequest request, @NonNull Executor executor, @NonNull DelegateConnectionStateCallback dc, @NonNull DelegateConnectionMessageCallback mc) throws ImsException { @@ -351,7 +351,7 @@ public class SipDelegateManager { * @param delegateConnection The SipDelegateConnection to destroy. * @param reason The reason for why this SipDelegateConnection was destroyed. */ - @RequiresPermission(Manifest.permission.MODIFY_PHONE_STATE) + @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void destroySipDelegate(@NonNull SipDelegateConnection delegateConnection, @SipDelegateDestroyReason int reason) { @@ -392,6 +392,7 @@ public class SipDelegateManager { * this condition. May be {@code null} if there was no reason String provided from the * network. */ + @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void triggerFullNetworkRegistration(@NonNull SipDelegateConnection connection, @IntRange(from = 100, to = 699) int sipCode, @Nullable String sipReason) { if (connection == null) { diff --git a/telephony/java/android/telephony/ims/SipMessage.java b/telephony/java/android/telephony/ims/SipMessage.java index 9cfa640fce18..ad6d73c39962 100644 --- a/telephony/java/android/telephony/ims/SipMessage.java +++ b/telephony/java/android/telephony/ims/SipMessage.java @@ -19,6 +19,7 @@ package android.telephony.ims; import static java.nio.charset.StandardCharsets.UTF_8; import android.annotation.NonNull; +import android.annotation.Nullable; import android.annotation.SystemApi; import android.os.Build; import android.os.Parcel; @@ -46,6 +47,8 @@ public final class SipMessage implements Parcelable { private final String mStartLine; private final String mHeaderSection; private final byte[] mContent; + private final String mViaBranchParam; + private final String mCallIdParam; /** * Represents a partially encoded SIP message. @@ -63,6 +66,9 @@ public final class SipMessage implements Parcelable { mStartLine = startLine; mHeaderSection = headerSection; mContent = content; + + mViaBranchParam = SipMessageParsingUtils.getTransactionId(mHeaderSection); + mCallIdParam = SipMessageParsingUtils.getCallId(mHeaderSection); } /** @@ -73,6 +79,8 @@ public final class SipMessage implements Parcelable { mHeaderSection = source.readString(); mContent = new byte[source.readInt()]; source.readByteArray(mContent); + mViaBranchParam = source.readString(); + mCallIdParam = source.readString(); } /** @@ -97,6 +105,25 @@ public final class SipMessage implements Parcelable { return mContent; } + /** + * @return the branch parameter enclosed in the Via header key's value. See RFC 3261 section + * 20.42 for more information on the Via header. If {@code null}, then there was either no + * Via parameter found in this SIP message's headers or no branch parameter found in the + * Via header. + */ + public @Nullable String getViaBranchParameter() { + return mViaBranchParam; + } + + /** + * @return the value associated with the call-id header of this SIP message. See RFC 3261 + * section 20.8 for more information on the call-id header. If {@code null}, then there was no + * call-id header found in this SIP message's headers. + */ + public @Nullable String getCallIdParameter() { + return mCallIdParam; + } + @Override public int describeContents() { return 0; @@ -108,6 +135,8 @@ public final class SipMessage implements Parcelable { dest.writeString(mHeaderSection); dest.writeInt(mContent.length); dest.writeByteArray(mContent); + dest.writeString(mViaBranchParam); + dest.writeString(mCallIdParam); } public static final @NonNull Creator<SipMessage> CREATOR = new Creator<SipMessage>() { diff --git a/telephony/java/android/telephony/ims/aidl/IRcsConfigCallback.aidl b/telephony/java/android/telephony/ims/aidl/IRcsConfigCallback.aidl index 5a8973e37bce..d0853d1846ac 100644 --- a/telephony/java/android/telephony/ims/aidl/IRcsConfigCallback.aidl +++ b/telephony/java/android/telephony/ims/aidl/IRcsConfigCallback.aidl @@ -25,5 +25,6 @@ oneway interface IRcsConfigCallback { void onAutoConfigurationErrorReceived(int errorCode, String errorString); void onConfigurationReset(); void onRemoved(); + void onPreProvisioningReceived(in byte[] config); } diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java index 9d919015087d..739946be2e5b 100644 --- a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java +++ b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java @@ -31,8 +31,6 @@ import android.telephony.ims.stub.SipDelegate; import android.text.TextUtils; import android.util.Log; -import com.android.internal.telephony.SipMessageParsingUtils; - import java.util.ArrayList; import java.util.Set; import java.util.concurrent.Executor; @@ -188,7 +186,7 @@ public class SipDelegateAidlWrapper implements DelegateStateCallback, DelegateMe } private void notifyLocalMessageFailedToBeReceived(SipMessage m, int reason) { - String transactionId = SipMessageParsingUtils.getTransactionId(m.getHeaderSection()); + String transactionId = m.getViaBranchParameter(); if (TextUtils.isEmpty(transactionId)) { Log.w(LOG_TAG, "failure to parse SipMessage."); throw new IllegalArgumentException("Malformed SipMessage, can not determine " diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java index c877aca8ba96..3cd27264295c 100644 --- a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java +++ b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java @@ -32,8 +32,6 @@ import android.text.TextUtils; import android.util.ArraySet; import android.util.Log; -import com.android.internal.telephony.SipMessageParsingUtils; - import java.util.List; import java.util.NoSuchElementException; import java.util.concurrent.Executor; @@ -268,7 +266,7 @@ public class SipDelegateConnectionAidlWrapper implements SipDelegateConnection, } private void notifyLocalMessageFailedToSend(SipMessage m, int reason) { - String transactionId = SipMessageParsingUtils.getTransactionId(m.getHeaderSection()); + String transactionId = m.getViaBranchParameter(); if (TextUtils.isEmpty(transactionId)) { Log.w(LOG_TAG, "sendMessage detected a malformed SipMessage and can not get a " + "transaction ID."); diff --git a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java index 34984e05e181..4dcb7f59f4a7 100644 --- a/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsConfigImplBase.java @@ -542,11 +542,34 @@ public class ImsConfigImplBase { } mRcsCallbacks.broadcastAction(c -> { try { - //TODO compressed by default? c.onAutoConfigurationErrorReceived(errorCode, errorString); } catch (RemoteException e) { Log.w(TAG, "dead binder in notifyAutoConfigurationErrorReceived, skipping."); } }); } + + /** + * Notifies application that pre-provisioning config is received. + * + * <p>Some carriers using ACS (auto configuration server) may send a carrier-specific + * pre-provisioning configuration XML if the user has not been provisioned for RCS + * services yet. When such provisioning XML is received, ACS client must call this + * method to notify the application with the XML. + * + * @param configXml the pre-provisioning config in carrier specified format. + */ + public final void notifyPreProvisioningReceived(@NonNull byte[] configXml) { + // can be null in testing + if (mRcsCallbacks == null) { + return; + } + mRcsCallbacks.broadcastAction(c -> { + try { + c.onPreProvisioningReceived(configXml); + } catch (RemoteException e) { + Log.w(TAG, "dead binder in notifyPreProvisioningReceived, skipping."); + } + }); + } } diff --git a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java index 5f8e93d02a00..8ad40ed1032c 100644 --- a/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsEcbmImplBase.java @@ -57,10 +57,10 @@ public class ImsEcbmImplBase { } 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."); + // Warn that the listener is being replaced while active + Log.w(TAG, "setListener is being called when there is already an active " + + "listener"); + mListener = listener; } } } diff --git a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java index 8e961acc7b36..ec1c7b3a92a8 100644 --- a/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsMultiEndpointImplBase.java @@ -62,10 +62,10 @@ public class ImsMultiEndpointImplBase { } 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."); + // Warn that the listener is being replaced while active + Log.w(TAG, "setListener is being called when there is already an active " + + "listener"); + mListener = listener; } } } diff --git a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java index 83b89aa8e814..eb3e8ed5a8e4 100644 --- a/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsUtImplBase.java @@ -224,11 +224,10 @@ public class ImsUtImplBase { } 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!"); + // Warn that the listener is being replaced while active + Log.w(TAG, "setListener is being called when there is already an active " + + "listener"); + mUtListener = new ImsUtListener(listener); } } diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java index 908869beb607..03e17fbc2c0d 100644 --- a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java +++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java @@ -31,6 +31,7 @@ import android.util.Pair; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Collection; import java.util.List; import java.util.concurrent.Executor; @@ -241,7 +242,7 @@ public class RcsCapabilityExchangeImplBase { /** * Notify the framework of the response to the SUBSCRIBE request from - * {@link #subscribeForCapabilities(List, SubscribeResponseCallback)}. + * {@link #subscribeForCapabilities(Collection, 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}, @@ -266,7 +267,7 @@ public class RcsCapabilityExchangeImplBase { /** * Notify the framework of the response to the SUBSCRIBE request from - * {@link #subscribeForCapabilities(List, SubscribeResponseCallback)} that also + * {@link #subscribeForCapabilities(Collection, SubscribeResponseCallback)} that also * includes a reason provided in the “reason” header. See RFC3326 for more * information. * @@ -385,13 +386,13 @@ public class RcsCapabilityExchangeImplBase { * {@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 uris A {@link Collection} of the {@link Uri}s that the framework is requesting the + * UCE capabilities for. * @param cb The callback of the subscribe request. */ // executor used is defined in the constructor. @SuppressLint("ExecutorRegistration") - public void subscribeForCapabilities(@NonNull List<Uri> uris, + public void subscribeForCapabilities(@NonNull Collection<Uri> uris, @NonNull SubscribeResponseCallback cb) { // Stub - to be implemented by service Log.w(LOG_TAG, "subscribeForCapabilities called with no implementation."); |