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

Commit 31399e10 authored by pkanwar's avatar pkanwar
Browse files

Provide an API to make USSD calls and read the responses.

Test: will be added in a subsequent CL.
Bug: 30973910
Change-Id: I8551323474c4d708d50a81001272812e7b651abc
parent be1e1a57
Loading
Loading
Loading
Loading
+69 −25
Original line number Diff line number Diff line
@@ -52,6 +52,7 @@ import android.telephony.UssdResponse;
import android.telephony.cdma.CdmaCellLocation;
import android.text.TextUtils;
import android.telephony.Rlog;

import android.util.Log;

import com.android.ims.ImsManager;
@@ -89,7 +90,9 @@ import com.android.internal.telephony.uicc.IsimUiccRecords;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -158,6 +161,7 @@ public class GsmCdmaPhone extends Phone {
    public GsmCdmaCallTracker mCT;
    public ServiceStateTracker mSST;
    private ArrayList <MmiCode> mPendingMMIs = new ArrayList<MmiCode>();
    private final Deque<MmiCode> mMMIQueue = new ArrayDeque<MmiCode>(USSD_MAX_QUEUE);
    private IccPhoneBookInterfaceManager mIccPhoneBookIntManager;

    private int mPrecisePhoneType;
@@ -1134,6 +1138,16 @@ public class GsmCdmaPhone extends Phone {
        }
    }

    private synchronized boolean addToMMIQueue(MmiCode mmi) {
        if (mPendingMMIs.size() >= 1) {
            mMMIQueue.offerLast(mmi);
            return true;
        }
        mPendingMMIs.add(mmi);
        mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
        return false;
    }

    @Override
    protected Connection dialInternal(String dialString, UUSInfo uusInfo, int videoState,
                                      Bundle intentExtras)
