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

Commit 18b32c39 authored by Hunsuk Choi's avatar Hunsuk Choi
Browse files

Implement resetScan of onRequestEmergencyNetworkScan

Make DomainSelector be able to reset scan history
before requesting next scan if needed.

Bug: 258112541
Test: atest domainselection/DomainSelectionConnectionTest
Change-Id: I0e834fc255dd56312c127148ae15365931f08b23
parent 3b053dc8
Loading
Loading
Loading
Loading
+56 −3
Original line number Diff line number Diff line
@@ -66,6 +66,8 @@ public class DomainSelectionConnection {
    protected static final int EVENT_QUALIFIED_NETWORKS_CHANGED = 2;
    protected static final int EVENT_SERVICE_CONNECTED = 3;
    protected static final int EVENT_SERVICE_BINDING_TIMEOUT = 4;
    protected static final int EVENT_RESET_NETWORK_SCAN_DONE = 5;
    protected static final int EVENT_LAST = EVENT_RESET_NETWORK_SCAN_DONE;

    private static final int DEFAULT_BIND_RETRY_TIMEOUT_MS = 4 * 1000;

@@ -73,6 +75,7 @@ public class DomainSelectionConnection {
    private static final int STATUS_DOMAIN_SELECTED  = 1 << 1;
    private static final int STATUS_WAIT_BINDING     = 1 << 2;
    private static final int STATUS_WAIT_SCAN_RESULT = 1 << 3;
    private static final int STATUS_WAIT_RESET_SCAN_RESULT = 1 << 4;

    /** Callback to receive responses from DomainSelectionConnection. */
    public interface DomainSelectionConnectionCallback {
@@ -85,6 +88,16 @@ public class DomainSelectionConnection {
        void onSelectionTerminated(@DisconnectCauses int cause);
    }

    private static class ScanRequest {
        final int[] mPreferredNetworks;
        final int mScanType;

        ScanRequest(int[] preferredNetworks, int scanType) {
            mPreferredNetworks = preferredNetworks;
            mScanType = scanType;
        }
    }

    /**
     * A wrapper class for {@link ITransportSelectorCallback} interface.
     */
@@ -166,7 +179,8 @@ public class DomainSelectionConnection {
        @Override
        public void onRequestEmergencyNetworkScan(
                @NonNull @RadioAccessNetworkType int[] preferredNetworks,
                @EmergencyScanType int scanType, @NonNull IWwanSelectorResultCallback cb) {
                @EmergencyScanType int scanType, boolean resetScan,
                @NonNull IWwanSelectorResultCallback cb) {
            synchronized (mLock) {
                if (checkState(STATUS_DISPOSED)) {
                    return;
@@ -176,7 +190,7 @@ public class DomainSelectionConnection {
                mHandler.post(() -> {
                    synchronized (mLock) {
                        DomainSelectionConnection.this.onRequestEmergencyNetworkScan(
                                preferredNetworks, scanType);
                                preferredNetworks, scanType, resetScan);
                    }
                });
            }
@@ -261,6 +275,17 @@ public class DomainSelectionConnection {
                        }
                    }
                    break;
                case EVENT_RESET_NETWORK_SCAN_DONE:
                    synchronized (mLock) {
                        clearState(STATUS_WAIT_RESET_SCAN_RESULT);
                        if (checkState(STATUS_DISPOSED)
                                || (mPendingScanRequest == null)) {
                            return;
                        }
                        onRequestEmergencyNetworkScan(mPendingScanRequest.mPreferredNetworks,
                                mPendingScanRequest.mScanType, false);
                    }
                    break;
                default:
                    loge("handleMessage unexpected msg=" + msg.what);
                    break;
@@ -306,6 +331,8 @@ public class DomainSelectionConnection {

    private @NonNull AndroidFuture<Integer> mOnComplete;

    private @Nullable ScanRequest mPendingScanRequest;

    /**
     * Creates an instance.
     *
@@ -435,10 +462,11 @@ public class DomainSelectionConnection {
     *
     * @param preferredNetworks The ordered list of preferred networks to scan.
     * @param scanType Indicates the scan preference, such as full service or limited service.
     * @param resetScan Indicates that the previous scan result shall be reset before scanning.
     */
    public void onRequestEmergencyNetworkScan(
            @NonNull @RadioAccessNetworkType int[] preferredNetworks,
            @EmergencyScanType int scanType) {
            @EmergencyScanType int scanType, boolean resetScan) {
        // Can be overridden if required

        synchronized (mLock) {
@@ -450,6 +478,29 @@ public class DomainSelectionConnection {
                return;
            }

            if (checkState(STATUS_WAIT_RESET_SCAN_RESULT)) {
                if (mPendingScanRequest != null) {
                    /* Consecutive scan requests without cancellation is not an expected use case.
                     * DomainSelector should cancel the previous request or wait for the result
                     * before requesting a new scan.*/
                    logi("onRequestEmergencyNetworkScan consecutive scan requests");
                    return;
                } else {
                    // The reset has not been completed.
                    // case1) Long delay in cancelEmergencyNetworkScan by modem.
                    // case2) A consecutive scan requests with short interval from DomainSelector.
                    logi("onRequestEmergencyNetworkScan reset not completed");
                }
                mPendingScanRequest = new ScanRequest(preferredNetworks, scanType);
                return;
            } else if (resetScan) {
                setState(STATUS_WAIT_RESET_SCAN_RESULT);
                mPendingScanRequest = new ScanRequest(preferredNetworks, scanType);
                mPhone.cancelEmergencyNetworkScan(resetScan,
                        mHandler.obtainMessage(EVENT_RESET_NETWORK_SCAN_DONE));
                return;
            }

            if (!mRegisteredRegistrant) {
                mPhone.registerForEmergencyNetworkScan(mHandler,
                        EVENT_EMERGENCY_NETWORK_SCAN_RESULT, null);
@@ -457,6 +508,7 @@ public class DomainSelectionConnection {
            }
            setState(STATUS_WAIT_SCAN_RESULT);
            mPhone.triggerEmergencyNetworkScan(preferredNetworks, scanType, null);
            mPendingScanRequest = null;
        }
    }

@@ -492,6 +544,7 @@ public class DomainSelectionConnection {
    }

    private void onCancel(boolean resetScan) {
        mPendingScanRequest = null;
        if (checkState(STATUS_WAIT_SCAN_RESULT)) {
            clearState(STATUS_WAIT_SCAN_RESULT);
            mPhone.cancelEmergencyNetworkScan(resetScan, null);
+1 −1
Original line number Diff line number Diff line
@@ -80,7 +80,7 @@ public class NormalCallDomainSelectionConnection extends DomainSelectionConnecti
    /** {@inheritDoc} */
    @Override
    public void onRequestEmergencyNetworkScan(@RadioAccessNetworkType int[] preferredNetworks,
            @EmergencyScanType int scanType) {
            @EmergencyScanType int scanType, boolean resetScan) {
        // Not expected with normal calling.
        // Override to prevent abnormal behavior.
    }
+205 −7
Original line number Diff line number Diff line
@@ -27,6 +27,7 @@ import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.any;
import static org.mockito.Mockito.anyBoolean;
import static org.mockito.Mockito.anyInt;
import static org.mockito.Mockito.doAnswer;
import static org.mockito.Mockito.doReturn;
@@ -36,6 +37,7 @@ import static org.mockito.Mockito.verify;
import android.net.Uri;
import android.os.AsyncResult;
import android.os.Handler;
import android.os.Message;
import android.os.RemoteException;
import android.telecom.PhoneAccount;
import android.telephony.AccessNetworkConstants;
@@ -173,7 +175,8 @@ public class DomainSelectionConnectionTest extends TelephonyTest {
        IWwanSelectorResultCallback resultCallback =
                Mockito.mock(IWwanSelectorResultCallback.class);

        wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType, resultCallback);
        wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType,
                false, resultCallback);
        processAllMessages();

        ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
@@ -198,6 +201,7 @@ public class DomainSelectionConnectionTest extends TelephonyTest {
        processAllMessages();

        verify(resultCallback).onComplete(eq(regResult));
        verify(mPhone, times(0)).cancelEmergencyNetworkScan(anyBoolean(), any());
    }

    @Test
@@ -223,8 +227,8 @@ public class DomainSelectionConnectionTest extends TelephonyTest {

        assertNotNull(wwanCallback);

        wwanCallback.onRequestEmergencyNetworkScan(new int[] { },
                SCAN_TYPE_NO_PREFERENCE, Mockito.mock(IWwanSelectorResultCallback.class));
        wwanCallback.onRequestEmergencyNetworkScan(new int[] { }, SCAN_TYPE_NO_PREFERENCE,
                false, Mockito.mock(IWwanSelectorResultCallback.class));
        processAllMessages();

        verify(mPhone).registerForEmergencyNetworkScan(any(), anyInt(), any());
@@ -236,6 +240,196 @@ public class DomainSelectionConnectionTest extends TelephonyTest {
        verify(mPhone).cancelEmergencyNetworkScan(eq(false), any());
    }

    @Test
    public void testWwanSelectorCallbackOnRequestEmergencyNetworkScanWithResetScan()
            throws Exception {
        mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
                mDomainSelectionController);

        ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();

        assertNotNull(transportCallback);

        DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
                mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
                false, 0, TELECOM_CALL_ID1, null, null, null);

        mDsc.selectDomain(attr);

        IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
        transportCallback.onCreated(domainSelector);

        IWwanSelectorCallback wwanCallback = onWwanSelected(transportCallback);

        assertNotNull(wwanCallback);

        int[] preferredNetworks = new int[] { EUTRAN, UTRAN };
        int scanType = SCAN_TYPE_NO_PREFERENCE;
        IWwanSelectorResultCallback resultCallback =
                Mockito.mock(IWwanSelectorResultCallback.class);

        wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType,
                true, resultCallback);
        processAllMessages();

        ArgumentCaptor<Message> msgCaptor = ArgumentCaptor.forClass(Message.class);

        verify(mPhone).cancelEmergencyNetworkScan(eq(true), msgCaptor.capture());

        verify(mPhone, times(0)).registerForEmergencyNetworkScan(any(), anyInt(), any());
        verify(mPhone, times(0)).triggerEmergencyNetworkScan(any(), anyInt(), any());

        Message msg = msgCaptor.getValue();

        assertNotNull(msg);

        AsyncResult unused = AsyncResult.forMessage(msg);
        msg.sendToTarget();
        processAllMessages();

        ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
        ArgumentCaptor<Integer> eventCaptor = ArgumentCaptor.forClass(Integer.class);

        verify(mPhone).registerForEmergencyNetworkScan(
                handlerCaptor.capture(), eventCaptor.capture(), any());

        int[] expectedPreferredNetworks = new int[] { EUTRAN, UTRAN };

        verify(mPhone).triggerEmergencyNetworkScan(eq(expectedPreferredNetworks),
                eq(scanType), any());

        Handler handler = handlerCaptor.getValue();
        int event = eventCaptor.getValue();

        assertNotNull(handler);

        EmergencyRegResult regResult =
                new EmergencyRegResult(UTRAN, 0, 0, true, false, 0, 0, "", "", "");
        handler.sendMessage(handler.obtainMessage(event, new AsyncResult(null, regResult, null)));
        processAllMessages();

        verify(resultCallback).onComplete(eq(regResult));
    }

    @Test
    public void testWwanSelectorCallbackOnRequestEmergencyNetworkScanWithResetScanDoneAndCancel()
            throws Exception {
        mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
                mDomainSelectionController);

        ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();

        assertNotNull(transportCallback);

        DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
                mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
                false, 0, TELECOM_CALL_ID1, null, null, null);

        mDsc.selectDomain(attr);

        IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
        transportCallback.onCreated(domainSelector);

        IWwanSelectorCallback wwanCallback = onWwanSelected(transportCallback);

        assertNotNull(wwanCallback);

        int[] preferredNetworks = new int[] { EUTRAN, UTRAN };
        int scanType = SCAN_TYPE_NO_PREFERENCE;
        IWwanSelectorResultCallback resultCallback =
                Mockito.mock(IWwanSelectorResultCallback.class);

        wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType,
                true, resultCallback);
        processAllMessages();

        ArgumentCaptor<Message> msgCaptor = ArgumentCaptor.forClass(Message.class);

        verify(mPhone).cancelEmergencyNetworkScan(eq(true), msgCaptor.capture());
        verify(mPhone, times(0)).registerForEmergencyNetworkScan(any(), anyInt(), any());
        verify(mPhone, times(0)).triggerEmergencyNetworkScan(any(), anyInt(), any());

        Message msg = msgCaptor.getValue();

        assertNotNull(msg);

        // Reset completes.
        AsyncResult unused = AsyncResult.forMessage(msg);
        msg.sendToTarget();
        processAllMessages();

        // Verify that scan is requested.
        verify(mPhone).registerForEmergencyNetworkScan(any(), anyInt(), any());
        verify(mPhone).triggerEmergencyNetworkScan(any(), anyInt(), any());

        // Cancele scan after reset completes.
        wwanCallback.onCancel();
        processAllMessages();

        // Verify scan request is canceled.
        verify(mPhone).cancelEmergencyNetworkScan(eq(false), any());
        verify(mPhone, times(2)).cancelEmergencyNetworkScan(anyBoolean(), any());
    }

    @Test
    public void testWwanSelectorCallbackOnRequestEmergencyNetworkScanWithResetScanAndCancel()
            throws Exception {
        mDsc = createConnection(mPhone, SELECTOR_TYPE_CALLING, true,
                mDomainSelectionController);

        ITransportSelectorCallback transportCallback = mDsc.getTransportSelectorCallback();

        assertNotNull(transportCallback);

        DomainSelectionService.SelectionAttributes attr = getSelectionAttributes(
                mPhone.getPhoneId(), mPhone.getSubId(), SELECTOR_TYPE_CALLING, true,
                false, 0, TELECOM_CALL_ID1, null, null, null);

        mDsc.selectDomain(attr);

        IDomainSelector domainSelector = Mockito.mock(IDomainSelector.class);
        transportCallback.onCreated(domainSelector);

        IWwanSelectorCallback wwanCallback = onWwanSelected(transportCallback);

        assertNotNull(wwanCallback);

        int[] preferredNetworks = new int[] { EUTRAN, UTRAN };
        int scanType = SCAN_TYPE_NO_PREFERENCE;
        IWwanSelectorResultCallback resultCallback =
                Mockito.mock(IWwanSelectorResultCallback.class);

        wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType,
                true, resultCallback);
        processAllMessages();

        ArgumentCaptor<Message> msgCaptor = ArgumentCaptor.forClass(Message.class);

        verify(mPhone).cancelEmergencyNetworkScan(eq(true), msgCaptor.capture());
        verify(mPhone, times(0)).registerForEmergencyNetworkScan(any(), anyInt(), any());
        verify(mPhone, times(0)).triggerEmergencyNetworkScan(any(), anyInt(), any());

        Message msg = msgCaptor.getValue();

        assertNotNull(msg);

        // Canceled before reset completes.
        wwanCallback.onCancel();
        processAllMessages();

        // Verify there is no additional cancel.
        verify(mPhone, times(1)).cancelEmergencyNetworkScan(anyBoolean(), any());

        // Reset completes
        AsyncResult unused = AsyncResult.forMessage(msg);
        msg.sendToTarget();
        processAllMessages();

        // Verify there is no scan request after reset completes.
        verify(mPhone, times(0)).registerForEmergencyNetworkScan(any(), anyInt(), any());
        verify(mPhone, times(0)).triggerEmergencyNetworkScan(any(), anyInt(), any());
    }

    @Test
    @SmallTest
    public void testDomainSelectorCancelSelection() throws Exception {
@@ -395,7 +589,8 @@ public class DomainSelectionConnectionTest extends TelephonyTest {
                Mockito.mock(IWwanSelectorResultCallback.class);

        // 1st scan request from remote service
        wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType, resultCallback);
        wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType,
                false, resultCallback);
        processAllMessages();

        ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
@@ -431,7 +626,8 @@ public class DomainSelectionConnectionTest extends TelephonyTest {
        // 2nd scan request
        IWwanSelectorResultCallback resultCallback2 =
                Mockito.mock(IWwanSelectorResultCallback.class);
        wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType, resultCallback2);
        wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType,
                false, resultCallback2);
        processAllMessages();

        // Verify that triggerEmergencyNetworkScan isn't called
@@ -478,7 +674,8 @@ public class DomainSelectionConnectionTest extends TelephonyTest {
                Mockito.mock(IWwanSelectorResultCallback.class);

        // 1st scan request from remote service
        wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType, resultCallback);
        wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType,
                false, resultCallback);
        processAllMessages();

        ArgumentCaptor<Handler> handlerCaptor = ArgumentCaptor.forClass(Handler.class);
@@ -519,7 +716,8 @@ public class DomainSelectionConnectionTest extends TelephonyTest {
        // 2nd scan request
        IWwanSelectorResultCallback resultCallback2 =
                Mockito.mock(IWwanSelectorResultCallback.class);
        wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType, resultCallback2);
        wwanCallback.onRequestEmergencyNetworkScan(preferredNetworks, scanType,
                false, resultCallback2);
        processAllMessages();

        // Verify that triggerEmergencyNetworkScan is called