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

Commit f4cc3112 authored by Tyler Gunn's avatar Tyler Gunn
Browse files

Fix NPE in TelecomManager#isOutgoingCallAllowed

There is a potential for a NPE if "excludeCall" is null.  Adding null
check and unit tests to verify operation of the isOutgoingCallAllowed API,
as well as basic outgoing self-managed calls (which rely on this API).

Test: Added unit tests.
Change-Id: Ia5e92a7cb418af0d131daa2ca88b7cd4d36ab057
Fixes: 67495237
parent ea932239
Loading
Loading
Loading
Loading
+4 −4
Original line number Diff line number Diff line
@@ -2893,10 +2893,10 @@ public class CallsManager extends Call.ListenerBase
            // Only permit outgoing calls if there is no ongoing emergency calls and all other calls
            // are associated with the current PhoneAccountHandle.
            return !hasEmergencyCall() && (
                    excludeCall.getHandoverSourceCall() != null ||
                            (!hasMaximumSelfManagedCalls(excludeCall, phoneAccountHandle) &&
                            !hasCallsForOtherPhoneAccount(phoneAccountHandle) &&
                            !hasManagedCalls()));
                    (excludeCall != null && excludeCall.getHandoverSourceCall() != null) || (
                            !hasMaximumSelfManagedCalls(excludeCall, phoneAccountHandle)
                                    && !hasCallsForOtherPhoneAccount(phoneAccountHandle)
                                    && !hasManagedCalls()));
        }
    }

+55 −0
Original line number Diff line number Diff line
@@ -920,4 +920,59 @@ public class BasicCallTests extends TelecomSystemTest {
        assert(!call.isVideoCallingSupported());
        assertEquals(VideoProfile.STATE_AUDIO_ONLY, call.getVideoState());
    }

    /**
     * Basic test to ensure that a self-managed ConnectionService can place a call.
     * @throws Exception
     */
    @LargeTest
    public void testSelfManagedOutgoing() throws Exception {
        PhoneAccountHandle phoneAccountHandle = mPhoneAccountSelfManaged.getAccountHandle();
        IdPair ids = startAndMakeActiveOutgoingCall("650-555-1212", phoneAccountHandle,
                mConnectionServiceFixtureA);

        // The InCallService should not know about the call since its self-managed.
        assertNull(mInCallServiceFixtureX.getCall(ids.mCallId));
    }

    /**
     * Basic test to ensure that a self-managed ConnectionService can add an incoming call.
     * @throws Exception
     */
    @LargeTest
    public void testSelfManagedIncoming() throws Exception {
        PhoneAccountHandle phoneAccountHandle = mPhoneAccountSelfManaged.getAccountHandle();
        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212", phoneAccountHandle,
                mConnectionServiceFixtureA);

        // The InCallService should not know about the call since its self-managed.
        assertNull(mInCallServiceFixtureX.getCall(ids.mCallId));
    }

    /**
     * Basic test to ensure that when there are no calls, we permit outgoing calls by a self managed
     * CS.
     * @throws Exception
     */
    @LargeTest
    public void testIsOutgoingCallPermitted() throws Exception {
        assertTrue(mTelecomSystem.getTelecomServiceImpl().getBinder()
                .isOutgoingCallPermitted(mPhoneAccountSelfManaged.getAccountHandle()));
    }

    /**
     * Basic test to ensure that when there are other calls, we do not permit outgoing calls by a
     * self managed CS.
     * @throws Exception
     */
    @LargeTest
    public void testIsOutgoingCallPermittedOngoing() throws Exception {
        // Start a regular call; the self-managed CS can't make a call now.
        IdPair ids = startAndMakeActiveIncomingCall("650-555-1212",
                mPhoneAccountA0.getAccountHandle(), mConnectionServiceFixtureA);
        assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());

        assertFalse(mTelecomSystem.getTelecomServiceImpl().getBinder()
                .isOutgoingCallPermitted(mPhoneAccountSelfManaged.getAccountHandle()));
    }
}
+112 −82
Original line number Diff line number Diff line
@@ -260,6 +260,16 @@ public class TelecomSystemTest extends TelecomTestCase {
                            PhoneAccount.CAPABILITY_CALL_PROVIDER |
                                    PhoneAccount.CAPABILITY_SIM_SUBSCRIPTION)
                    .build();
    final PhoneAccount mPhoneAccountSelfManaged =
            PhoneAccount.builder(
                    new PhoneAccountHandle(
                            mConnectionServiceComponentNameA,
                            "id SM"),
                    "Phone account service A SM")
                    .addSupportedUriScheme("tel")
                    .setCapabilities(
                            PhoneAccount.CAPABILITY_SELF_MANAGED)
                    .build();
    final PhoneAccount mPhoneAccountB0 =
            PhoneAccount.builder(
                    new PhoneAccountHandle(
@@ -468,6 +478,7 @@ public class TelecomSystemTest extends TelecomTestCase {
        mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountA0);
        mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountA1);
        mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountA2);
        mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountSelfManaged);
        mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountB0);
        mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountE0);
        mTelecomSystem.getPhoneAccountRegistrar().registerPhoneAccount(mPhoneAccountE1);
