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

Commit d488df87 authored by Hunsuk Choi's avatar Hunsuk Choi Committed by Android (Google) Code Review
Browse files

Merge "Block onWwanSelected until setEmergencyMode completes" into main

parents de6fd3d0 b5e7e19a
Loading
Loading
Loading
Loading
+46 −18
Original line number Diff line number Diff line
@@ -138,14 +138,32 @@ public class DomainSelectionConnection {
                if (mWwanSelectorCallback == null) {
                    mWwanSelectorCallback = new WwanSelectorCallbackAdaptor();
                }
                if (mIsTestMode || !mIsEmergency
                        || (mSelectorType != DomainSelectionService.SELECTOR_TYPE_CALLING)) {
                    initHandler();
                    mHandler.post(() -> {
                        onWwanSelectedAsyncInternal(cb);
                    });
                } else {
                    Thread workerThread = new Thread(new Runnable() {
                        @Override
                        public void run() {
                            onWwanSelectedAsyncInternal(cb);
                        }
                    });
                    workerThread.start();
                }
            }
        }

        private void onWwanSelectedAsyncInternal(
                @NonNull final ITransportSelectorResultCallback cb) {
            synchronized (mLock) {
                if (checkState(STATUS_DISPOSED)) {
                    return;
                }
                        DomainSelectionConnection.this.onWwanSelected();
            }
            DomainSelectionConnection.this.onWwanSelected();
            try {
                cb.onCompleted(mWwanSelectorCallback);
            } catch (RemoteException e) {
@@ -156,8 +174,6 @@ public class DomainSelectionConnection {
                    waitForServiceBinding(null);
                }
            }
                });
            }
        }

        @Override
