Loading src/java/com/android/internal/telephony/imsphone/ImsPhone.java +64 −18 Original line number Diff line number Diff line Loading @@ -139,6 +139,7 @@ import java.util.Arrays; import java.util.List; import java.util.concurrent.Executor; import java.util.function.Consumer; import java.util.stream.Stream; /** * {@hide} Loading Loading @@ -2539,10 +2540,6 @@ public class ImsPhone extends ImsPhoneBase { /** Sets the IMS phone number from IMS associated URIs, if any found. */ @VisibleForTesting public void setPhoneNumberForSourceIms(Uri[] uris) { String phoneNumber = extractPhoneNumberFromAssociatedUris(uris); if (phoneNumber == null) { return; } int subId = getSubId(); if (!SubscriptionManager.isValidSubscriptionId(subId)) { // Defending b/219080264: Loading @@ -2551,16 +2548,33 @@ public class ImsPhone extends ImsPhoneBase { // IMS callbacks are sent back to telephony after SIM state changed. return; } SubscriptionInfoInternal subInfo = mSubscriptionManagerService .getSubscriptionInfoInternal(subId); if (subInfo != null) { phoneNumber = PhoneNumberUtils.formatNumberToE164(phoneNumber, subInfo.getCountryIso()); if (subInfo == null) { loge("trigger setPhoneNumberForSourceIms, but subInfo is null"); return; } String subCountryIso = subInfo.getCountryIso(); String phoneNumber = extractPhoneNumberFromAssociatedUris(uris, /*isGlobalFormat*/true); if (phoneNumber != null) { phoneNumber = PhoneNumberUtils.formatNumberToE164(phoneNumber, subCountryIso); if (phoneNumber == null) { loge("format to E164 failed"); return; } mSubscriptionManagerService.setNumberFromIms(subId, phoneNumber); } else if (isAllowNonGlobalNumberFormat()) { // If carrier config has true for KEY_IGNORE_GLOBAL_PHONE_NUMBER_FORMAT_BOOL and // P-Associated-Uri does not have global number, // try to find phone number excluding '+' one more time. phoneNumber = extractPhoneNumberFromAssociatedUris(uris, /*isGlobalFormat*/false); if (phoneNumber == null) { loge("extract phone number without '+' failed"); return; } mSubscriptionManagerService.setNumberFromIms(subId, phoneNumber); } else { logd("extract phone number failed"); } } Loading @@ -2570,24 +2584,40 @@ public class ImsPhone extends ImsPhoneBase { * <p>Associated URIs are public user identities, and phone number could be used: * see 3GPP TS 24.229 5.4.1.2 and 3GPP TS 23.003 13.4. This algotihm look for the * possible "global number" in E.164 format. * <p>If true try finding phone number even if the P-Associated-Uri does not have global * number format. */ private static String extractPhoneNumberFromAssociatedUris(Uri[] uris) { private static String extractPhoneNumberFromAssociatedUris(Uri[] uris, boolean isGlobalFormat) { if (uris == null) { return null; } return Arrays.stream(uris) Stream<String> intermediate = Arrays.stream(uris) // Phone number is an opaque URI "tel:<phone-number>" or "sip:<phone-number>@<...>" .filter(u -> u != null && u.isOpaque()) .filter(u -> "tel".equalsIgnoreCase(u.getScheme()) || "sip".equalsIgnoreCase(u.getScheme())) .map(Uri::getSchemeSpecificPart) .map(Uri::getSchemeSpecificPart); if (isGlobalFormat) { // "Global number" should be in E.164 format starting with "+" e.g. "+447539447777" .filter(ssp -> ssp != null && ssp.startsWith("+")) return intermediate.filter(ssp -> ssp != null && ssp.startsWith("+")) // Remove whatever after "@" for sip URI .map(ssp -> ssp.split("@")[0]) // Returns the first winner .findFirst() .orElse(null); } else { // non global number format return intermediate.filter(ssp -> ssp != null) // Remove whatever after "@" for sip URI .map(ssp -> ssp.split("@")[0]) // regular expression, allow only number .filter(ssp -> ssp.matches("^[0-9]+$")) // Returns the first winner .findFirst() .orElse(null); } } public IccRecords getIccRecords() { Loading Loading @@ -2790,6 +2820,22 @@ public class ImsPhone extends ImsPhoneBase { pw.flush(); } private boolean isAllowNonGlobalNumberFormat() { PersistableBundle persistableBundle = null; CarrierConfigManager carrierConfigManager = (CarrierConfigManager) mContext .getSystemService(Context.CARRIER_CONFIG_SERVICE); if (carrierConfigManager != null) { persistableBundle = carrierConfigManager.getConfigForSubId(getSubId(), CarrierConfigManager.Ims.KEY_ALLOW_NON_GLOBAL_PHONE_NUMBER_FORMAT_BOOL); } if (persistableBundle != null) { return persistableBundle.getBoolean( CarrierConfigManager.Ims.KEY_ALLOW_NON_GLOBAL_PHONE_NUMBER_FORMAT_BOOL, false); } return false; } private void logi(String s) { Rlog.i(LOG_TAG, "[" + mPhoneId + "] " + s); } Loading tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java +62 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.nullable; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; Loading Loading @@ -1049,6 +1050,67 @@ public class ImsPhoneTest extends TelephonyTest { mContextFixture.addCallingOrSelfPermission(""); } @Test @SmallTest public void testSetPhoneNumberForSourceIgnoreGlobalPhoneNumberFormat() { // In reality the method under test runs in phone process so has MODIFY_PHONE_STATE mContextFixture.addCallingOrSelfPermission(MODIFY_PHONE_STATE); int subId = 1; doReturn(subId).when(mPhone).getSubId(); doReturn(new SubscriptionInfoInternal.Builder().setId(subId).setSimSlotIndex(0) .setCountryIso("gb").build()).when(mSubscriptionManagerService) .getSubscriptionInfoInternal(subId); // Set carrier config to ignore global phone number format PersistableBundle bundle = new PersistableBundle(); bundle.putBoolean( CarrierConfigManager.Ims.KEY_ALLOW_NON_GLOBAL_PHONE_NUMBER_FORMAT_BOOL, true); doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(eq(subId), eq(CarrierConfigManager.Ims.KEY_ALLOW_NON_GLOBAL_PHONE_NUMBER_FORMAT_BOOL)); // 1. Two non-global phone number; 1st is set. Uri[] associatedUris = new Uri[] { Uri.parse("sip:01012345678@lte-uplus.co.kr"), Uri.parse("tel:01012345678") }; mImsPhoneUT.setPhoneNumberForSourceIms(associatedUris); verify(mSubscriptionManagerService).setNumberFromIms(subId, "01012345678"); // 2. 1st non-global phone number and 2nd global number; 2nd is set. associatedUris = new Uri[] { Uri.parse("sip:01012345678@lte-uplus.co.kr"), Uri.parse("tel:+821012345678") }; mImsPhoneUT.setPhoneNumberForSourceIms(associatedUris); verify(mSubscriptionManagerService).setNumberFromIms(subId, "+821012345678"); // 3. 1st sip-uri is not phone number and 2nd valid: 2nd is set. associatedUris = new Uri[] { Uri.parse("sip:john.doe@ims.x.com"), Uri.parse("sip:01022223333@lte-uplus.co.kr"), Uri.parse("tel:01022223333") }; mImsPhoneUT.setPhoneNumberForSourceIms(associatedUris); verify(mSubscriptionManagerService).setNumberFromIms(subId, "01022223333"); clearInvocations(mSubscriptionManagerService); // 4. Invalid phone number : not set. associatedUris = new Uri[] { Uri.parse("sip:john.doe@ims.x.com"), Uri.parse("sip:hone3333@lte-uplus.co.kr"), Uri.parse("tel:abcd1234555") }; mImsPhoneUT.setPhoneNumberForSourceIms(associatedUris); verify(mSubscriptionManagerService, never()).setNumberFromIms(anyInt(), anyString()); // Clean up mContextFixture.addCallingOrSelfPermission(""); } /** * Verifies that valid radio technology is passed to RIL * when IMS registration state changes to registered. Loading Loading
src/java/com/android/internal/telephony/imsphone/ImsPhone.java +64 −18 Original line number Diff line number Diff line Loading @@ -139,6 +139,7 @@ import java.util.Arrays; import java.util.List; import java.util.concurrent.Executor; import java.util.function.Consumer; import java.util.stream.Stream; /** * {@hide} Loading Loading @@ -2539,10 +2540,6 @@ public class ImsPhone extends ImsPhoneBase { /** Sets the IMS phone number from IMS associated URIs, if any found. */ @VisibleForTesting public void setPhoneNumberForSourceIms(Uri[] uris) { String phoneNumber = extractPhoneNumberFromAssociatedUris(uris); if (phoneNumber == null) { return; } int subId = getSubId(); if (!SubscriptionManager.isValidSubscriptionId(subId)) { // Defending b/219080264: Loading @@ -2551,16 +2548,33 @@ public class ImsPhone extends ImsPhoneBase { // IMS callbacks are sent back to telephony after SIM state changed. return; } SubscriptionInfoInternal subInfo = mSubscriptionManagerService .getSubscriptionInfoInternal(subId); if (subInfo != null) { phoneNumber = PhoneNumberUtils.formatNumberToE164(phoneNumber, subInfo.getCountryIso()); if (subInfo == null) { loge("trigger setPhoneNumberForSourceIms, but subInfo is null"); return; } String subCountryIso = subInfo.getCountryIso(); String phoneNumber = extractPhoneNumberFromAssociatedUris(uris, /*isGlobalFormat*/true); if (phoneNumber != null) { phoneNumber = PhoneNumberUtils.formatNumberToE164(phoneNumber, subCountryIso); if (phoneNumber == null) { loge("format to E164 failed"); return; } mSubscriptionManagerService.setNumberFromIms(subId, phoneNumber); } else if (isAllowNonGlobalNumberFormat()) { // If carrier config has true for KEY_IGNORE_GLOBAL_PHONE_NUMBER_FORMAT_BOOL and // P-Associated-Uri does not have global number, // try to find phone number excluding '+' one more time. phoneNumber = extractPhoneNumberFromAssociatedUris(uris, /*isGlobalFormat*/false); if (phoneNumber == null) { loge("extract phone number without '+' failed"); return; } mSubscriptionManagerService.setNumberFromIms(subId, phoneNumber); } else { logd("extract phone number failed"); } } Loading @@ -2570,24 +2584,40 @@ public class ImsPhone extends ImsPhoneBase { * <p>Associated URIs are public user identities, and phone number could be used: * see 3GPP TS 24.229 5.4.1.2 and 3GPP TS 23.003 13.4. This algotihm look for the * possible "global number" in E.164 format. * <p>If true try finding phone number even if the P-Associated-Uri does not have global * number format. */ private static String extractPhoneNumberFromAssociatedUris(Uri[] uris) { private static String extractPhoneNumberFromAssociatedUris(Uri[] uris, boolean isGlobalFormat) { if (uris == null) { return null; } return Arrays.stream(uris) Stream<String> intermediate = Arrays.stream(uris) // Phone number is an opaque URI "tel:<phone-number>" or "sip:<phone-number>@<...>" .filter(u -> u != null && u.isOpaque()) .filter(u -> "tel".equalsIgnoreCase(u.getScheme()) || "sip".equalsIgnoreCase(u.getScheme())) .map(Uri::getSchemeSpecificPart) .map(Uri::getSchemeSpecificPart); if (isGlobalFormat) { // "Global number" should be in E.164 format starting with "+" e.g. "+447539447777" .filter(ssp -> ssp != null && ssp.startsWith("+")) return intermediate.filter(ssp -> ssp != null && ssp.startsWith("+")) // Remove whatever after "@" for sip URI .map(ssp -> ssp.split("@")[0]) // Returns the first winner .findFirst() .orElse(null); } else { // non global number format return intermediate.filter(ssp -> ssp != null) // Remove whatever after "@" for sip URI .map(ssp -> ssp.split("@")[0]) // regular expression, allow only number .filter(ssp -> ssp.matches("^[0-9]+$")) // Returns the first winner .findFirst() .orElse(null); } } public IccRecords getIccRecords() { Loading Loading @@ -2790,6 +2820,22 @@ public class ImsPhone extends ImsPhoneBase { pw.flush(); } private boolean isAllowNonGlobalNumberFormat() { PersistableBundle persistableBundle = null; CarrierConfigManager carrierConfigManager = (CarrierConfigManager) mContext .getSystemService(Context.CARRIER_CONFIG_SERVICE); if (carrierConfigManager != null) { persistableBundle = carrierConfigManager.getConfigForSubId(getSubId(), CarrierConfigManager.Ims.KEY_ALLOW_NON_GLOBAL_PHONE_NUMBER_FORMAT_BOOL); } if (persistableBundle != null) { return persistableBundle.getBoolean( CarrierConfigManager.Ims.KEY_ALLOW_NON_GLOBAL_PHONE_NUMBER_FORMAT_BOOL, false); } return false; } private void logi(String s) { Rlog.i(LOG_TAG, "[" + mPhoneId + "] " + s); } Loading
tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneTest.java +62 −0 Original line number Diff line number Diff line Loading @@ -47,6 +47,7 @@ import static org.mockito.Matchers.anyInt; import static org.mockito.Matchers.anyLong; import static org.mockito.Matchers.nullable; import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.clearInvocations; import static org.mockito.Mockito.doAnswer; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; Loading Loading @@ -1049,6 +1050,67 @@ public class ImsPhoneTest extends TelephonyTest { mContextFixture.addCallingOrSelfPermission(""); } @Test @SmallTest public void testSetPhoneNumberForSourceIgnoreGlobalPhoneNumberFormat() { // In reality the method under test runs in phone process so has MODIFY_PHONE_STATE mContextFixture.addCallingOrSelfPermission(MODIFY_PHONE_STATE); int subId = 1; doReturn(subId).when(mPhone).getSubId(); doReturn(new SubscriptionInfoInternal.Builder().setId(subId).setSimSlotIndex(0) .setCountryIso("gb").build()).when(mSubscriptionManagerService) .getSubscriptionInfoInternal(subId); // Set carrier config to ignore global phone number format PersistableBundle bundle = new PersistableBundle(); bundle.putBoolean( CarrierConfigManager.Ims.KEY_ALLOW_NON_GLOBAL_PHONE_NUMBER_FORMAT_BOOL, true); doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(eq(subId), eq(CarrierConfigManager.Ims.KEY_ALLOW_NON_GLOBAL_PHONE_NUMBER_FORMAT_BOOL)); // 1. Two non-global phone number; 1st is set. Uri[] associatedUris = new Uri[] { Uri.parse("sip:01012345678@lte-uplus.co.kr"), Uri.parse("tel:01012345678") }; mImsPhoneUT.setPhoneNumberForSourceIms(associatedUris); verify(mSubscriptionManagerService).setNumberFromIms(subId, "01012345678"); // 2. 1st non-global phone number and 2nd global number; 2nd is set. associatedUris = new Uri[] { Uri.parse("sip:01012345678@lte-uplus.co.kr"), Uri.parse("tel:+821012345678") }; mImsPhoneUT.setPhoneNumberForSourceIms(associatedUris); verify(mSubscriptionManagerService).setNumberFromIms(subId, "+821012345678"); // 3. 1st sip-uri is not phone number and 2nd valid: 2nd is set. associatedUris = new Uri[] { Uri.parse("sip:john.doe@ims.x.com"), Uri.parse("sip:01022223333@lte-uplus.co.kr"), Uri.parse("tel:01022223333") }; mImsPhoneUT.setPhoneNumberForSourceIms(associatedUris); verify(mSubscriptionManagerService).setNumberFromIms(subId, "01022223333"); clearInvocations(mSubscriptionManagerService); // 4. Invalid phone number : not set. associatedUris = new Uri[] { Uri.parse("sip:john.doe@ims.x.com"), Uri.parse("sip:hone3333@lte-uplus.co.kr"), Uri.parse("tel:abcd1234555") }; mImsPhoneUT.setPhoneNumberForSourceIms(associatedUris); verify(mSubscriptionManagerService, never()).setNumberFromIms(anyInt(), anyString()); // Clean up mContextFixture.addCallingOrSelfPermission(""); } /** * Verifies that valid radio technology is passed to RIL * when IMS registration state changes to registered. Loading