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

Commit f34afddf authored by Grant Menke's avatar Grant Menke Committed by Android (Google) Code Review
Browse files

Merge "Revert "Unbind CS if connection is not created within 15 seconds."" into main

parents 6004901a 1f15e021
Loading
Loading
Loading
Loading
+1 −95
Original line number Diff line number Diff line
@@ -44,7 +44,6 @@ import android.telecom.ConnectionService;
import android.telecom.DisconnectCause;
import android.telecom.GatewayInfo;
import android.telecom.Log;
import android.telecom.Logging.Runnable;
import android.telecom.Logging.Session;
import android.telecom.ParcelableConference;
import android.telecom.ParcelableConnection;
@@ -74,13 +73,10 @@ import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import java.util.Objects;

@@ -94,28 +90,10 @@ import java.util.Objects;
public class ConnectionServiceWrapper extends ServiceBinder implements
        ConnectionServiceFocusManager.ConnectionServiceFocus, CallSourceService {

    /**
     * Anomaly Report UUIDs and corresponding error descriptions specific to CallsManager.
     */
    public static final UUID CREATE_CONNECTION_TIMEOUT_ERROR_UUID =
            UUID.fromString("54b7203d-a79f-4cbd-b639-85cd93a39cbb");
    public static final String CREATE_CONNECTION_TIMEOUT_ERROR_MSG =
            "Timeout expired before Telecom connection was created.";
    public static final UUID CREATE_CONFERENCE_TIMEOUT_ERROR_UUID =
            UUID.fromString("caafe5ea-2472-4c61-b2d8-acb9d47e13dd");
    public static final String CREATE_CONFERENCE_TIMEOUT_ERROR_MSG =
            "Timeout expired before Telecom conference was created.";

    private static final String TELECOM_ABBREVIATION = "cast";
    private static final long SERVICE_BINDING_TIMEOUT = 15000L;
    private CompletableFuture<Pair<Integer, Location>> mQueryLocationFuture = null;
    private @Nullable CancellationSignal mOngoingQueryLocationRequest = null;
    private final ExecutorService mQueryLocationExecutor = Executors.newSingleThreadExecutor();
    private ScheduledExecutorService mScheduledExecutor =
            Executors.newSingleThreadScheduledExecutor();
    // Pre-allocate space for 2 calls; realistically thats all we should ever need (tm)
    private final Map<Call, ScheduledFuture<?>> mScheduledFutureMap = new ConcurrentHashMap<>(2);
    private AnomalyReporterAdapter mAnomalyReporter = new AnomalyReporterAdapterImpl();

    private final class Adapter extends IConnectionServiceAdapter.Stub {

@@ -129,12 +107,6 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
            try {
                synchronized (mLock) {
                    logIncoming("handleCreateConnectionComplete %s", callId);
                    Call call = mCallIdMapper.getCall(callId);
                    if (call != null && mScheduledFutureMap.containsKey(call)) {
                        ScheduledFuture<?> existingTimeout = mScheduledFutureMap.get(call);
                        existingTimeout.cancel(false /* cancelIfRunning */);
                        mScheduledFutureMap.remove(call);
                    }
                    // Check status hints image for cross user access
                    if (connection.getStatusHints() != null) {
                        Icon icon = connection.getStatusHints().getIcon();
@@ -173,12 +145,6 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
            try {
                synchronized (mLock) {
                    logIncoming("handleCreateConferenceComplete %s", callId);
                    Call call = mCallIdMapper.getCall(callId);
                    if (call != null && mScheduledFutureMap.containsKey(call)) {
                        ScheduledFuture<?> existingTimeout = mScheduledFutureMap.get(call);
                        existingTimeout.cancel(false /* cancelIfRunning */);
                        mScheduledFutureMap.remove(call);
                    }
                    // Check status hints image for cross user access
                    if (conference.getStatusHints() != null) {
                        Icon icon = conference.getStatusHints().getIcon();
@@ -1645,29 +1611,6 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
                        .setParticipants(call.getParticipants())
                        .setIsAdhocConferenceCall(call.isAdhocConferenceCall())
                        .build();
                Runnable r = new Runnable("CSW.cC", mLock) {
                    @Override
                    public void loggedRun() {
                        if (!call.isCreateConnectionComplete()) {
                            Log.e(this, new Exception(),
                                    "Conference %s creation timeout",
                                    getComponentName());
                            Log.addEvent(call, LogUtils.Events.CREATE_CONFERENCE_TIMEOUT,
                                    Log.piiHandle(call.getHandle()) + " via:" +
                                            getComponentName().getPackageName());
                            mAnomalyReporter.reportAnomaly(
                                    CREATE_CONFERENCE_TIMEOUT_ERROR_UUID,
                                    CREATE_CONFERENCE_TIMEOUT_ERROR_MSG);
                            response.handleCreateConferenceFailure(
                                    new DisconnectCause(DisconnectCause.ERROR));
                        }
                    }
                };
                // Post cleanup to the executor service and cache the future, so we can cancel it if
                // needed.
                ScheduledFuture<?> future = mScheduledExecutor.schedule(r.getRunnableToCancel(),
                        SERVICE_BINDING_TIMEOUT, TimeUnit.MILLISECONDS);
                mScheduledFutureMap.put(call, future);
                try {
                    mServiceInterface.createConference(
                            call.getConnectionManagerPhoneAccount(),
@@ -1768,29 +1711,6 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
                        .setRttPipeFromInCall(call.getInCallToCsRttPipeForCs())
                        .setRttPipeToInCall(call.getCsToInCallRttPipeForCs())
                        .build();
                Runnable r = new Runnable("CSW.cC", mLock) {
                    @Override
                    public void loggedRun() {
                        if (!call.isCreateConnectionComplete()) {
                            Log.e(this, new Exception(),
                                    "Connection %s creation timeout",
                                    getComponentName());
                            Log.addEvent(call, LogUtils.Events.CREATE_CONNECTION_TIMEOUT,
                                    Log.piiHandle(call.getHandle()) + " via:" +
                                            getComponentName().getPackageName());
                            mAnomalyReporter.reportAnomaly(
                                    CREATE_CONNECTION_TIMEOUT_ERROR_UUID,
                                    CREATE_CONNECTION_TIMEOUT_ERROR_MSG);
                            response.handleCreateConnectionFailure(
                                    new DisconnectCause(DisconnectCause.ERROR));
                        }
                    }
                };
                // Post cleanup to the executor service and cache the future, so we can cancel it if
                // needed.
                ScheduledFuture<?> future = mScheduledExecutor.schedule(r.getRunnableToCancel(),
                        SERVICE_BINDING_TIMEOUT, TimeUnit.MILLISECONDS);
                mScheduledFutureMap.put(call, future);
                try {
                    if (mFlags.cswServiceInterfaceIsNull() && mServiceInterface == null) {
                        mPendingResponses.remove(callId).handleCreateConnectionFailure(
@@ -2262,8 +2182,7 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
        }
    }

    @VisibleForTesting
    public void addCall(Call call) {
    void addCall(Call call) {
        if (mCallIdMapper.getCallId(call) == null) {
            mCallIdMapper.addCall(call);
        }
@@ -2488,8 +2407,6 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
        handleConnectionServiceDeath();
        mCallsManager.handleConnectionServiceDeath(this);
        mServiceInterface = null;
        mScheduledExecutor.shutdown();
        mScheduledExecutor = null;
    }

    @Override
@@ -2609,7 +2526,6 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
            }
        }
        mCallIdMapper.clear();
        mScheduledFutureMap.clear();

        if (mConnSvrFocusListener != null) {
            mConnSvrFocusListener.onConnectionServiceDeath(this);
@@ -2735,14 +2651,4 @@ public class ConnectionServiceWrapper extends ServiceBinder implements
        sb.append("]");
        return sb.toString();
    }

    @VisibleForTesting
    public void setScheduledExecutorService(ScheduledExecutorService service) {
        mScheduledExecutor = service;
    }

    @VisibleForTesting
    public void setAnomalyReporterAdapter(AnomalyReporterAdapter mAnomalyReporterAdapter){
        mAnomalyReporter = mAnomalyReporterAdapter;
    }
}
+0 −2
Original line number Diff line number Diff line
@@ -139,10 +139,8 @@ public class LogUtils {
        public static final String STOP_CALL_WAITING_TONE = "STOP_CALL_WAITING_TONE";
        public static final String START_CONNECTION = "START_CONNECTION";
        public static final String CREATE_CONNECTION_FAILED = "CREATE_CONNECTION_FAILED";
        public static final String CREATE_CONNECTION_TIMEOUT = "CREATE_CONNECTION_TIMEOUT";
        public static final String START_CONFERENCE = "START_CONFERENCE";
        public static final String CREATE_CONFERENCE_FAILED = "CREATE_CONFERENCE_FAILED";
        public static final String CREATE_CONFERENCE_TIMEOUT = "CREATE_CONFERENCE_TIMEOUT";
        public static final String BIND_CS = "BIND_CS";
        public static final String CS_BOUND = "CS_BOUND";
        public static final String CONFERENCE_WITH = "CONF_WITH";
+0 −2
Original line number Diff line number Diff line
@@ -1036,7 +1036,6 @@ public class BasicCallTests extends TelecomSystemTest {
        call.setTargetPhoneAccount(mPhoneAccountA1.getAccountHandle());
        assert(call.isVideoCallingSupportedByPhoneAccount());
        assertEquals(VideoProfile.STATE_BIDIRECTIONAL, call.getVideoState());
        call.setIsCreateConnectionComplete(true);
    }

    /**
@@ -1060,7 +1059,6 @@ public class BasicCallTests extends TelecomSystemTest {
        call.setTargetPhoneAccount(mPhoneAccountA2.getAccountHandle());
        assert(!call.isVideoCallingSupportedByPhoneAccount());
        assertEquals(VideoProfile.STATE_AUDIO_ONLY, call.getVideoState());
        call.setIsCreateConnectionComplete(true);
    }

    /**
+0 −39
Original line number Diff line number Diff line
@@ -59,7 +59,6 @@ import android.media.AudioManager;
import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Looper;
import android.os.OutcomeReceiver;
import android.os.Process;
@@ -88,7 +87,6 @@ import android.widget.Toast;
import androidx.test.filters.MediumTest;
import androidx.test.filters.SmallTest;

import com.android.internal.telecom.IConnectionService;
import com.android.server.telecom.AnomalyReporterAdapter;
import com.android.server.telecom.AsyncRingtonePlayer;
import com.android.server.telecom.Call;
@@ -107,7 +105,6 @@ 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.CreateConnectionResponse;
import com.android.server.telecom.DefaultDialerCache;
import com.android.server.telecom.EmergencyCallDiagnosticLogger;
import com.android.server.telecom.EmergencyCallHelper;
@@ -319,7 +316,6 @@ public class CallsManagerTest extends TelecomTestCase {
    @Mock private IncomingCallFilterGraph mIncomingCallFilterGraph;
    @Mock private Context mMockCreateContextAsUser;
    @Mock private UserManager mMockCurrentUserManager;
    @Mock private IConnectionService mIConnectionService;
    @Mock private TelecomMetricsController mMockTelecomMetricsController;
    private CallsManager mCallsManager;

@@ -420,17 +416,11 @@ public class CallsManagerTest extends TelecomTestCase {
                .thenReturn(mMockCreateContextAsUser);
        when(mMockCreateContextAsUser.getSystemService(UserManager.class))
                .thenReturn(mMockCurrentUserManager);
        when(mIConnectionService.asBinder()).thenReturn(mock(IBinder.class));

        mComponentContextFixture.addConnectionService(
                SIM_1_ACCOUNT.getAccountHandle().getComponentName(), mIConnectionService);
    }

    @Override
    @After
    public void tearDown() throws Exception {
        mComponentContextFixture.removeConnectionService(
                SIM_1_ACCOUNT.getAccountHandle().getComponentName(), mIConnectionService);
        super.tearDown();
    }

@@ -3251,35 +3241,6 @@ public class CallsManagerTest extends TelecomTestCase {
        assertTrue(result.contains("onReceiveResult"));
    }

    @Test
    public void testConnectionServiceCreateConnectionTimeout() throws Exception {
        ConnectionServiceWrapper service = new ConnectionServiceWrapper(
                SIM_1_ACCOUNT.getAccountHandle().getComponentName(), null,
                mPhoneAccountRegistrar, mCallsManager, mContext, mLock, null, mFeatureFlags);
        TestScheduledExecutorService scheduledExecutorService = new TestScheduledExecutorService();
        service.setScheduledExecutorService(scheduledExecutorService);
        Call call = addSpyCall();
        service.addCall(call);
        when(call.isCreateConnectionComplete()).thenReturn(false);
        CreateConnectionResponse response = mock(CreateConnectionResponse.class);

        service.createConnection(call, response);
        waitUntilConditionIsTrueOrTimeout(new Condition() {
            @Override
            public Object expected() {
                return true;
            }

            @Override
            public Object actual() {
                return scheduledExecutorService.isRunnableScheduledAtTime(15000L);
            }
        }, 5000L, "Expected job failed to schedule");
        scheduledExecutorService.advanceTime(15000L);
        verify(response).handleCreateConnectionFailure(
                eq(new DisconnectCause(DisconnectCause.ERROR)));
    }

    @SmallTest
    @Test
    public void testOnFailedOutgoingCallUnholdsCallAfterLocallyDisconnect() {