Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit d672dc84 authored by TreeHugger Robot's avatar TreeHugger Robot Committed by Android (Google) Code Review
Browse files

Merge "Populate IMS phone number"

parents 99da7df5 71b41aa7
Loading
Loading
Loading
Loading
+57 −0
Original line number Diff line number Diff line
@@ -16,6 +16,7 @@

package com.android.internal.telephony.imsphone;

import static android.provider.Telephony.SimInfo.COLUMN_PHONE_NUMBER_SOURCE_IMS;
import static android.telephony.ims.ImsManager.EXTRA_WFC_REGISTRATION_FAILURE_MESSAGE;
import static android.telephony.ims.ImsManager.EXTRA_WFC_REGISTRATION_FAILURE_TITLE;

@@ -70,6 +71,7 @@ import android.telephony.CarrierConfigManager;
import android.telephony.NetworkRegistrationInfo;
import android.telephony.PhoneNumberUtils;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyManager;
import android.telephony.UssdResponse;
@@ -105,6 +107,7 @@ import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.PhoneNotifier;
import com.android.internal.telephony.ServiceStateTracker;
import com.android.internal.telephony.SubscriptionController;
import com.android.internal.telephony.TelephonyComponentFactory;
import com.android.internal.telephony.TelephonyIntents;
import com.android.internal.telephony.dataconnection.TransportManager;
@@ -122,6 +125,7 @@ import com.android.telephony.Rlog;
import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;

@@ -2485,9 +2489,62 @@ public class ImsPhone extends ImsPhoneBase {
        public void handleImsSubscriberAssociatedUriChanged(Uri[] uris) {
            if (DBG) logd("handleImsSubscriberAssociatedUriChanged");
            setCurrentSubscriberUris(uris);
            setPhoneNumberForSourceIms(uris);
        }
    };

    /** 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;
        }
        SubscriptionController subController = SubscriptionController.getInstance();
        int subId = getSubId();
        String countryIso = getCountryIso(subController, subId);
        // Format the number as one more defense to reject garbage values:
        // phoneNumber will become null.
        phoneNumber = PhoneNumberUtils.formatNumberToE164(phoneNumber, countryIso);
        if (phoneNumber == null) {
            return;
        }
        subController.setSubscriptionProperty(subId, COLUMN_PHONE_NUMBER_SOURCE_IMS, phoneNumber);
    }

    private static String getCountryIso(SubscriptionController subController, int subId) {
        SubscriptionInfo info = subController.getSubscriptionInfo(subId);
        String countryIso = info == null ? "" : info.getCountryIso();
        // info.getCountryIso() may return null
        return countryIso == null ? "" : countryIso;
    }

    /**
     * Finds the phone number from associated URIs.
     *
     * <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.
     */
    private static String extractPhoneNumberFromAssociatedUris(Uri[] uris) {
        if (uris == null) {
            return null;
        }
        return 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)
                // "Global number" should be in E.164 format starting with "+" e.g. "+447539447777"
                .filter(ssp -> ssp != null && ssp.startsWith("+"))
                // Remove whatever after "@" for sip URI
                .map(ssp -> ssp.split("@")[0])
                // Returns the first winner
                .findFirst()
                .orElse(null);
    }

    public IccRecords getIccRecords() {
        return mDefaultPhone.getIccRecords();
    }
+96 −0
Original line number Diff line number Diff line
@@ -16,6 +16,8 @@

package com.android.internal.telephony.imsphone;

