diff options
author | Eric Arseneau <earseneau@google.com> | 2021-12-19 22:49:43 -0800 |
---|---|---|
committer | Eric Arseneau <earseneau@google.com> | 2021-12-22 12:52:50 -0800 |
commit | 3e8cb98421761bb7dfafe59a22a15fe2e176f272 (patch) | |
tree | 754d2b985bde4574c8789e254b120866cf23002a /telephony/java/android | |
parent | 48cbb14e1815430efd7ff5086e7a4c70e75d475f (diff) | |
parent | 6c2cb6876a30dee0b94d946ca529e06cd96b9642 (diff) |
Merge s-mpr-2021-12-05
Change-Id: Ic2889f5eb531008340529eadc36ec8efc62b1984
Diffstat (limited to 'telephony/java/android')
4 files changed, 387 insertions, 18 deletions
diff --git a/telephony/java/android/telephony/AvailableNetworkInfo.java b/telephony/java/android/telephony/AvailableNetworkInfo.java index a1c5bbefbbe1..ae597e02f33c 100644 --- a/telephony/java/android/telephony/AvailableNetworkInfo.java +++ b/telephony/java/android/telephony/AvailableNetworkInfo.java @@ -19,6 +19,7 @@ package android.telephony; import android.annotation.NonNull; import android.os.Parcel; import android.os.Parcelable; +import android.telephony.RadioAccessSpecifier; import java.util.ArrayList; import java.util.Arrays; @@ -76,13 +77,28 @@ public final class AvailableNetworkInfo implements Parcelable { * Opportunistic network service will use these bands to scan. * * When no specific bands are specified (empty array or null) CBRS band - * {@link AccessNetworkConstants.EutranBand.BAND_48} will be used for network scan. + * {@link AccessNetworkConstants.EutranBand.BAND_48 + * } will be used for network scan. * * See {@link AccessNetworkConstants} for details. + * + * @deprecated use {@link #mRadioAccessSpecifiers} instead */ + @Deprecated private ArrayList<Integer> mBands; /** + * Returns a list of {@link RadioAccessSpecifier} associated with the available network. + * Opportunistic network service will use this to determine which bands to scan for. + * + * If this entry is left empty, {@link RadioAcccessSpecifier}s with {@link AccessNetworkType}s + * of {@link AccessNetworkConstants.AccessNetworkType.EUTRAN} and {@link + * AccessNetworkConstants.AccessNetworkType.NGRAN} with bands 48 and 71 on each will be assumed + * by Opportunistic network service. + */ + private ArrayList<RadioAccessSpecifier> mRadioAccessSpecifiers; + + /** * Return subscription Id of the available network. * This value must be one of the entry retrieved from * {@link SubscriptionManager#getOpportunisticSubscriptions} @@ -129,6 +145,22 @@ public final class AvailableNetworkInfo implements Parcelable { return (List<Integer>) mBands.clone(); } + /** + * Returns a list of {@link RadioAccessSpecifier} associated with the available network. + * Opportunistic network service will use this to determine which bands to scan for. + * + * the returned value is one of {@link AccessNetworkConstants.AccessNetworkType}. When no + * specific access network type is specified, {@link RadioAccessSpecifier}s with {@link + * AccessNetworkType}s of {@link AccessNetworkConstants.AccessNetworkType.EUTRAN} and {@link + * AccessNetworkConstants.AccessNetworkType.NGRAN} with bands 48 and 71 on each will be assumed + * by Opportunistic network service. + * @return the access network type associated with the available network. + * @hide + */ + public List<RadioAccessSpecifier> getRadioAccessSpecifiers() { + return (List<RadioAccessSpecifier>) mRadioAccessSpecifiers.clone(); + } + @Override public int describeContents() { return 0; @@ -140,6 +172,7 @@ public final class AvailableNetworkInfo implements Parcelable { dest.writeInt(mPriority); dest.writeStringList(mMccMncs); dest.writeList(mBands); + dest.writeList(mRadioAccessSpecifiers); } private AvailableNetworkInfo(Parcel in) { @@ -149,14 +182,25 @@ public final class AvailableNetworkInfo implements Parcelable { in.readStringList(mMccMncs); mBands = new ArrayList<>(); in.readList(mBands, Integer.class.getClassLoader()); + mRadioAccessSpecifiers = new ArrayList<>(); + in.readList(mRadioAccessSpecifiers, RadioAccessSpecifier.class.getClassLoader()); } public AvailableNetworkInfo(int subId, int priority, @NonNull List<String> mccMncs, @NonNull List<Integer> bands) { + this(subId, priority, mccMncs, bands, + new ArrayList<RadioAccessSpecifier>()); + } + + /** @hide */ + private AvailableNetworkInfo(int subId, int priority, @NonNull List<String> mccMncs, + @NonNull List<Integer> bands, @NonNull List<RadioAccessSpecifier> + radioAccessSpecifiers) { mSubId = subId; mPriority = priority; mMccMncs = new ArrayList<String>(mccMncs); mBands = new ArrayList<Integer>(bands); + mRadioAccessSpecifiers = new ArrayList<RadioAccessSpecifier>(radioAccessSpecifiers); } @Override @@ -177,12 +221,13 @@ public final class AvailableNetworkInfo implements Parcelable { && mPriority == ani.mPriority && (((mMccMncs != null) && mMccMncs.equals(ani.mMccMncs))) - && mBands.equals(ani.mBands)); + && mBands.equals(ani.mBands)) + && mRadioAccessSpecifiers.equals(ani.getRadioAccessSpecifiers()); } @Override public int hashCode() { - return Objects.hash(mSubId, mPriority, mMccMncs, mBands); + return Objects.hash(mSubId, mPriority, mMccMncs, mBands, mRadioAccessSpecifiers); } public static final @android.annotation.NonNull Parcelable.Creator<AvailableNetworkInfo> CREATOR = @@ -204,6 +249,72 @@ public final class AvailableNetworkInfo implements Parcelable { + " mSubId: " + mSubId + " mPriority: " + mPriority + " mMccMncs: " + Arrays.toString(mMccMncs.toArray()) - + " mBands: " + Arrays.toString(mBands.toArray())); + + " mBands: " + Arrays.toString(mBands.toArray()) + + " mRadioAccessSpecifiers: " + Arrays.toString(mRadioAccessSpecifiers.toArray())); + } + + /** + * Provides a convenient way to set the fields of a {@link AvailableNetworkInfo} when + * creating a new instance. + * + * <p>The example below shows how you might create a new {@code AvailableNetworkInfo}: + * + * <pre><code> + * + * AvailableNetworkInfo aNI = new AvailableNetworkInfo.Builder() + * .setSubId(1) + * .setPriority(AvailableNetworkInfo.PRIORITY_MED) + * .build(); + * </code></pre> + * + * @hide + */ + public static final class Builder { + private int mSubId = Integer.MIN_VALUE; + private int mPriority = AvailableNetworkInfo.PRIORITY_LOW; + private ArrayList<String> mMccMncs = new ArrayList<>(); + private ArrayList<Integer> mBands = new ArrayList<>(); + private ArrayList<RadioAccessSpecifier> mRadioAccessSpecifiers = new ArrayList<>(); + + public @NonNull Builder setSubId(int subId) { + mSubId = subId; + return this; + } + + public @NonNull Builder setPriority(int priority) { + if (priority > AvailableNetworkInfo.PRIORITY_LOW + || priority < AvailableNetworkInfo.PRIORITY_HIGH) { + throw new IllegalArgumentException("A valid priority must be set"); + } + mPriority = priority; + return this; + } + + public @NonNull Builder setMccMncs(@NonNull ArrayList<String> mccMncs) { + Objects.requireNonNull(mccMncs, "A non-null ArrayList of mccmncs must be set. An empty " + + "list is still accepted. Please read documentation in " + + "AvailableNetworkService to see consequences of an empty Arraylist."); + mMccMncs = mccMncs; + return this; + } + + public @NonNull Builder setRadioAccessSpecifiers( + @NonNull ArrayList<RadioAccessSpecifier> radioAccessSpecifiers) { + Objects.requireNonNull(radioAccessSpecifiers, "A non-null ArrayList of " + + "RadioAccessSpecifiers must be set. An empty list is still accepted. Please " + + "read documentation in AvailableNetworkService to see consequences of an " + + "empty Arraylist."); + mRadioAccessSpecifiers = radioAccessSpecifiers; + return this; + } + + public @NonNull AvailableNetworkInfo build() { + if (mSubId == Integer.MIN_VALUE) { + throw new IllegalArgumentException("A valid subId must be set"); + } + + return new AvailableNetworkInfo(mSubId, mPriority, mMccMncs, mBands, + mRadioAccessSpecifiers); + } } } diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index 0dfbc22df71f..548efb82bee7 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -1003,6 +1003,21 @@ public class CarrierConfigManager { = "carrier_use_ims_first_for_emergency_bool"; /** + * When {@code true}, the determination of whether to place a call as an emergency call will be + * based on the known {@link android.telephony.emergency.EmergencyNumber}s for the SIM on which + * the call is being placed. In a dual SIM scenario, if Sim A has the emergency numbers + * 123, 456 and Sim B has the emergency numbers 789, and the user places a call on SIM A to 789, + * it will not be treated as an emergency call in this case. + * When {@code false}, the determination is based on the emergency numbers from all device SIMs, + * regardless of which SIM the call is being placed on. If Sim A has the emergency numbers + * 123, 456 and Sim B has the emergency numbers 789, and the user places a call on SIM A to 789, + * the call will be dialed as an emergency number, but with an unspecified routing. + * @hide + */ + public static final String KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL = + "use_only_dialed_sim_ecc_list_bool"; + + /** * When IMS instant lettering is available for a carrier (see * {@link #KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL}), determines the list of characters * which may not be contained in messages. Should be specified as a regular expression suitable @@ -3814,6 +3829,109 @@ public class CarrierConfigManager { "opportunistic_network_max_backoff_time_long"; /** + * Controls SS-RSRP threshold in dBm at which 5G opportunistic network will be considered good + * enough for internet data. + * + * @hide + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_SS_RSRP_INT = + "opportunistic_network_entry_threshold_ss_rsrp_int"; + + /** + * Controls SS-RSRQ threshold in dB at which 5G opportunistic network will be considered good + * enough for internet data. + * + * @hide + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE = + "opportunistic_network_entry_threshold_ss_rsrq_double"; + + /** + * Controls SS-RSRP threshold in dBm below which 5G opportunistic network available will not + * be considered good enough for internet data. + * + * @hide + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRP_INT = + "opportunistic_network_exit_threshold_ss_rsrp_int"; + + /** + * Controls SS-RSRQ threshold in dB below which 5G opportunistic network available will not + * be considered good enough for internet data. + * + * @hide + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRQ_DOUBLE = + "opportunistic_network_exit_threshold_ss_rsrq_double"; + + /** + * Controls back off time in milliseconds for switching back to + * 5G opportunistic subscription. This time will be added to + * {@link CarrierConfigManager#KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG} to + * determine hysteresis time if there is ping pong situation + * (determined by system app or 1st party app) between primary and 5G opportunistic + * subscription. Ping ping situation is defined in + * #KEY_OPPORTUNISTIC_NETWORK_5G_PING_PONG_TIME_LONG. + * If ping pong situation continuous #KEY_OPPORTUNISTIC_5G_NETWORK_BACKOFF_TIME_LONG + * will be added to previously determined hysteresis time. + * + * @hide + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_5G_BACKOFF_TIME_LONG = + "opportunistic_network_5g_backoff_time_long"; + + /** + * Controls the max back off time in milliseconds for switching back to + * 5G opportunistic subscription. + * This time will be the max hysteresis that can be determined irrespective of there is + * continuous ping pong situation or not as described in + * #KEY_OPPORTUNISTIC_NETWORK_5G_PING_PONG_TIME_LONG and + * #KEY_OPPORTUNISTIC_NETWORK_5G_BACKOFF_TIME_LONG. + * + * @hide + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_5G_MAX_BACKOFF_TIME_LONG = + "opportunistic_network_5g_max_backoff_time_long"; + + /** + * Controls the ping pong determination of 5G opportunistic network. + * If opportunistic network is determined as out of service or below + * #KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRP_INT or + * #KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRQ_INT within + * #KEY_OPPORTUNISTIC_NETWORK_5G_PING_PONG_TIME_LONG of switching to opportunistic network, + * it will be determined as ping pong situation by system app or 1st party app. + * + * @hide + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_5G_PING_PONG_TIME_LONG = + "opportunistic_network_5g_ping_pong_time_long"; + + /** + * Controls hysteresis time in milliseconds for which will be waited before switching + * data to a 5G opportunistic network. + * + * @hide + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG = + "opportunistic_network_5g_data_switch_hysteresis_time_long"; + + /** + * Controls hysteresis time in milliseconds for which will be waited before switching from + * 5G opportunistic network to primary network. + * + * @hide + */ + public static final String KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG = + "opportunistic_network_5g_data_switch_exit_hysteresis_time_long"; + /** + * Controls whether 4G opportunistic networks should be scanned for possible data switch. + * + * @hide + */ + public static final String KEY_ENABLE_4G_OPPORTUNISTIC_NETWORK_SCAN_BOOL = + "enabled_4g_opportunistic_network_scan_bool"; + + /** * Indicates zero or more emergency number prefix(es), because some carrier requires * if users dial an emergency number address with a specific prefix, the combination of the * prefix and the address is also a valid emergency number to dial. For example, an emergency @@ -5121,6 +5239,16 @@ public class CarrierConfigManager { "display_no_data_notification_on_permanent_failure_bool"; /** + * Boolean indicating if the VoNR setting is visible in the Call Settings menu. + * If true, the VoNR setting menu will be visible. If false, the menu will be gone. + * + * Disabled by default. + * + * @hide + */ + public static final String KEY_VONR_SETTING_VISIBILITY_BOOL = "vonr_setting_visibility_bool"; + + /** * Determine whether unthrottle data retry when tracking area code (TAC/LAC) from cell changes * * @hide @@ -5222,6 +5350,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_CARRIER_IMS_GBA_REQUIRED_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_INSTANT_LETTERING_AVAILABLE_BOOL, false); sDefaults.putBoolean(KEY_CARRIER_USE_IMS_FIRST_FOR_EMERGENCY_BOOL, true); + sDefaults.putBoolean(KEY_USE_ONLY_DIALED_SIM_ECC_LIST_BOOL, false); sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WWAN_PACKAGE_OVERRIDE_STRING, ""); sDefaults.putString(KEY_CARRIER_NETWORK_SERVICE_WLAN_PACKAGE_OVERRIDE_STRING, ""); sDefaults.putString(KEY_CARRIER_QUALIFIED_NETWORKS_SERVICE_PACKAGE_OVERRIDE_STRING, ""); @@ -5690,7 +5819,25 @@ public class CarrierConfigManager { sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_BACKOFF_TIME_LONG, 10000); /* Default value is 60 seconds. */ sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_MAX_BACKOFF_TIME_LONG, 60000); - sDefaults.putAll(ImsServiceEntitlement.getDefaults()); + /* Default value is -111 dBm. */ + sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_SS_RSRP_INT, -111); + /* Default value is -18.5 dB. */ + sDefaults.putDouble(KEY_OPPORTUNISTIC_NETWORK_ENTRY_THRESHOLD_SS_RSRQ_DOUBLE, -18.5); + /* Default value is -120 dBm. */ + sDefaults.putInt(KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRP_INT, -120); + /* Default value is -18.5 dB. */ + sDefaults.putDouble(KEY_OPPORTUNISTIC_NETWORK_EXIT_THRESHOLD_SS_RSRQ_DOUBLE, -18.5); + /* Default value is 10 seconds. */ + sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_BACKOFF_TIME_LONG, 10000); + /* Default value is 60 seconds. */ + sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_MAX_BACKOFF_TIME_LONG, 60000); + /* Default value is 60 seconds. */ + sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_PING_PONG_TIME_LONG, 60000); + /* Default value is 2 seconds. */ + sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_HYSTERESIS_TIME_LONG, 2000); + /* Default value is 2 seconds. */ + sDefaults.putLong(KEY_OPPORTUNISTIC_NETWORK_5G_DATA_SWITCH_EXIT_HYSTERESIS_TIME_LONG, 2000); + sDefaults.putBoolean(KEY_ENABLE_4G_OPPORTUNISTIC_NETWORK_SCAN_BOOL, true); sDefaults.putAll(Gps.getDefaults()); sDefaults.putIntArray(KEY_CDMA_ENHANCED_ROAMING_INDICATOR_FOR_HOME_NETWORK_INT_ARRAY, new int[] { @@ -5762,7 +5909,7 @@ public class CarrierConfigManager { sDefaults.putString(KEY_CARRIER_PROVISIONING_APP_STRING, ""); sDefaults.putBoolean(KEY_DISPLAY_NO_DATA_NOTIFICATION_ON_PERMANENT_FAILURE_BOOL, false); sDefaults.putBoolean(KEY_UNTHROTTLE_DATA_RETRY_WHEN_TAC_CHANGES_BOOL, false); - sDefaults.putBoolean(KEY_CARRIER_SUPPORTS_MULTIANCHOR_CONFERENCE, false); + sDefaults.putBoolean(KEY_VONR_SETTING_VISIBILITY_BOOL, false); sDefaults.putStringArray(KEY_MULTI_APN_ARRAY_FOR_SAME_GID, new String[] { "52FF:mms,supl,hipri,default,fota:SA:nrphone", "52FF:mms,supl,hipri,default,fota:NSA:nxtgenphone", diff --git a/telephony/java/android/telephony/SignalStrengthUpdateRequest.java b/telephony/java/android/telephony/SignalStrengthUpdateRequest.java index fe7e5976b132..41e24ddb3fa6 100644 --- a/telephony/java/android/telephony/SignalStrengthUpdateRequest.java +++ b/telephony/java/android/telephony/SignalStrengthUpdateRequest.java @@ -26,8 +26,10 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Comparator; +import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Set; @@ -101,9 +103,11 @@ public final class SignalStrengthUpdateRequest implements Parcelable { } mSignalThresholdInfos = new ArrayList<>(signalThresholdInfos); - // Sort the collection with RAN ascending order, make the ordering not matter for equals + // Sort the collection with RAN and then SignalMeasurementType ascending order, make the + // ordering not matter for equals mSignalThresholdInfos.sort( - Comparator.comparingInt(SignalThresholdInfo::getRadioAccessNetworkType)); + Comparator.comparingInt(SignalThresholdInfo::getRadioAccessNetworkType) + .thenComparing(SignalThresholdInfo::getSignalMeasurementType)); return this; } @@ -144,7 +148,7 @@ public final class SignalStrengthUpdateRequest implements Parcelable { * @return the SignalStrengthUpdateRequest object * * @throws IllegalArgumentException if the SignalThresholdInfo collection is empty size, the - * radio access network type in the collection is not unique + * signal measurement type for the same RAN in the collection is not unique */ public @NonNull SignalStrengthUpdateRequest build() { return new SignalStrengthUpdateRequest(mSignalThresholdInfos, @@ -258,14 +262,23 @@ public final class SignalStrengthUpdateRequest implements Parcelable { } /** - * Throw IAE when the RAN in the collection is not unique. + * Throw IAE if SignalThresholdInfo collection is null or empty, + * or the SignalMeasurementType for the same RAN in the collection is not unique. */ private static void validate(Collection<SignalThresholdInfo> infos) { - Set<Integer> uniqueRan = new HashSet<>(infos.size()); + if (infos == null || infos.isEmpty()) { + throw new IllegalArgumentException("SignalThresholdInfo collection is null or empty"); + } + + // Map from RAN to set of SignalMeasurementTypes + Map<Integer, Set<Integer>> ranToTypes = new HashMap<>(infos.size()); for (SignalThresholdInfo info : infos) { final int ran = info.getRadioAccessNetworkType(); - if (!uniqueRan.add(ran)) { - throw new IllegalArgumentException("RAN: " + ran + " is not unique"); + final int type = info.getSignalMeasurementType(); + ranToTypes.putIfAbsent(ran, new HashSet<>()); + if (!ranToTypes.get(ran).add(type)) { + throw new IllegalArgumentException( + "SignalMeasurementType " + type + " for RAN " + ran + " is not unique"); } } } diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index 799930c53669..ba0d6afe25a4 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -3515,7 +3515,8 @@ public class TelephonyManager { */ private int getLogicalSlotIndex(int physicalSlotIndex) { UiccSlotInfo[] slotInfos = getUiccSlotsInfo(); - if (slotInfos != null && physicalSlotIndex >= 0 && physicalSlotIndex < slotInfos.length) { + if (slotInfos != null && physicalSlotIndex >= 0 && physicalSlotIndex < slotInfos.length + && slotInfos[physicalSlotIndex] != null) { return slotInfos[physicalSlotIndex].getLogicalSlotIdx(); } @@ -8888,7 +8889,8 @@ public class TelephonyManager { } /** - * Set the preferred network type to global mode which includes LTE, CDMA, EvDo and GSM/WCDMA. + * Set the preferred network type to global mode which includes NR, LTE, CDMA, EvDo + * and GSM/WCDMA. * * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). * @@ -8899,7 +8901,8 @@ public class TelephonyManager { } /** - * Set the preferred network type to global mode which includes LTE, CDMA, EvDo and GSM/WCDMA. + * Set the preferred network type to global mode which includes NR, LTE, CDMA, EvDo + * and GSM/WCDMA. * * <p>Requires that the calling app has carrier privileges (see {@link #hasCarrierPrivileges}). * @@ -8907,7 +8910,7 @@ public class TelephonyManager { * @hide */ public boolean setPreferredNetworkTypeToGlobal(int subId) { - return setPreferredNetworkType(subId, RILConstants.NETWORK_MODE_LTE_CDMA_EVDO_GSM_WCDMA); + return setPreferredNetworkType(subId, RILConstants.NETWORK_MODE_NR_LTE_CDMA_EVDO_GSM_WCDMA); } /** @@ -12178,6 +12181,100 @@ public class TelephonyManager { } /** + * No error. Operation succeeded. + * @hide + */ + public static final int ENABLE_VONR_SUCCESS = 0; + + /** + * Radio is not available. + * @hide + */ + public static final int ENABLE_VONR_RADIO_NOT_AVAILABLE = 2; + + /** + * Internal Radio error. + * @hide + */ + public static final int ENABLE_VONR_RADIO_ERROR = 3; + + /** + * Voice over NR enable/disable request is received when system is in invalid state. + * @hide + */ + public static final int ENABLE_VONR_RADIO_INVALID_STATE = 4; + + /** + * Voice over NR enable/disable request is not supported. + * @hide + */ + public static final int ENABLE_VONR_REQUEST_NOT_SUPPORTED = 5; + + /** @hide */ + @Retention(RetentionPolicy.SOURCE) + @IntDef(prefix = {"EnableVoNrResult"}, value = { + ENABLE_VONR_SUCCESS, + ENABLE_VONR_RADIO_NOT_AVAILABLE, + ENABLE_VONR_RADIO_ERROR, + ENABLE_VONR_RADIO_INVALID_STATE, + ENABLE_VONR_REQUEST_NOT_SUPPORTED}) + public @interface EnableVoNrResult {} + + /** + * Enable or disable Voice over NR (VoNR) + * + * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the + * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultDataSubscriptionId()} + * + * <p>Requires Permission: + * {@link android.Manifest.permission#MODIFY_PHONE_STATE MODIFY_PHONE_STATE}. + * + * @param enabled enable or disable VoNR. + * @throws IllegalStateException if the Telephony process is not currently available. + * @hide + */ + @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) + public @EnableVoNrResult int setVoNrEnabled(boolean enabled) { + try { + ITelephony service = getITelephony(); + if (service != null) { + return service.setVoNrEnabled( + getSubId(SubscriptionManager.getDefaultDataSubscriptionId()), enabled); + } else { + throw new IllegalStateException("telephony service is null."); + } + } catch (RemoteException e) { + Log.e(TAG, "Error calling ITelephony#setVoNrEnabled", e); + } + + return ENABLE_VONR_RADIO_INVALID_STATE; + } + + /** + * Is Voice over NR (VoNR) enabled. + * @return true if Voice over NR (VoNR) is enabled else false. Enabled state does not mean + * voice call over NR is active or voice ove NR is available. It means the device is allowed to + * register IMS over NR. + * @throws IllegalStateException if the Telephony process is not currently available. + * @hide + */ + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + public boolean isVoNrEnabled() { + try { + ITelephony telephony = getITelephony(); + if (telephony != null) { + return telephony.isVoNrEnabled(getSubId()); + } else { + throw new IllegalStateException("telephony service is null."); + } + } catch (RemoteException ex) { + Rlog.e(TAG, "isVoNrEnabled RemoteException", ex); + ex.rethrowFromSystemServer(); + } + return false; + } + + /** * Carrier action to start or stop reporting default network available events. * * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the @@ -14242,7 +14339,8 @@ public class TelephonyManager { if (callForwardingInfo.getNumber() == null) { throw new IllegalArgumentException("callForwarding number is null"); } - if (callForwardingInfo.getTimeoutSeconds() <= 0) { + if (callForwardingReason == CallForwardingInfo.REASON_NO_REPLY + && callForwardingInfo.getTimeoutSeconds() <= 0) { throw new IllegalArgumentException("callForwarding timeout isn't positive"); } } |