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

Commit 9bb8309a authored by Hunter Knepshield's avatar Hunter Knepshield Committed by Android (Google) Code Review
Browse files

Merge "Telephony plumbing for SIM call manager voice status"

parents 7ddd6335 1486908c
Loading
Loading
Loading
Loading
+54 −27
Original line number Diff line number Diff line
@@ -267,6 +267,9 @@ public class GsmCdmaPhone extends Phone {

    private int mRilVersion;
    private boolean mBroadcastEmergencyCallStateChanges = false;
    private @ServiceState.RegState int mTelecomVoiceServiceStateOverride =
            ServiceState.STATE_OUT_OF_SERVICE;

    private CarrierKeyDownloadManager mCDM;
    private CarrierInfoManager mCIM;

@@ -614,19 +617,19 @@ public class GsmCdmaPhone extends Phone {
    @Override
    @NonNull
    public ServiceState getServiceState() {
        if (mSST == null || mSST.mSS.getState() != ServiceState.STATE_IN_SERVICE) {
            if (mImsPhone != null) {
                return mergeServiceStates((mSST == null)
                                ? new ServiceState() : mSST.getServiceState(),
                        mImsPhone.getServiceState());
            }
        ServiceState baseSs = mSST != null ? mSST.getServiceState() : new ServiceState();
        ServiceState imsSs = mImsPhone != null ? mImsPhone.getServiceState() : new ServiceState();
        return mergeVoiceServiceStates(baseSs, imsSs, mTelecomVoiceServiceStateOverride);
    }

        if (mSST != null) {
            return mSST.getServiceState();
        } else {
            // avoid potential NPE in EmergencyCallHelper during Phone switch
            return new ServiceState();
    @Override
    public void setVoiceServiceStateOverride(boolean hasService) {
        int newOverride =
                hasService ? ServiceState.STATE_IN_SERVICE : ServiceState.STATE_OUT_OF_SERVICE;
        boolean changed = newOverride != mTelecomVoiceServiceStateOverride;
        mTelecomVoiceServiceStateOverride = newOverride;
        if (changed && mSST != null) {
            mSST.onTelecomVoiceServiceStateOverrideChanged();
        }
    }

@@ -1109,28 +1112,48 @@ public class GsmCdmaPhone extends Phone {
    }

    /**
     * ImsService reports "IN_SERVICE" for its voice registration state even if the device
     * has lost the physical link to the tower. This helper method merges the IMS and modem
     * ServiceState, only overriding the voice registration state when we are registered to IMS. In
     * this case the voice registration state may be "OUT_OF_SERVICE", so override the voice
     * registration state with the data registration state.
     * Amends {@code baseSs} if its voice registration state is {@code OUT_OF_SERVICE}.
     *
     * <p>Even if the device has lost the CS link to the tower, there are two potential additional
     * sources of voice capability not directly saved inside ServiceStateTracker:
     *
     * <ul>
     *   <li>IMS voice registration state ({@code imsSs}) - if this is {@code IN_SERVICE} for voice,
     *       we substite {@code baseSs#getDataRegState} as the final voice service state (ImsService
     *       reports {@code IN_SERVICE} for its voice registration state even if the device has lost
     *       the physical link to the tower)
     *   <li>OTT voice capability provided through telecom ({@code telecomSs}) - if this is {@code
     *       IN_SERVICE}, we directly substitute it as the final voice service state
     * </ul>
     */
    private ServiceState mergeServiceStates(ServiceState baseSs, ServiceState imsSs) {
        // No need to merge states if the baseSs is IN_SERVICE.
    private static ServiceState mergeVoiceServiceStates(
            ServiceState baseSs, ServiceState imsSs, @ServiceState.RegState int telecomSs) {
        if (baseSs.getState() == ServiceState.STATE_IN_SERVICE) {
            // No need to merge states if the baseSs is IN_SERVICE.
            return baseSs;
        }
        // "IN_SERVICE" in this case means IMS is registered.
        if (imsSs.getState() != ServiceState.STATE_IN_SERVICE) {
            return baseSs;
        }

        ServiceState newSs = new ServiceState(baseSs);
        // If any of the following additional sources are IN_SERVICE, we use that since voice calls
        // can be routed through something other than the CS link.
        @ServiceState.RegState int finalVoiceSs = ServiceState.STATE_OUT_OF_SERVICE;
        if (telecomSs == ServiceState.STATE_IN_SERVICE) {
            // If telecom reports there's a PhoneAccount that can provide voice service
            // (CAPABILITY_VOICE_CALLING_AVAILABLE), then we trust that info as it may account for
            // external possibilities like wi-fi calling provided by the SIM call manager app. Note
            // that CAPABILITY_PLACE_EMERGENCY_CALLS is handled separately.
            finalVoiceSs = telecomSs;
        } else if (imsSs.getState() == ServiceState.STATE_IN_SERVICE) {
            // Voice override for IMS case. In this case, voice registration is OUT_OF_SERVICE, but
            // IMS is available, so use data registration state as a basis for determining
            // whether or not the physical link is available.
        newSs.setVoiceRegState(baseSs.getDataRegistrationState());
        newSs.setEmergencyOnly(false); // only get here if voice is IN_SERVICE
            finalVoiceSs = baseSs.getDataRegistrationState();
        }
        if (finalVoiceSs != ServiceState.STATE_IN_SERVICE) {
            // None of the additional sources provide a usable route, and they only use IN/OUT.
            return baseSs;
        }
        ServiceState newSs = new ServiceState(baseSs);
        newSs.setVoiceRegState(finalVoiceSs);
        newSs.setEmergencyOnly(false); // Must be IN_SERVICE if we're here
        return newSs;
    }

@@ -4287,6 +4310,10 @@ public class GsmCdmaPhone extends Phone {
        }
        pw.println(" isCspPlmnEnabled()=" + isCspPlmnEnabled());
        pw.println(" mManualNetworkSelectionPlmn=" + mManualNetworkSelectionPlmn);
        pw.println(
                " mTelecomVoiceServiceStateOverride=" + mTelecomVoiceServiceStateOverride + "("
                        + ServiceState.rilServiceStateToString(mTelecomVoiceServiceStateOverride)
                        + ")");
        pw.flush();
    }

+9 −13
Original line number Diff line number Diff line
@@ -1916,6 +1916,15 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
        return null;
    }

    /**
     * Override to merge into {@link #getServiceState} when telecom has registered a SIM call
     * manager that supports over-the-top SIM-based calling (e.g. carrier-provided wi-fi calling
     * implementation).
     *
     * @param hasService Whether or not the SIM call manager currently provides over-the-top voice
     */
    public void setVoiceServiceStateOverride(boolean hasService) {}

    /**
     * Check whether the radio is off for thermal reason.
     *
@@ -4180,19 +4189,6 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
        return mPhoneId;
    }

    /**
     * Return the service state of mImsPhone if it is STATE_IN_SERVICE
     * otherwise return the current voice service state
     */
    public int getVoicePhoneServiceState() {
        Phone imsPhone = mImsPhone;
        if (imsPhone != null
                && imsPhone.getServiceState().getState() == ServiceState.STATE_IN_SERVICE) {
            return ServiceState.STATE_IN_SERVICE;
        }
        return getServiceState().getState();
    }

    /**
     * Override the service provider name and the operator name for the current ICCID.
     */
+17 −0
Original line number Diff line number Diff line
@@ -285,6 +285,9 @@ public class ServiceStateTracker extends Handler {
    private static final int EVENT_POWER_OFF_RADIO_IMS_DEREG_TIMEOUT   = 62;
    protected static final int EVENT_RESET_LAST_KNOWN_CELL_IDENTITY    = 63;
    private static final int EVENT_REGISTER_DATA_NETWORK_EXISTING_CHANGED = 64;
    // Telecom has un/registered a PhoneAccount that provides OTT voice calling capability, e.g.
    // wi-fi calling.
    protected static final int EVENT_TELECOM_VOICE_SERVICE_STATE_OVERRIDE_CHANGED = 65;

    /**
     * The current service state.
@@ -1735,6 +1738,15 @@ public class ServiceStateTracker extends Handler {
                break;
            }

            case EVENT_TELECOM_VOICE_SERVICE_STATE_OVERRIDE_CHANGED:
                if (DBG) log("EVENT_TELECOM_VOICE_SERVICE_STATE_OVERRIDE_CHANGED");
                // Similar to IMS, OTT voice state will only affect the merged service state if the
                // CS voice service state of GsmCdma phone is not STATE_IN_SERVICE.
                if (mSS.getState() != ServiceState.STATE_IN_SERVICE) {
                    mPhone.notifyServiceStateChanged(mPhone.getServiceState());
                }
                break;

            default:
                log("Unhandled message with number: " + msg.what);
                break;
@@ -5227,6 +5239,11 @@ public class ServiceStateTracker extends Handler {
        }
    }

    /** Called when telecom has reported a voice service state change. */
    public void onTelecomVoiceServiceStateOverrideChanged() {
        sendMessage(obtainMessage(EVENT_TELECOM_VOICE_SERVICE_STATE_OVERRIDE_CHANGED));
    }

    private void dumpCellInfoList(PrintWriter pw) {
        pw.print(" mLastCellInfoList={");
        if(mLastCellInfoList != null) {
+33 −0
Original line number Diff line number Diff line
@@ -1752,4 +1752,37 @@ public class GsmCdmaPhoneTest extends TelephonyTest {

        mPhoneUT.setImsPhone(mImsPhone);
    }

    @Test
    public void testSetVoiceServiceStateOverride() throws Exception {
        // Start with CS voice and IMS both OOS, no override
        ServiceState csServiceState = new ServiceState();
        csServiceState.setStateOutOfService();
        csServiceState.setDataRegState(ServiceState.STATE_IN_SERVICE);
        doReturn(csServiceState).when(mSST).getServiceState();
        ServiceState imsServiceState = new ServiceState();
        imsServiceState.setStateOutOfService();
        doReturn(imsServiceState).when(mImsPhone).getServiceState();
        replaceInstance(Phone.class, "mImsPhone", mPhoneUT, mImsPhone);

        assertEquals(ServiceState.STATE_OUT_OF_SERVICE, mPhoneUT.getServiceState().getState());

        // Now set the telecom override
        mPhoneUT.setVoiceServiceStateOverride(true);
        verify(mSST).onTelecomVoiceServiceStateOverrideChanged();
        assertEquals(ServiceState.STATE_IN_SERVICE, mPhoneUT.getServiceState().getState());

        // IMS and telecom voice are treated as equivalent for merging purposes
        imsServiceState.setVoiceRegState(ServiceState.STATE_IN_SERVICE);
        assertEquals(ServiceState.STATE_IN_SERVICE, mPhoneUT.getServiceState().getState());

        // Clearing the telecom override still lets IMS override separately
        mPhoneUT.setVoiceServiceStateOverride(false);
        verify(mSST, times(2)).onTelecomVoiceServiceStateOverrideChanged();
        assertEquals(ServiceState.STATE_IN_SERVICE, mPhoneUT.getServiceState().getState());

        // And now removing the IMS IN_SERVICE results in the base OOS showing through
        imsServiceState.setStateOutOfService();
        assertEquals(ServiceState.STATE_OUT_OF_SERVICE, mPhoneUT.getServiceState().getState());
    }
}