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

Commit 667525a8 authored by Android Build Coastguard Worker's avatar Android Build Coastguard Worker
Browse files

Snap for 11816316 from 9f8be83f to 24Q3-release

Change-Id: I894dadc1abbfece5191948d880f40c500617fecd
parents ccc13fe6 9f8be83f
Loading
Loading
Loading
Loading
+12 −1
Original line number Diff line number Diff line
@@ -18,3 +18,14 @@ flag {
  description: "Used in DisconnectCause and TelephonyConnection if a non-emergency call fails on a device with no 2G, to guard whether a user can see an updated error message reminding the 2G is disabled and potentially disrupting their call connectivity"
  bug: "300142897"
}

# OWNER=stevestatia TARGET=24Q4
flag {
    name: "remove_country_code_from_local_singapore_calls"
    namespace: "telephony"
    description: "Fix bug where the country code is being shown when merging in local Singapore numbers to conference calls."
    bug:"284416645"
    metadata {
        purpose: PURPOSE_BUGFIX
    }
}
+72 −1
Original line number Diff line number Diff line
@@ -157,6 +157,11 @@ public class ImsPhoneConnection extends Connection implements
     */
    private boolean mIsHeldByRemote = false;

    /**
     * Used to indicate if both the user and carrier config have enabled the business composer.
     */
    private boolean mIsBusinessComposerFeatureEnabled = false;

    //***** Event Constants
    private static final int EVENT_DTMF_DONE = 1;
    private static final int EVENT_PAUSE_DONE = 2;
@@ -230,6 +235,10 @@ public class ImsPhoneConnection extends Connection implements
        mCreateTime = System.currentTimeMillis();
        mUusInfo = null;

        if (com.android.server.telecom.flags.Flags.businessCallComposer()) {
            setIsBusinessComposerFeatureEnabled(phone);
        }

        // Ensure any extras set on the ImsCallProfile at the start of the call are cached locally
        // in the ImsPhoneConnection.  This isn't going to inform any listeners (since the original
        // connection is not likely to be associated with a TelephonyConnection yet).
