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

Commit a141b57d authored by Brad Ebinger's avatar Brad Ebinger
Browse files

Implement isInEmergencySmsMode for emergency SMS

When an SMS is sent, check to see if the destination is to
an emergency number. If so, put telephony in an emergency SMS
mode for a carrier determined amount of time for location queries
from the network will be serviced, independent of user settings.

Bug: 126091115
Test: atest FrameworksTelephonyTests
Change-Id: I4a5f7f4c6a0ad8a9506f6436e08d347bdf242f0d
parent 57d3ed2c
Loading
Loading
Loading
Loading
+6 −0
Original line number Original line Diff line number Diff line
@@ -716,6 +716,12 @@ public class GsmCdmaPhone extends Phone {
        }
        }
    }
    }


    @Override
    public boolean isInEmergencySmsMode() {
        return super.isInEmergencySmsMode()
                || (mImsPhone != null && mImsPhone.isInEmergencySmsMode());
    }

    //CDMA
    //CDMA
    private void sendEmergencyCallbackModeChange(){
    private void sendEmergencyCallbackModeChange(){
        //Send an Intent
        //Send an Intent
+1 −0
Original line number Original line Diff line number Diff line
@@ -125,6 +125,7 @@ public class ImsSmsDispatcher extends SMSDispatcher {
            switch(status) {
            switch(status) {
                case ImsSmsImplBase.SEND_STATUS_OK:
                case ImsSmsImplBase.SEND_STATUS_OK:
                    tracker.onSent(mContext);
                    tracker.onSent(mContext);
                    mPhone.notifySmsSent(tracker.mDestAddress);
                    break;
                    break;
                case ImsSmsImplBase.SEND_STATUS_ERROR:
                case ImsSmsImplBase.SEND_STATUS_ERROR:
                    tracker.onFailed(mContext, reason, 0 /* errorCode */);
                    tracker.onFailed(mContext, reason, 0 /* errorCode */);
+79 −0
Original line number Original line Diff line number Diff line
@@ -36,6 +36,7 @@ import android.os.Message;
import android.os.PersistableBundle;
import android.os.PersistableBundle;
import android.os.Registrant;
import android.os.Registrant;
import android.os.RegistrantList;
import android.os.RegistrantList;
import android.os.SystemClock;
import android.os.SystemProperties;
import android.os.SystemProperties;
import android.os.WorkSource;
import android.os.WorkSource;
import android.preference.PreferenceManager;
import android.preference.PreferenceManager;
@@ -62,6 +63,7 @@ import android.telephony.data.ApnSetting.ApnType;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.emergency.EmergencyNumber;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.telephony.ims.stub.ImsRegistrationImplBase;
import android.text.TextUtils;
import android.text.TextUtils;
import android.util.LocalLog;
import android.util.SparseArray;
import android.util.SparseArray;


import com.android.ims.ImsCall;
import com.android.ims.ImsCall;
@@ -154,6 +156,11 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
    // Key used to read/write data_roaming_is_user_setting pref
    // Key used to read/write data_roaming_is_user_setting pref
    public static final String DATA_ROAMING_IS_USER_SETTING_KEY = "data_roaming_is_user_setting_key";
    public static final String DATA_ROAMING_IS_USER_SETTING_KEY = "data_roaming_is_user_setting_key";


    // Default value when there has been no last emergency SMS time recorded yet.
    private static final int EMERGENCY_SMS_NO_TIME_RECORDED = -1;
    // The max timer value that the platform can be in emergency SMS mode (5 minutes).
    private static final int EMERGENCY_SMS_TIMER_MAX_MS = 300000;

    /* Event Constants */
    /* Event Constants */
    protected static final int EVENT_RADIO_AVAILABLE             = 1;
    protected static final int EVENT_RADIO_AVAILABLE             = 1;
    /** Supplementary Service Notification received. */
    /** Supplementary Service Notification received. */
@@ -285,6 +292,7 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
    // Keep track of whether or not the phone is in Emergency Callback Mode for Phone and
    // Keep track of whether or not the phone is in Emergency Callback Mode for Phone and
    // subclasses
    // subclasses
    protected boolean mIsPhoneInEcmState = false;
    protected boolean mIsPhoneInEcmState = false;
    private volatile long mTimeLastEmergencySmsSentMs = EMERGENCY_SMS_NO_TIME_RECORDED;


    // Variable to cache the video capability. When RAT changes, we lose this info and are unable
    // Variable to cache the video capability. When RAT changes, we lose this info and are unable
    // to recover from the state. We cache it and notify listeners when they register.
    // to recover from the state. We cache it and notify listeners when they register.
@@ -371,6 +379,8 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {


    protected Registrant mPostDialHandler;
    protected Registrant mPostDialHandler;


    protected final LocalLog mLocalLog;

    private Looper mLooper; /* to insure registrants are in correct thread*/
    private Looper mLooper; /* to insure registrants are in correct thread*/


    @UnsupportedAppUsage
    @UnsupportedAppUsage
@@ -509,6 +519,7 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
        mActionAttached = this.getClass().getPackage().getName() + ".action_attached";
        mActionAttached = this.getClass().getPackage().getName() + ".action_attached";
        mAppSmsManager = telephonyComponentFactory.inject(AppSmsManager.class.getName())
        mAppSmsManager = telephonyComponentFactory.inject(AppSmsManager.class.getName())
                .makeAppSmsManager(context);
                .makeAppSmsManager(context);
        mLocalLog = new LocalLog(64);


        if (Build.IS_DEBUGGABLE) {
        if (Build.IS_DEBUGGABLE) {
            mTelephonyTester = new TelephonyTester(this);
            mTelephonyTester = new TelephonyTester(this);
@@ -901,6 +912,62 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
    protected void setIsInEmergencyCall() {
    protected void setIsInEmergencyCall() {
    }
    }


    /**
     * Notify the phone that an SMS has been sent. This will be used determine if the SMS was sent
     * to an emergency address.
     * @param destinationAddress the address that the SMS was sent to.
     */
    public void notifySmsSent(String destinationAddress) {
        TelephonyManager m = (TelephonyManager) getContext().getSystemService(
                Context.TELEPHONY_SERVICE);
        if (m != null && m.isEmergencyNumber(destinationAddress)) {
            mLocalLog.log("Emergency SMS detected, recording time.");
            mTimeLastEmergencySmsSentMs = SystemClock.elapsedRealtime();
        }
    }

    /**
     * Determine if the Phone has recently sent an emergency SMS and is still in the interval of
     * time defined by a carrier that we may need to do perform special actions, for example
     * override user setting for location so the carrier can find the user's location for emergency
     * services.
     *
     * @return true if the device is in emergency SMS mode, false otherwise.
     */
    public boolean isInEmergencySmsMode() {
        long lastSmsTimeMs = mTimeLastEmergencySmsSentMs;
        if (lastSmsTimeMs == EMERGENCY_SMS_NO_TIME_RECORDED) {
            // an emergency SMS hasn't been sent since the last check.
            return false;
        }
        CarrierConfigManager configManager = (CarrierConfigManager)
                getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
        PersistableBundle b = configManager.getConfigForSubId(getSubId());
        if (b == null) {
            // default for KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT is 0 and CarrierConfig isn't
            // available, so return false.
            return false;
        }
        int eSmsTimerMs = b.getInt(CarrierConfigManager.KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT, 0);
        if (eSmsTimerMs == 0) {
            // We do not support this feature for this carrier.
            return false;
        }
        if (eSmsTimerMs > EMERGENCY_SMS_TIMER_MAX_MS) {
            eSmsTimerMs = EMERGENCY_SMS_TIMER_MAX_MS;
        }
        boolean isInEmergencySmsMode = SystemClock.elapsedRealtime()
                <= (lastSmsTimeMs + eSmsTimerMs);
        if (!isInEmergencySmsMode) {
            // Shortcut this next time so we do not have to waste time if another emergency SMS
            // hasn't been sent since the last query.
            mTimeLastEmergencySmsSentMs = EMERGENCY_SMS_NO_TIME_RECORDED;
        } else {
            mLocalLog.log("isInEmergencySmsMode: queried while eSMS mode is active.");
        }
        return isInEmergencySmsMode;
    }

    protected void migrateFrom(Phone from) {
    protected void migrateFrom(Phone from) {
        migrate(mHandoverRegistrants, from.mHandoverRegistrants);
        migrate(mHandoverRegistrants, from.mHandoverRegistrants);
        migrate(mPreciseCallStateRegistrants, from.mPreciseCallStateRegistrants);
        migrate(mPreciseCallStateRegistrants, from.mPreciseCallStateRegistrants);
@@ -3978,6 +4045,7 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
        pw.println(" getVoiceMessageCount()=" + getVoiceMessageCount());
        pw.println(" getVoiceMessageCount()=" + getVoiceMessageCount());
        pw.println(" getActiveApnTypes()=" + getActiveApnTypes());
        pw.println(" getActiveApnTypes()=" + getActiveApnTypes());
        pw.println(" needsOtaServiceProvisioning=" + needsOtaServiceProvisioning());
        pw.println(" needsOtaServiceProvisioning=" + needsOtaServiceProvisioning());
        pw.println(" isInEmergencySmsMode=" + isInEmergencySmsMode());
        pw.flush();
        pw.flush();
        pw.println("++++++++++++++++++++++++++++++++");
        pw.println("++++++++++++++++++++++++++++++++");


@@ -4099,5 +4167,16 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {
            pw.flush();
            pw.flush();
            pw.println("++++++++++++++++++++++++++++++++");
            pw.println("++++++++++++++++++++++++++++++++");
        }
        }

        pw.println("Phone Local Log: ");
        if (mLocalLog != null) {
            try {
                mLocalLog.dump(fd, pw, args);
            } catch (Exception e) {
                e.printStackTrace();
            }
            pw.flush();
            pw.println("++++++++++++++++++++++++++++++++");
        }
    }
    }
}
}
+1 −0
Original line number Original line Diff line number Diff line
@@ -678,6 +678,7 @@ public abstract class SMSDispatcher extends Handler {
                deliveryPendingList.add(tracker);
                deliveryPendingList.add(tracker);
            }
            }
            tracker.onSent(mContext);
            tracker.onSent(mContext);
            mPhone.notifySmsSent(tracker.mDestAddress);
        } else {
        } else {
            if (DBG) Rlog.d(TAG, "SMS send failed");
            if (DBG) Rlog.d(TAG, "SMS send failed");


+27 −0
Original line number Original line Diff line number Diff line
@@ -357,6 +357,33 @@ public class GsmCdmaPhoneTest extends TelephonyTest {
        assertFalse(mPhoneUT.handlePinMmi("1234567890"));
        assertFalse(mPhoneUT.handlePinMmi("1234567890"));
    }
    }


    @Test
    @SmallTest
    public void testEmergencySmsMode() {
        String emergencyNumber = "111";
        String nonEmergencyNumber = "222";
        mContextFixture.getCarrierConfigBundle().putInt(
                CarrierConfigManager.KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT, 200);
        doReturn(true).when(mTelephonyManager).isEmergencyNumber(emergencyNumber);

        mPhoneUT.notifySmsSent(nonEmergencyNumber);
        waitForMs(50);
        assertFalse(mPhoneUT.isInEmergencySmsMode());

        mPhoneUT.notifySmsSent(emergencyNumber);
        waitForMs(50);
        assertTrue(mPhoneUT.isInEmergencySmsMode());
        waitForMs(200);
        assertFalse(mPhoneUT.isInEmergencySmsMode());

        // Feature not supported
        mContextFixture.getCarrierConfigBundle().putInt(
                CarrierConfigManager.KEY_EMERGENCY_SMS_MODE_TIMER_MS_INT, 0);
        mPhoneUT.notifySmsSent(emergencyNumber);
        waitForMs(50);
        assertFalse(mPhoneUT.isInEmergencySmsMode());
    }

    @Test
    @Test
    @SmallTest
    @SmallTest
    public void testSendBurstDtmf() {
    public void testSendBurstDtmf() {