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

Commit c5411e1a authored by Grace Jia's avatar Grace Jia Committed by Android (Google) Code Review
Browse files

Merge "Block normal outgoing call when there's an ongoing emergency call." into sc-dev

parents 2525a6df 302eff83
Loading
Loading
Loading
Loading
+21 −0
Original line number Diff line number Diff line
@@ -1675,6 +1675,21 @@ public class CallsManager extends Call.ListenerBase
                        }
                    }

                    if (!finalCall.isEmergencyCall() && isInEmergencyCall()) {
                        Log.i(CallsManager.this, "Aborting call since there's an"
                                + " ongoing emergency call");
                        // If the ongoing call is a managed call, we will prevent the outgoing
                        // call from dialing.
                        if (isConference) {
                            notifyCreateConferenceFailed(finalCall.getTargetPhoneAccount(),
                                    finalCall);
                        } else {
                            notifyCreateConnectionFailed(
                                    finalCall.getTargetPhoneAccount(), finalCall);
                        }
                        return CompletableFuture.completedFuture(null);
                    }

                    // If we can not supportany more active calls, our options are to move a call
                    // to hold, disconnect a call, or cancel this call altogether.
                    boolean isRoomForCall = finalCall.isEmergencyCall() ?
@@ -5528,4 +5543,10 @@ public class CallsManager extends Call.ListenerBase
    public void addToPendingCallsToDisconnect(Call call) {
        mPendingCallsToDisconnect.add(call);
    }

    @VisibleForTesting
    public void addConnectionServiceRepositoryCache(ComponentName componentName,
            UserHandle userHandle, ConnectionServiceWrapper service) {
        mConnectionServiceRepository.setService(componentName, userHandle, service);
    }
}
+7 −0
Original line number Diff line number Diff line
@@ -79,6 +79,13 @@ public class ConnectionServiceRepository {
        return service;
    }

    @VisibleForTesting
    public void setService(ComponentName componentName, UserHandle userHandle,
            ConnectionServiceWrapper service) {
        Pair<ComponentName, UserHandle> cacheKey = Pair.create(componentName, userHandle);
        mServiceCache.put(cacheKey, service);
    }

    /**
     * Dumps the state of the {@link ConnectionServiceRepository}.
     *
+2 −1
Original line number Diff line number Diff line
@@ -1362,7 +1362,8 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
     * create a connection has been denied or failed.
     * @param call The call.
     */
    void createConnectionFailed(final Call call) {
    @VisibleForTesting
    public void createConnectionFailed(final Call call) {
        Log.d(this, "createConnectionFailed(%s) via %s.", call, getComponentName());
        BindCallback callback = new BindCallback() {
            @Override
+45 −0
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ import static junit.framework.TestCase.fail;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -36,6 +37,8 @@ import static org.mockito.Mockito.doReturn;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.reset;
import static org.mockito.Mockito.spy;
import static org.mockito.Mockito.timeout;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;
@@ -54,6 +57,7 @@ import android.os.UserHandle;
import android.telecom.CallerInfo;
import android.telecom.Connection;
import android.telecom.DisconnectCause;
import android.telecom.Log;
import android.telecom.PhoneAccount;
import android.telecom.PhoneAccountHandle;
import android.telecom.TelecomManager;
@@ -77,6 +81,7 @@ import com.android.server.telecom.CallsManagerListenerBase;
import com.android.server.telecom.ClockProxy;
import com.android.server.telecom.ConnectionServiceFocusManager;
import com.android.server.telecom.ConnectionServiceFocusManager.ConnectionServiceFocusManagerFactory;
import com.android.server.telecom.ConnectionServiceWrapper;
import com.android.server.telecom.DefaultDialerCache;
import com.android.server.telecom.EmergencyCallHelper;
import com.android.server.telecom.HeadsetMediaButton;
@@ -1110,6 +1115,46 @@ public class CallsManagerTest extends TelecomTestCase {
        assertFalse(mCallsManager.isInEmergencyCall());
    }


    @SmallTest
    @Test
    public void testBlockNonEmergencyCallDuringEmergencyCall() throws Exception {
        // Setup a call which the network identified as an emergency call.
        Call ongoingCall = addSpyCall();
        ongoingCall.setConnectionProperties(Connection.PROPERTY_NETWORK_IDENTIFIED_EMERGENCY_CALL);
        assertTrue(mCallsManager.isInEmergencyCall());

        Call newCall = addSpyCall(CallState.NEW);
        ConnectionServiceWrapper service = mock(ConnectionServiceWrapper.class);
        doReturn(SIM_2_HANDLE.getComponentName()).when(service).getComponentName();

        // Ensure contact info lookup succeeds
        doAnswer(invocation -> {
            Uri handle = invocation.getArgument(0);
            CallerInfo info = new CallerInfo();
            CompletableFuture<Pair<Uri, CallerInfo>> callerInfoFuture = new CompletableFuture<>();
            callerInfoFuture.complete(new Pair<>(handle, info));
            return callerInfoFuture;
        }).when(mCallerInfoLookupHelper).startLookup(any(Uri.class));

        // Ensure we have candidate phone account handle info.
        when(mPhoneAccountRegistrar.getOutgoingPhoneAccountForScheme(any(), any())).thenReturn(
                SIM_1_HANDLE);
        when(mPhoneAccountRegistrar.getCallCapablePhoneAccounts(any(), anyBoolean(),
                any(), anyInt(), anyInt())).thenReturn(
                new ArrayList<>(Arrays.asList(SIM_1_HANDLE, SIM_2_HANDLE)));
        mCallsManager.addConnectionServiceRepositoryCache(SIM_2_HANDLE.getComponentName(),
                SIM_2_HANDLE.getUserHandle(), service);

        CompletableFuture<Call> callFuture = mCallsManager.startOutgoingCall(
                newCall.getHandle(), newCall.getTargetPhoneAccount(), new Bundle(),
                UserHandle.CURRENT, new Intent(), "com.test.stuff");

        verify(service, timeout(TEST_TIMEOUT)).createConnectionFailed(any());
        Call result = callFuture.get(TEST_TIMEOUT, TimeUnit.MILLISECONDS);
        assertNull(result);
    }

    @SmallTest
    @Test
    public void testHasEmergencyCallIncomingCallPermitted() {