@@ -1389,10 +1398,18 @@ public class ImsPhoneConnection extends Connection implements
     * ImsCallProfile.EXTRA_ASSERTED_DISPLAY_NAME). This helper notifies Telecom of the business
     * composer values which will then be injected into the android.telecom.Call object.
     */
    private void maybeInjectBusinessComposerExtras(Bundle extras) {
    @VisibleForTesting
    public void maybeInjectBusinessComposerExtras(Bundle extras) {
        if (extras == null) {
            return;
        }
        // Telephony should check that the business composer features is on BEFORE
        // propagating the business call extras.  This prevents the user from getting
        // business call info when they turned the feature off.
        if (!mIsBusinessComposerFeatureEnabled) {
            Rlog.i(LOG_TAG, "mIBCE: business composer feature is NOT enabled");
            return;
        }
        try {
            if (extras.containsKey(ImsCallProfile.EXTRA_IS_BUSINESS_CALL)
                    && !extras.containsKey(android.telecom.Call.EXTRA_IS_BUSINESS_CALL)) {
@@ -1413,6 +1430,60 @@ public class ImsPhoneConnection extends Connection implements
        }
    }

    @VisibleForTesting
    public boolean getIsBusinessComposerFeatureEnabled() {
        return mIsBusinessComposerFeatureEnabled;
    }

    @VisibleForTesting
    public void setIsBusinessComposerFeatureEnabled(Phone phone) {
        mIsBusinessComposerFeatureEnabled = isBusinessComposerEnabledByConfig(phone)
                && isBusinessOnlyCallComposerEnabledByUser(phone);
        Rlog.i(LOG_TAG, String.format(
                "setIsBusinessComposerFeatureEnabled:  mIsBusinessComposerFeatureEnabled=[%b], "
                        + "phone=[%s]", mIsBusinessComposerFeatureEnabled, phone));
    }

    /**
     * Returns whether the carrier supports and has enabled the business composer
     */
    @VisibleForTesting
    public boolean isBusinessComposerEnabledByConfig(Phone phone) {
        PersistableBundle b = null;
        CarrierConfigManager configMgr = phone.getContext().getSystemService(
                CarrierConfigManager.class);

        if (configMgr != null) {
            // If an invalid subId is used, this bundle will contain default values.
            b = configMgr.getConfigForSubId(phone.getSubId());
        }
        if (b != null) {
            return b.getBoolean(CarrierConfigManager.KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL);
        } else {
            // Return static default defined in CarrierConfigManager.
            return CarrierConfigManager.getDefaultConfig()
                    .getBoolean(CarrierConfigManager.KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL);
        }
    }

    /**
     * Returns whether the user has enabled the business composer
     */
    @VisibleForTesting
    public boolean isBusinessOnlyCallComposerEnabledByUser(Phone phone) {
        if (phone == null || phone.getContext() == null) {
            return false;
        }
        TelephonyManager tm = (TelephonyManager)
                phone.getContext().getSystemService(Context.TELEPHONY_SERVICE);
        if (tm == null) {
            Rlog.e(LOG_TAG, "isBusinessOnlyCallComposerEnabledByUser: TelephonyManager is null");
            return false;
        }
        return tm.getCallComposerStatus() == TelephonyManager.CALL_COMPOSER_STATUS_BUSINESS_ONLY
                || tm.getCallComposerStatus() == TelephonyManager.CALL_COMPOSER_STATUS_ON;
    }

    private static boolean areBundlesEqual(Bundle extras, Bundle newExtras) {
        if (extras == null || newExtras == null) {
            return extras == newExtras;
+64 −11
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static com.android.internal.telephony.flags.Flags.dataRatMetricEnabled;
import android.os.Handler;
import android.os.HandlerExecutor;
import android.os.HandlerThread;
import android.telephony.PhysicalChannelConfig;
import android.telephony.PreciseDataConnectionState;
import android.telephony.SubscriptionManager;
import android.telephony.TelephonyCallback;
@@ -50,8 +51,10 @@ public class DataConnectionStateTracker {
    private int mSubId;
    private HashMap<Integer, PreciseDataConnectionState> mLastPreciseDataConnectionState =
            new HashMap<>();
    private PreciseDataConnectionStateListenerImpl mDataConnectionStateListener;
    private TelephonyListenerImpl mTelephonyListener;
    private int mActiveDataSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
    private int mChannelCountEnum = TelephonyStatsLog
            .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_UNSPECIFIED;

    private final SubscriptionManager.OnSubscriptionsChangedListener mSubscriptionsChangedListener =
            new SubscriptionManager.OnSubscriptionsChangedListener() {
@@ -136,15 +139,15 @@ public class DataConnectionStateTracker {
        TelephonyManager telephonyManager =
                mPhone.getContext().getSystemService(TelephonyManager.class);
        if (telephonyManager != null) {
            mDataConnectionStateListener = new PreciseDataConnectionStateListenerImpl(mExecutor);
            mDataConnectionStateListener.register(telephonyManager.createForSubscriptionId(subId));
            mTelephonyListener = new TelephonyListenerImpl(mExecutor);
            mTelephonyListener.register(telephonyManager.createForSubscriptionId(subId));
        }
    }

    private void unregisterTelephonyListener() {
        if (mDataConnectionStateListener != null) {
            mDataConnectionStateListener.unregister();
            mDataConnectionStateListener = null;
        if (mTelephonyListener != null) {
            mTelephonyListener.unregister();
            mTelephonyListener = null;
        }
    }

@@ -167,7 +170,11 @@ public class DataConnectionStateTracker {
        return sDataConnectionStateTracker.valueAt(0).mActiveDataSubId;
    }

    /** Log RAT if the active data subId changes to another subId with a different RAT */
    /**
     * Log RAT if the active data subId changes to another subId with a different RAT.
     *
     * @param subId the current active data subId
     */
    private void logRATChanges(int subId) {
        if (mSubId == subId && mActiveDataSubId != subId) {
            int newDataRat = mPhone.getServiceStateTracker()
@@ -188,13 +195,14 @@ public class DataConnectionStateTracker {
        }
    }

    private class PreciseDataConnectionStateListenerImpl extends TelephonyCallback
    private class TelephonyListenerImpl extends TelephonyCallback
            implements TelephonyCallback.PreciseDataConnectionStateListener,
            TelephonyCallback.ActiveDataSubscriptionIdListener {
            TelephonyCallback.ActiveDataSubscriptionIdListener,
            TelephonyCallback.PhysicalChannelConfigListener {
        private final Executor mExecutor;
        private TelephonyManager mTelephonyManager = null;

        PreciseDataConnectionStateListenerImpl(Executor executor) {
        TelephonyListenerImpl(Executor executor) {
            mExecutor = executor;
        }

@@ -223,8 +231,53 @@ public class DataConnectionStateTracker {
        public void onActiveDataSubscriptionIdChanged(int subId) {
            if (dataRatMetricEnabled()) {
                logRATChanges(subId);
            }
            mActiveDataSubId = subId;
        }

        @Override
        public void onPhysicalChannelConfigChanged(List<PhysicalChannelConfig> configs) {
            logChannelChange(configs);
        }

        /** Log channel number if it changes for active data subscription*/
        private void logChannelChange(List<PhysicalChannelConfig> configs) {
            int connectedChannelCount = configs.size();
            int channelCountEnum = TelephonyStatsLog
                    .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_UNSPECIFIED;
            switch(connectedChannelCount) {
                case 0:
                    channelCountEnum = TelephonyStatsLog
                            .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_ONE;
                    break;
                case 1:
                    channelCountEnum = TelephonyStatsLog
                            .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_ONE;
                    break;
                case 2:
                    channelCountEnum = TelephonyStatsLog
                            .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_TWO;
                    break;
                case 3:
                    channelCountEnum = TelephonyStatsLog
                            .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_THREE;
                    break;
                case 4:
                    channelCountEnum = TelephonyStatsLog
                            .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_FOUR;
                    break;
                // Greater than 4
                default:
                    channelCountEnum = TelephonyStatsLog
                            .CONNECTED_CHANNEL_CHANGED__CONNECTED_CHANNEL_COUNT__CHANNEL_COUNT_FIVE;
            }
            if (mChannelCountEnum != channelCountEnum) {
                if (mSubId != mActiveDataSubId) {
                    TelephonyStatsLog.write(TelephonyStatsLog.CONNECTED_CHANNEL_CHANGED,
                            channelCountEnum);
                }
                mChannelCountEnum = channelCountEnum;
            }
        }
    }
}
+60 −0
Original line number Diff line number Diff line
@@ -21,7 +21,10 @@ import static junit.framework.Assert.assertFalse;
import static junit.framework.Assert.assertNull;
import static junit.framework.Assert.assertTrue;

import com.android.internal.telephony.flags.Flags;

import android.net.Uri;
import android.platform.test.flag.junit.SetFlagsRule;
import android.telephony.PhoneNumberUtils;
import android.text.SpannableStringBuilder;
import android.text.style.TtsSpan;
@@ -32,6 +35,7 @@ import androidx.test.filters.SmallTest;
import org.junit.After;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Rule;
import org.junit.Test;

public class PhoneNumberUtilsTest {
@@ -40,6 +44,8 @@ public class PhoneNumberUtilsTest {

    private int mOldMinMatch;

    @Rule public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();

    @Before
    public void setUp() throws Exception {
        mOldMinMatch = PhoneNumberUtils.getMinMatchForTest();
@@ -613,6 +619,60 @@ public class PhoneNumberUtilsTest {
        assertEquals("+1 650-555-1212", PhoneNumberUtils.formatNumber("+16505551212", "jp"));
    }

    /**
     * Test to ensure that when international calls to Singapore are being placed the country
     * code is present with and without the feature flag enabled.
     */
    @SmallTest
    @Test
    public void testFormatSingaporeInternational() {
        // Disable feature flag.
        mSetFlagsRule.disableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS);

        // International call from a US iso
        assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "US"));

        // Lowercase country iso
        assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "us"));

        // Enable feature flag
        mSetFlagsRule.enableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS);

        // Internal call from a US iso
        assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "US"));

        // Lowercase country iso
        assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "us"));
        mSetFlagsRule.disableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS);
    }

    /**
     * Test to ensure that when local calls from Singaporean numbers are being placed to other
     * Singaporean numbers the country code +65 is not being shown.
     */
    @SmallTest
    @Test
    public void testFormatSingaporeNational() {
        // Disable feature flag.
        mSetFlagsRule.disableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS);

        // Local call from a Singaporean number to a Singaporean number
        assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "SG"));

        // Lowercase country iso.
        assertEquals("+65 6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "sg"));

        // Enable feature flag.
        mSetFlagsRule.enableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS);

        // Local call from a Singaporean number to a Singaporean number.
        assertEquals("6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "SG"));

        // Lowercase country iso.
        assertEquals("6521 8000", PhoneNumberUtils.formatNumber("+6565218000", "sg"));
        mSetFlagsRule.disableFlags(Flags.FLAG_REMOVE_COUNTRY_CODE_FROM_LOCAL_SINGAPORE_CALLS);
    }

    @SmallTest
    @Test
    public void testFormatNumber_LeadingStarAndHash() {
+128 −0
Original line number Diff line number Diff line
@@ -40,6 +40,8 @@ import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.telephony.CarrierConfigManager;
import android.telephony.DisconnectCause;
import android.telephony.PhoneNumberUtils;
import android.telephony.ServiceState;
@@ -57,6 +59,7 @@ import com.android.ims.ImsException;
import com.android.internal.telephony.Call;
import com.android.internal.telephony.Connection;
import com.android.internal.telephony.GsmCdmaCall;
import com.android.internal.telephony.Phone;
import com.android.internal.telephony.PhoneConstants;
import com.android.internal.telephony.TelephonyTest;
import com.android.internal.telephony.imsphone.ImsPhone.ImsDialArgs;
@@ -95,6 +98,8 @@ public class ImsPhoneConnectionTest extends TelephonyTest {
        mForeGroundCall = mock(ImsPhoneCall.class);
        mBackGroundCall = mock(ImsPhoneCall.class);
        mRingGroundCall = mock(ImsPhoneCall.class);
        mTelephonyManager = mock(TelephonyManager.class);
        mCarrierConfigManager = mock(CarrierConfigManager.class);
        replaceInstance(Handler.class, "mLooper", mImsCT, Looper.myLooper());
        replaceInstance(ImsPhoneCallTracker.class, "mForegroundCall", mImsCT, mForeGroundCall);
        replaceInstance(ImsPhoneCallTracker.class, "mBackgroundCall", mImsCT, mBackGroundCall);
@@ -103,6 +108,10 @@ public class ImsPhoneConnectionTest extends TelephonyTest {

        mImsCallProfile.mCallExtras = mBundle;
        doReturn(ImsPhoneCall.State.IDLE).when(mForeGroundCall).getState();

        // By default, turn off the business composer
        setUserEnabledBusinessComposer(false);
        setCarrierConfigBusinessComposer(false);
    }

    @After
@@ -431,6 +440,97 @@ public class ImsPhoneConnectionTest extends TelephonyTest {
                ImsPhoneConnection.toTelecomVerificationStatus(90210));
    }

    /**
     * Assert the helper method
     * {@link ImsPhoneConnection#isBusinessOnlyCallComposerEnabledByUser(Phone)} is Working As
     * Intended.
     */
    @Test
    @SmallTest
    public void testIsBusinessOnlyCallComposerEnabledByUser() {
        mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false);
        assertFalse(mConnectionUT.isBusinessOnlyCallComposerEnabledByUser(mImsPhone));
        setUserEnabledBusinessComposer(true);
        assertTrue(mConnectionUT.isBusinessOnlyCallComposerEnabledByUser(mImsPhone));
        setUserEnabledBusinessComposer(false);
        assertFalse(mConnectionUT.isBusinessOnlyCallComposerEnabledByUser(mImsPhone));
    }

    /**
     * Assert the helper method
     * {@link ImsPhoneConnection#isBusinessComposerEnabledByConfig(Phone)} is Working As
     * Intended.
     */
    @Test
    @SmallTest
    public void testBusinessComposerEnabledByCarrierConfig() {
        mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false);
        assertFalse(mConnectionUT.isBusinessComposerEnabledByConfig(mImsPhone));
        setCarrierConfigBusinessComposer(true);
        assertTrue(mConnectionUT.isBusinessComposerEnabledByConfig(mImsPhone));
        setCarrierConfigBusinessComposer(false);
        assertFalse(mConnectionUT.isBusinessComposerEnabledByConfig(mImsPhone));
    }

    /**
     * Verify that the {@link ImsPhoneConnection#getIsBusinessComposerFeatureEnabled()} only
     * returns true when it is enabled by the CarrierConfigManager and user.
     */
    @Test
    @SmallTest
    public void testIncomingImsCallSetsTheBusinessComposerFeatureStatus() {
        mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false);
        assertFalse(mConnectionUT.getIsBusinessComposerFeatureEnabled());

        setUserEnabledBusinessComposer(true);
        setCarrierConfigBusinessComposer(false);
        mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false);
        assertFalse(mConnectionUT.getIsBusinessComposerFeatureEnabled());

        setUserEnabledBusinessComposer(false);
        setCarrierConfigBusinessComposer(true);
        mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false);
        assertFalse(mConnectionUT.getIsBusinessComposerFeatureEnabled());

        setUserEnabledBusinessComposer(true);
        setCarrierConfigBusinessComposer(true);
        mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false);
        assertTrue(mConnectionUT.getIsBusinessComposerFeatureEnabled());
    }

    /**
     * If the business composer feature is off but ImsCallProfile extras still injected by the lower
     * layer, Telephony should NOT inject the telecom call extras.
     */
    @Test
    @SmallTest
    public void testMaybeInjectBusinessExtrasWithFeatureOff() {
        setUserEnabledBusinessComposer(false);
        setCarrierConfigBusinessComposer(false);
        mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false);
        assertFalse(mConnectionUT.getIsBusinessComposerFeatureEnabled());
        Bundle businessExtras = getBusinessExtras();
        mConnectionUT.maybeInjectBusinessComposerExtras(businessExtras);
        assertFalse(businessExtras.containsKey(android.telecom.Call.EXTRA_IS_BUSINESS_CALL));
        assertFalse(businessExtras.containsKey(android.telecom.Call.EXTRA_ASSERTED_DISPLAY_NAME));
    }

    /**
     * Verify if the business composer feature is on, telephony is injecting the telecom call extras
     */
    @Test
    @SmallTest
    public void testMaybeInjectBusinessExtrasWithFeatureOn() {
        setUserEnabledBusinessComposer(true);
        setCarrierConfigBusinessComposer(true);
        mConnectionUT = new ImsPhoneConnection(mImsPhone, mImsCall, mImsCT, mForeGroundCall, false);
        assertTrue(mConnectionUT.getIsBusinessComposerFeatureEnabled());
        Bundle businessExtras = getBusinessExtras();
        mConnectionUT.maybeInjectBusinessComposerExtras(businessExtras);
        assertTrue(businessExtras.containsKey(android.telecom.Call.EXTRA_IS_BUSINESS_CALL));
        assertTrue(businessExtras.containsKey(android.telecom.Call.EXTRA_ASSERTED_DISPLAY_NAME));
    }

    @Test
    @SmallTest
    public void testSetRedirectingAddress() {
@@ -481,4 +581,32 @@ public class ImsPhoneConnectionTest extends TelephonyTest {
        latch.await(TIMEOUT_MILLIS, TimeUnit.MILLISECONDS);
        assertTrue(receivedCountCallback[0]);
    }

    private void setUserEnabledBusinessComposer(boolean isEnabled) {
        when(mPhone.getContext()).thenReturn(mContext);
        when(mContext.getSystemService(TelephonyManager.class)).thenReturn(mTelephonyManager);
        if (isEnabled) {
            when(mTelephonyManager.getCallComposerStatus()).thenReturn(
                    TelephonyManager.CALL_COMPOSER_STATUS_BUSINESS_ONLY);
        } else {
            when(mTelephonyManager.getCallComposerStatus()).thenReturn(
                    TelephonyManager.CALL_COMPOSER_STATUS_OFF);
        }
    }

    private void setCarrierConfigBusinessComposer(boolean isEnabled) {
        when(mPhone.getContext()).thenReturn(mContext);
        when(mContext.getSystemService(CarrierConfigManager.class)).thenReturn(
                mCarrierConfigManager);
        PersistableBundle b = new PersistableBundle();
        b.putBoolean(CarrierConfigManager.KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL, isEnabled);
        when(mCarrierConfigManager.getConfigForSubId(mPhone.getSubId())).thenReturn(b);
    }

    private Bundle getBusinessExtras() {
        Bundle businessExtras = new Bundle();
        businessExtras.putBoolean(ImsCallProfile.EXTRA_IS_BUSINESS_CALL, true);
        businessExtras.putString(ImsCallProfile.EXTRA_ASSERTED_DISPLAY_NAME, "Google");
        return businessExtras;
    }
}