@@ -333,6 +349,8 @@ public class DomainSelectionConnection {

    private @Nullable ScanRequest mPendingScanRequest;

    private boolean mIsTestMode = false;

    /**
     * Creates an instance.
     *
@@ -760,6 +778,16 @@ public class DomainSelectionConnection {
        return (mStatus & stateBit) == stateBit;
    }

    /**
     * Set whether it is unit test or not.
     *
     * @param testMode Indicates whether it is unit test or not.
     */
    @VisibleForTesting
    public void setTestMode(boolean testMode) {
        mIsTestMode = testMode;
    }

    /**
     * Dumps local log.
     */
+1 −1
Original line number Diff line number Diff line
@@ -109,7 +109,7 @@ public class EmergencyCallDomainSelectionConnection extends DomainSelectionConne
    /** {@inheritDoc} */
    @Override
    public void onWwanSelected() {
        mEmergencyStateTracker.onEmergencyTransportChanged(
        mEmergencyStateTracker.onEmergencyTransportChangedAndWait(
                EmergencyStateTracker.EMERGENCY_TYPE_CALL, MODE_EMERGENCY_WWAN);
    }

+76 −0
Original line number Diff line number Diff line
@@ -35,6 +35,7 @@ import android.os.Looper;
import android.os.Message;
import android.os.PersistableBundle;
import android.os.PowerManager;
import android.os.SystemClock;
import android.os.UserHandle;
import android.preference.PreferenceManager;
import android.provider.Settings;
@@ -93,6 +94,8 @@ public class EmergencyStateTracker {
    private static final long DEFAULT_ECM_EXIT_TIMEOUT_MS = 300000;
    private static final int DEFAULT_EPDN_DISCONNECTION_TIMEOUT_MS = 500;

    private static final int DEFAULT_TRANSPORT_CHANGE_TIMEOUT_MS = 1 * 1000;

    /** The emergency types used when setting the emergency mode on modem. */
    @Retention(RetentionPolicy.SOURCE)
    @IntDef(prefix = "EMERGENCY_TYPE_",
@@ -150,6 +153,8 @@ public class EmergencyStateTracker {
    private CompletableFuture<Integer> mSmsEmergencyModeFuture;
    private boolean mIsTestEmergencyNumberForSms;

    private CompletableFuture<Boolean> mEmergencyTransportChangedFuture;

    private final android.util.ArrayMap<Integer, Boolean> mNoSimEcbmSupported =
            new android.util.ArrayMap<>();
    private final CarrierConfigManager.CarrierConfigChangeListener mCarrierConfigChangeListener =
@@ -297,6 +302,9 @@ public class EmergencyStateTracker {
                    }
                    setEmergencyModeInProgress(false);

                    // Transport changed from WLAN to WWAN or CALLBACK to WWAN
                    maybeNotifyTransportChangeCompleted(emergencyType, false);

                    if (emergencyType == EMERGENCY_TYPE_CALL) {
                        setIsInEmergencyCall(true);
                        completeEmergencyMode(emergencyType);
@@ -600,6 +608,9 @@ public class EmergencyStateTracker {
                clearEmergencyCallInfo();
            }
        }

        // Release any blocked thread immediately
        maybeNotifyTransportChangeCompleted(EMERGENCY_TYPE_CALL, true);
    }

    private void clearEmergencyCallInfo() {
@@ -643,6 +654,8 @@ public class EmergencyStateTracker {
                + emergencyTypeToString(emergencyType));

        if (mEmergencyMode == mode) {
            // Initial transport selection of DomainSelector
            maybeNotifyTransportChangeCompleted(emergencyType, false);
            return;
        }
        mEmergencyMode = mode;
@@ -816,6 +829,69 @@ public class EmergencyStateTracker {
        return mLastEmergencyRegistrationResult;
    }

    private void waitForTransportChangeCompleted(CompletableFuture<Boolean> future) {
        if (future != null) {
            synchronized (future) {
                if ((mEmergencyMode == MODE_EMERGENCY_NONE)
                        || mHandler.getLooper().isCurrentThread()) {
                    // Do not block the Handler's thread
                    return;
                }
                long now = SystemClock.elapsedRealtime();
                long deadline = now + DEFAULT_TRANSPORT_CHANGE_TIMEOUT_MS;
                // Guard with while loop to handle spurious wakeups
                while (!future.isDone() && now < deadline) {
                    try {
                        future.wait(deadline - now);
                    } catch (Exception e) {
                        Rlog.e(TAG, "waitForTransportChangeCompleted wait e=" + e);
                    }
                    now = SystemClock.elapsedRealtime();
                }
            }
        }
    }

    private void maybeNotifyTransportChangeCompleted(@EmergencyType int emergencyType,
            boolean enforced) {
        if (emergencyType != EMERGENCY_TYPE_CALL) {
            // It's not for the emergency call
            return;
        }
        CompletableFuture<Boolean> future = mEmergencyTransportChangedFuture;
        if (future != null) {
            synchronized (future) {
                if (!future.isDone()
                        && ((!isEmergencyModeInProgress() && mEmergencyMode == MODE_EMERGENCY_WWAN)
                                || enforced)) {
                    future.complete(Boolean.TRUE);
                    future.notifyAll();
                }
            }
        }
    }

    /**
     * Handles emergency transport change by setting new emergency mode.
     *
     * @param emergencyType the emergency type to identify an emergency call or SMS
     * @param mode the new emergency mode
     */
    public void onEmergencyTransportChangedAndWait(@EmergencyType int emergencyType,
            @EmergencyConstants.EmergencyMode int mode) {
        // Wait for the completion of setting MODE_EMERGENCY_WWAN only for emergency calls
        if (emergencyType == EMERGENCY_TYPE_CALL && mode == MODE_EMERGENCY_WWAN) {
            CompletableFuture<Boolean> future = new CompletableFuture<>();
            synchronized (future) {
                mEmergencyTransportChangedFuture = future;
                onEmergencyTransportChanged(emergencyType, mode);
                waitForTransportChangeCompleted(future);
            }
            return;
        }
        onEmergencyTransportChanged(emergencyType, mode);
    }

    /**
     * Handles emergency transport change by setting new emergency mode.
     *
+1 −0
Original line number Diff line number Diff line
@@ -777,6 +777,7 @@ public class DomainSelectionConnectionTest extends TelephonyTest {
            boolean isEmergency, DomainSelectionController controller) throws Exception {
        DomainSelectionConnection dsc = new DomainSelectionConnection(phone,
                selectorType, isEmergency, controller);
        dsc.setTestMode(true);
        replaceInstance(DomainSelectionConnection.class, "mLooper",
                dsc, mTestableLooper.getLooper());
        return dsc;
+3 −2
Original line number Diff line number Diff line
@@ -95,6 +95,7 @@ public class EmergencyCallDomainSelectionConnectionTest extends TelephonyTest {
        doReturn(mAnm).when(mPhone).getAccessNetworksManager();
        mEcDsc = new EmergencyCallDomainSelectionConnection(mPhone,
                mDomainSelectionController, mEmergencyStateTracker);
        mEcDsc.setTestMode(true);
        replaceInstance(DomainSelectionConnection.class, "mLooper",
                mEcDsc, mTestableLooper.getLooper());
        mTransportCallback = mEcDsc.getTransportSelectorCallback();
@@ -184,7 +185,7 @@ public class EmergencyCallDomainSelectionConnectionTest extends TelephonyTest {
        IWwanSelectorCallback wwanCallback = onWwanSelected(mTransportCallback);

        assertFalse(future.isDone());
        verify(mEmergencyStateTracker).onEmergencyTransportChanged(
        verify(mEmergencyStateTracker).onEmergencyTransportChangedAndWait(
                eq(EmergencyStateTracker.EMERGENCY_TYPE_CALL), eq(MODE_EMERGENCY_WWAN));

        wwanCallback.onDomainSelected(DOMAIN_CS, false);
@@ -222,7 +223,7 @@ public class EmergencyCallDomainSelectionConnectionTest extends TelephonyTest {
        IWwanSelectorCallback wwanCallback = onWwanSelected(mTransportCallback);

        assertFalse(future.isDone());
        verify(mEmergencyStateTracker).onEmergencyTransportChanged(
        verify(mEmergencyStateTracker).onEmergencyTransportChangedAndWait(
                eq(EmergencyStateTracker.EMERGENCY_TYPE_CALL), eq(MODE_EMERGENCY_WWAN));

        wwanCallback.onDomainSelected(DOMAIN_PS, true);
Loading