@@ -658,7 +669,8 @@ public class TelecomSystemTest extends TelecomTestCase {
        mCallerInfoAsyncQueryFactoryFixture.mRequests.forEach(
                CallerInfoAsyncQueryFactoryFixture.Request::reply);

        if (!hasInCallAdapter) {
        boolean isSelfManaged = phoneAccountHandle == mPhoneAccountSelfManaged.getAccountHandle();
        if (!hasInCallAdapter && !isSelfManaged) {
            verify(mInCallServiceFixtureX.getTestDouble())
                    .setInCallAdapter(
                            any(IInCallAdapter.class));
@@ -680,6 +692,7 @@ public class TelecomSystemTest extends TelecomTestCase {
        ArgumentCaptor<BroadcastReceiver> newOutgoingCallReceiver =
                ArgumentCaptor.forClass(BroadcastReceiver.class);

        if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
            verify(mComponentContextFixture.getTestDouble().getApplicationContext(),
                    times(mNumOutgoingCallsMade))
                    .sendOrderedBroadcastAsUser(
@@ -692,7 +705,6 @@ public class TelecomSystemTest extends TelecomTestCase {
                            anyInt(),
                            anyString(),
                            nullable(Bundle.class));

            // Pass on the new outgoing call Intent
            // Set a dummy PendingResult so the BroadcastReceiver agrees to accept onReceive()
            newOutgoingCallReceiver.getValue().setPendingResult(
@@ -701,6 +713,7 @@ public class TelecomSystemTest extends TelecomTestCase {
                    newOutgoingCallIntent.getValue().getStringExtra(Intent.EXTRA_PHONE_NUMBER));
            newOutgoingCallReceiver.getValue().onReceive(mComponentContextFixture.getTestDouble(),
                    newOutgoingCallIntent.getValue());
        }

        return mInCallServiceFixtureX.mLatestCallId;
    }
@@ -747,8 +760,13 @@ public class TelecomSystemTest extends TelecomTestCase {
        verify(connectionServiceFixture.getTestDouble(), timeout(TEST_TIMEOUT))
                .createConnectionComplete(anyString(), any());

        if (phoneAccountHandle == mPhoneAccountSelfManaged.getAccountHandle()) {
            assertEquals(startingNumCalls, mInCallServiceFixtureX.mCallById.size());
            assertEquals(startingNumCalls, mInCallServiceFixtureY.mCallById.size());
        } else {
            assertEquals(startingNumCalls + 1, mInCallServiceFixtureX.mCallById.size());
            assertEquals(startingNumCalls + 1, mInCallServiceFixtureY.mCallById.size());
        }

        assertEquals(mInCallServiceFixtureX.mLatestCallId, mInCallServiceFixtureY.mLatestCallId);

@@ -824,15 +842,14 @@ public class TelecomSystemTest extends TelecomTestCase {
        // is added, future interactions as triggered by the ConnectionService, through the various
        // test fixtures, will be synchronous.

        if (!hasInCallAdapter) {
        if (!hasInCallAdapter
                && phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
            verify(mInCallServiceFixtureX.getTestDouble(), timeout(TEST_TIMEOUT))
                    .setInCallAdapter(any(IInCallAdapter.class));
            verify(mInCallServiceFixtureY.getTestDouble(), timeout(TEST_TIMEOUT))
                    .setInCallAdapter(any(IInCallAdapter.class));
        }

            // Give the InCallService time to respond

            assertTrueWithTimeout(new Predicate<Void>() {
                @Override
                public boolean apply(Void v) {
@@ -874,7 +891,9 @@ public class TelecomSystemTest extends TelecomTestCase {
                }
            });

        assertEquals(mInCallServiceFixtureX.mLatestCallId, mInCallServiceFixtureY.mLatestCallId);
            assertEquals(mInCallServiceFixtureX.mLatestCallId,
                    mInCallServiceFixtureY.mLatestCallId);
        }

        return new IdPair(connectionServiceFixture.mLatestConnectionId,
                mInCallServiceFixtureX.mLatestCallId);
@@ -898,17 +917,22 @@ public class TelecomSystemTest extends TelecomTestCase {
                Process.myUserHandle(), videoState);

        connectionServiceFixture.sendSetDialing(ids.mConnectionId);
        assertEquals(Call.STATE_DIALING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
        assertEquals(Call.STATE_DIALING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
        if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
            assertEquals(Call.STATE_DIALING,
                    mInCallServiceFixtureX.getCall(ids.mCallId).getState());
            assertEquals(Call.STATE_DIALING,
                    mInCallServiceFixtureY.getCall(ids.mCallId).getState());
        }

        connectionServiceFixture.sendSetVideoState(ids.mConnectionId);

        when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CONNECT_TIME);
        when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CONNECT_ELAPSED_TIME);
        connectionServiceFixture.sendSetActive(ids.mConnectionId);
        if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
            assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
            assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());

        }
        return ids;
    }

@@ -928,8 +952,11 @@ public class TelecomSystemTest extends TelecomTestCase {
            int videoState) throws Exception {
        IdPair ids = startIncomingPhoneCall(number, phoneAccountHandle, connectionServiceFixture);

        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
        assertEquals(Call.STATE_RINGING, mInCallServiceFixtureY.getCall(ids.mCallId).getState());
        if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
            assertEquals(Call.STATE_RINGING,
                    mInCallServiceFixtureX.getCall(ids.mCallId).getState());
            assertEquals(Call.STATE_RINGING,
                    mInCallServiceFixtureY.getCall(ids.mCallId).getState());

            mInCallServiceFixtureX.mInCallAdapter
                    .answerCall(ids.mCallId, videoState);
@@ -941,13 +968,16 @@ public class TelecomSystemTest extends TelecomTestCase {
                verify(connectionServiceFixture.getTestDouble())
                        .answerVideo(eq(ids.mConnectionId), eq(videoState), any());
            }
        }

        when(mClockProxy.currentTimeMillis()).thenReturn(TEST_CONNECT_TIME);
        when(mClockProxy.elapsedRealtime()).thenReturn(TEST_CONNECT_ELAPSED_TIME);
        connectionServiceFixture.sendSetActive(ids.mConnectionId);

        if (phoneAccountHandle != mPhoneAccountSelfManaged.getAccountHandle()) {
            assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureX.getCall(ids.mCallId).getState());
            assertEquals(Call.STATE_ACTIVE, mInCallServiceFixtureY.getCall(ids.mCallId).getState());

        }
        return ids;
    }