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

Commit eb1881bf authored by Pankaj Kanwar's avatar Pankaj Kanwar Committed by Android (Google) Code Review
Browse files

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

parents e38ec737 31399e10
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;
@@ -155,6 +158,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;
@@ -1130,6 +1134,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)
@@ -1161,8 +1175,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) {
@@ -1172,10 +1195,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) {
@@ -1201,15 +1221,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
@@ -1865,12 +1903,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));
            }
@@ -1922,18 +1958,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();

@@ -374,15 +378,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(
@@ -550,6 +573,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 {
@@ -600,12 +633,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
@@ -1026,17 +1069,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);
                }
            }
        }
    }
@@ -1055,12 +1106,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));