diff options
author | Scott Lobdell <slobdell@google.com> | 2021-04-25 19:53:32 +0000 |
---|---|---|
committer | Daniel Norman <danielnorman@google.com> | 2021-04-29 09:44:07 -0700 |
commit | 2051462f672b5986ef321bf1de3657e7653864e8 (patch) | |
tree | 1dee6334f2b0a68d3cc2e532e6f89bb16149aa7d /telephony/java | |
parent | b22baa1593b2ee33200d009f7f56d1c44a75ac6d (diff) | |
parent | ab6136865a519a27d731b4caa3e782bdf02cfd91 (diff) |
Merge SP1A.210425.001
Change-Id: I8d45e47c131320cac5e794fd629fdef84dd3bcfc
Diffstat (limited to 'telephony/java')
34 files changed, 1340 insertions, 501 deletions
diff --git a/telephony/java/android/telephony/AccessNetworkConstants.java b/telephony/java/android/telephony/AccessNetworkConstants.java index 83b71ff747dc..ac50d101feb9 100644 --- a/telephony/java/android/telephony/AccessNetworkConstants.java +++ b/telephony/java/android/telephony/AccessNetworkConstants.java @@ -63,6 +63,7 @@ public final class AccessNetworkConstants { switch (transportType) { case TRANSPORT_TYPE_WWAN: return "WWAN"; case TRANSPORT_TYPE_WLAN: return "WLAN"; + case TRANSPORT_TYPE_INVALID: return "INVALID"; default: return Integer.toString(transportType); } } @@ -660,18 +661,18 @@ public final class AccessNetworkConstants { this.band = band; this.downlinkLowKhz = downlinkLowKhz; this.downlinkOffset = downlinkOffset; + this.downlinkRange = downlinkRange; this.uplinkLowKhz = uplinkLowKhz; this.uplinkOffset = uplinkOffset; - this.downlinkRange = downlinkRange; this.uplinkRange = uplinkRange; } int band; int downlinkLowKhz; int downlinkOffset; + int downlinkRange; int uplinkLowKhz; int uplinkOffset; - int downlinkRange; int uplinkRange; } diff --git a/telephony/java/android/telephony/AccessNetworkUtils.java b/telephony/java/android/telephony/AccessNetworkUtils.java index f29f3bd352be..6b820459be98 100644 --- a/telephony/java/android/telephony/AccessNetworkUtils.java +++ b/telephony/java/android/telephony/AccessNetworkUtils.java @@ -598,7 +598,8 @@ public class AccessNetworkUtils { : earfcnFrequency.downlinkOffset; break; } else { - Log.e(TAG, "Band and the range of EARFCN are not consistent."); + Rlog.w(TAG,"Band and the range of EARFCN are not consistent: band = " + band + + " ,earfcn = " + earfcn + " ,isUplink = " + isUplink); return INVALID_FREQUENCY; } } @@ -617,7 +618,7 @@ public class AccessNetworkUtils { } private static boolean isInEarfcnRange(int earfcn, EutranBandArfcnFrequency earfcnFrequency, - boolean isUplink) { + boolean isUplink) { if (isUplink) { return earfcn >= earfcnFrequency.uplinkOffset && earfcn <= earfcnFrequency.uplinkRange; } else { @@ -640,7 +641,8 @@ public class AccessNetworkUtils { : uarfcnFrequency.downlinkOffset; break; } else { - Log.e(TAG, "Band and the range of UARFCN are not consistent."); + Rlog.w(TAG,"Band and the range of UARFCN are not consistent: band = " + band + + " ,uarfcn = " + uarfcn + " ,isUplink = " + isUplink); return INVALID_FREQUENCY; } } @@ -716,7 +718,8 @@ public class AccessNetworkUtils { arfcnOffset); break; } else { - Log.e(TAG, "Band and the range of ARFCN are not consistent."); + Rlog.w(TAG,"Band and the range of ARFCN are not consistent: band = " + band + + " ,arfcn = " + arfcn + " ,isUplink = " + isUplink); return INVALID_FREQUENCY; } } @@ -733,7 +736,7 @@ public class AccessNetworkUtils { * Downlink actual frequency(kHz) = Uplink actual frequency + 10 */ private static int convertArfcnToFrequency(int arfcn, int uplinkFrequencyFirstKhz, - int arfcnOffset) { + int arfcnOffset) { return uplinkFrequencyFirstKhz + 200 * (arfcn - arfcnOffset); } diff --git a/telephony/java/android/telephony/CarrierBandwidth.java b/telephony/java/android/telephony/CarrierBandwidth.java deleted file mode 100644 index 9e1dee0162b9..000000000000 --- a/telephony/java/android/telephony/CarrierBandwidth.java +++ /dev/null @@ -1,226 +0,0 @@ -/* - * Copyright (C) 2020 The Android Open Source Project - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package android.telephony; - -import android.annotation.NonNull; -import android.annotation.Nullable; -import android.annotation.RequiresFeature; -import android.annotation.SystemApi; -import android.os.Parcel; -import android.os.Parcelable; - -import java.util.Objects; - -/** - * Defines downlink and uplink capacity of a network in kbps - * @hide - */ -@SystemApi -public final class CarrierBandwidth implements Parcelable { - /** - * Any field that is not reported shall be set to INVALID - */ - public static final int INVALID = -1; - - /** - * Estimated downlink capacity in kbps of the primary carrier. - * This bandwidth estimate shall be the estimated maximum sustainable link bandwidth. - * This will be {@link #INVALID} if the network is not connected - */ - private int mPrimaryDownlinkCapacityKbps; - - /** - * Estimated uplink capacity in kbps of the primary carrier. - * This bandwidth estimate shall be the estimated maximum sustainable link bandwidth. - * This will be {@link #INVALID} if the network is not connected - */ - private int mPrimaryUplinkCapacityKbps; - - /** - * Estimated downlink capacity in kbps of the secondary carrier in a dual connected network. - * This bandwidth estimate shall be the estimated maximum sustainable link bandwidth. - * This will be {@link #INVALID} if the network is not connected - */ - private int mSecondaryDownlinkCapacityKbps; - - /** - * Estimated uplink capacity in kbps of the secondary carrier in a dual connected network. - * This bandwidth estimate shall be the estimated maximum sustainable link bandwidth. - * This will be {@link #INVALID} if the network is not connected - */ - private int mSecondaryUplinkCapacityKbps; - - /** @hide **/ - public CarrierBandwidth(Parcel in) { - mPrimaryDownlinkCapacityKbps = in.readInt(); - mPrimaryUplinkCapacityKbps = in.readInt(); - mSecondaryDownlinkCapacityKbps = in.readInt(); - mSecondaryUplinkCapacityKbps = in.readInt(); - } - - /** @hide **/ - public CarrierBandwidth() { - mPrimaryDownlinkCapacityKbps = INVALID; - mPrimaryUplinkCapacityKbps = INVALID; - mSecondaryDownlinkCapacityKbps = INVALID; - mSecondaryUplinkCapacityKbps = INVALID; - } - - /** - * Constructor. - * - * @param primaryDownlinkCapacityKbps Estimated downlink capacity in kbps of - * the primary carrier. - * @param primaryUplinkCapacityKbps Estimated uplink capacity in kbps of - * the primary carrier. - * @param secondaryDownlinkCapacityKbps Estimated downlink capacity in kbps of - * the secondary carrier - * @param secondaryUplinkCapacityKbps Estimated uplink capacity in kbps of - * the secondary carrier - */ - public CarrierBandwidth(int primaryDownlinkCapacityKbps, int primaryUplinkCapacityKbps, - int secondaryDownlinkCapacityKbps, int secondaryUplinkCapacityKbps) { - mPrimaryDownlinkCapacityKbps = primaryDownlinkCapacityKbps; - mPrimaryUplinkCapacityKbps = primaryUplinkCapacityKbps; - mSecondaryDownlinkCapacityKbps = secondaryDownlinkCapacityKbps; - mSecondaryUplinkCapacityKbps = secondaryUplinkCapacityKbps; - } - - /** - * 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 - * - * @return The estimated first hop upstream (device to network) bandwidth. - */ - public int getPrimaryDownlinkCapacityKbps() { - return mPrimaryDownlinkCapacityKbps; - } - - /** - * 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 - * - * @return The estimated first hop downstream (network to device) bandwidth. - */ - public int getPrimaryUplinkCapacityKbps() { - return mPrimaryUplinkCapacityKbps; - } - - /** - * 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: - * <ol> - * <li>The network is not connected</li> - * <li>The device does not support - * {@link android.telephony.TelephonyManager#CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE}.</li> - * </ol> - * - * @return The estimated first hop upstream (device to network) bandwidth. - */ - @RequiresFeature( - enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported", - value = TelephonyManager.CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE) - public int getSecondaryDownlinkCapacityKbps() { - return mSecondaryDownlinkCapacityKbps; - } - - /** - * 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: - * <ol> - * <li>The network is not connected</li> - * <li>The device does not support - * {@link android.telephony.TelephonyManager#CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE}.</li> - * </ol> - * @return The estimated first hop downstream (network to device) bandwidth. - */ - @RequiresFeature( - enforcement = "android.telephony.TelephonyManager#isRadioInterfaceCapabilitySupported", - value = TelephonyManager.CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE) - public int getSecondaryUplinkCapacityKbps() { - return mSecondaryUplinkCapacityKbps; - } - - @NonNull - @Override - public String toString() { - return "CarrierBandwidth: {primaryDownlinkCapacityKbps=" + mPrimaryDownlinkCapacityKbps - + " primaryUplinkCapacityKbps=" + mPrimaryUplinkCapacityKbps - + " secondaryDownlinkCapacityKbps=" + mSecondaryDownlinkCapacityKbps - + " secondaryUplinkCapacityKbps=" + mSecondaryUplinkCapacityKbps - + "}"; - } - - @Override - public int hashCode() { - return Objects.hash( - mPrimaryDownlinkCapacityKbps, - mPrimaryUplinkCapacityKbps, - mSecondaryDownlinkCapacityKbps, - mSecondaryUplinkCapacityKbps); - } - - @Override - public boolean equals(@Nullable Object o) { - if (o == null || !(o instanceof CallQuality) || hashCode() != o.hashCode()) { - return false; - } - if (this == o) { - return true; - } - CarrierBandwidth s = (CarrierBandwidth) o; - return (mPrimaryDownlinkCapacityKbps == s.mPrimaryDownlinkCapacityKbps - && mPrimaryUplinkCapacityKbps == s.mPrimaryUplinkCapacityKbps - && mSecondaryDownlinkCapacityKbps == s.mSecondaryDownlinkCapacityKbps - && mSecondaryDownlinkCapacityKbps == s.mSecondaryDownlinkCapacityKbps); - } - - /** - * {@link Parcelable#describeContents} - */ - public int describeContents() { - return 0; - } - - /** - * {@link Parcelable#writeToParcel} - * @hide - */ - public void writeToParcel(Parcel dest, int flags) { - dest.writeInt(mPrimaryDownlinkCapacityKbps); - dest.writeInt(mPrimaryUplinkCapacityKbps); - dest.writeInt(mSecondaryDownlinkCapacityKbps); - dest.writeInt(mSecondaryUplinkCapacityKbps); - } - - public static final @android.annotation.NonNull Parcelable.Creator<CarrierBandwidth> CREATOR = - new Parcelable.Creator() { - public CarrierBandwidth createFromParcel(Parcel in) { - return new CarrierBandwidth(in); - } - - public CarrierBandwidth[] newArray(int size) { - return new CarrierBandwidth[size]; - } - }; -} diff --git a/telephony/java/android/telephony/CarrierConfigManager.java b/telephony/java/android/telephony/CarrierConfigManager.java index b9c2f2a72451..6acc8ab991d3 100644 --- a/telephony/java/android/telephony/CarrierConfigManager.java +++ b/telephony/java/android/telephony/CarrierConfigManager.java @@ -4259,7 +4259,6 @@ public class CarrierConfigManager { * 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"; @@ -4973,6 +4972,14 @@ public class CarrierConfigManager { public static final String KEY_DISPLAY_NO_DATA_NOTIFICATION_ON_PERMANENT_FAILURE_BOOL = "display_no_data_notification_on_permanent_failure_bool"; + /** + * Determine whether unthrottle data retry when tracking area code (TAC/LAC) from cell changes + * + * @hide + */ + public static final String KEY_UNTHROTTLE_DATA_RETRY_WHEN_TAC_CHANGES_BOOL = + "unthrottle_data_retry_when_tac_changes_bool"; + /** * Flag indicating whether carrier supports multianchor conference. * In multianchor conference, a participant of a conference can add @@ -5155,6 +5162,7 @@ public class CarrierConfigManager { + "320000:5000,640000:5000,1280000:5000,1800000:5000", "mms:default_randomization=2000,5000,10000,20000,40000,80000:5000,160000:5000," + "320000:5000,640000:5000,1280000:5000,1800000:5000", + "ims:max_retries=10, 5000, 5000, 5000", "others:max_retries=3, 5000, 5000, 5000"}); sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_DELAY_DEFAULT_LONG, 20000); sDefaults.putLong(KEY_CARRIER_DATA_CALL_APN_DELAY_FASTER_LONG, 3000); @@ -5596,6 +5604,7 @@ public class CarrierConfigManager { sDefaults.putBoolean(KEY_DISPLAY_CALL_STRENGTH_INDICATOR_BOOL, true); 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.putStringArray(KEY_MULTI_APN_ARRAY_FOR_SAME_GID, new String[] { "52FF:mms,supl,hipri,default,fota:SA:nrphone", diff --git a/telephony/java/android/telephony/CellIdentityNr.java b/telephony/java/android/telephony/CellIdentityNr.java index 2d2420da2a9a..cdd54cd25311 100644 --- a/telephony/java/android/telephony/CellIdentityNr.java +++ b/telephony/java/android/telephony/CellIdentityNr.java @@ -118,7 +118,7 @@ public final class CellIdentityNr extends CellIdentity { @Override public @NonNull CellIdentityNr sanitizeLocationInfo() { return new CellIdentityNr(CellInfo.UNAVAILABLE, CellInfo.UNAVAILABLE, mNrArfcn, - mBands, mMccStr, mMncStr, CellInfo.UNAVAILABLE, mAlphaLong, mAlphaShort, + mBands, mMccStr, mMncStr, CellInfo.UNAVAILABLE_LONG, mAlphaLong, mAlphaShort, mAdditionalPlmns); } diff --git a/telephony/java/android/telephony/CellSignalStrengthNr.java b/telephony/java/android/telephony/CellSignalStrengthNr.java index bde62fb2977c..ac01afa51729 100644 --- a/telephony/java/android/telephony/CellSignalStrengthNr.java +++ b/telephony/java/android/telephony/CellSignalStrengthNr.java @@ -134,7 +134,7 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa * * Range [0, 15] for each CQI. */ - private List<Integer> mCsiCqiReport;; + private List<Integer> mCsiCqiReport; private int mSsRsrp; private int mSsRsrq; private int mSsSinr; @@ -172,13 +172,13 @@ public final class CellSignalStrengthNr extends CellSignalStrength implements Pa * @hide */ public CellSignalStrengthNr(int csiRsrp, int csiRsrq, int csiSinr, int csiCqiTableIndex, - List<Integer> csiCqiReport, int ssRsrp, int ssRsrq, int ssSinr) { + List<Byte> csiCqiReport, int ssRsrp, int ssRsrq, int ssSinr) { mCsiRsrp = inRangeOrUnavailable(csiRsrp, -140, -44); mCsiRsrq = inRangeOrUnavailable(csiRsrq, -20, -3); mCsiSinr = inRangeOrUnavailable(csiSinr, -23, 23); mCsiCqiTableIndex = inRangeOrUnavailable(csiCqiTableIndex, 1, 3); - mCsiCqiReport = csiCqiReport.stream() - .map(cqi -> new Integer(inRangeOrUnavailable(cqi.intValue(), 1, 3))) + mCsiCqiReport = csiCqiReport.stream() + .map(cqi -> new Integer(inRangeOrUnavailable(Byte.toUnsignedInt(cqi), 1, 3))) .collect(Collectors.toList()); mSsRsrp = inRangeOrUnavailable(ssRsrp, -140, -44); mSsRsrq = inRangeOrUnavailable(ssRsrq, -43, 20); diff --git a/telephony/java/android/telephony/DataFailCause.java b/telephony/java/android/telephony/DataFailCause.java index c8ed82cd2a3f..4d5b6ace39ab 100644 --- a/telephony/java/android/telephony/DataFailCause.java +++ b/telephony/java/android/telephony/DataFailCause.java @@ -1055,6 +1055,20 @@ public final class DataFailCause { */ public static final int HANDOVER_FAILED = 0x10006; + /** + * Enterprise setup failure: duplicate CID in DataCallResponse. + * + * @hide + */ + public static final int DUPLICATE_CID = 0x10007; + + /** + * Enterprise setup failure: no default data connection set up yet. + * + * @hide + */ + public static final int NO_DEFAULT_DATA = 0x10008; + private static final Map<Integer, String> sFailCauseMap; static { sFailCauseMap = new HashMap<>(); @@ -1426,6 +1440,8 @@ public final class DataFailCause { sFailCauseMap.put(IPV6_PREFIX_UNAVAILABLE, "IPV6_PREFIX_UNAVAILABLE"); sFailCauseMap.put(HANDOFF_PREFERENCE_CHANGED, "HANDOFF_PREFERENCE_CHANGED"); sFailCauseMap.put(SLICE_REJECTED, "SLICE_REJECTED"); + sFailCauseMap.put(MATCH_ALL_RULE_NOT_ALLOWED, "MATCH_ALL_RULE_NOT_ALLOWED"); + sFailCauseMap.put(ALL_MATCHING_RULES_FAILED, "ALL_MATCHING_RULES_FAILED"); sFailCauseMap.put(IWLAN_PDN_CONNECTION_REJECTION, "IWLAN_PDN_CONNECTION_REJECTION"); sFailCauseMap.put(IWLAN_MAX_CONNECTION_REACHED, "IWLAN_MAX_CONNECTION_REACHED"); sFailCauseMap.put(IWLAN_SEMANTIC_ERROR_IN_THE_TFT_OPERATION, @@ -1481,6 +1497,9 @@ public final class DataFailCause { sFailCauseMap.put(UNACCEPTABLE_NETWORK_PARAMETER, "UNACCEPTABLE_NETWORK_PARAMETER"); sFailCauseMap.put(LOST_CONNECTION, "LOST_CONNECTION"); + sFailCauseMap.put(HANDOVER_FAILED, "HANDOVER_FAILED"); + sFailCauseMap.put(DUPLICATE_CID, "DUPLICATE_CID"); + sFailCauseMap.put(NO_DEFAULT_DATA, "NO_DEFAULT_DATA"); } private DataFailCause() { @@ -1580,6 +1599,9 @@ public final class DataFailCause { add(RADIO_NOT_AVAILABLE); add(UNACCEPTABLE_NETWORK_PARAMETER); add(SIGNAL_LOST); + add(DUPLICATE_CID); + add(MATCH_ALL_RULE_NOT_ALLOWED); + add(ALL_MATCHING_RULES_FAILED); } }; } diff --git a/telephony/java/android/telephony/SubscriptionManager.java b/telephony/java/android/telephony/SubscriptionManager.java index d8ac08298530..2616ec8cc04f 100644 --- a/telephony/java/android/telephony/SubscriptionManager.java +++ b/telephony/java/android/telephony/SubscriptionManager.java @@ -2785,7 +2785,8 @@ public class SubscriptionManager { * @param subId the subscriber this override applies to. * @param overrideUnmetered set if the billing relationship should be * considered unmetered. - * @param networkTypes the network types this override applies to. + * @param networkTypes the network types this override applies to. If no + * network types are specified, override values will be ignored. * {@see TelephonyManager#getAllNetworkTypes()} * @param timeoutMillis the timeout after which the requested override will * be automatically cleared, or {@code 0} to leave in the @@ -2849,7 +2850,8 @@ public class SubscriptionManager { * @param subId the subscriber this override applies to. * @param overrideCongested set if the subscription should be considered * congested. - * @param networkTypes the network types this override applies to. + * @param networkTypes the network types this override applies to. If no + * network types are specified, override values will be ignored. * {@see TelephonyManager#getAllNetworkTypes()} * @param timeoutMillis the timeout after which the requested override will * be automatically cleared, or {@code 0} to leave in the diff --git a/telephony/java/android/telephony/TelephonyManager.java b/telephony/java/android/telephony/TelephonyManager.java index b3886c274ae4..931915f55960 100644 --- a/telephony/java/android/telephony/TelephonyManager.java +++ b/telephony/java/android/telephony/TelephonyManager.java @@ -64,7 +64,6 @@ import android.os.ParcelFileDescriptor; import android.os.ParcelUuid; import android.os.Parcelable; import android.os.PersistableBundle; -import android.os.Process; import android.os.RemoteException; import android.os.ResultReceiver; import android.os.SystemProperties; @@ -90,7 +89,7 @@ import android.telephony.CallForwardingInfo.CallForwardingReason; import android.telephony.VisualVoicemailService.VisualVoicemailTask; import android.telephony.data.ApnSetting; import android.telephony.data.ApnSetting.MvnoType; -import android.telephony.data.SlicingConfig; +import android.telephony.data.NetworkSlicingConfig; import android.telephony.emergency.EmergencyNumber; import android.telephony.emergency.EmergencyNumber.EmergencyServiceCategories; import android.telephony.gba.UaSecurityProtocolIdentifier; @@ -428,10 +427,6 @@ public class TelephonyManager { return null; } - private boolean isSystemProcess() { - return Process.myUid() == Process.SYSTEM_UID; - } - /** * Post a runnable to the BackgroundThread. * @@ -4210,19 +4205,12 @@ public class TelephonyManager { try { IPhoneSubInfo info = getSubscriberInfoService(); if (info == null) { - Rlog.e(TAG, "IMSI error: Subscriber Info is null"); - if (!isSystemProcess()) { - throw new RuntimeException("IMSI error: Subscriber Info is null"); - } - return; + throw new RuntimeException("IMSI error: Subscriber Info is null"); } int subId = getSubId(SubscriptionManager.getDefaultDataSubscriptionId()); info.resetCarrierKeysForImsiEncryption(subId, mContext.getOpPackageName()); } catch (RemoteException ex) { - Rlog.e(TAG, "getCarrierInfoForImsiEncryption RemoteException" + ex); - if (!isSystemProcess()) { - ex.rethrowAsRuntimeException(); - } + Rlog.e(TAG, "Telephony#getCarrierInfoForImsiEncryption RemoteException" + ex); } } @@ -4889,11 +4877,11 @@ public class TelephonyManager { /** * Return the set of IMSIs that should be considered "merged together" for data usage - * purposes. Unlike {@link #getMergedSubscriberIds()} this API merge IMSIs based on - * subscription grouping: IMSI of those in the same group will all be returned. - * Return the current IMSI if there is no subscription group. - * - * <p>Requires the calling app to have READ_PRIVILEGED_PHONE_STATE permission. + * purposes. This API merges IMSIs based on subscription grouping: IMSI of those in the same + * group will all be returned. + * Return the current IMSI if there is no subscription group, see + * {@link SubscriptionManager#createSubscriptionGroup(List)} for the definition of a group, + * otherwise return an empty array if there is a failure. * * @hide */ @@ -4906,7 +4894,6 @@ public class TelephonyManager { return telephony.getMergedImsisFromGroup(getSubId(), getOpPackageName()); } } catch (RemoteException ex) { - } catch (NullPointerException ex) { } return new String[0]; } @@ -5619,17 +5606,11 @@ public class TelephonyManager { try { final ITelephony telephony = getITelephony(); if (telephony == null) { - if (!isSystemProcess()) { - throw new RuntimeException("Telephony service unavailable"); - } return; } telephony.sendDialerSpecialCode(mContext.getOpPackageName(), inputCode); } catch (RemoteException ex) { - // This could happen if binder process crashes. - if (!isSystemProcess()) { - ex.rethrowAsRuntimeException(); - } + Rlog.e(TAG, "Telephony#sendDialerSpecialCode RemoteException" + ex); } } @@ -9172,7 +9153,7 @@ public class TelephonyManager { /** @hide */ @SystemApi - @SuppressLint("RequiresPermission") + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int checkCarrierPrivilegesForPackage(String pkgName) { try { ITelephony telephony = getITelephony(); @@ -9188,7 +9169,7 @@ public class TelephonyManager { /** @hide */ @SystemApi - @SuppressLint("RequiresPermission") + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public int checkCarrierPrivilegesForPackageAnyPhone(String pkgName) { try { ITelephony telephony = getITelephony(); @@ -9210,6 +9191,7 @@ public class TelephonyManager { /** @hide */ @SystemApi + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public List<String> getCarrierPackageNamesForIntentAndPhone(Intent intent, int phoneId) { try { ITelephony telephony = getITelephony(); @@ -9224,6 +9206,7 @@ public class TelephonyManager { } /** @hide */ + @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public List<String> getPackagesWithCarrierPrivileges() { try { ITelephony telephony = getITelephony(); @@ -9948,9 +9931,7 @@ public class TelephonyManager { throw new IllegalStateException("telephony service is null."); } } catch (RemoteException ex) { - if (!isSystemProcess()) { - ex.rethrowAsRuntimeException(); - } + Rlog.e(TAG, "Telephony#getMobileProvisioningUrl RemoteException" + ex); } return null; } @@ -10102,14 +10083,15 @@ public class TelephonyManager { /** * Sets the roaming mode for CDMA phone to the given mode {@code mode}. If the phone is not - * CDMA capable, this method does nothing. + * CDMA capable, this method throws an IllegalStateException. * * <p>If this object has been created with {@link #createForSubscriptionId}, applies to the * given subId. Otherwise, applies to {@link SubscriptionManager#getDefaultSubscriptionId()} * * @param mode CDMA roaming mode. * @throws SecurityException if the caller does not have the permission. - * @throws IllegalStateException if the Telephony process or radio is not currently available. + * @throws IllegalStateException if the Telephony process or radio is not currently available, + * the device is not CDMA capable, or the request fails. * * @see #CDMA_ROAMING_MODE_RADIO_DEFAULT * @see #CDMA_ROAMING_MODE_HOME @@ -10125,7 +10107,9 @@ public class TelephonyManager { @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCdmaRoamingMode(@CdmaRoamingMode int mode) { - if (getPhoneType() != PHONE_TYPE_CDMA) return; + if (getPhoneType() != PHONE_TYPE_CDMA) { + throw new IllegalStateException("Phone does not support CDMA."); + } try { ITelephony telephony = getITelephony(); if (telephony != null) { @@ -10207,11 +10191,12 @@ public class TelephonyManager { /** * Sets the subscription mode for CDMA phone to the given mode {@code mode}. If the phone is not - * CDMA capable, this method does nothing. + * CDMA capable, this method throws an IllegalStateException. * * @param mode CDMA subscription mode. * @throws SecurityException if the caller does not have the permission. - * @throws IllegalStateException if the Telephony process is not currently available. + * @throws IllegalStateException if the Telephony process or radio is not currently available, + * the device is not CDMA capable, or the request fails. * * @see #CDMA_SUBSCRIPTION_UNKNOWN * @see #CDMA_SUBSCRIPTION_RUIM_SIM @@ -10226,7 +10211,9 @@ public class TelephonyManager { @SystemApi @RequiresPermission(android.Manifest.permission.MODIFY_PHONE_STATE) public void setCdmaSubscriptionMode(@CdmaSubscription int mode) { - if (getPhoneType() != PHONE_TYPE_CDMA) return; + if (getPhoneType() != PHONE_TYPE_CDMA) { + throw new IllegalStateException("Phone does not support CDMA."); + } try { ITelephony telephony = getITelephony(); if (telephony != null) { @@ -11767,26 +11754,26 @@ public class TelephonyManager { } /** - * Return a list of certs in hex string from loaded carrier privileges access rules. - * - * @return a list of certificate in hex string. return {@code null} if there is no certs - * or privilege rules are not loaded yet. + * Return a list of certs as hex strings from loaded carrier privileges access rules. * - * <p>Requires Permission: - * {@link android.Manifest.permission#READ_PRIVILEGED_PHONE_STATE} + * @return a list of certificates as hex strings, or an empty list if there are no certs or + * privilege rules are not loaded yet. * @hide */ + @TestApi @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) + @NonNull public List<String> getCertsFromCarrierPrivilegeAccessRules() { + List<String> certs = null; try { ITelephony service = getITelephony(); if (service != null) { - return service.getCertsFromCarrierPrivilegeAccessRules(getSubId()); + certs = service.getCertsFromCarrierPrivilegeAccessRules(getSubId()); } } catch (RemoteException ex) { // This could happen if binder process crashes. } - return null; + return certs == null ? Collections.emptyList() : certs; } /** @@ -13934,9 +13921,7 @@ public class TelephonyManager { return service.isDataEnabledForApn(apnType, getSubId(), pkgForDebug); } } catch (RemoteException ex) { - if (!isSystemProcess()) { - ex.rethrowAsRuntimeException(); - } + Rlog.e(TAG, "Telephony#isDataEnabledForApn RemoteException" + ex); } return false; } @@ -13956,9 +13941,7 @@ public class TelephonyManager { return service.isApnMetered(apnType, getSubId()); } } catch (RemoteException ex) { - if (!isSystemProcess()) { - ex.rethrowAsRuntimeException(); - } + Rlog.e(TAG, "Telephony#isApnMetered RemoteException" + ex); } return true; } @@ -14018,9 +14001,7 @@ public class TelephonyManager { service.setSystemSelectionChannels(specifiers, getSubId(), aidlConsumer); } } catch (RemoteException ex) { - if (!isSystemProcess()) { - ex.rethrowAsRuntimeException(); - } + Rlog.e(TAG, "Telephony#setSystemSelectionChannels RemoteException" + ex); } } @@ -14048,9 +14029,7 @@ public class TelephonyManager { throw new IllegalStateException("telephony service is null."); } } catch (RemoteException ex) { - if (!isSystemProcess()) { - ex.rethrowAsRuntimeException(); - } + Rlog.e(TAG, "Telephony#getSystemSelectionChannels RemoteException" + ex); } return new ArrayList<>(); } @@ -14079,9 +14058,7 @@ public class TelephonyManager { return service.isMvnoMatched(getSubId(), mvnoType, mvnoMatchData); } } catch (RemoteException ex) { - if (!isSystemProcess()) { - ex.rethrowAsRuntimeException(); - } + Rlog.e(TAG, "Telephony#matchesCurrentSimOperator RemoteException" + ex); } return false; } @@ -14482,10 +14459,7 @@ public class TelephonyManager { service.setMobileDataPolicyEnabled(getSubId(), policy, enabled); } } catch (RemoteException ex) { - // This could happen if binder process crashes. - if (!isSystemProcess()) { - ex.rethrowAsRuntimeException(); - } + Rlog.e(TAG, "Telephony#setMobileDataPolicyEnabled RemoteException" + ex); } } @@ -14505,10 +14479,7 @@ public class TelephonyManager { return service.isMobileDataPolicyEnabled(getSubId(), policy); } } catch (RemoteException ex) { - // This could happen if binder process crashes. - if (!isSystemProcess()) { - ex.rethrowAsRuntimeException(); - } + Rlog.e(TAG, "Telephony#isMobileDataPolicyEnabled RemoteException" + ex); } return false; } @@ -15012,9 +14983,7 @@ public class TelephonyManager { throw new IllegalStateException("telephony service is null."); } } catch (RemoteException ex) { - if (!isSystemProcess()) { - ex.rethrowAsRuntimeException(); - } + Rlog.e(TAG, "Telephony#getEquivalentHomePlmns RemoteException" + ex); } return Collections.emptyList(); @@ -15072,13 +15041,20 @@ public class TelephonyManager { public static final String CAPABILITY_SLICING_CONFIG_SUPPORTED = "CAPABILITY_SLICING_CONFIG_SUPPORTED"; - /** @hide */ + /** + * A list of the radio interface capability values with public valid constants. + * + * Here is a related list for the systemapi-only valid constants: + * CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE + * CAPABILITY_ALLOWED_NETWORK_TYPES_USED + * CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE + * CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING + * + * @hide + * TODO(b/185508047): Doc generation for mixed public/systemapi StringDefs formats badly. + */ @Retention(RetentionPolicy.SOURCE) @StringDef(prefix = "CAPABILITY_", value = { - CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE, - CAPABILITY_ALLOWED_NETWORK_TYPES_USED, - CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE, - CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING, CAPABILITY_SLICING_CONFIG_SUPPORTED, }) public @interface RadioInterfaceCapability {} @@ -15090,10 +15066,7 @@ public class TelephonyManager { * * @param capability the name of the capability to check for * @return the availability of the capability - * - * @hide */ - @SystemApi public boolean isRadioInterfaceCapabilitySupported( @NonNull @RadioInterfaceCapability String capability) { try { @@ -15106,9 +15079,7 @@ public class TelephonyManager { throw new IllegalStateException("telephony service is null."); } } catch (RemoteException ex) { - if (!isSystemProcess()) { - ex.rethrowAsRuntimeException(); - } + Rlog.e(TAG, "Telephony#isRadioInterfaceCapabilitySupported RemoteException" + ex); } return false; } @@ -15677,7 +15648,7 @@ public class TelephonyManager { * Exception that may be supplied to the callback in {@link #getNetworkSlicingConfiguration} if * something goes awry. */ - public static class SlicingException extends Exception { + public static class NetworkSlicingException extends Exception { /** * Getting the current slicing configuration successfully. Used internally only. * @hide @@ -15686,11 +15657,13 @@ public class TelephonyManager { /** * The system timed out waiting for a response from the Radio. + * @hide */ public static final int ERROR_TIMEOUT = 1; /** * The modem returned a failure. + * @hide */ public static final int ERROR_MODEM_ERROR = 2; @@ -15700,20 +15673,44 @@ public class TelephonyManager { ERROR_MODEM_ERROR, }) @Retention(RetentionPolicy.SOURCE) - public @interface SlicingError {} + public @interface NetworkSlicingError {} private final int mErrorCode; - public SlicingException(@SlicingError int errorCode) { + /** @hide */ + public NetworkSlicingException(@NetworkSlicingError int errorCode) { mErrorCode = errorCode; } - /** - * Fetches the error code associated with this exception. - * @return An error code. - */ - public @SlicingError int getErrorCode() { - return mErrorCode; + @Override + public String toString() { + switch (mErrorCode) { + case ERROR_TIMEOUT: return "ERROR_TIMEOUT"; + case ERROR_MODEM_ERROR: return "ERROR_MODEM_ERROR"; + default: return "UNDEFINED"; + } + } + } + + /** + * Exception that is supplied to the callback in {@link #getNetworkSlicingConfiguration} if the + * system timed out waiting for a response from the Radio. + */ + public class TimeoutException extends NetworkSlicingException { + /** @hide */ + public TimeoutException(int errorCode) { + super(errorCode); + } + } + + /** + * Exception that is supplied to the callback in {@link #getNetworkSlicingConfiguration} if the + * modem returned a failure. + */ + public class ModemErrorException extends NetworkSlicingException { + /** @hide */ + public ModemErrorException(int errorCode) { + super(errorCode); } } @@ -15744,7 +15741,7 @@ public class TelephonyManager { @RequiresPermission(android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE) public void getNetworkSlicingConfiguration( @NonNull @CallbackExecutor Executor executor, - @NonNull OutcomeReceiver<SlicingConfig, SlicingException> callback) { + @NonNull OutcomeReceiver<NetworkSlicingConfig, NetworkSlicingException> callback) { Objects.requireNonNull(executor); Objects.requireNonNull(callback); @@ -15756,12 +15753,17 @@ public class TelephonyManager { telephony.getSlicingConfig(new ResultReceiver(null) { @Override protected void onReceiveResult(int resultCode, Bundle result) { - if (resultCode != SlicingException.SUCCESS) { + if (resultCode == NetworkSlicingException.ERROR_TIMEOUT) { + executor.execute(() -> callback.onError( + new TimeoutException(resultCode))); + return; + } else if (resultCode == NetworkSlicingException.ERROR_MODEM_ERROR) { executor.execute(() -> callback.onError( - new SlicingException(resultCode))); + new ModemErrorException(resultCode))); return; } - SlicingConfig slicingConfig = + + NetworkSlicingConfig slicingConfig = result.getParcelable(KEY_SLICING_CONFIG_HANDLE); executor.execute(() -> callback.onResult(slicingConfig)); } diff --git a/telephony/java/android/telephony/data/SlicingConfig.aidl b/telephony/java/android/telephony/data/NetworkSlicingConfig.aidl index ad93d8cafeba..cd4a8f1e45be 100644 --- a/telephony/java/android/telephony/data/SlicingConfig.aidl +++ b/telephony/java/android/telephony/data/NetworkSlicingConfig.aidl @@ -16,4 +16,4 @@ package android.telephony.data; -parcelable SlicingConfig; +parcelable NetworkSlicingConfig; diff --git a/telephony/java/android/telephony/data/SlicingConfig.java b/telephony/java/android/telephony/data/NetworkSlicingConfig.java index 990e4d218930..dec787f40ff2 100644 --- a/telephony/java/android/telephony/data/SlicingConfig.java +++ b/telephony/java/android/telephony/data/NetworkSlicingConfig.java @@ -28,22 +28,22 @@ import java.util.Objects; /** * Represents a slicing configuration */ -public final class SlicingConfig implements Parcelable { +public final class NetworkSlicingConfig implements Parcelable { private final List<UrspRule> mUrspRules; private final List<NetworkSliceInfo> mSliceInfo; - public SlicingConfig() { + public NetworkSlicingConfig() { mUrspRules = new ArrayList<UrspRule>(); mSliceInfo = new ArrayList<NetworkSliceInfo>(); } /** @hide */ - public SlicingConfig(android.hardware.radio.V1_6.SlicingConfig sc) { + public NetworkSlicingConfig(android.hardware.radio.V1_6.SlicingConfig sc) { this(sc.urspRules, sc.sliceInfo); } /** @hide */ - public SlicingConfig(List<android.hardware.radio.V1_6.UrspRule> urspRules, + public NetworkSlicingConfig(List<android.hardware.radio.V1_6.UrspRule> urspRules, List<android.hardware.radio.V1_6.SliceInfo> sliceInfo) { mUrspRules = new ArrayList<UrspRule>(); for (android.hardware.radio.V1_6.UrspRule ur : urspRules) { @@ -69,7 +69,7 @@ public final class SlicingConfig implements Parcelable { } /** @hide */ - public SlicingConfig(Parcel p) { + public NetworkSlicingConfig(Parcel p) { mUrspRules = p.createTypedArrayList(UrspRule.CREATOR); mSliceInfo = p.createTypedArrayList(NetworkSliceInfo.CREATOR); } @@ -96,16 +96,16 @@ public final class SlicingConfig implements Parcelable { dest.writeTypedList(mSliceInfo, flags); } - public static final @NonNull Parcelable.Creator<SlicingConfig> CREATOR = - new Parcelable.Creator<SlicingConfig>() { + public static final @NonNull Parcelable.Creator<NetworkSlicingConfig> CREATOR = + new Parcelable.Creator<NetworkSlicingConfig>() { @Override - public SlicingConfig createFromParcel(Parcel source) { - return new SlicingConfig(source); + public NetworkSlicingConfig createFromParcel(Parcel source) { + return new NetworkSlicingConfig(source); } @Override - public SlicingConfig[] newArray(int size) { - return new SlicingConfig[size]; + public NetworkSlicingConfig[] newArray(int size) { + return new NetworkSlicingConfig[size]; } }; @@ -118,7 +118,7 @@ public final class SlicingConfig implements Parcelable { public boolean equals(@Nullable Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; - SlicingConfig that = (SlicingConfig) o; + NetworkSlicingConfig that = (NetworkSlicingConfig) o; return mUrspRules.size() == that.mUrspRules.size() && mUrspRules.containsAll(that.mUrspRules) && mSliceInfo.size() == that.mSliceInfo.size() diff --git a/telephony/java/android/telephony/data/QosBearerFilter.java b/telephony/java/android/telephony/data/QosBearerFilter.java index 6c1c653f13d0..5642549d7313 100644 --- a/telephony/java/android/telephony/data/QosBearerFilter.java +++ b/telephony/java/android/telephony/data/QosBearerFilter.java @@ -31,7 +31,6 @@ import java.util.ArrayList; import java.util.List; import java.util.Objects; - /** * Class that stores QOS filter parameters as defined in * 3gpp 24.008 10.5.6.12 and 3gpp 24.501 9.11.4.13. diff --git a/telephony/java/android/telephony/data/TrafficDescriptor.java b/telephony/java/android/telephony/data/TrafficDescriptor.java index d813bc58fe6f..2178fc1717b9 100644 --- a/telephony/java/android/telephony/data/TrafficDescriptor.java +++ b/telephony/java/android/telephony/data/TrafficDescriptor.java @@ -21,6 +21,7 @@ import android.annotation.Nullable; import android.os.Parcel; import android.os.Parcelable; +import java.util.Arrays; import java.util.Objects; /** @@ -31,11 +32,11 @@ import java.util.Objects; */ public final class TrafficDescriptor implements Parcelable { private final String mDnn; - private final String mOsAppId; + private final byte[] mOsAppId; private TrafficDescriptor(@NonNull Parcel in) { mDnn = in.readString(); - mOsAppId = in.readString(); + mOsAppId = in.createByteArray(); } /** @@ -45,14 +46,15 @@ public final class TrafficDescriptor implements Parcelable { * * @hide */ - public TrafficDescriptor(String dnn, String osAppId) { + public TrafficDescriptor(String dnn, byte[] 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. + * @return the DNN of this traffic descriptor if one is included by the network, null + * otherwise. */ public @Nullable String getDataNetworkName() { return mDnn; @@ -60,10 +62,11 @@ public final class TrafficDescriptor implements Parcelable { /** * OsAppId is the app id as defined in 3GPP TS 24.526 Section 5.2, and it identifies a traffic - * category. - * @return the OS App ID of this traffic descriptor. + * category. It includes the OS Id component of the field as defined in the specs. + * @return the OS App ID of this traffic descriptor if one is included by the network, null + * otherwise. */ - public @Nullable String getOsAppId() { + public @Nullable byte[] getOsAppId() { return mOsAppId; } @@ -80,7 +83,7 @@ public final class TrafficDescriptor implements Parcelable { @Override public void writeToParcel(@NonNull Parcel dest, int flags) { dest.writeString(mDnn); - dest.writeString(mOsAppId); + dest.writeByteArray(mOsAppId); } public static final @NonNull Parcelable.Creator<TrafficDescriptor> CREATOR = @@ -101,7 +104,7 @@ public final class TrafficDescriptor implements Parcelable { 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); + return Objects.equals(mDnn, that.mDnn) && Arrays.equals(mOsAppId, that.mOsAppId); } @Override @@ -121,10 +124,11 @@ public final class TrafficDescriptor implements Parcelable { * .setDnn("") * .build(); * </code></pre> + * */ public static final class Builder { private String mDnn = null; - private String mOsAppId = null; + private byte[] mOsAppId = null; /** * Default constructor for Builder. @@ -144,12 +148,12 @@ public final class TrafficDescriptor implements Parcelable { } /** - * Set the OS App ID. + * Set the OS App ID (including OS Id as defind in the specs). * * @return The same instance of the builder. */ @NonNull - public Builder setOsAppId(@NonNull String osAppId) { + public Builder setOsAppId(@NonNull byte[] osAppId) { this.mOsAppId = osAppId; return this; } diff --git a/telephony/java/android/telephony/data/UrspRule.java b/telephony/java/android/telephony/data/UrspRule.java index e2c47fd86b4b..fbe199975b00 100644 --- a/telephony/java/android/telephony/data/UrspRule.java +++ b/telephony/java/android/telephony/data/UrspRule.java @@ -84,8 +84,8 @@ public final class UrspRule implements Parcelable { android.hardware.radio.V1_6.TrafficDescriptor td) { String dnn = td.dnn.getDiscriminator() == OptionalDnn.hidl_discriminator.noinit ? null : td.dnn.value(); - String osAppId = td.osAppId.getDiscriminator() == OptionalOsAppId.hidl_discriminator.noinit - ? null : new String(arrayListToPrimitiveArray(td.osAppId.value().osAppId)); + byte[] osAppId = td.osAppId.getDiscriminator() == OptionalOsAppId.hidl_discriminator.noinit + ? null : arrayListToPrimitiveArray(td.osAppId.value().osAppId); TrafficDescriptor.Builder builder = new TrafficDescriptor.Builder(); if (dnn != null) { builder.setDataNetworkName(dnn); diff --git a/telephony/java/android/telephony/ims/DelegateStateCallback.java b/telephony/java/android/telephony/ims/DelegateStateCallback.java index 6bf992e64480..2b4fb7d5cbf3 100644 --- a/telephony/java/android/telephony/ims/DelegateStateCallback.java +++ b/telephony/java/android/telephony/ims/DelegateStateCallback.java @@ -79,10 +79,30 @@ public interface DelegateStateCallback { * messages routing should be delayed until the {@link SipDelegate} sends the IMS configuration * change event to reduce conditions where the remote application is using a stale IMS * configuration. + * @deprecated This is being removed from API surface, Use + * {@link #onConfigurationChanged(SipDelegateConfiguration)} instead. */ + @Deprecated void onImsConfigurationChanged(@NonNull SipDelegateImsConfiguration config); /** + * Call to notify the remote application of a configuration change associated with this + * {@link SipDelegate}. + * <p> + * The remote application will not be able to proceed sending SIP messages until after this + * configuration is sent the first time, so this configuration should be sent as soon as the + * {@link SipDelegate} has access to these configuration parameters. + * <p> + * Incoming SIP messages should not be routed to the remote application until AFTER this + * configuration change is sent to ensure that the remote application can respond correctly. + * Similarly, if there is an event that triggers the IMS configuration to change, incoming SIP + * messages routing should be delayed until the {@link SipDelegate} sends the IMS configuration + * change event to reduce conditions where the remote application is using a stale IMS + * configuration. + */ + void onConfigurationChanged(@NonNull SipDelegateConfiguration config); + + /** * Call to notify the remote application that the {@link SipDelegate} has modified the IMS * registration state of the RCS feature tags that were requested as part of the initial * {@link DelegateRequest}. diff --git a/telephony/java/android/telephony/ims/ImsMmTelManager.java b/telephony/java/android/telephony/ims/ImsMmTelManager.java index 4b2829685d66..7ba6f36d28e2 100644 --- a/telephony/java/android/telephony/ims/ImsMmTelManager.java +++ b/telephony/java/android/telephony/ims/ImsMmTelManager.java @@ -714,15 +714,8 @@ public class ImsMmTelManager implements RegistrationManager { * @see android.telephony.CarrierConfigManager#KEY_CARRIER_IMS_GBA_REQUIRED_BOOL * @see #isAvailable(int, int) * - * @param imsRegTech The IMS registration technology, can be one of the following: - * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE}, - * {@link ImsRegistrationImplBase#REGISTRATION_TECH_CROSS_SIM}, - * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN} - * @param capability The IMS MmTel capability to query, can be one of the following: - * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE}, - * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO}, - * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT}, - * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS} + * @param imsRegTech The IMS registration technology. + * @param capability The IMS MmTel capability to query. * @return {@code true} if the MmTel IMS capability is capable for this subscription, false * otherwise. * @hide @@ -749,15 +742,8 @@ public class ImsMmTelManager implements RegistrationManager { * * @see #isCapable(int, int) * - * @param imsRegTech The IMS registration technology, can be one of the following: - * {@link ImsRegistrationImplBase#REGISTRATION_TECH_LTE}, - * {@link ImsRegistrationImplBase#REGISTRATION_TECH_CROSS_SIM}, - * {@link ImsRegistrationImplBase#REGISTRATION_TECH_IWLAN} - * @param capability The IMS MmTel capability to query, can be one of the following: - * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VOICE}, - * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_VIDEO}, - * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_UT}, - * {@link MmTelFeature.MmTelCapabilities#CAPABILITY_TYPE_SMS} + * @param imsRegTech The IMS registration technology. + * @param capability The IMS MmTel capability to query. * @return {@code true} if the MmTel IMS capability is available for this subscription, false * otherwise. * @hide diff --git a/telephony/java/android/telephony/ims/RcsConfig.java b/telephony/java/android/telephony/ims/RcsConfig.java index 8a3121118fde..d7c3f98fa997 100644 --- a/telephony/java/android/telephony/ims/RcsConfig.java +++ b/telephony/java/android/telephony/ims/RcsConfig.java @@ -48,8 +48,12 @@ public final class RcsConfig implements Parcelable { private static final String LOG_TAG = "RcsConfig"; private static final boolean DBG = Build.IS_ENG; - // Tag for Rcs Volte single registration defined in RCC.07 A.1.6.2 - private static final String TAG_SINGLE_REGISTRATION = "rcsVolteSingleRegistration"; + // Tag and attribute defined in RCC.07 A.2 + private static final String TAG_PARM = "parm"; + private static final String ATTRIBUTE_NAME = "name"; + private static final String ATTRIBUTE_VALUE = "value"; + // Keyword for Rcs Volte single registration defined in RCC.07 A.1.6.2 + private static final String PARM_SINGLE_REGISTRATION = "rcsVolteSingleRegistration"; private final HashMap<String, String> mValues = new HashMap<>(); @@ -71,7 +75,27 @@ public final class RcsConfig implements Parcelable { String tag = null; while (eventType != XmlPullParser.END_DOCUMENT) { if (eventType == XmlPullParser.START_TAG) { - tag = xpp.getName().trim(); + tag = xpp.getName().trim().toLowerCase(); + if (tag.equals(TAG_PARM)) { + int count = xpp.getAttributeCount(); + String key = null; + String value = null; + if (count > 1) { + for (int i = 0; i < count; i++) { + String name = xpp.getAttributeName(i).trim().toLowerCase(); + if (name.equals(ATTRIBUTE_NAME)) { + key = xpp.getAttributeValue(xpp.getAttributeNamespace(i), + name).trim().toLowerCase(); + } else if (name.equals(ATTRIBUTE_VALUE)) { + value = xpp.getAttributeValue(xpp.getAttributeNamespace(i), + name).trim(); + } + } + } + if (key != null && value != null) { + mValues.put(key, value); + } + } } else if (eventType == XmlPullParser.END_TAG) { tag = null; } else if (eventType == XmlPullParser.TEXT) { @@ -102,6 +126,7 @@ public final class RcsConfig implements Parcelable { * @return Returns the config value if it exists, or defaultVal. */ public @Nullable String getString(@NonNull String tag, @Nullable String defaultVal) { + tag = tag.trim().toLowerCase(); return mValues.containsKey(tag) ? mValues.get(tag) : defaultVal; } @@ -114,6 +139,7 @@ public final class RcsConfig implements Parcelable { * @return Returns the config value if it exists and is a valid int, or defaultVal. */ public int getInteger(@NonNull String tag, int defaultVal) { + tag = tag.trim().toLowerCase(); try { return Integer.parseInt(mValues.get(tag)); } catch (NumberFormatException e) { @@ -131,6 +157,7 @@ public final class RcsConfig implements Parcelable { * @return Returns the config value if it exists, or defaultVal. */ public boolean getBoolean(@NonNull String tag, boolean defaultVal) { + tag = tag.trim().toLowerCase(); if (!mValues.containsKey(tag)) { return defaultVal; } @@ -145,15 +172,15 @@ public final class RcsConfig implements Parcelable { * @return Returns true if it exists, or false. */ public boolean hasConfig(@NonNull String tag) { - return mValues.containsKey(tag); + return mValues.containsKey(tag.trim().toLowerCase()); } /** * Check whether Rcs Volte single registration is supported by the config. */ public boolean isRcsVolteSingleRegistrationSupported() { - return getBoolean(TAG_SINGLE_REGISTRATION, false) - || getInteger(TAG_SINGLE_REGISTRATION, 0) != 0; + return getBoolean(PARM_SINGLE_REGISTRATION, false) + || getInteger(PARM_SINGLE_REGISTRATION, 0) != 0; } @Override diff --git a/telephony/java/android/telephony/ims/RegistrationManager.java b/telephony/java/android/telephony/ims/RegistrationManager.java index c682afe8178a..a2015cd8f22c 100644 --- a/telephony/java/android/telephony/ims/RegistrationManager.java +++ b/telephony/java/android/telephony/ims/RegistrationManager.java @@ -83,6 +83,8 @@ public interface RegistrationManager { AccessNetworkConstants.TRANSPORT_TYPE_INVALID); put(ImsRegistrationImplBase.REGISTRATION_TECH_LTE, AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + put(ImsRegistrationImplBase.REGISTRATION_TECH_NR, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); put(ImsRegistrationImplBase.REGISTRATION_TECH_IWLAN, AccessNetworkConstants.TRANSPORT_TYPE_WLAN); /* As the cross sim will be using ePDG tunnel over internet, it behaves diff --git a/telephony/java/android/telephony/CarrierBandwidth.aidl b/telephony/java/android/telephony/ims/SipDelegateConfiguration.aidl index d0861b88e737..2fc9c48fb9fc 100644 --- a/telephony/java/android/telephony/CarrierBandwidth.aidl +++ b/telephony/java/android/telephony/ims/SipDelegateConfiguration.aidl @@ -1,5 +1,5 @@ /* - * Copyright 2020 The Android Open Source Project + * 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. @@ -13,5 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package android.telephony; -parcelable CarrierBandwidth;
\ No newline at end of file + +package android.telephony.ims; + +parcelable SipDelegateConfiguration; diff --git a/telephony/java/android/telephony/ims/SipDelegateConfiguration.java b/telephony/java/android/telephony/ims/SipDelegateConfiguration.java new file mode 100644 index 000000000000..1bf5cad49c53 --- /dev/null +++ b/telephony/java/android/telephony/ims/SipDelegateConfiguration.java @@ -0,0 +1,932 @@ +/* + * Copyright (C) 2021 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.telephony.ims; + +import android.annotation.IntDef; +import android.annotation.IntRange; +import android.annotation.NonNull; +import android.annotation.Nullable; +import android.annotation.SystemApi; +import android.net.InetAddresses; +import android.net.Uri; +import android.os.Parcel; +import android.os.Parcelable; +import android.telephony.ims.stub.SipDelegate; +import android.util.Log; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.net.InetAddress; +import java.net.InetSocketAddress; +import java.net.UnknownHostException; +import java.util.Objects; + +/** + * The IMS registration and other attributes that the {@link SipDelegateConnection} used by the + * IMS application will need to be aware of to correctly generate outgoing {@link SipMessage}s. + * <p> + * The IMS service must generate new instances of this configuration as the IMS configuration + * managed by the IMS service changes. Along with each {@link SipDelegateConfiguration} instance + * containing the configuration is the "version", which should be incremented every time a new + * {@link SipDelegateConfiguration} instance is created. The {@link SipDelegateConnection} will + * include the version of the {@link SipDelegateConfiguration} instance that it used in order for + * the {@link SipDelegate} to easily identify if the IMS application used a now stale configuration + * to generate the {@link SipMessage} and return + * {@link SipDelegateManager#MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION} in + * {@link DelegateMessageCallback#onMessageSendFailure(String, int)} so that the IMS application can + * regenerate that {@link SipMessage} using the correct {@link SipDelegateConfiguration} + * instance. + * <p> + * Every time the IMS configuration state changes in the IMS service, a full configuration should + * be generated. The new {@link SipDelegateConfiguration} instance should not be an incremental + * update. + * @see Builder + * @hide + */ +@SystemApi +public final class SipDelegateConfiguration implements Parcelable { + + /** + * The SIP transport uses UDP. + */ + public static final int SIP_TRANSPORT_UDP = 0; + + /** + * The SIP transport uses TCP. + */ + public static final int SIP_TRANSPORT_TCP = 1; + + /**@hide*/ + @IntDef(prefix = "SIP_TRANSPORT_", value = { + SIP_TRANSPORT_UDP, + SIP_TRANSPORT_TCP + }) + @Retention(RetentionPolicy.SOURCE) + public @interface TransportType {} + + /** + * The value returned by {@link #getMaxUdpPayloadSizeBytes()} when it is not defined. + */ + public static final int UDP_PAYLOAD_SIZE_UNDEFINED = -1; + + /** + * SIP over IPSec configuration + */ + public static final class IpSecConfiguration { + private final int mLocalTxPort; + private final int mLocalRxPort; + private final int mLastLocalTxPort; + private final int mRemoteTxPort; + private final int mRemoteRxPort; + private final int mLastRemoteTxPort; + private final String mSecurityHeader; + + /** + * Describes the SIP over IPSec configuration the SipDelegate will need to use. + * + * @param localTxPort Local SIP port number used to send traffic. + * @param localRxPort Local SIP port number used to receive traffic. + * @param lastLocalTxPort Local SIP port number used for the previous IPsec security + * association. + * @param remoteTxPort Remote port number used by the SIP server to send SIP traffic. + * @param remoteRxPort Remote port number used by the SIP server to receive incoming SIP + * traffic. + * @param lastRemoteTxPort Remote port number used by the SIP server to send SIP traffic on + * the previous IPSec security association. + * @param securityHeader The value of the SIP security verify header. + */ + public IpSecConfiguration(int localTxPort, int localRxPort, int lastLocalTxPort, + int remoteTxPort, int remoteRxPort, int lastRemoteTxPort, + @NonNull String securityHeader) { + mLocalTxPort = localTxPort; + mLocalRxPort = localRxPort; + mLastLocalTxPort = lastLocalTxPort; + mRemoteTxPort = remoteTxPort; + mRemoteRxPort = remoteRxPort; + mLastRemoteTxPort = lastRemoteTxPort; + mSecurityHeader = securityHeader; + } + + /** + * @return The local SIP port number used to send traffic. + */ + public int getLocalTxPort() { + return mLocalTxPort; + } + + /** + * @return The Local SIP port number used to receive traffic. + */ + public int getLocalRxPort() { + return mLocalRxPort; + } + + /** + * @return The last local SIP port number used for the previous IPsec security association. + */ + public int getLastLocalTxPort() { + return mLastLocalTxPort; + } + + /** + * @return The remote port number used by the SIP server to send SIP traffic. + */ + public int getRemoteTxPort() { + return mRemoteTxPort; + } + + /** + * @return the remote port number used by the SIP server to receive incoming SIP traffic. + */ + public int getRemoteRxPort() { + return mRemoteRxPort; + } + + /** + * @return the remote port number used by the SIP server to send SIP traffic on the previous + * IPSec security association. + */ + public int getLastRemoteTxPort() { + return mLastRemoteTxPort; + } + + /** + * @return The value of the SIP security verify header. + */ + public @NonNull String getSipSecurityVerifyHeader() { + return mSecurityHeader; + } + + /** + * Helper for parcelling this object. + * @hide + */ + public void addToParcel(Parcel dest) { + dest.writeInt(mLocalTxPort); + dest.writeInt(mLocalRxPort); + dest.writeInt(mLastLocalTxPort); + dest.writeInt(mRemoteTxPort); + dest.writeInt(mRemoteRxPort); + dest.writeInt(mLastRemoteTxPort); + dest.writeString(mSecurityHeader); + } + + /** + * Helper for unparcelling this object. + * @hide + */ + public static IpSecConfiguration fromParcel(Parcel source) { + return new IpSecConfiguration(source.readInt(), source.readInt(), source.readInt(), + source.readInt(), source.readInt(), source.readInt(), source.readString()); + } + + @Override + public String toString() { + return "IpSecConfiguration{" + "localTx=" + mLocalTxPort + ", localRx=" + mLocalRxPort + + ", lastLocalTx=" + mLastLocalTxPort + ", remoteTx=" + mRemoteTxPort + + ", remoteRx=" + mRemoteRxPort + ", lastRemoteTx=" + mLastRemoteTxPort + + ", securityHeader=" + mSecurityHeader + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + IpSecConfiguration that = (IpSecConfiguration) o; + return mLocalTxPort == that.mLocalTxPort + && mLocalRxPort == that.mLocalRxPort + && mLastLocalTxPort == that.mLastLocalTxPort + && mRemoteTxPort == that.mRemoteTxPort + && mRemoteRxPort == that.mRemoteRxPort + && mLastRemoteTxPort == that.mLastRemoteTxPort + && Objects.equals(mSecurityHeader, that.mSecurityHeader); + } + + @Override + public int hashCode() { + return Objects.hash(mLocalTxPort, mLocalRxPort, mLastLocalTxPort, mRemoteTxPort, + mRemoteRxPort, mLastRemoteTxPort, mSecurityHeader); + } + } + + /** + * Creates a new instance of {@link SipDelegateConfiguration} composed from optional + * configuration items. + */ + public static final class Builder { + private final SipDelegateConfiguration mConfig; + + /** + * + * @param version The version associated with the {@link SipDelegateConfiguration} instance + * being built. See {@link #getVersion()} for more information. + * @param transportType The transport type to use for SIP signalling. + * @param localAddr The local socket address used for SIP traffic. + * @param serverAddr The SIP server or P-CSCF default IP address for sip traffic. + * @see InetAddresses#parseNumericAddress(String) for how to create an + * {@link InetAddress} without requiring a DNS lookup. + */ + public Builder(@IntRange(from = 0) long version, @TransportType int transportType, + @NonNull InetSocketAddress localAddr, @NonNull InetSocketAddress serverAddr) { + mConfig = new SipDelegateConfiguration(version, transportType, localAddr, + serverAddr); + } + + /** + * Create a new {@link SipDelegateConfiguration} instance with the same exact configuration + * as the passed in instance, except for the version parameter, which will be incremented + * by 1. + * <p> + * This method is useful for cases where only a small subset of configurations have changed + * and the new configuration is based off of the old configuration. + * @param c The older {@link SipDelegateConfiguration} instance to base this instance's + * configuration off of. + */ + public Builder(@NonNull SipDelegateConfiguration c) { + mConfig = c.copyAndIncrementVersion(); + } + + /** + * Sets whether or not SIP compact form is enabled for the associated SIP delegate. + * <p> + * If unset, this configuration defaults to {@code false}. + * @param isEnabled {@code true} if SIP compact form is enabled for the associated SIP + * Delegate, {@code false} if it is not. + * @return this Builder instance with the compact form configuration set. + */ + public @NonNull Builder setSipCompactFormEnabled(boolean isEnabled) { + mConfig.mIsSipCompactFormEnabled = isEnabled; + return this; + } + + /** + * Sets whether or not underlying SIP keepalives are enabled for the associated SIP + * delegate. + * <p> + * If unset, this configuration defaults to {@code false}. + * @param isEnabled {@code true} if SIP keepalives are enabled for the associated SIP + * Delegate, {@code false} if it is not. + * @return this Builder instance with the new configuration set. + */ + public @NonNull Builder setSipKeepaliveEnabled(boolean isEnabled) { + mConfig.mIsSipKeepaliveEnabled = isEnabled; + return this; + } + + /** + * Sets the max SIP payload size in bytes to be sent on UDP. If the SIP message payload is + * greater than the max UDP payload size, then TCP must be used. + * <p> + * If unset, this configuration defaults to {@link #UDP_PAYLOAD_SIZE_UNDEFINED}, or no + * size specified. + * @param size The maximum SIP payload size in bytes for UDP. + * @return this Builder instance with the new configuration set. + */ + public @NonNull Builder setMaxUdpPayloadSizeBytes(@IntRange(from = 1) int size) { + mConfig.mMaxUdpPayloadSize = size; + return this; + } + + /** + * Sets the IMS public user identifier. + * <p> + * If unset, this configuration defaults to {@code null}, or no identifier specified. + * @param id The IMS public user identifier. + * @return this Builder instance with the new configuration set. + */ + public @NonNull Builder setPublicUserIdentifier(@Nullable String id) { + mConfig.mPublicUserIdentifier = id; + return this; + } + + /** + * Sets the IMS private user identifier. + * <p> + * If unset, this configuration defaults to {@code null}, or no identifier specified. + * @param id The IMS private user identifier. + * @return this Builder instance with the new configuration set. + */ + public @NonNull Builder setPrivateUserIdentifier(@Nullable String id) { + mConfig.mPrivateUserIdentifier = id; + return this; + } + + /** + * Sets the IMS home domain. + * <p> + * If unset, this configuration defaults to {@code null}, or no domain specified. + * @param domain The IMS home domain. + * @return this Builder instance with the new configuration set. + */ + public @NonNull Builder setHomeDomain(@Nullable String domain) { + mConfig.mHomeDomain = domain; + return this; + } + + /** + * Sets the IMEI of the associated device. + * <p> + * Application can include the Instance-ID feature tag {@code "+sip.instance"} in the + * Contact header with a value of the device IMEI in the form + * {@code "urn:gsma:imei:<device IMEI>"}. + * <p> + * If unset, this configuration defaults to {@code null}, or no IMEI string specified. + * @param imei The IMEI of the device. + * @return this Builder instance with the new configuration set. + */ + public @NonNull Builder setImei(@Nullable String imei) { + mConfig.mImei = imei; + return this; + } + + /** + * Set the optional {@link IpSecConfiguration} instance used if the associated SipDelegate + * is communicating over IPSec. + * <p> + * If unset, this configuration defaults to {@code null} + * @param c The IpSecConfiguration instance to set. + * @return this Builder instance with IPSec configuration set. + */ + public @NonNull Builder setIpSecConfiguration(@Nullable IpSecConfiguration c) { + mConfig.mIpSecConfiguration = c; + return this; + } + + /** + * Describes the Device's Public IP Address and port that is set when Network Address + * Translation is enabled and the device is behind a NAT. + * <p> + * If unset, this configuration defaults to {@code null} + * @param addr The {@link InetAddress} representing the device's public IP address and port + * when behind a NAT. + * @return this Builder instance with the new configuration set. + * @see InetAddresses#parseNumericAddress(String) For an example of how to create an + * instance of {@link InetAddress} without causing a DNS lookup. + */ + public @NonNull Builder setNatSocketAddress(@Nullable InetSocketAddress addr) { + mConfig.mNatAddress = addr; + return this; + } + + /** + * Sets the optional URI of the device's Globally routable user-agent URI (GRUU) if this + * feature is enabled for the SIP delegate. + * <p> + * If unset, this configuration defaults to {@code null} + * @param uri The GRUU to set. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setPublicGruuUri(@Nullable Uri uri) { + mConfig.mGruu = uri; + return this; + } + + /** + * Sets the SIP authentication header value. + * <p> + * If unset, this configuration defaults to {@code null}. + * @param header The SIP authentication header's value. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setSipAuthenticationHeader(@Nullable String header) { + mConfig.mSipAuthHeader = header; + return this; + } + + /** + * Sets the SIP authentication nonce. + * <p> + * If unset, this configuration defaults to {@code null}. + * @param nonce The SIP authentication nonce. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setSipAuthenticationNonce(@Nullable String nonce) { + mConfig.mSipAuthNonce = nonce; + return this; + } + + /** + * Sets the SIP service route header value. + * <p> + * If unset, this configuration defaults to {@code null}. + * @param header The SIP service route header value. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setSipServiceRouteHeader(@Nullable String header) { + mConfig.mServiceRouteHeader = header; + return this; + } + + /** + * Sets the SIP path header value. + * <p> + * If unset, this configuration defaults to {@code null}. + * @param header The SIP path header value. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setSipPathHeader(@Nullable String header) { + mConfig.mPathHeader = header; + return this; + } + + /** + * Sets the SIP User-Agent header value. + * <p> + * If unset, this configuration defaults to {@code null}. + * @param header The SIP User-Agent header value. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setSipUserAgentHeader(@Nullable String header) { + mConfig.mUserAgentHeader = header; + return this; + } + + /** + * Sets the SIP Contact header's User parameter value. + * <p> + * If unset, this configuration defaults to {@code null}. + * @param param The SIP Contact header's User parameter value. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setSipContactUserParameter(@Nullable String param) { + mConfig.mContactUserParam = param; + return this; + } + + /** + * Sets the SIP P-Access-Network-Info (P-ANI) header value. Populated for networks that + * require this information to be provided as part of outgoing SIP messages. + * <p> + * If unset, this configuration defaults to {@code null}. + * @param header The SIP P-ANI header value. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setSipPaniHeader(@Nullable String header) { + mConfig.mPaniHeader = header; + return this; + } + + /** + * Sets the SIP P-Last-Access-Network-Info (P-LANI) header value. Populated for + * networks that require this information to be provided as part of outgoing SIP messages. + * <p> + * If unset, this configuration defaults to {@code null}. + * @param header The SIP P-LANI header value. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setSipPlaniHeader(@Nullable String header) { + mConfig.mPlaniHeader = header; + return this; + } + + /** + * Sets the SIP Cellular-Network-Info (CNI) header value (See 3GPP 24.229, section 7.2.15), + * populated for networks that require this information to be provided as part of outgoing + * SIP messages. + * <p> + * If unset, this configuration defaults to {@code null}. + * @param header The SIP P-LANI header value. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setSipCniHeader(@Nullable String header) { + mConfig.mCniHeader = header; + return this; + } + + /** + * Sets the SIP P-associated-uri header value. + * <p> + * If unset, this configuration defaults to {@code null}. + * @param header The SIP P-associated-uri header value. + * @return this builder instance with the new configuration set. + */ + public @NonNull Builder setSipAssociatedUriHeader(@Nullable String header) { + mConfig.mAssociatedUriHeader = header; + return this; + } + + /** + * @return A {@link SipDelegateConfiguration} instance with the optional configurations set. + */ + public @NonNull SipDelegateConfiguration build() { + return mConfig; + } + } + + private final long mVersion; + private final int mTransportType; + private final InetSocketAddress mLocalAddress; + private final InetSocketAddress mSipServerAddress; + private boolean mIsSipCompactFormEnabled = false; + private boolean mIsSipKeepaliveEnabled = false; + private int mMaxUdpPayloadSize = -1; + private String mPublicUserIdentifier = null; + private String mPrivateUserIdentifier = null; + private String mHomeDomain = null; + private String mImei = null; + private Uri mGruu = null; + private String mSipAuthHeader = null; + private String mSipAuthNonce = null; + private String mServiceRouteHeader = null; + private String mPathHeader = null; + private String mUserAgentHeader = null; + private String mContactUserParam = null; + private String mPaniHeader = null; + private String mPlaniHeader = null; + private String mCniHeader = null; + private String mAssociatedUriHeader = null; + private IpSecConfiguration mIpSecConfiguration = null; + private InetSocketAddress mNatAddress = null; + + + private SipDelegateConfiguration(long version, int transportType, + InetSocketAddress localAddress, InetSocketAddress sipServerAddress) { + mVersion = version; + mTransportType = transportType; + mLocalAddress = localAddress; + mSipServerAddress = sipServerAddress; + } + + private SipDelegateConfiguration(Parcel source) { + mVersion = source.readLong(); + mTransportType = source.readInt(); + mLocalAddress = readAddressFromParcel(source); + mSipServerAddress = readAddressFromParcel(source); + mIsSipCompactFormEnabled = source.readBoolean(); + mIsSipKeepaliveEnabled = source.readBoolean(); + mMaxUdpPayloadSize = source.readInt(); + mPublicUserIdentifier = source.readString(); + mPrivateUserIdentifier = source.readString(); + mHomeDomain = source.readString(); + mImei = source.readString(); + mGruu = source.readParcelable(null); + mSipAuthHeader = source.readString(); + mSipAuthNonce = source.readString(); + mServiceRouteHeader = source.readString(); + mPathHeader = source.readString(); + mUserAgentHeader = source.readString(); + mContactUserParam = source.readString(); + mPaniHeader = source.readString(); + mPlaniHeader = source.readString(); + mCniHeader = source.readString(); + mAssociatedUriHeader = source.readString(); + boolean isIpsecConfigAvailable = source.readBoolean(); + if (isIpsecConfigAvailable) { + mIpSecConfiguration = IpSecConfiguration.fromParcel(source); + } + boolean isNatConfigAvailable = source.readBoolean(); + if (isNatConfigAvailable) { + mNatAddress = readAddressFromParcel(source); + } + } + + @Override + public void writeToParcel(@NonNull Parcel dest, int flags) { + dest.writeLong(mVersion); + dest.writeInt(mTransportType); + writeAddressToParcel(mLocalAddress, dest); + writeAddressToParcel(mSipServerAddress, dest); + dest.writeBoolean(mIsSipCompactFormEnabled); + dest.writeBoolean(mIsSipKeepaliveEnabled); + dest.writeInt(mMaxUdpPayloadSize); + dest.writeString(mPublicUserIdentifier); + dest.writeString(mPrivateUserIdentifier); + dest.writeString(mHomeDomain); + dest.writeString(mImei); + dest.writeParcelable(mGruu, flags); + dest.writeString(mSipAuthHeader); + dest.writeString(mSipAuthNonce); + dest.writeString(mServiceRouteHeader); + dest.writeString(mPathHeader); + dest.writeString(mUserAgentHeader); + dest.writeString(mContactUserParam); + dest.writeString(mPaniHeader); + dest.writeString(mPlaniHeader); + dest.writeString(mCniHeader); + dest.writeString(mAssociatedUriHeader); + dest.writeBoolean(mIpSecConfiguration != null); + if (mIpSecConfiguration != null) { + mIpSecConfiguration.addToParcel(dest); + } + dest.writeBoolean(mNatAddress != null); + if (mNatAddress != null) { + writeAddressToParcel(mNatAddress, dest); + } + } + + /** + * @return A copy of this instance with an incremented version. + * @hide + */ + public SipDelegateConfiguration copyAndIncrementVersion() { + SipDelegateConfiguration c = new SipDelegateConfiguration(getVersion() + 1, mTransportType, + mLocalAddress, mSipServerAddress); + c.mIsSipCompactFormEnabled = mIsSipCompactFormEnabled; + c.mIsSipKeepaliveEnabled = mIsSipKeepaliveEnabled; + c.mMaxUdpPayloadSize = mMaxUdpPayloadSize; + c.mIpSecConfiguration = mIpSecConfiguration; + c.mNatAddress = mNatAddress; + c.mPublicUserIdentifier = mPublicUserIdentifier; + c.mPrivateUserIdentifier = mPrivateUserIdentifier; + c.mHomeDomain = mHomeDomain; + c.mImei = mImei; + c.mGruu = mGruu; + c.mSipAuthHeader = mSipAuthHeader; + c.mSipAuthNonce = mSipAuthNonce; + c.mServiceRouteHeader = mServiceRouteHeader; + c.mPathHeader = mPathHeader; + c.mUserAgentHeader = mUserAgentHeader; + c.mContactUserParam = mContactUserParam; + c.mPaniHeader = mPaniHeader; + c.mPlaniHeader = mPlaniHeader; + c.mCniHeader = mCniHeader; + c.mAssociatedUriHeader = mAssociatedUriHeader; + return c; + } + + /** + * An integer representing the version number of this SipDelegateImsConfiguration. + * {@link SipMessage}s that are created using this configuration will also have a this + * version number associated with them, which will allow the IMS service to validate that the + * {@link SipMessage} was using the latest configuration during creation and not a stale + * configuration due to race conditions between the configuration being updated and the RCS + * application not receiving the updated configuration before generating a new message. + * <p> + * The version number should be a positive number that starts at 0 and increments sequentially + * as new {@link SipDelegateConfiguration} instances are created to update the IMS + * configuration state. + * + * @return the version number associated with this {@link SipDelegateConfiguration}. + */ + public @IntRange(from = 0) long getVersion() { + return mVersion; + } + + /** + * @return The Transport type of the SIP delegate. + */ + public @TransportType int getTransportType() { + return mTransportType; + } + + /** + * @return The local IP address and port used for SIP traffic. + */ + public @NonNull InetSocketAddress getLocalAddress() { + return mLocalAddress; + } + + /** + * @return The default IP Address and port of the SIP server or P-CSCF used for SIP traffic. + */ + public @NonNull InetSocketAddress getSipServerAddress() { + return mSipServerAddress; + } + + /** + * @return {@code true} if SIP compact form is enabled for the associated SIP Delegate, + * {@code false} if it is not. + */ + public boolean isSipCompactFormEnabled() { + return mIsSipCompactFormEnabled; + } + + /** + * @return {@code true} if SIP keepalives are enabled for the associated SIP Delegate, + * {@code false} if it is not. + */ + public boolean isSipKeepaliveEnabled() { + return mIsSipKeepaliveEnabled; + } + + /** + * @return The maximum SIP payload size in bytes for UDP or {code -1} if no value was set. + */ + public int getMaxUdpPayloadSizeBytes() { + return mMaxUdpPayloadSize; + } + + /** + * @return The IMS public user identifier or {@code null} if it was not set. + */ + public @Nullable String getPublicUserIdentifier() { + return mPublicUserIdentifier; + } + + /** + * @return The IMS private user identifier or {@code null} if it was not set. + */ + public @Nullable String getPrivateUserIdentifier() { + return mPrivateUserIdentifier; + } + + /** + * @return The IMS home domain or {@code null} if it was not set. + */ + public @Nullable String getHomeDomain() { + return mHomeDomain; + } + + /** + * get the IMEI of the associated device. + * <p> + * Application can include the Instance-ID feature tag {@code "+sip.instance"} in the Contact + * header with a value of the device IMEI in the form {@code "urn:gsma:imei:<device IMEI>"}. + * @return The IMEI of the device or {@code null} if it was not set. + */ + public @Nullable String getImei() { + return mImei; + } + + /** + * @return The IPSec configuration that must be used because SIP is communicating over IPSec. + * This returns {@code null} SIP is not communicating over IPSec. + */ + public @Nullable IpSecConfiguration getIpSecConfiguration() { + return mIpSecConfiguration; + } + + /** + * @return The public IP address and port of the device due to it being behind a NAT. + * This returns {@code null} if the device is not behind a NAT. + */ + public @Nullable InetSocketAddress getNatSocketAddress() { + return mNatAddress; + } + + /** + * @return The device's Globally routable user-agent URI (GRUU) or {@code null} if this feature + * is not enabled for the SIP delegate. + */ + public @Nullable Uri getPublicGruuUri() { + return mGruu; + } + + /** + * @return The value of the SIP authentication header or {@code null} if there is none set. + */ + public @Nullable String getSipAuthenticationHeader() { + return mSipAuthHeader; + } + + /** + * @return The value of the SIP authentication nonce or {@code null} if there is none set. + */ + public @Nullable String getSipAuthenticationNonce() { + return mSipAuthNonce; + } + + /** + * @return The value of the SIP service route header or {@code null} if there is none set. + */ + public @Nullable String getSipServiceRouteHeader() { + return mServiceRouteHeader; + } + + /** + * @return The value of the SIP path header or {@code null} if there is none set. + */ + public @Nullable String getSipPathHeader() { + return mPathHeader; + } + + /** + * @return The value of the SIP User-Agent header or {@code null} if there is none set. + */ + public @Nullable String getSipUserAgentHeader() { + return mUserAgentHeader; + } + /** + * @return The value of the SIP Contact header's User parameter or {@code null} if there is + * none set. + */ + public @Nullable String getSipContactUserParameter() { + return mContactUserParam; + } + + /** + * @return The value of the SIP P-Access-Network-Info (P-ANI) header or {@code null} if there is + * none set. + */ + public @Nullable String getSipPaniHeader() { + return mPaniHeader; + } + /** + * @return The value of the SIP P-Last-Access-Network-Info (P-LANI) header or {@code null} if + * there is none set. + */ + public @Nullable String getSipPlaniHeader() { + return mPlaniHeader; + } + + /** + * @return The value of the SIP Cellular-Network-Info (CNI) header or {@code null} if there is + * none set. + */ + public @Nullable String getSipCniHeader() { + return mCniHeader; + } + + /** + * @return The value of the SIP P-associated-uri header or {@code null} if there is none set. + */ + public @Nullable String getSipAssociatedUriHeader() { + return mAssociatedUriHeader; + } + + private void writeAddressToParcel(InetSocketAddress addr, Parcel dest) { + dest.writeByteArray(addr.getAddress().getAddress()); + dest.writeInt(addr.getPort()); + } + + private InetSocketAddress readAddressFromParcel(Parcel source) { + final byte[] addressBytes = source.createByteArray(); + final int port = source.readInt(); + try { + return new InetSocketAddress(InetAddress.getByAddress(addressBytes), port); + } catch (UnknownHostException e) { + // Should not happen, as length of array was verified before parcelling. + Log.e("SipDelegateConfiguration", "exception reading address, returning null"); + return null; + } + } + + @Override + public int describeContents() { + return 0; + } + + public static final @NonNull Creator<SipDelegateConfiguration> CREATOR = + new Creator<SipDelegateConfiguration>() { + @Override + public SipDelegateConfiguration createFromParcel(Parcel source) { + return new SipDelegateConfiguration(source); + } + + @Override + public SipDelegateConfiguration[] newArray(int size) { + return new SipDelegateConfiguration[size]; + } + }; + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + SipDelegateConfiguration that = (SipDelegateConfiguration) o; + return mVersion == that.mVersion + && mTransportType == that.mTransportType + && mIsSipCompactFormEnabled == that.mIsSipCompactFormEnabled + && mIsSipKeepaliveEnabled == that.mIsSipKeepaliveEnabled + && mMaxUdpPayloadSize == that.mMaxUdpPayloadSize + && Objects.equals(mLocalAddress, that.mLocalAddress) + && Objects.equals(mSipServerAddress, that.mSipServerAddress) + && Objects.equals(mPublicUserIdentifier, that.mPublicUserIdentifier) + && Objects.equals(mPrivateUserIdentifier, that.mPrivateUserIdentifier) + && Objects.equals(mHomeDomain, that.mHomeDomain) + && Objects.equals(mImei, that.mImei) + && Objects.equals(mGruu, that.mGruu) + && Objects.equals(mSipAuthHeader, that.mSipAuthHeader) + && Objects.equals(mSipAuthNonce, that.mSipAuthNonce) + && Objects.equals(mServiceRouteHeader, that.mServiceRouteHeader) + && Objects.equals(mPathHeader, that.mPathHeader) + && Objects.equals(mUserAgentHeader, that.mUserAgentHeader) + && Objects.equals(mContactUserParam, that.mContactUserParam) + && Objects.equals(mPaniHeader, that.mPaniHeader) + && Objects.equals(mPlaniHeader, that.mPlaniHeader) + && Objects.equals(mCniHeader, that.mCniHeader) + && Objects.equals(mAssociatedUriHeader, that.mAssociatedUriHeader) + && Objects.equals(mIpSecConfiguration, that.mIpSecConfiguration) + && Objects.equals(mNatAddress, that.mNatAddress); + } + + @Override + public int hashCode() { + return Objects.hash(mVersion, mTransportType, mLocalAddress, mSipServerAddress, + mIsSipCompactFormEnabled, mIsSipKeepaliveEnabled, mMaxUdpPayloadSize, + mPublicUserIdentifier, mPrivateUserIdentifier, mHomeDomain, mImei, mGruu, + mSipAuthHeader, mSipAuthNonce, mServiceRouteHeader, mPathHeader, mUserAgentHeader, + mContactUserParam, mPaniHeader, mPlaniHeader, mCniHeader, mAssociatedUriHeader, + mIpSecConfiguration, mNatAddress); + } + + @Override + public String toString() { + return "SipDelegateConfiguration{ mVersion=" + mVersion + ", mTransportType=" + + mTransportType + '}'; + } +} diff --git a/telephony/java/android/telephony/ims/SipDelegateConnection.java b/telephony/java/android/telephony/ims/SipDelegateConnection.java index d7a19bc0cb62..4dbb08d14ccd 100644 --- a/telephony/java/android/telephony/ims/SipDelegateConnection.java +++ b/telephony/java/android/telephony/ims/SipDelegateConnection.java @@ -48,7 +48,7 @@ public interface SipDelegateConnection { * sending the message. * @param sipMessage The SipMessage to be sent. * @param configVersion The SipDelegateImsConfiguration version used to construct the - * SipMessage. See {@link SipDelegateImsConfiguration#getVersion} for more + * SipMessage. See {@link SipDelegateConfiguration#getVersion} for more */ void sendMessage(@NonNull SipMessage sipMessage, long configVersion); diff --git a/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java b/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java index 8762b6a712f2..ffbfde65e2d3 100644 --- a/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java +++ b/telephony/java/android/telephony/ims/SipDelegateImsConfiguration.java @@ -21,35 +21,21 @@ import android.annotation.Nullable; import android.annotation.StringDef; import android.annotation.SuppressLint; import android.annotation.SystemApi; +import android.net.InetAddresses; +import android.net.Uri; import android.os.Parcel; import android.os.Parcelable; import android.os.PersistableBundle; -import android.telephony.ims.stub.SipDelegate; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.net.InetSocketAddress; /** - * The IMS registration and other attributes that the {@link SipDelegateConnection} used by the - * IMS application will need to be aware of to correctly generate outgoing {@link SipMessage}s. - * <p> - * The IMS service must generate new instances of this configuration as the IMS configuration - * managed by the IMS service changes. Along with each {@link SipDelegateImsConfiguration} instance - * containing the configuration is the "version", which should be incremented every time a new - * {@link SipDelegateImsConfiguration} instance is created. The {@link SipDelegateConnection} will - * include the version of the {@link SipDelegateImsConfiguration} instance that it used in order for - * the {@link SipDelegate} to easily identify if the IMS application used a now stale configuration - * to generate the {@link SipMessage} and return - * {@link SipDelegateManager#MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION} in - * {@link DelegateMessageCallback#onMessageSendFailure(String, int)} so that the IMS application can - * regenerate that {@link SipMessage} using the correct {@link SipDelegateImsConfiguration} - * instance. - * <p> - * Every time the IMS configuration state changes in the IMS service, a full configuration should - * be generated. The new {@link SipDelegateImsConfiguration} instance should not be an incremental - * update. * @hide + * @deprecated Use {@link SipDelegateConfiguration} instead. */ +@Deprecated @SystemApi public final class SipDelegateImsConfiguration implements Parcelable { @@ -501,6 +487,10 @@ public final class SipDelegateImsConfiguration implements Parcelable { * {@link SipMessage} was using the latest configuration during creation and not a stale * configuration due to race conditions between the configuration being updated and the RCS * application not receiving the updated configuration before generating a new message. + * <p> + * The version number should be a positive number that starts at 0 and increments sequentially + * as new {@link SipDelegateImsConfiguration} instances are created to update the IMS + * configuration state. * * @return the version number associated with this {@link SipDelegateImsConfiguration}. */ @@ -531,4 +521,68 @@ public final class SipDelegateImsConfiguration implements Parcelable { return new SipDelegateImsConfiguration[size]; } }; + + /** + * Temporary helper to transition from old form of config to new form. + * @return new config + * @hide + */ + public SipDelegateConfiguration toNewConfig() { + // IP version is now included in call to InetSocketAddr + String transportTypeString = getString(KEY_SIP_CONFIG_TRANSPORT_TYPE_STRING); + int transportType = (transportTypeString != null + && transportTypeString.equals(SIP_TRANSPORT_UDP)) + ? SipDelegateConfiguration.SIP_TRANSPORT_UDP + : SipDelegateConfiguration.SIP_TRANSPORT_TCP; + SipDelegateConfiguration.Builder builder = new SipDelegateConfiguration.Builder(mVersion, + transportType, + getSocketAddr(getString(KEY_SIP_CONFIG_UE_DEFAULT_IPADDRESS_STRING), + getInt(KEY_SIP_CONFIG_UE_DEFAULT_PORT_INT, -1)), + getSocketAddr(getString(KEY_SIP_CONFIG_SERVER_DEFAULT_IPADDRESS_STRING), + getInt(KEY_SIP_CONFIG_SERVER_DEFAULT_PORT_INT, -1))); + builder.setSipCompactFormEnabled( + getBoolean(KEY_SIP_CONFIG_IS_COMPACT_FORM_ENABLED_BOOL, false)); + builder.setSipKeepaliveEnabled( + getBoolean(KEY_SIP_CONFIG_IS_KEEPALIVE_ENABLED_BOOL, false)); + builder.setMaxUdpPayloadSizeBytes(getInt(KEY_SIP_CONFIG_MAX_PAYLOAD_SIZE_ON_UDP_INT, -1)); + builder.setPublicUserIdentifier(getString(KEY_SIP_CONFIG_UE_PUBLIC_USER_ID_STRING)); + builder.setPrivateUserIdentifier(getString(KEY_SIP_CONFIG_UE_PRIVATE_USER_ID_STRING)); + builder.setHomeDomain(getString(KEY_SIP_CONFIG_HOME_DOMAIN_STRING)); + builder.setImei(getString(KEY_SIP_CONFIG_IMEI_STRING)); + builder.setSipAuthenticationHeader(getString(KEY_SIP_CONFIG_AUTHENTICATION_HEADER_STRING)); + builder.setSipAuthenticationNonce(getString(KEY_SIP_CONFIG_AUTHENTICATION_NONCE_STRING)); + builder.setSipServiceRouteHeader(getString(KEY_SIP_CONFIG_SERVICE_ROUTE_HEADER_STRING)); + builder.setSipPathHeader(getString(KEY_SIP_CONFIG_PATH_HEADER_STRING)); + builder.setSipUserAgentHeader(getString(KEY_SIP_CONFIG_USER_AGENT_HEADER_STRING)); + builder.setSipContactUserParameter(getString(KEY_SIP_CONFIG_URI_USER_PART_STRING)); + builder.setSipPaniHeader(getString(KEY_SIP_CONFIG_P_ACCESS_NETWORK_INFO_HEADER_STRING)); + builder.setSipPlaniHeader( + getString(KEY_SIP_CONFIG_P_LAST_ACCESS_NETWORK_INFO_HEADER_STRING)); + builder.setSipCniHeader(getString(KEY_SIP_CONFIG_CELLULAR_NETWORK_INFO_HEADER_STRING)); + builder.setSipAssociatedUriHeader(getString(KEY_SIP_CONFIG_P_ASSOCIATED_URI_HEADER_STRING)); + if (getBoolean(KEY_SIP_CONFIG_IS_GRUU_ENABLED_BOOL, false)) { + builder.setPublicGruuUri(Uri.parse(getString(KEY_SIP_CONFIG_UE_PUBLIC_GRUU_STRING))); + } + if (getBoolean(KEY_SIP_CONFIG_IS_IPSEC_ENABLED_BOOL, false)) { + builder.setIpSecConfiguration(new SipDelegateConfiguration.IpSecConfiguration( + getInt(KEY_SIP_CONFIG_UE_IPSEC_CLIENT_PORT_INT, -1), + getInt(KEY_SIP_CONFIG_UE_IPSEC_SERVER_PORT_INT, -1), + getInt(KEY_SIP_CONFIG_UE_IPSEC_OLD_CLIENT_PORT_INT, -1), + getInt(KEY_SIP_CONFIG_SERVER_IPSEC_CLIENT_PORT_INT, -1), + getInt(KEY_SIP_CONFIG_SERVER_IPSEC_SERVER_PORT_INT, -1), + getInt(KEY_SIP_CONFIG_SERVER_IPSEC_OLD_CLIENT_PORT_INT, -1), + getString(KEY_SIP_CONFIG_SECURITY_VERIFY_HEADER_STRING)) + ); + } + if (getBoolean(KEY_SIP_CONFIG_IS_NAT_ENABLED_BOOL, false)) { + builder.setNatSocketAddress(getSocketAddr( + getString(KEY_SIP_CONFIG_UE_PUBLIC_IPADDRESS_WITH_NAT_STRING), + getInt(KEY_SIP_CONFIG_UE_PUBLIC_PORT_WITH_NAT_INT, -1))); + } + return builder.build(); + } + + private InetSocketAddress getSocketAddr(String ipAddr, int port) { + return new InetSocketAddress(InetAddresses.parseNumericAddress(ipAddr), port); + } } diff --git a/telephony/java/android/telephony/ims/SipDelegateManager.java b/telephony/java/android/telephony/ims/SipDelegateManager.java index 171842b26cb0..ca01d0f664db 100644 --- a/telephony/java/android/telephony/ims/SipDelegateManager.java +++ b/telephony/java/android/telephony/ims/SipDelegateManager.java @@ -39,6 +39,7 @@ import com.android.internal.annotations.VisibleForTesting; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.util.Objects; import java.util.concurrent.Executor; /** @@ -125,12 +126,12 @@ public class SipDelegateManager { public static final int MESSAGE_FAILURE_REASON_NOT_REGISTERED = 9; /** - * The outgoing SIP message has not been sent because the {@link SipDelegateImsConfiguration} + * The outgoing SIP message has not been sent because the {@link SipDelegateConfiguration} * version associated with the outgoing {@link SipMessage} is now stale and has failed * validation checks. * <p> * The @link SipMessage} should be recreated using the newest - * {@link SipDelegateImsConfiguration} and sent again. + * {@link SipDelegateConfiguration} and sent again. */ public static final int MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION = 10; @@ -322,9 +323,10 @@ public class SipDelegateManager { public void createSipDelegate(@NonNull DelegateRequest request, @NonNull Executor executor, @NonNull DelegateConnectionStateCallback dc, @NonNull DelegateConnectionMessageCallback mc) throws ImsException { - if (request == null || executor == null || dc == null || mc == null) { - throw new IllegalArgumentException("Invalid arguments passed into createSipDelegate"); - } + Objects.requireNonNull(request, "The DelegateRequest must not be null."); + Objects.requireNonNull(executor, "The Executor must not be null."); + Objects.requireNonNull(dc, "The DelegateConnectionStateCallback must not be null."); + Objects.requireNonNull(mc, "The DelegateConnectionMessageCallback must not be null."); try { SipDelegateConnectionAidlWrapper wrapper = new SipDelegateConnectionAidlWrapper(executor, dc, mc); @@ -355,10 +357,7 @@ public class SipDelegateManager { @RequiresPermission(Manifest.permission.PERFORM_IMS_SINGLE_REGISTRATION) public void destroySipDelegate(@NonNull SipDelegateConnection delegateConnection, @SipDelegateDestroyReason int reason) { - - if (delegateConnection == null) { - throw new IllegalArgumentException("invalid argument passed into destroySipDelegate"); - } + Objects.requireNonNull(delegateConnection, "SipDelegateConnection can not be null."); if (delegateConnection instanceof SipDelegateConnectionAidlWrapper) { SipDelegateConnectionAidlWrapper w = (SipDelegateConnectionAidlWrapper) delegateConnection; @@ -396,9 +395,7 @@ public class SipDelegateManager { @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) { - throw new IllegalArgumentException("invalid connection."); - } + Objects.requireNonNull(connection, "SipDelegateConnection can not be null."); if (connection instanceof SipDelegateConnectionAidlWrapper) { SipDelegateConnectionAidlWrapper w = (SipDelegateConnectionAidlWrapper) connection; try { diff --git a/telephony/java/android/telephony/ims/SipMessage.java b/telephony/java/android/telephony/ims/SipMessage.java index d21fcab264d3..391372ac8ac1 100644 --- a/telephony/java/android/telephony/ims/SipMessage.java +++ b/telephony/java/android/telephony/ims/SipMessage.java @@ -203,23 +203,6 @@ public final class SipMessage implements Parcelable { } /** - * @return the UTF-8 encoded SIP message. - * @deprecated Use {@link #toEncodedMessage} instead - */ - @Deprecated - public @NonNull byte[] getEncodedMessage() { - byte[] header = new StringBuilder() - .append(mStartLine) - .append(mHeaderSection) - .append(CRLF) - .toString().getBytes(UTF_8); - byte[] sipMessage = new byte[header.length + mContent.length]; - System.arraycopy(header, 0, sipMessage, 0, header.length); - System.arraycopy(mContent, 0, sipMessage, header.length, mContent.length); - return sipMessage; - } - - /** * According RFC-3261 section 7, SIP is a text protocol and uses the UTF-8 charset. Its format * consists of a start-line, one or more header fields, an empty line indicating the end of the * header fields, and an optional message-body. diff --git a/telephony/java/android/telephony/ims/aidl/ISipDelegateConnectionStateCallback.aidl b/telephony/java/android/telephony/ims/aidl/ISipDelegateConnectionStateCallback.aidl index ddfcb9994cb8..855000bb57fb 100644 --- a/telephony/java/android/telephony/ims/aidl/ISipDelegateConnectionStateCallback.aidl +++ b/telephony/java/android/telephony/ims/aidl/ISipDelegateConnectionStateCallback.aidl @@ -18,6 +18,7 @@ package android.telephony.ims.aidl; import android.telephony.ims.DelegateRegistrationState; import android.telephony.ims.FeatureTagState; +import android.telephony.ims.SipDelegateConfiguration; import android.telephony.ims.SipDelegateImsConfiguration; import android.telephony.ims.aidl.ISipDelegate; @@ -30,5 +31,6 @@ oneway interface ISipDelegateConnectionStateCallback { void onFeatureTagStatusChanged(in DelegateRegistrationState registrationState, in List<FeatureTagState> deniedFeatureTags); void onImsConfigurationChanged(in SipDelegateImsConfiguration registeredSipConfig); + void onConfigurationChanged(in SipDelegateConfiguration registeredSipConfig); void onDestroyed(int reason); } diff --git a/telephony/java/android/telephony/ims/aidl/ISipDelegateStateCallback.aidl b/telephony/java/android/telephony/ims/aidl/ISipDelegateStateCallback.aidl index 609ee260cbab..4c3c93d36188 100644 --- a/telephony/java/android/telephony/ims/aidl/ISipDelegateStateCallback.aidl +++ b/telephony/java/android/telephony/ims/aidl/ISipDelegateStateCallback.aidl @@ -18,6 +18,7 @@ package android.telephony.ims.aidl; import android.telephony.ims.DelegateRegistrationState; import android.telephony.ims.FeatureTagState; +import android.telephony.ims.SipDelegateConfiguration; import android.telephony.ims.SipDelegateImsConfiguration; import android.telephony.ims.aidl.ISipDelegate; @@ -29,5 +30,6 @@ oneway interface ISipDelegateStateCallback { void onCreated(ISipDelegate c, in List<FeatureTagState> deniedFeatureTags); void onFeatureTagRegistrationChanged(in DelegateRegistrationState registrationState); void onImsConfigurationChanged(in SipDelegateImsConfiguration registeredSipConfig); + void onConfigurationChanged(in SipDelegateConfiguration registeredSipConfig); void onDestroyed(int reason); } diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java index 6a98d80d6b9b..c18ab33eb2c9 100644 --- a/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java +++ b/telephony/java/android/telephony/ims/aidl/SipDelegateAidlWrapper.java @@ -24,6 +24,7 @@ import android.telephony.ims.DelegateMessageCallback; import android.telephony.ims.DelegateRegistrationState; import android.telephony.ims.DelegateStateCallback; import android.telephony.ims.FeatureTagState; +import android.telephony.ims.SipDelegateConfiguration; import android.telephony.ims.SipDelegateImsConfiguration; import android.telephony.ims.SipDelegateManager; import android.telephony.ims.SipMessage; @@ -166,6 +167,15 @@ public class SipDelegateAidlWrapper implements DelegateStateCallback, DelegateMe } @Override + public void onConfigurationChanged(@NonNull SipDelegateConfiguration config) { + try { + mStateBinder.onConfigurationChanged(config); + } catch (RemoteException e) { + // BinderDied will trigger destroySipDelegate, so just ignore this locally. + } + } + + @Override public void onDestroyed(int reasonCode) { mDelegate = null; try { diff --git a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java index 0abb49574a73..47ddcb9696db 100644 --- a/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java +++ b/telephony/java/android/telephony/ims/aidl/SipDelegateConnectionAidlWrapper.java @@ -21,6 +21,7 @@ import android.os.IBinder; import android.os.RemoteException; import android.telephony.ims.DelegateRegistrationState; import android.telephony.ims.FeatureTagState; +import android.telephony.ims.SipDelegateConfiguration; import android.telephony.ims.SipDelegateConnection; import android.telephony.ims.SipDelegateImsConfiguration; import android.telephony.ims.SipDelegateManager; @@ -90,6 +91,17 @@ public class SipDelegateConnectionAidlWrapper implements SipDelegateConnection, } @Override + public void onConfigurationChanged(SipDelegateConfiguration registeredSipConfig) { + final long token = Binder.clearCallingIdentity(); + try { + mExecutor.execute(() -> + mStateCallback.onConfigurationChanged(registeredSipConfig)); + } finally { + Binder.restoreCallingIdentity(token); + } + } + + @Override public void onDestroyed(int reason) { invalidateSipDelegateBinder(); final long token = Binder.clearCallingIdentity(); diff --git a/telephony/java/android/telephony/ims/feature/RcsFeature.java b/telephony/java/android/telephony/ims/feature/RcsFeature.java index b384e50d9f03..ddd6fbe38cf4 100644 --- a/telephony/java/android/telephony/ims/feature/RcsFeature.java +++ b/telephony/java/android/telephony/ims/feature/RcsFeature.java @@ -120,8 +120,8 @@ public class RcsFeature extends ImsFeature { @Nullable ICapabilityExchangeEventListener listener) throws RemoteException { CapabilityExchangeEventListener listenerWrapper = new CapabilityExchangeAidlWrapper(listener); - executeMethodAsync(() -> mReference.setCapabilityExchangeEventListener( - mExecutor, listenerWrapper), "setCapabilityExchangeEventListener"); + executeMethodAsync(() -> mReference.setCapabilityExchangeEventListener(listenerWrapper), + "setCapabilityExchangeEventListener"); } @Override @@ -385,30 +385,6 @@ public class RcsFeature extends ImsFeature { * operation and the RcsFeature sets the status of the capability to true using * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. * - * @param executor The executor for the framework to use when request RCS resquests to this - * service. - * @param listener A {@link CapabilityExchangeEventListener} to send the capability exchange - * event to the framework. - * @return An instance of {@link RcsCapabilityExchangeImplBase} that implements capability - * exchange if it is supported by the device. - * @hide - */ - public @NonNull RcsCapabilityExchangeImplBase createCapabilityExchangeImpl( - @NonNull Executor executor, @NonNull CapabilityExchangeEventListener listener) { - // Base Implementation, override to implement functionality - return new RcsCapabilityExchangeImplBase(executor); - } - - /** - * Retrieve the implementation of UCE for this {@link RcsFeature}, which can use either - * presence or OPTIONS for capability exchange. - * - * Will only be requested by the framework if capability exchange is configured - * as capable during a - * {@link #changeEnabledCapabilities(CapabilityChangeRequest, CapabilityCallbackProxy)} - * operation and the RcsFeature sets the status of the capability to true using - * {@link #notifyCapabilitiesStatusChanged(RcsImsCapabilities)}. - * * @param listener A {@link CapabilityExchangeEventListener} to send the capability exchange * event to the framework. * @return An instance of {@link RcsCapabilityExchangeImplBase} that implements capability @@ -461,17 +437,15 @@ public class RcsFeature extends ImsFeature { /** * Set the capability exchange listener. - * @param executor The executor for the framework to use when request RCS requests to this - * service. * @param listener A {@link CapabilityExchangeEventListener} to send the capability exchange * event to the framework. */ - private void setCapabilityExchangeEventListener(@NonNull Executor executor, + private void setCapabilityExchangeEventListener( @Nullable CapabilityExchangeEventListener listener) { synchronized (mLock) { mCapExchangeEventListener = listener; if (mCapExchangeEventListener != null) { - initRcsCapabilityExchangeImplBase(executor, mCapExchangeEventListener); + initRcsCapabilityExchangeImplBase(mCapExchangeEventListener); } else { // Remove the RcsCapabilityExchangeImplBase instance when the capability exchange // instance has been removed in the framework. @@ -486,19 +460,17 @@ public class RcsFeature extends ImsFeature { /** * Initialize the RcsCapabilityExchangeImplBase instance if the capability exchange instance * has already been created in the framework. - * @param executor The executor for the framework to use when request RCS requests to this - * service. * @param listener A {@link CapabilityExchangeEventListener} to send the capability exchange * event to the framework. */ - private void initRcsCapabilityExchangeImplBase(@NonNull Executor executor, + private void initRcsCapabilityExchangeImplBase( @NonNull CapabilityExchangeEventListener listener) { synchronized (mLock) { // Remove the original instance if (mCapabilityExchangeImpl != null) { removeCapabilityExchangeImpl(mCapabilityExchangeImpl); } - mCapabilityExchangeImpl = createCapabilityExchangeImpl(executor, listener); + mCapabilityExchangeImpl = createCapabilityExchangeImpl(listener); } } diff --git a/telephony/java/android/telephony/ims/stub/DelegateConnectionStateCallback.java b/telephony/java/android/telephony/ims/stub/DelegateConnectionStateCallback.java index 02218ead0ad7..c078637e3791 100644 --- a/telephony/java/android/telephony/ims/stub/DelegateConnectionStateCallback.java +++ b/telephony/java/android/telephony/ims/stub/DelegateConnectionStateCallback.java @@ -21,6 +21,7 @@ import android.annotation.SystemApi; import android.telephony.ims.DelegateRegistrationState; import android.telephony.ims.DelegateRequest; import android.telephony.ims.FeatureTagState; +import android.telephony.ims.SipDelegateConfiguration; import android.telephony.ims.SipDelegateConnection; import android.telephony.ims.SipDelegateImsConfiguration; import android.telephony.ims.SipDelegateManager; @@ -44,7 +45,7 @@ import java.util.Set; * <p> * In order to start sending SIP messages, the SIP configuration parameters will need to be * received, so the messaging application should make no assumptions about these parameters and wait - * until {@link #onImsConfigurationChanged(SipDelegateImsConfiguration)} has been called. This is + * until {@link #onConfigurationChanged(SipDelegateConfiguration)} has been called. This is * guaranteed to happen after the first {@link #onFeatureTagStatusChanged} if there is at least one * feature tag that has been successfully associated with the {@link SipDelegateConnection}. If all * feature tags were denied, no IMS configuration will be sent. @@ -135,8 +136,32 @@ public interface DelegateConnectionStateCallback { * not compleed yet. * * @param registeredSipConfig The configuration of the IMS stack registered on the IMS network. + * @deprecated Will not be in final API, use + * {@link #onConfigurationChanged(SipDelegateConfiguration)} instead}. */ - void onImsConfigurationChanged(@NonNull SipDelegateImsConfiguration registeredSipConfig); + @Deprecated + default void onImsConfigurationChanged( + @NonNull SipDelegateImsConfiguration registeredSipConfig) { + onConfigurationChanged(registeredSipConfig.toNewConfig()); + } + + /** + * IMS configuration of the underlying IMS stack used by this IMS application for construction + * of the SIP messages that will be sent over the carrier's network. + * <p> + * There should never be assumptions made about the configuration of the underling IMS stack and + * the IMS application should wait for this indication before sending out any outgoing SIP + * messages. + * <p> + * Configuration may change due to IMS registration changes as well as + * other optional events on the carrier network. If IMS stack is already registered at the time + * of callback registration, then this method shall be invoked with the current configuration. + * Otherwise, there may be a delay in this method being called if initial IMS registration has + * not compleed yet. + * + * @param registeredSipConfig The configuration of the IMS stack registered on the IMS network. + */ + default void onConfigurationChanged(@NonNull SipDelegateConfiguration registeredSipConfig) {} /** * The previously created {@link SipDelegateConnection} instance delivered via diff --git a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java index 39994be34865..02bcdec621c1 100644 --- a/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java +++ b/telephony/java/android/telephony/ims/stub/ImsRegistrationImplBase.java @@ -57,7 +57,8 @@ public class ImsRegistrationImplBase { REGISTRATION_TECH_NONE, REGISTRATION_TECH_LTE, REGISTRATION_TECH_IWLAN, - REGISTRATION_TECH_CROSS_SIM + REGISTRATION_TECH_CROSS_SIM, + REGISTRATION_TECH_NR }) @Retention(RetentionPolicy.SOURCE) public @interface ImsRegistrationTech {} @@ -66,19 +67,24 @@ public class ImsRegistrationImplBase { */ public static final int REGISTRATION_TECH_NONE = -1; /** - * IMS is registered to IMS via LTE. + * This ImsService is registered to IMS via LTE. */ public static final int REGISTRATION_TECH_LTE = 0; /** - * IMS is registered to IMS via IWLAN. + * This ImsService is registered to IMS via IWLAN. */ public static final int REGISTRATION_TECH_IWLAN = 1; /** - * IMS is registered to IMS via internet over second subscription. + * This ImsService is registered to IMS via internet over second subscription. */ public static final int REGISTRATION_TECH_CROSS_SIM = 2; + /** + * This ImsService is registered to IMS via NR. + */ + public static final int REGISTRATION_TECH_NR = 3; + // Registration states, used to notify new ImsRegistrationImplBase#Callbacks of the current // state. // The unknown state is set as the initialization state. This is so that we do not call back diff --git a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java index 57616d35f8fa..474eb05ca19c 100644 --- a/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java +++ b/telephony/java/android/telephony/ims/stub/RcsCapabilityExchangeImplBase.java @@ -356,21 +356,6 @@ public class RcsCapabilityExchangeImplBase { void onTerminated(@NonNull String reason, long retryAfterMilliseconds) throws ImsException; } - private Executor mBinderExecutor; - - /** - * Create a new RcsCapabilityExchangeImplBase instance. - * - * @param executor The executor that remote calls from the framework will be called on. - * @hide - */ - public RcsCapabilityExchangeImplBase(@NonNull Executor executor) { - if (executor == null) { - throw new IllegalArgumentException("executor must not be null"); - } - mBinderExecutor = executor; - } - /** * Create a new RcsCapabilityExchangeImplBase instance. */ diff --git a/telephony/java/android/telephony/ims/stub/SipDelegate.java b/telephony/java/android/telephony/ims/stub/SipDelegate.java index d5198a0aa25c..997d00bc91c7 100644 --- a/telephony/java/android/telephony/ims/stub/SipDelegate.java +++ b/telephony/java/android/telephony/ims/stub/SipDelegate.java @@ -21,8 +21,8 @@ import android.annotation.SystemApi; import android.telephony.ims.DelegateMessageCallback; import android.telephony.ims.DelegateRegistrationState; import android.telephony.ims.ImsService; +import android.telephony.ims.SipDelegateConfiguration; import android.telephony.ims.SipDelegateConnection; -import android.telephony.ims.SipDelegateImsConfiguration; import android.telephony.ims.SipDelegateManager; import android.telephony.ims.SipMessage; @@ -38,7 +38,7 @@ import android.telephony.ims.SipMessage; * modified to include the features managed by these SipDelegates. * <p> * This SipDelegate will need to notify the remote application of the registration of these features - * as well as the associated {@link SipDelegateImsConfiguration} before the application can start + * as well as the associated {@link SipDelegateConfiguration} before the application can start * sending/receiving SIP messages via the transport. See * {@link android.telephony.ims.DelegateStateCallback} for more information. * @hide @@ -55,9 +55,9 @@ public interface SipDelegate { * {@link DelegateMessageCallback#onMessageSendFailure(String, int)}. * @param message The SIP message to be sent over the operator’s network. * @param configVersion The SipDelegateImsConfiguration version used to construct the - * SipMessage. See {@link SipDelegateImsConfiguration} for more information. If the + * SipMessage. See {@link SipDelegateConfiguration} for more information. If the * version specified here does not match the most recently constructed - * {@link SipDelegateImsConfiguration}, this message should fail validation checks and + * {@link SipDelegateConfiguration}, this message should fail validation checks and * {@link DelegateMessageCallback#onMessageSendFailure} should be called with code * {@link SipDelegateManager#MESSAGE_FAILURE_REASON_STALE_IMS_CONFIGURATION}. */ diff --git a/telephony/java/com/android/internal/telephony/ITelephony.aidl b/telephony/java/com/android/internal/telephony/ITelephony.aidl index afc538d3bae3..00ddec298dcf 100644 --- a/telephony/java/com/android/internal/telephony/ITelephony.aidl +++ b/telephony/java/com/android/internal/telephony/ITelephony.aidl @@ -1063,11 +1063,13 @@ interface ITelephony { /** * Similar to above, but check for the package whose name is pkgName. + * Requires that the calling app has READ_PRIVILEGED_PHONE_STATE permission */ int checkCarrierPrivilegesForPackage(int subId, String pkgName); /** * Similar to above, but check across all phones. + * Requires that the calling app has READ_PRIVILEGED_PHONE_STATE permission */ int checkCarrierPrivilegesForPackageAnyPhone(String pkgName); @@ -1075,6 +1077,8 @@ interface ITelephony { * Returns list of the package names of the carrier apps that should handle the input intent * and have carrier privileges for the given phoneId. * + * Requires that the calling app has READ_PRIVILEGED_PHONE_STATE permission + * * @param intent Intent that will be sent. * @param phoneId The phoneId on which the carrier app has carrier privileges. * @return list of carrier app package names that can handle the intent on phoneId. @@ -1443,11 +1447,13 @@ interface ITelephony { /** * Returns a list of packages that have carrier privileges for the specific phone. + * Requires that the calling app has READ_PRIVILEGED_PHONE_STATE permission */ List<String> getPackagesWithCarrierPrivileges(int phoneId); /** * Returns a list of packages that have carrier privileges. + * Requires that the calling app has READ_PRIVILEGED_PHONE_STATE permission */ List<String> getPackagesWithCarrierPrivilegesForAllPhones(); |