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

Commit 5adf6825 authored by Tyler Gunn's avatar Tyler Gunn
Browse files

Fix issue where inprogress self-managed call is not seen by car mode ui.

InCallController had an assumption that we should only try to connect
to the car mode UI when we have to first disconnect the non-car mode ui.
For regular calls this assumption is okay.  However, it is possible that
the car mode ui will also handle self-managed calls, which means we need
to start up the car mode ui even though the regular dialer is not running.

Test: Added unit tests to cover this case.
Test: Used Android auto desktop head unit and test telecom app to
generate a selfmanaged call; verified that the fix corrects the issue
and auto sees the call in question when it starts up.
Bug: 137776943
Fixes: 154245428
Merged-In: Iad9c0d8b68557ff0d2d4acdf1ed0eb1ac7ee56df
Change-Id: Ibbf6cf98dfa4fe0a724e1a6ca785184dffaeefb9

Change-Id: Iaa6b1a55ae90e8c6ef94e6930f63f1bd329498d4
parent b4dd260d
Loading
Loading
Loading
Loading
+2 −2
Original line number Diff line number Diff line
@@ -543,9 +543,9 @@ public class InCallController extends CallsManagerListenerBase {
                if (newConnection != mCurrentConnection) {
                    if (mIsConnected) {
                        mCurrentConnection.disconnect();
                    }
                    int result = newConnection.connect(null);
                    mIsConnected = result == CONNECTION_SUCCEEDED;
                    }
                    mCurrentConnection = newConnection;
                }
            }
