diff options
author | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-05-07 21:07:05 +0000 |
---|---|---|
committer | Android Build Coastguard Worker <android-build-coastguard-worker@google.com> | 2022-05-07 21:07:05 +0000 |
commit | 5fdaf4ec937d8d8a5de5943090067aac41157c14 (patch) | |
tree | 69b7396411f5e69e690910c73bf9c0d3c64c4676 | |
parent | f8ea84388153fb5282ddfa25182a641f4c4aa800 (diff) | |
parent | 04dfd01b0b54ea9755e4187cccafe183142a1a61 (diff) | |
download | ims-5fdaf4ec937d8d8a5de5943090067aac41157c14.tar.gz |
Snap for 8557511 from 04dfd01b0b54ea9755e4187cccafe183142a1a61 to tm-d1-release
Change-Id: I4711b6ce56daa12f1506eb282c26011fde8c5e32
4 files changed, 261 insertions, 13 deletions
diff --git a/src/java/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityInfo.java b/src/java/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityInfo.java index 7fcb1ff7..dc794331 100644 --- a/src/java/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityInfo.java +++ b/src/java/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityInfo.java @@ -20,6 +20,7 @@ import static android.telephony.ims.RcsContactUceCapability.SOURCE_TYPE_CACHED; import android.content.Context; import android.net.Uri; +import android.telecom.PhoneAccount; import android.telecom.TelecomManager; import android.telephony.AccessNetworkConstants; import android.telephony.ims.ImsRegistrationAttributes; @@ -273,10 +274,33 @@ public class DeviceCapabilityInfo { } /** - * Get the IMS associated URI. It will first get the uri of MMTEL if it is not empty, otherwise - * it will try to get the uri of RCS. The null will be returned if both MMTEL and RCS are empty. + * Get the first URI from the "p-associated-uri" header included in the IMS registration + * response. + * @param preferTelUri If {@code true}, prefer returning the first TEL URI. If no TEL + * URIs exist, this method will still return the preferred (first) SIP URI + * in the header. If {@code false}, we will return the first URI + * in the "p-associated-uri" header, independent of the URI scheme. */ - public synchronized Uri getImsAssociatedUri() { + public synchronized Uri getImsAssociatedUri(boolean preferTelUri) { + if (preferTelUri) { + if (!mRcsAssociatedUris.isEmpty()) { + for (Uri rcsAssociatedUri : mRcsAssociatedUris) { + if (PhoneAccount.SCHEME_TEL.equalsIgnoreCase(rcsAssociatedUri.getScheme())) { + return rcsAssociatedUri; + } + } + } + if (!mMmtelAssociatedUris.isEmpty()) { + for (Uri mmtelAssociatedUri : mMmtelAssociatedUris) { + if (PhoneAccount.SCHEME_TEL.equalsIgnoreCase(mmtelAssociatedUri.getScheme())) { + return mmtelAssociatedUri; + } + } + } + } + + // Either we have not found a TEL URI or we do not prefer TEL URIs. Get the first URI from + // p-associated-uri list. if (!mRcsAssociatedUris.isEmpty()) { return mRcsAssociatedUris.get(0); } else if (!mMmtelAssociatedUris.isEmpty()) { @@ -473,7 +497,7 @@ public class DeviceCapabilityInfo { // Get the device's capabilities with the PRESENCE mechanism. private RcsContactUceCapability getPresenceCapabilities(Context context) { - Uri uri = PublishUtils.getDeviceContactUri(context, mSubId, this); + Uri uri = PublishUtils.getDeviceContactUri(context, mSubId, this, true); if (uri == null) { logw("getPresenceCapabilities: uri is empty"); return null; @@ -534,7 +558,7 @@ public class DeviceCapabilityInfo { // Get the device's capabilities with the OPTIONS mechanism. private RcsContactUceCapability getOptionsCapabilities(Context context) { - Uri uri = PublishUtils.getDeviceContactUri(context, mSubId, this); + Uri uri = PublishUtils.getDeviceContactUri(context, mSubId, this, false); if (uri == null) { logw("getOptionsCapabilities: uri is empty"); return null; diff --git a/src/java/com/android/ims/rcs/uce/presence/publish/PublishUtils.java b/src/java/com/android/ims/rcs/uce/presence/publish/PublishUtils.java index ea1d11b9..1a67a40a 100644 --- a/src/java/com/android/ims/rcs/uce/presence/publish/PublishUtils.java +++ b/src/java/com/android/ims/rcs/uce/presence/publish/PublishUtils.java @@ -18,6 +18,7 @@ package com.android.ims.rcs.uce.presence.publish; import android.content.Context; import android.net.Uri; +import android.telecom.PhoneAccount; import android.telephony.PhoneNumberUtils; import android.telephony.TelephonyManager; import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities; @@ -25,6 +26,9 @@ import android.telephony.ims.feature.RcsFeature.RcsImsCapabilities.RcsImsCapabil import android.text.TextUtils; import android.util.Log; +import com.android.i18n.phonenumbers.NumberParseException; +import com.android.i18n.phonenumbers.PhoneNumberUtil; +import com.android.i18n.phonenumbers.Phonenumber; import com.android.ims.rcs.uce.util.UceUtils; import java.util.Arrays; @@ -39,29 +43,49 @@ public class PublishUtils { private static final String SCHEME_TEL = "tel"; private static final String DOMAIN_SEPARATOR = "@"; + /** + * @return the contact URI of this device for either a PRESENCE or OPTIONS capabilities request. + * We will first try to use the IMS service associated URIs from the p-associated-uri header + * in the IMS registration response. If this is not available, we will fall back to using the + * SIM card information to generate the URI. + */ public static Uri getDeviceContactUri(Context context, int subId, - DeviceCapabilityInfo deviceCap) { - // Get the uri from the IMS associated URI which is provided by the IMS service. - Uri contactUri = deviceCap.getImsAssociatedUri(); + DeviceCapabilityInfo deviceCap, boolean isForPresence) { + boolean preferTelUri = false; + if (isForPresence) { + preferTelUri = UceUtils.isTelUriForPidfXmlEnabled(context, subId); + } + // Get the uri from the IMS p-associated-uri header which is provided by the IMS service. + Uri contactUri = deviceCap.getImsAssociatedUri(preferTelUri); if (contactUri != null) { - Log.d(LOG_TAG, "getDeviceContactUri: ims associated uri"); + Uri convertedUri = preferTelUri ? getConvertedTelUri(context, contactUri) : contactUri; + Log.d(LOG_TAG, "getDeviceContactUri: returning " + + (contactUri.equals(convertedUri) ? "found" : "converted") + + " ims associated uri"); return contactUri; } + // No IMS service provided URIs, so generate the contact uri from ISIM. TelephonyManager telephonyManager = getTelephonyManager(context, subId); if (telephonyManager == null) { Log.w(LOG_TAG, "getDeviceContactUri: TelephonyManager is null"); return null; } - - // Get the contact uri from ISIM. contactUri = getContactUriFromIsim(telephonyManager); if (contactUri != null) { Log.d(LOG_TAG, "getDeviceContactUri: impu"); - return contactUri; + if (preferTelUri) { + return getConvertedTelUri(context, contactUri); + } else { + return contactUri; + } } else { Log.d(LOG_TAG, "getDeviceContactUri: line number"); - return getContactUriFromLine1Number(telephonyManager); + if (preferTelUri) { + return getConvertedTelUri(context, getContactUriFromLine1Number(telephonyManager)); + } else { + return getContactUriFromLine1Number(telephonyManager); + } } } @@ -136,6 +160,41 @@ public class PublishUtils { } } + /** + * @return a TEL URI version of the contact URI if given a SIP URI. If given a TEL URI, this + * method will return the same value given. + */ + private static Uri getConvertedTelUri(Context context, Uri contactUri) { + if (contactUri == null) { + return null; + } + if (contactUri.getScheme().equalsIgnoreCase(SCHEME_SIP)) { + TelephonyManager manager = context.getSystemService(TelephonyManager.class); + if (manager.getIsimDomain() == null) { + return contactUri; + } + + String numbers = contactUri.getSchemeSpecificPart(); + String[] numberParts = numbers.split("[@;:]"); + String number = numberParts[0]; + + String simCountryIso = manager.getSimCountryIso(); + if (!TextUtils.isEmpty(simCountryIso)) { + simCountryIso = simCountryIso.toUpperCase(); + PhoneNumberUtil util = PhoneNumberUtil.getInstance(); + try { + Phonenumber.PhoneNumber phoneNumber = util.parse(number, simCountryIso); + number = util.format(phoneNumber, PhoneNumberUtil.PhoneNumberFormat.E164); + String telUri = SCHEME_TEL + ":" + number; + contactUri = Uri.parse(telUri); + } catch (NumberParseException e) { + Log.w(LOG_TAG, "formatNumber: could not format " + number + ", error: " + e); + } + } + } + return contactUri; + } + static @RcsImsCapabilityFlag int getCapabilityType(Context context, int subId) { boolean isPresenceSupported = UceUtils.isPresenceSupported(context, subId); boolean isSipOptionsSupported = UceUtils.isSipOptionsSupported(context, subId); diff --git a/src/java/com/android/ims/rcs/uce/util/UceUtils.java b/src/java/com/android/ims/rcs/uce/util/UceUtils.java index 58796983..c5f2b122 100644 --- a/src/java/com/android/ims/rcs/uce/util/UceUtils.java +++ b/src/java/com/android/ims/rcs/uce/util/UceUtils.java @@ -210,6 +210,22 @@ public class UceUtils { } /** + * Check whether tel uri should be used for pidf xml + */ + public static boolean isTelUriForPidfXmlEnabled(Context context, int subId) { + CarrierConfigManager configManager = context.getSystemService(CarrierConfigManager.class); + if (configManager == null) { + return false; + } + PersistableBundle config = configManager.getConfigForSubId(subId); + if (config == null) { + return false; + } + return config.getBoolean( + CarrierConfigManager.Ims.KEY_USE_TEL_URI_FOR_PIDF_XML_BOOL); + } + + /** * Get the minimum time that allow two PUBLISH requests can be executed continuously. * * @param subId The subscribe ID diff --git a/tests/src/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityInfoTest.java b/tests/src/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityInfoTest.java new file mode 100644 index 00000000..c977a080 --- /dev/null +++ b/tests/src/com/android/ims/rcs/uce/presence/publish/DeviceCapabilityInfoTest.java @@ -0,0 +1,149 @@ +/* + * Copyright (C) 2022 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 com.android.ims.rcs.uce.presence.publish; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; + +import android.net.Uri; +import android.telecom.PhoneAccount; + +import androidx.test.ext.junit.runners.AndroidJUnit4; +import androidx.test.filters.SmallTest; + +import com.android.ims.ImsTestBase; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; + +@RunWith(AndroidJUnit4.class) +public class DeviceCapabilityInfoTest extends ImsTestBase { + + int mSubId = 1; + + String sipNumber = "123456789"; + String telNumber = "987654321"; + + @Before + public void setUp() throws Exception { + super.setUp(); + } + + @After + public void tearDown() throws Exception { + super.tearDown(); + } + + @Test + @SmallTest + public void testGetImsAssociatedUriWithoutPreferTelUri() throws Exception { + DeviceCapabilityInfo deviceCapInfo = createDeviceCapabilityInfo(); + + Uri[] uris = new Uri[2]; + uris[0] = Uri.fromParts(PhoneAccount.SCHEME_SIP, sipNumber, null); + uris[1] = Uri.fromParts(PhoneAccount.SCHEME_TEL, telNumber, null); + + // When stored in the order of SIP, TEL URI, check whether the SIP URI saved at + // the beginning is retrieved. + deviceCapInfo.updateRcsAssociatedUri(uris); + Uri outUri = deviceCapInfo.getImsAssociatedUri(false); + + String numbers = outUri.getSchemeSpecificPart(); + String[] numberParts = numbers.split("[@;:]"); + String number = numberParts[0]; + + assertEquals(number, sipNumber); + + // When stored in the order of TEL, SIP URI, check whether the TEL URI saved at + // the beginning is retrieved. + deviceCapInfo = createDeviceCapabilityInfo(); + + uris[0] = Uri.fromParts(PhoneAccount.SCHEME_TEL, telNumber, null); + uris[1] = Uri.fromParts(PhoneAccount.SCHEME_SIP, sipNumber, null); + + deviceCapInfo.updateRcsAssociatedUri(uris); + outUri = deviceCapInfo.getImsAssociatedUri(false); + + numbers = outUri.getSchemeSpecificPart(); + numberParts = numbers.split("[@;:]"); + number = numberParts[0]; + + assertEquals(number, telNumber); + } + + @Test + @SmallTest + public void testGetImsAssociatedUriWithPreferTelUri() throws Exception { + DeviceCapabilityInfo deviceCapInfo = createDeviceCapabilityInfo(); + + Uri[] uris = new Uri[2]; + uris[0] = Uri.fromParts(PhoneAccount.SCHEME_SIP, sipNumber, null); + uris[1] = Uri.fromParts(PhoneAccount.SCHEME_TEL, telNumber, null); + + // Check whether TEL URI is returned when preferTelUri is true even if SIP and TEL URI + // are in the order. + deviceCapInfo.updateRcsAssociatedUri(uris); + Uri outUri = deviceCapInfo.getImsAssociatedUri(true); + + String numbers = outUri.getSchemeSpecificPart(); + String[] numberParts = numbers.split("[@;:]"); + String number = numberParts[0]; + + assertEquals(number, telNumber); + + // If preferTelUri is true, check if a TEL URI is returned. + deviceCapInfo = createDeviceCapabilityInfo(); + + uris[0] = Uri.fromParts(PhoneAccount.SCHEME_TEL, telNumber, null); + uris[1] = Uri.fromParts(PhoneAccount.SCHEME_SIP, sipNumber, null); + + deviceCapInfo.updateRcsAssociatedUri(uris); + outUri = deviceCapInfo.getImsAssociatedUri(true); + + numbers = outUri.getSchemeSpecificPart(); + numberParts = numbers.split("[@;:]"); + number = numberParts[0]; + + assertEquals(number, telNumber); + + // If there is only SIP URI, this method will still return a SIP URI, since there are no TEL + // URIs found in the list. + deviceCapInfo = createDeviceCapabilityInfo(); + + uris[0] = Uri.fromParts(PhoneAccount.SCHEME_SIP, telNumber, null); + uris[1] = Uri.fromParts(PhoneAccount.SCHEME_SIP, sipNumber, null); + + deviceCapInfo.updateRcsAssociatedUri(uris); + outUri = deviceCapInfo.getImsAssociatedUri(true); + + numbers = outUri.getSchemeSpecificPart(); + numberParts = numbers.split("[@;:]"); + number = numberParts[0]; + + assertEquals(number, telNumber); + + } + + private DeviceCapabilityInfo createDeviceCapabilityInfo() { + DeviceCapabilityInfo deviceCapInfo = new DeviceCapabilityInfo(mSubId, null); + return deviceCapInfo; + } + +}
\ No newline at end of file |