@@ -1165,8 +1179,17 @@ public class GsmCdmaPhone extends Phone {
            } else if (mmi.isTemporaryModeCLIR()) {
                return mCT.dial(mmi.mDialingNumber, mmi.getCLIRMode(), uusInfo, intentExtras);
            } else {
                mPendingMMIs.add(mmi);
                mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
                return dialInternal(mmi);
            }
        } else {
            return mCT.dial(newDialString);
        }
    }

    protected Connection dialInternal(MmiCode mmi) {
        if (addToMMIQueue(mmi)) {
            return null;
        }
        try {
            mmi.processCode();
        } catch (CallStateException e) {
@@ -1176,10 +1199,7 @@ public class GsmCdmaPhone extends Phone {
        // FIXME should this return null or something else?
        return null;
    }
        } else {
            return mCT.dial(newDialString);
        }
    }


    @Override
    public boolean handlePinMmi(String dialString) {
@@ -1205,15 +1225,33 @@ public class GsmCdmaPhone extends Phone {
        return false;
    }

    private synchronized boolean isMmiQueueFull() {
        return (mMMIQueue.size() >= USSD_MAX_QUEUE - 1);
    }

    private void sendUssdResponse(String ussdRequest, CharSequence message, int returnCode,
                                   ResultReceiver wrappedCallback) {
        UssdResponse response = new UssdResponse(ussdRequest, message);
        Bundle returnData = new Bundle();
        returnData.putParcelable(TelephonyManager.USSD_RESPONSE, response);
        wrappedCallback.send(returnCode, returnData);
    }

    @Override
    public boolean handleUssdRequest(String ussdRequest, ResultReceiver wrappedCallback) {
        if (!isPhoneTypeGsm() || isMmiQueueFull()) {
            //todo: replace the generic failure with specific error code.
            sendUssdResponse(ussdRequest, null, TelephonyManager.USSD_RETURN_FAILURE,
                    wrappedCallback );
            return true;
        }
        try {
            dialInternal(ussdRequest, null, VideoProfile.STATE_AUDIO_ONLY, null, wrappedCallback);
            return true;
        } catch (Exception e) {
            logd("exception" + e);
            return false;
        }
        return true;
    }

    @Override
@@ -1869,12 +1907,10 @@ public class GsmCdmaPhone extends Phone {

            ResultReceiver receiverCallback = mmi.getUssdCallbackReceiver();
            if (receiverCallback != null) {
                UssdResponse response = new UssdResponse(mmi.getDialString(), mmi.getMessage());
                Bundle returnData = new Bundle();
                returnData.putParcelable(TelephonyManager.USSD_RESPONSE, response);
                int returnCode = (mmi.getState() ==  MmiCode.State.COMPLETE) ?
                    TelephonyManager.USSD_RETURN_SUCCESS : TelephonyManager.USSD_RETURN_FAILURE;
                receiverCallback.send(returnCode, returnData);
                sendUssdResponse(mmi.getDialString(), mmi.getMessage(), returnCode,
                        receiverCallback );
            } else {
                mMmiCompleteRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
            }
@@ -1926,18 +1962,26 @@ public class GsmCdmaPhone extends Phone {
            } else {
                found.onUssdFinished(ussdMessage, isUssdRequest);
            }
        } else { // pending USSD not found
        } else if (!isUssdError && ussdMessage != null) {
            // pending USSD not found
            // The network may initiate its own USSD request

            // ignore everything that isnt a Notify or a Request
            // also, discard if there is no message to present
            if (!isUssdError && ussdMessage != null) {
            GsmMmiCode mmi;
            mmi = GsmMmiCode.newNetworkInitiatedUssd(ussdMessage,
                                                   isUssdRequest,
                                                   GsmCdmaPhone.this,
                                                   mUiccApplication.get());
            onNetworkInitiatedUssd(mmi);
        } else {
            if (mMMIQueue.peek() != null) {
                try {

                    dialInternal(mMMIQueue.remove());
                } catch (Exception e) {
                    logd("Exception:" + e);
                }
            }
        }
    }
+2 −0
Original line number Diff line number Diff line
@@ -93,6 +93,8 @@ public abstract class Phone extends Handler implements PhoneInternalInterface {

    protected final static Object lockForRadioTechnologyChange = new Object();

    protected final int USSD_MAX_QUEUE = 10;

    private BroadcastReceiver mImsIntentReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
+65 −16
Original line number Diff line number Diff line
@@ -104,7 +104,9 @@ import com.android.internal.telephony.uicc.IccRecords;

import java.io.FileDescriptor;
import java.io.PrintWriter;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Deque;
import java.util.List;

/**
@@ -136,6 +138,8 @@ public class ImsPhone extends ImsPhoneBase {
    ImsPhoneCallTracker mCT;
    ImsExternalCallTracker mExternalCallTracker;
    private ArrayList <ImsPhoneMmiCode> mPendingMMIs = new ArrayList<ImsPhoneMmiCode>();
    private final Deque<ImsPhoneMmiCode> mMMIQueue =
            new ArrayDeque<ImsPhoneMmiCode>(USSD_MAX_QUEUE);

    private ServiceState mSS = new ServiceState();

@@ -376,15 +380,34 @@ public class ImsPhone extends ImsPhoneBase {
        return true;
    }

    private synchronized boolean isMmiQueueFull() {
        return (mMMIQueue.size() >= USSD_MAX_QUEUE - 1);
    }

    private void sendUssdResponse(String ussdRequest, CharSequence message, int returnCode,
                                   ResultReceiver wrappedCallback) {
        UssdResponse response = new UssdResponse(ussdRequest, message);
        Bundle returnData = new Bundle();
        returnData.putParcelable(TelephonyManager.USSD_RESPONSE, response);
        wrappedCallback.send(returnCode, returnData);

    }

    @Override
    public boolean handleUssdRequest(String ussdRequest, ResultReceiver wrappedCallback) {
        if (isMmiQueueFull()) {
            //todo: replace the generic failure with specific error code.
            sendUssdResponse(ussdRequest, null, TelephonyManager.USSD_RETURN_FAILURE,
                    wrappedCallback );
            return true;
        }
        try {
            dialInternal(ussdRequest, VideoProfile.STATE_AUDIO_ONLY, null, wrappedCallback);
           return true;
        } catch (Exception e) {
            Rlog.d(LOG_TAG, "exception" + e);
            return false;
        }
        return true;
    }

    private boolean handleCallWaitingIncallSupplementaryService(
@@ -552,6 +575,16 @@ public class ImsPhone extends ImsPhoneBase {
        mDefaultPhone.notifyForVideoCapabilityChanged(isVideoCapable);
    }

    protected synchronized boolean addToMMIQueue(ImsPhoneMmiCode mmi) {
        if (mPendingMMIs.size() >= 1) {
            mMMIQueue.offerLast(mmi);
            return true;
        }
        mPendingMMIs.add(mmi);
        mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
        return false;
    }

    @Override
    public Connection
    dial(String dialString, int videoState) throws CallStateException {
@@ -602,12 +635,22 @@ public class ImsPhone extends ImsPhoneBase {
            // try to initiate dialing with default phone
            throw new CallStateException(CS_FALLBACK);
        } else {
            mPendingMMIs.add(mmi);
            mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
            mmi.processCode();
            return dialInternal(mmi);
        }
    }

    protected Connection dialInternal(ImsPhoneMmiCode mmi) {
        if (addToMMIQueue(mmi)) {
            return null;
        }
        try {
            mmi.processCode();
        } catch (CallStateException e) {
            //do nothing
        }

        // FIXME should this return null or something else?
        return null;
    }

    @Override
@@ -1028,17 +1071,25 @@ public class ImsPhone extends ImsPhoneBase {
            } else {
                found.onUssdFinished(ussdMessage, isUssdRequest);
            }
        } else { // pending USSD not found
        } else if (!isUssdError && ussdMessage != null) {
                // pending USSD not found
                // The network may initiate its own USSD request

                // ignore everything that isnt a Notify or a Request
                // also, discard if there is no message to present
            if (!isUssdError && ussdMessage != null) {
                ImsPhoneMmiCode mmi;
                mmi = ImsPhoneMmiCode.newNetworkInitiatedUssd(ussdMessage,
                        isUssdRequest,
                        this);
                onNetworkInitiatedUssd(mmi);
        } else {
            if (mMMIQueue.peek() != null) {
                try {

                    dialInternal(mMMIQueue.remove());
                } catch (Exception e) {
                    Rlog.d(LOG_TAG,"Exception:" + e);
                }
            }
        }
    }
@@ -1057,12 +1108,10 @@ public class ImsPhone extends ImsPhoneBase {
        if (mPendingMMIs.remove(mmi) || mmi.isUssdRequest()) {
            ResultReceiver receiverCallback = mmi.getUssdCallbackReceiver();
            if (receiverCallback != null) {
                UssdResponse response = new UssdResponse(mmi.getDialString(), mmi.getMessage());
                Bundle returnData = new Bundle();
                returnData.putParcelable(TelephonyManager.USSD_RESPONSE, response);
                int returnCode = (mmi.getState() ==  MmiCode.State.COMPLETE) ?
                        TelephonyManager.USSD_RETURN_SUCCESS : TelephonyManager.USSD_RETURN_FAILURE;
                receiverCallback.send(returnCode, returnData);
                sendUssdResponse(mmi.getDialString(), mmi.getMessage(), returnCode,
                        receiverCallback );
            } else {
                mMmiCompleteRegistrants.notifyRegistrants(
                    new AsyncResult(null, mmi, null));