+123 −5
Original line number Diff line number Diff line
@@ -824,7 +824,107 @@ public class InCallControllerTests extends TelecomTestCase {
        assertTrue(bindTimeout.getNow(false));
    }

    /**
     * Verify that if we go from a dialer which doesn't support self managed calls to a car mode
     * dialer that does support them, we will bind.
     */
    @MediumTest
    @Test
    public void testBindToService_SelfManagedCarModeUI() throws Exception {
        setupMocks(true /* isExternalCall */, true /* isSelfManaged*/);
        setupMockPackageManager(true /* default */, true /* system */, true /* external calls */,
                false /* selfManagedInDefaultDialer */, true /* selfManagedInCarModeDialer */);

        // Bind; we should not bind to anything right now; the dialer does not support self
        // managed calls.
        mInCallController.bindToServices(mMockCall);

        // Bind InCallServices; make sure no binding took place.  InCallController handles not
        // binding initially, but the rebind (see next test case) will always happen.
        verify(mMockContext, never()).bindServiceAsUser(
                any(Intent.class),
                any(ServiceConnection.class),
                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
                        | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS),
                eq(UserHandle.CURRENT));

        // Now switch to car mode.
        // Enable car mode and enter car mode at default priority.
        when(mMockSystemStateHelper.isCarMode()).thenReturn(true);
        mInCallController.handleCarModeChange(UiModeManager.DEFAULT_PRIORITY, CAR_PKG, true);

        ArgumentCaptor<Intent> bindIntentCaptor = ArgumentCaptor.forClass(Intent.class);
        verify(mMockContext, times(1)).bindServiceAsUser(
                bindIntentCaptor.capture(),
                any(ServiceConnection.class),
                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
                        | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS),
                eq(UserHandle.CURRENT));
        // Verify bind car mode ui
        assertEquals(1, bindIntentCaptor.getAllValues().size());
        verifyBinding(bindIntentCaptor, 0, CAR_PKG, CAR_CLASS);
    }

    /**
     * Verify that if we go from a dialer which doesn't support self managed calls to a car mode
     * dialer that does not support them, the calls are not sent to the call mode UI.
     */
    @MediumTest
    @Test
    public void testBindToService_SelfManagedNoCarModeUI() throws Exception {
        setupMocks(true /* isExternalCall */, true /* isSelfManaged*/);
        setupMockPackageManager(true /* default */, true /* system */, true /* external calls */,
                false /* selfManagedInDefaultDialer */, false /* selfManagedInCarModeDialer */);

        // Bind; we should not bind to anything right now; the dialer does not support self
        // managed calls.
        mInCallController.bindToServices(mMockCall);

        // Bind InCallServices; make sure no binding took place.
        verify(mMockContext, never()).bindServiceAsUser(
                any(Intent.class),
                any(ServiceConnection.class),
                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
                        | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS),
                eq(UserHandle.CURRENT));

        // Now switch to car mode.
        // Enable car mode and enter car mode at default priority.
        when(mMockSystemStateHelper.isCarMode()).thenReturn(true);
        mInCallController.handleCarModeChange(UiModeManager.DEFAULT_PRIORITY, CAR_PKG, true);

        // We currently will bind to the car-mode InCallService even if there are no calls available
        // for it.  Its not perfect, but it reflects the fact that the InCallController isn't
        // sophisticated enough to realize until its already bound whether there are in fact calls
        // which will be sent to it.
        ArgumentCaptor<ServiceConnection> serviceConnectionCaptor =
                ArgumentCaptor.forClass(ServiceConnection.class);
        verify(mMockContext, times(1)).bindServiceAsUser(
                any(Intent.class),
                serviceConnectionCaptor.capture(),
                eq(Context.BIND_AUTO_CREATE | Context.BIND_FOREGROUND_SERVICE
                        | Context.BIND_ALLOW_BACKGROUND_ACTIVITY_STARTS),
                eq(UserHandle.CURRENT));

        ServiceConnection serviceConnection = serviceConnectionCaptor.getValue();
        ComponentName defDialerComponentName = new ComponentName(DEF_PKG, DEF_CLASS);
        IBinder mockBinder = mock(IBinder.class);
        IInCallService mockInCallService = mock(IInCallService.class);
        when(mockBinder.queryLocalInterface(anyString())).thenReturn(mockInCallService);

        // Emulate successful connection.
        serviceConnection.onServiceConnected(defDialerComponentName, mockBinder);
        verify(mockInCallService).setInCallAdapter(any(IInCallAdapter.class));

        // We should not have gotten informed about any calls
        verify(mockInCallService, never()).addCall(any(ParcelableCall.class));
    }

    private void setupMocks(boolean isExternalCall) {
        setupMocks(isExternalCall, false /* isSelfManagedCall */);
    }

    private void setupMocks(boolean isExternalCall, boolean isSelfManagedCall) {
        when(mMockCallsManager.getCurrentUserHandle()).thenReturn(mUserHandle);
        when(mMockContext.getPackageManager()).thenReturn(mMockPackageManager);
        when(mMockCallsManager.isInEmergencyCall()).thenReturn(false);
@@ -834,9 +934,11 @@ public class InCallControllerTests extends TelecomTestCase {
        when(mMockContext.bindServiceAsUser(any(Intent.class), any(ServiceConnection.class),
                anyInt(), eq(UserHandle.CURRENT))).thenReturn(true);
        when(mMockCall.isExternalCall()).thenReturn(isExternalCall);
        when(mMockCall.isSelfManaged()).thenReturn(isSelfManagedCall);
    }

    private ResolveInfo getDefResolveInfo(final boolean includeExternalCalls) {
    private ResolveInfo getDefResolveInfo(final boolean includeExternalCalls,
            final boolean includeSelfManagedCalls) {
        return new ResolveInfo() {{
            serviceInfo = new ServiceInfo();
            serviceInfo.packageName = DEF_PKG;
@@ -851,11 +953,15 @@ public class InCallControllerTests extends TelecomTestCase {
                serviceInfo.metaData.putBoolean(
                        TelecomManager.METADATA_INCLUDE_EXTERNAL_CALLS, true);
            }
            if (includeSelfManagedCalls) {
                serviceInfo.metaData.putBoolean(
                        TelecomManager.METADATA_INCLUDE_SELF_MANAGED_CALLS, true);
            }
        }};
    }

    private ResolveInfo getCarModeResolveinfo(final String packageName, final String className,
            final boolean includeExternalCalls) {
            final boolean includeExternalCalls, final boolean includeSelfManagedCalls) {
        return new ResolveInfo() {{
            serviceInfo = new ServiceInfo();
            serviceInfo.packageName = packageName;
@@ -874,6 +980,10 @@ public class InCallControllerTests extends TelecomTestCase {
                serviceInfo.metaData.putBoolean(
                        TelecomManager.METADATA_INCLUDE_EXTERNAL_CALLS, true);
            }
            if (includeSelfManagedCalls) {
                serviceInfo.metaData.putBoolean(
                        TelecomManager.METADATA_INCLUDE_SELF_MANAGED_CALLS, true);
            }
        }};
    }

@@ -901,7 +1011,14 @@ public class InCallControllerTests extends TelecomTestCase {

    private void setupMockPackageManager(final boolean useDefaultDialer,
            final boolean useSystemDialer, final boolean includeExternalCalls) {
        setupMockPackageManager(useDefaultDialer, useSystemDialer, includeExternalCalls,
                false /* self mgd */, false /* self mgd */);
    }

    private void setupMockPackageManager(final boolean useDefaultDialer,
            final boolean useSystemDialer, final boolean includeExternalCalls,
            final boolean includeSelfManagedCallsInDefaultDialer,
            final boolean includeSelfManagedCallsInCarModeDialer) {
        doAnswer(new Answer() {
            @Override
            public Object answer(InvocationOnMock invocation) throws Throwable {
@@ -915,7 +1032,8 @@ public class InCallControllerTests extends TelecomTestCase {
                LinkedList<ResolveInfo> resolveInfo = new LinkedList<ResolveInfo>();
                if (!TextUtils.isEmpty(packageName)) {
                    if (packageName.equals(DEF_PKG) && useDefaultDialer) {
                        resolveInfo.add(getDefResolveInfo(includeExternalCalls));
                        resolveInfo.add(getDefResolveInfo(includeExternalCalls,
                                includeSelfManagedCallsInDefaultDialer));
                    }

                    if (packageName.equals(SYS_PKG) && useSystemDialer) {
@@ -928,12 +1046,12 @@ public class InCallControllerTests extends TelecomTestCase {

                    if (packageName.equals(CAR_PKG)) {
                        resolveInfo.add(getCarModeResolveinfo(CAR_PKG, CAR_CLASS,
                                includeExternalCalls));
                                includeExternalCalls, includeSelfManagedCallsInCarModeDialer));
                    }

                    if (packageName.equals(CAR2_PKG)) {
                        resolveInfo.add(getCarModeResolveinfo(CAR2_PKG, CAR2_CLASS,
                                includeExternalCalls));
                                includeExternalCalls, includeSelfManagedCallsInCarModeDialer));
                    }
                }
                return resolveInfo;