import static android.Manifest.permission.MODIFY_PHONE_STATE;
import static android.provider.Telephony.SimInfo.COLUMN_PHONE_NUMBER_SOURCE_IMS;
import static android.telephony.CarrierConfigManager.USSD_OVER_CS_ONLY;
import static android.telephony.CarrierConfigManager.USSD_OVER_CS_PREFERRED;
import static android.telephony.CarrierConfigManager.USSD_OVER_IMS_ONLY;
@@ -40,6 +42,7 @@ import static org.mockito.Mockito.doNothing;
import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.doThrow;
import static org.mockito.Mockito.eq;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.times;
@@ -49,6 +52,7 @@ import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Intent;
import android.content.res.Resources;
import android.net.Uri;
import android.os.AsyncResult;
import android.os.Bundle;
import android.os.Handler;
@@ -57,6 +61,7 @@ import android.os.PersistableBundle;
import android.sysprop.TelephonyProperties;
import android.telephony.CarrierConfigManager;
import android.telephony.ServiceState;
import android.telephony.SubscriptionInfo;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsCallProfile;
import android.telephony.ims.ImsReasonInfo;
@@ -976,6 +981,97 @@ public class ImsPhoneTest extends TelephonyTest {
        mImsPhoneUT.handleMessage(m);
    }

    @Test
    @SmallTest
    public void testSetPhoneNumberForSourceIms() {
        // 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();
        SubscriptionInfo subInfo = mock(SubscriptionInfo.class);
        doReturn("gb").when(subInfo).getCountryIso();
        doReturn(subInfo).when(mSubscriptionController).getSubscriptionInfo(subId);

        // 1. Two valid phone number; 1st is set.
        Uri[] associatedUris = new Uri[] {
            Uri.parse("sip:+447539447777@ims.x.com"),
            Uri.parse("tel:+447539446666")
        };
        mImsPhoneUT.setPhoneNumberForSourceIms(associatedUris);

        verify(mSubscriptionController).setSubscriptionProperty(
                subId, COLUMN_PHONE_NUMBER_SOURCE_IMS, "+447539447777");

        // 2. 1st invalid and 2nd valid: 2nd is set.
        associatedUris = new Uri[] {
            Uri.parse("sip:447539447777@ims.x.com"),
            Uri.parse("tel:+447539446666")
        };
        mImsPhoneUT.setPhoneNumberForSourceIms(associatedUris);

        verify(mSubscriptionController).setSubscriptionProperty(
                subId, COLUMN_PHONE_NUMBER_SOURCE_IMS, "+447539446666");

        // 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("tel:+447539446677"),
            Uri.parse("sip:+447539447766@ims.x.com")
        };
        mImsPhoneUT.setPhoneNumberForSourceIms(associatedUris);

        verify(mSubscriptionController).setSubscriptionProperty(
                subId, COLUMN_PHONE_NUMBER_SOURCE_IMS, "+447539446677");

        // Clean up
        mContextFixture.addCallingOrSelfPermission("");
    }

    @Test
    @SmallTest
    public void testSetPhoneNumberForSourceImsNegativeCases() {
        // 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();
        SubscriptionInfo subInfo = mock(SubscriptionInfo.class);
        doReturn("gb").when(subInfo).getCountryIso();
        doReturn(subInfo).when(mSubscriptionController).getSubscriptionInfo(subId);

        // 1. No valid phone number; do not set
        Uri[] associatedUris = new Uri[] {
            Uri.parse("sip:447539447777@ims.x.com"),
            Uri.parse("tel:447539446666")
        };
        mImsPhoneUT.setPhoneNumberForSourceIms(associatedUris);

        verify(mSubscriptionController, never()).setSubscriptionProperty(
                anyInt(), any(), any());

        // 2. no URI; do not set
        associatedUris = new Uri[] {};
        mImsPhoneUT.setPhoneNumberForSourceIms(associatedUris);

        verify(mSubscriptionController, never()).setSubscriptionProperty(
                anyInt(), any(), any());

        // 3. null URI; do not set
        associatedUris = new Uri[] { null };
        mImsPhoneUT.setPhoneNumberForSourceIms(associatedUris);

        verify(mSubscriptionController, never()).setSubscriptionProperty(
                anyInt(), any(), any());

        // 4. null pointer; do not set
        mImsPhoneUT.setPhoneNumberForSourceIms(null);

        verify(mSubscriptionController, never()).setSubscriptionProperty(
                anyInt(), any(), any());

        // Clean up
        mContextFixture.addCallingOrSelfPermission("");
    }

    private ServiceState getServiceStateDataAndVoice(int rat, int regState, boolean isRoaming) {
        ServiceState ss = new ServiceState();
        ss.setStateOutOfService();