CatService.java revision cbaa45bbf2cab852b6c9c3a887e9f803d4e857ea
10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/*
20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2007 The Android Open Source Project
30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License");
50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License.
60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at
70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *      http://www.apache.org/licenses/LICENSE-2.0
90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software
110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS,
120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and
140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License.
150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepackage com.android.internal.telephony.cat;
180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Context;
200825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Intent;
210825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.pm.PackageManager;
220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.pm.ResolveInfo;
230825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.AsyncResult;
240825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Handler;
250825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.HandlerThread;
260825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Message;
270825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.SystemProperties;
280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
290825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.CommandsInterface;
30d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccFileHandler;
31d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccRecords;
32d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccUtils;
33d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.UiccCard;
34d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.UiccCardApplication;
350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
370825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.ByteArrayOutputStream;
380825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.List;
390825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Locale;
400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
410825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleclass RilMessage {
420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    int mId;
430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    Object mData;
440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    ResultCode mResCode;
450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    RilMessage(int msgId, String rawData) {
470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mId = msgId;
480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mData = rawData;
490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    RilMessage(RilMessage other) {
520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        this.mId = other.mId;
530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        this.mData = other.mData;
540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        this.mResCode = other.mResCode;
550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/**
590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Class that implements SIM Toolkit Telephony Service. Interacts with the RIL
600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * and application.
610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * {@hide}
630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
640825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic class CatService extends Handler implements AppInterface {
65cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    private static final boolean DBG = false;
660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Class members
680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static IccRecords mIccRecords;
69e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private static UiccCardApplication mUiccApplication;
700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Service members.
720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Protects singleton instance lazy initialization.
730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final Object sInstanceLock = new Object();
740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static CatService sInstance;
750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private CommandsInterface mCmdIf;
760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private Context mContext;
770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private CatCmdMessage mCurrntCmd = null;
780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private CatCmdMessage mMenuCmd = null;
790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private RilMessageDecoder mMsgDecoder = null;
810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean mStkAppInstalled = false;
820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Service constants.
840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int MSG_ID_SESSION_END              = 1;
850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int MSG_ID_PROACTIVE_COMMAND        = 2;
860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int MSG_ID_EVENT_NOTIFY             = 3;
870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int MSG_ID_CALL_SETUP               = 4;
880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int MSG_ID_REFRESH                  = 5;
890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int MSG_ID_RESPONSE                 = 6;
900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int MSG_ID_SIM_READY                = 7;
910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int MSG_ID_RIL_MSG_DECODED          = 10;
930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Events to signal SIM presence or absent in the device.
950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int MSG_ID_ICC_RECORDS_LOADED       = 20;
960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int DEV_ID_KEYPAD      = 0x01;
980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int DEV_ID_UICC        = 0x81;
990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int DEV_ID_TERMINAL    = 0x82;
1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final String STK_DEFAULT = "Defualt Message";
1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /* Intentionally private for singleton */
103e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private CatService(CommandsInterface ci, UiccCardApplication ca, IccRecords ir,
104e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            Context context, IccFileHandler fh, UiccCard ic) {
105e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (ci == null || ca == null || ir == null || context == null || fh == null
1060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                || ic == null) {
1070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new NullPointerException(
1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    "Service: Input parameters must not be null");
1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCmdIf = ci;
1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mContext = context;
1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Get the RilMessagesDecoder for decoding the messages.
1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mMsgDecoder = RilMessageDecoder.getInstance(this, fh);
1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Register ril events handling.
1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCmdIf.setOnCatSessionEnd(this, MSG_ID_SESSION_END, null);
1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCmdIf.setOnCatProactiveCmd(this, MSG_ID_PROACTIVE_COMMAND, null);
1190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCmdIf.setOnCatEvent(this, MSG_ID_EVENT_NOTIFY, null);
1200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCmdIf.setOnCatCallSetUp(this, MSG_ID_CALL_SETUP, null);
1210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        //mCmdIf.setOnSimRefresh(this, MSG_ID_REFRESH, null);
1220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mIccRecords = ir;
124e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mUiccApplication = ca;
1250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Register for SIM ready event.
127e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mUiccApplication.registerForReady(this, MSG_ID_SIM_READY, null);
1280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mIccRecords.registerForRecordsLoaded(this, MSG_ID_ICC_RECORDS_LOADED, null);
1290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Check if STK application is availalbe
1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mStkAppInstalled = isStkAppInstalled();
1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CatLog.d(this, "Running CAT service. STK app installed:" + mStkAppInstalled);
1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void dispose() {
1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mIccRecords.unregisterForRecordsLoaded(this);
1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCmdIf.unSetOnCatSessionEnd(this);
1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCmdIf.unSetOnCatProactiveCmd(this);
1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCmdIf.unSetOnCatEvent(this);
1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCmdIf.unSetOnCatCallSetUp(this);
1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        this.removeCallbacksAndMessages(null);
1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
146cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    protected void finalize() {
1480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CatLog.d(this, "Service finalized");
1490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void handleRilMsg(RilMessage rilMsg) {
1520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (rilMsg == null) {
1530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return;
1540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // dispatch messages
1570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CommandParams cmdParams = null;
1580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        switch (rilMsg.mId) {
1590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_EVENT_NOTIFY:
1600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (rilMsg.mResCode == ResultCode.OK) {
1610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                cmdParams = (CommandParams) rilMsg.mData;
1620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (cmdParams != null) {
1630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    handleCommand(cmdParams, false);
1640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
1650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
1670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_PROACTIVE_COMMAND:
1680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            try {
1690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                cmdParams = (CommandParams) rilMsg.mData;
1700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } catch (ClassCastException e) {
1710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // for error handling : cast exception
1720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                CatLog.d(this, "Fail to parse proactive command");
1731e5f46c0477703b0eef40278cfa101d20b53091aJohn Wang                // Don't send Terminal Resp if command detail is not available
1749fdeecb4aa06552efcc535f21718cae45cc604e2Wink Saville                if (mCurrntCmd != null) {
1751e5f46c0477703b0eef40278cfa101d20b53091aJohn Wang                    sendTerminalResponse(mCurrntCmd.mCmdDet, ResultCode.CMD_DATA_NOT_UNDERSTOOD,
1760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                     false, 0x00, null);
1771e5f46c0477703b0eef40278cfa101d20b53091aJohn Wang                }
1780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
1790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (cmdParams != null) {
1810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (rilMsg.mResCode == ResultCode.OK) {
1820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    handleCommand(cmdParams, true);
1830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else {
1840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // for proactive commands that couldn't be decoded
1850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // successfully respond with the code generated by the
1860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // message decoder.
1870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    sendTerminalResponse(cmdParams.cmdDet, rilMsg.mResCode,
1880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            false, 0, null);
1890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
1900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
1920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_REFRESH:
1930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            cmdParams = (CommandParams) rilMsg.mData;
1940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (cmdParams != null) {
1950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                handleCommand(cmdParams, false);
1960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
1970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
1980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_SESSION_END:
1990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            handleSessionEnd();
2000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
2010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_CALL_SETUP:
2020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // prior event notify command supplied all the information
2030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // needed for set up call processing.
2040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
2050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
2060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
2070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
2090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Handles RIL_UNSOL_STK_EVENT_NOTIFY or RIL_UNSOL_STK_PROACTIVE_COMMAND command
2100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * from RIL.
2110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Sends valid proactive command data to the application using intents.
2120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE will be send back if the command is
2130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * from RIL_UNSOL_STK_PROACTIVE_COMMAND.
2140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
2150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void handleCommand(CommandParams cmdParams, boolean isProactiveCmd) {
2160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CatLog.d(this, cmdParams.getCommandType().name());
2170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
2180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CharSequence message;
2190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CatCmdMessage cmdMsg = new CatCmdMessage(cmdParams);
2200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        switch (cmdParams.getCommandType()) {
2210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case SET_UP_MENU:
2220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (removeMenu(cmdMsg.getMenu())) {
2230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    mMenuCmd = null;
2240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else {
2250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    mMenuCmd = cmdMsg;
2260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
2270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null);
2280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
2290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case DISPLAY_TEXT:
2300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // when application is not required to respond, send an immediate response.
2310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (!cmdMsg.geTextMessage().responseNeeded) {
2320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null);
2330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
2340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
2350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case REFRESH:
2360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // ME side only handles refresh commands which meant to remove IDLE
2370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // MODE TEXT.
2380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                cmdParams.cmdDet.typeOfCommand = CommandType.SET_UP_IDLE_MODE_TEXT.value();
2390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
2400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case SET_UP_IDLE_MODE_TEXT:
2410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null);
2420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
2430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case PROVIDE_LOCAL_INFORMATION:
2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ResponseData resp;
2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                switch (cmdParams.cmdDet.commandQualifier) {
2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    case CommandParamsFactory.DTTZ_SETTING:
2470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        resp = new DTTZResponseData(null);
2480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, resp);
2490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        break;
2500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    case CommandParamsFactory.LANGUAGE_SETTING:
2510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        resp = new LanguageResponseData(Locale.getDefault().getLanguage());
2520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, resp);
2530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        break;
2540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    default:
2550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null);
2560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
2570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // No need to start STK app here.
2580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return;
2590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case LAUNCH_BROWSER:
2600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if ((((LaunchBrowserParams) cmdParams).confirmMsg.text != null)
2610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        && (((LaunchBrowserParams) cmdParams).confirmMsg.text.equals(STK_DEFAULT))) {
2620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    message = mContext.getText(com.android.internal.R.string.launchBrowserDefault);
2630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    ((LaunchBrowserParams) cmdParams).confirmMsg.text = message.toString();
2640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
2650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
2660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case SELECT_ITEM:
2670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case GET_INPUT:
2680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case GET_INKEY:
2690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
2700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case SEND_DTMF:
2710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case SEND_SMS:
2720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case SEND_SS:
2730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case SEND_USSD:
2740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if ((((DisplayTextParams)cmdParams).textMsg.text != null)
2750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        && (((DisplayTextParams)cmdParams).textMsg.text.equals(STK_DEFAULT))) {
2760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    message = mContext.getText(com.android.internal.R.string.sending);
2770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    ((DisplayTextParams)cmdParams).textMsg.text = message.toString();
2780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
2790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
2800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case PLAY_TONE:
2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
2820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case SET_UP_CALL:
2830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if ((((CallSetupParams) cmdParams).confirmMsg.text != null)
2840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        && (((CallSetupParams) cmdParams).confirmMsg.text.equals(STK_DEFAULT))) {
2850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    message = mContext.getText(com.android.internal.R.string.SetupCallDefault);
2860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    ((CallSetupParams) cmdParams).confirmMsg.text = message.toString();
2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
2880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
2890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case OPEN_CHANNEL:
2900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case CLOSE_CHANNEL:
2910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case RECEIVE_DATA:
2920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case SEND_DATA:
2930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                BIPClientParams cmd = (BIPClientParams) cmdParams;
2940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (cmd.bHasAlphaId && (cmd.textMsg.text == null)) {
2950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    CatLog.d(this, "cmd " + cmdParams.getCommandType() + " with null alpha id");
2960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // If alpha length is zero, we just respond with OK.
2970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (isProactiveCmd) {
2980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null);
2990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
3000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    return;
3010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
3020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // Respond with permanent failure to avoid retry if STK app is not present.
3030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (!mStkAppInstalled) {
3040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    CatLog.d(this, "No STK application found.");
3050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (isProactiveCmd) {
3060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        sendTerminalResponse(cmdParams.cmdDet,
3070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                             ResultCode.BEYOND_TERMINAL_CAPABILITY,
3080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                             false, 0, null);
3090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        return;
3100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
3110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
3120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                /*
3130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                 * CLOSE_CHANNEL, RECEIVE_DATA and SEND_DATA can be delivered by
3140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                 * either PROACTIVE_COMMAND or EVENT_NOTIFY.
3150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                 * If PROACTIVE_COMMAND is used for those commands, send terminal
3160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                 * response here.
3170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                 */
3180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (isProactiveCmd &&
3190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    ((cmdParams.getCommandType() == CommandType.CLOSE_CHANNEL) ||
3200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                     (cmdParams.getCommandType() == CommandType.RECEIVE_DATA) ||
3210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                     (cmdParams.getCommandType() == CommandType.SEND_DATA))) {
3220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    sendTerminalResponse(cmdParams.cmdDet, ResultCode.OK, false, 0, null);
3230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
3240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
3250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            default:
3260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                CatLog.d(this, "Unsupported command");
3270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return;
3280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCurrntCmd = cmdMsg;
3300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Intent intent = new Intent(AppInterface.CAT_CMD_ACTION);
3310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        intent.putExtra("STK CMD", cmdMsg);
3320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mContext.sendBroadcast(intent);
3330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
3360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Handles RIL_UNSOL_STK_SESSION_END unsolicited command from RIL.
3370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
3380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
3390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void handleSessionEnd() {
3400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CatLog.d(this, "SESSION END");
3410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCurrntCmd = mMenuCmd;
3430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Intent intent = new Intent(AppInterface.CAT_SESSION_END_ACTION);
3440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mContext.sendBroadcast(intent);
3450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
3460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void sendTerminalResponse(CommandDetails cmdDet,
3480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            ResultCode resultCode, boolean includeAdditionalInfo,
3490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int additionalInfo, ResponseData resp) {
3500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (cmdDet == null) {
3520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return;
3530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ByteArrayOutputStream buf = new ByteArrayOutputStream();
3550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Input cmdInput = null;
3570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (mCurrntCmd != null) {
3580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            cmdInput = mCurrntCmd.geInput();
3590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // command details
3620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int tag = ComprehensionTlvTag.COMMAND_DETAILS.value();
3630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (cmdDet.compRequired) {
3640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            tag |= 0x80;
3650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(tag);
3670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(0x03); // length
3680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(cmdDet.commandNumber);
3690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(cmdDet.typeOfCommand);
3700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(cmdDet.commandQualifier);
3710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // device identities
3730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // According to TS102.223/TS31.111 section 6.8 Structure of
3740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // TERMINAL RESPONSE, "For all SIMPLE-TLV objects with Min=N,
3750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // the ME should set the CR(comprehension required) flag to
3760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // comprehension not required.(CR=0)"
3770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Since DEVICE_IDENTITIES and DURATION TLVs have Min=N,
3780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // the CR flag is not set.
3790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        tag = ComprehensionTlvTag.DEVICE_IDENTITIES.value();
3800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(tag);
3810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(0x02); // length
3820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(DEV_ID_TERMINAL); // source device id
3830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(DEV_ID_UICC); // destination device id
3840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // result
3860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        tag = 0x80 | ComprehensionTlvTag.RESULT.value();
3870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(tag);
3880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int length = includeAdditionalInfo ? 2 : 1;
3890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(length);
3900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(resultCode.value());
3910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // additional info
3930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (includeAdditionalInfo) {
3940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            buf.write(additionalInfo);
3950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
3960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
3970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Fill optional data for each corresponding command
3980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (resp != null) {
3990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            resp.format(buf);
4000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
4010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            encodeOptionalTags(cmdDet, resultCode, cmdInput, buf);
4020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        byte[] rawData = buf.toByteArray();
4050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String hexString = IccUtils.bytesToHexString(rawData);
406cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        if (DBG) {
4070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            CatLog.d(this, "TERMINAL RESPONSE: " + hexString);
4080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCmdIf.sendTerminalResponse(hexString, null);
4110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void encodeOptionalTags(CommandDetails cmdDet,
4140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            ResultCode resultCode, Input cmdInput, ByteArrayOutputStream buf) {
4150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CommandType cmdType = AppInterface.CommandType.fromInt(cmdDet.typeOfCommand);
4160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (cmdType != null) {
4170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            switch (cmdType) {
4180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                case GET_INKEY:
4190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // ETSI TS 102 384,27.22.4.2.8.4.2.
4200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // If it is a response for GET_INKEY command and the response timeout
4210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // occured, then add DURATION TLV for variable timeout case.
4220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if ((resultCode.value() == ResultCode.NO_RESPONSE_FROM_USER.value()) &&
4230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        (cmdInput != null) && (cmdInput.duration != null)) {
4240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        getInKeyResponse(buf, cmdInput);
4250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
4260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    break;
4270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                case PROVIDE_LOCAL_INFORMATION:
4280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if ((cmdDet.commandQualifier == CommandParamsFactory.LANGUAGE_SETTING) &&
4290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        (resultCode.value() == ResultCode.OK.value())) {
4300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        getPliResponse(buf);
4310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
4320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    break;
4330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                default:
4340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    CatLog.d(this, "encodeOptionalTags() Unsupported Cmd details=" + cmdDet);
4350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    break;
4360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
4370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } else {
4380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            CatLog.d(this, "encodeOptionalTags() bad Cmd details=" + cmdDet);
4390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void getInKeyResponse(ByteArrayOutputStream buf, Input cmdInput) {
4430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int tag = ComprehensionTlvTag.DURATION.value();
4440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(tag);
4460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(0x02); // length
4470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(cmdInput.duration.timeUnit.SECOND.value()); // Time (Unit,Seconds)
4480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(cmdInput.duration.timeInterval); // Time Duration
4490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void getPliResponse(ByteArrayOutputStream buf) {
4520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Locale Language Setting
4540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String lang = SystemProperties.get("persist.sys.language");
4550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (lang != null) {
4570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // tag
4580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            int tag = ComprehensionTlvTag.LANGUAGE.value();
4590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            buf.write(tag);
4600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            ResponseData.writeLength(buf, lang.length());
4610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            buf.write(lang.getBytes(), 0, lang.length());
4620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
4640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void sendMenuSelection(int menuId, boolean helpRequired) {
4660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ByteArrayOutputStream buf = new ByteArrayOutputStream();
4680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // tag
4700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int tag = BerTlv.BER_MENU_SELECTION_TAG;
4710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(tag);
4720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // length
4740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(0x00); // place holder
4750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // device identities
4770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        tag = 0x80 | ComprehensionTlvTag.DEVICE_IDENTITIES.value();
4780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(tag);
4790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(0x02); // length
4800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(DEV_ID_KEYPAD); // source device id
4810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(DEV_ID_UICC); // destination device id
4820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // item identifier
4840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        tag = 0x80 | ComprehensionTlvTag.ITEM_ID.value();
4850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(tag);
4860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(0x01); // length
4870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        buf.write(menuId); // menu identifier chosen
4880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // help request
4900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (helpRequired) {
4910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            tag = ComprehensionTlvTag.HELP_REQUEST.value();
4920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            buf.write(tag);
4930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            buf.write(0x00); // length
4940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
4950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        byte[] rawData = buf.toByteArray();
4970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
4980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // write real length
4990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int len = rawData.length - 2; // minus (tag + length)
5000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        rawData[1] = (byte) len;
5010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        String hexString = IccUtils.bytesToHexString(rawData);
5030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCmdIf.sendEnvelope(hexString, null);
5050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
5080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Used for instantiating/updating the Service from the GsmPhone or CdmaPhone constructor.
5090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
5100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param ci CommandsInterface object
5110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param context phone app context
5120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param ic Icc card
5130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return The only Service object in the system
5140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
515e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public static CatService getInstance(CommandsInterface ci,
516e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            Context context, UiccCard ic) {
517e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        UiccCardApplication ca = null;
518e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        IccFileHandler fh = null;
519e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        IccRecords ir = null;
520e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (ic != null) {
521e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            /* Since Cat is not tied to any application, but rather is Uicc application
522e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka             * in itself - just get first FileHandler and IccRecords object
523e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka             */
524e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ca = ic.getApplicationIndex(0);
525e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (ca != null) {
526e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                fh = ca.getIccFileHandler();
527e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                ir = ca.getIccRecords();
528e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
529e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
5300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        synchronized (sInstanceLock) {
5310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (sInstance == null) {
532e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (ci == null || ca == null || ir == null || context == null || fh == null
5330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        || ic == null) {
5340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    return null;
5350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
5360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                HandlerThread thread = new HandlerThread("Cat Telephony service");
5370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                thread.start();
538e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                sInstance = new CatService(ci, ca, ir, context, fh, ic);
5390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                CatLog.d(sInstance, "NEW sInstance");
5400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if ((ir != null) && (mIccRecords != ir)) {
541e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (mIccRecords != null) {
542e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    mIccRecords.unregisterForRecordsLoaded(sInstance);
543e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                }
544e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
545e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (mUiccApplication != null) {
546e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    mUiccApplication.unregisterForReady(sInstance);
547e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                }
548e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                CatLog.d(sInstance,
549e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                        "Reinitialize the Service with SIMRecords and UiccCardApplication");
5500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mIccRecords = ir;
551e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                mUiccApplication = ca;
5520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // re-Register for SIM ready event.
5540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mIccRecords.registerForRecordsLoaded(sInstance, MSG_ID_ICC_RECORDS_LOADED, null);
555e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                mUiccApplication.registerForReady(sInstance, MSG_ID_SIM_READY, null);
5560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                CatLog.d(sInstance, "sr changed reinitialize and return current sInstance");
5570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
5580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                CatLog.d(sInstance, "Return current sInstance");
5590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
5600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return sInstance;
5610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
5650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Used by application to get an AppInterface object.
5660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
5670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return The only Service object in the system
5680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
5690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static AppInterface getInstance() {
570e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return getInstance(null, null, null);
5710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    @Override
5740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void handleMessage(Message msg) {
5750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        switch (msg.what) {
5770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_SESSION_END:
5780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_PROACTIVE_COMMAND:
5790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_EVENT_NOTIFY:
5800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_REFRESH:
5810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            CatLog.d(this, "ril message arrived");
5820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            String data = null;
5830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (msg.obj != null) {
5840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                AsyncResult ar = (AsyncResult) msg.obj;
5850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (ar != null && ar.result != null) {
5860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    try {
5870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        data = (String) ar.result;
5880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    } catch (ClassCastException e) {
5890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        break;
5900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
5910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
5920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
5930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mMsgDecoder.sendStartDecodingMessageParams(new RilMessage(msg.what, data));
5940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
5950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_CALL_SETUP:
5960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mMsgDecoder.sendStartDecodingMessageParams(new RilMessage(msg.what, null));
5970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
5980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_ICC_RECORDS_LOADED:
5990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
6000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_RIL_MSG_DECODED:
6010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            handleRilMsg((RilMessage) msg.obj);
6020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
6030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_RESPONSE:
6040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            handleCmdResponse((CatResponseMessage) msg.obj);
6050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
6060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_SIM_READY:
6070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            CatLog.d(this, "SIM ready. Reporting STK service running now...");
6080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mCmdIf.reportStkServiceIsRunning(null);
6090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
6100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        default:
6110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new AssertionError("Unrecognized CAT command: " + msg.what);
6120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
615cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
6160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public synchronized void onCmdResponse(CatResponseMessage resMsg) {
6170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (resMsg == null) {
6180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return;
6190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // queue a response message.
6210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Message msg = this.obtainMessage(MSG_ID_RESPONSE, resMsg);
6220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        msg.sendToTarget();
6230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean validateResponse(CatResponseMessage resMsg) {
6260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (mCurrntCmd != null) {
6270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return (resMsg.cmdDet.compareTo(mCurrntCmd.mCmdDet));
6280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return false;
6300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean removeMenu(Menu menu) {
6330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
6340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (menu.items.size() == 1 && menu.items.get(0) == null) {
6350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return true;
6360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
6370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (NullPointerException e) {
6380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            CatLog.d(this, "Unable to get Menu's items size");
6390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return true;
6400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return false;
6420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void handleCmdResponse(CatResponseMessage resMsg) {
6450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Make sure the response details match the last valid command. An invalid
6460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // response is a one that doesn't have a corresponding proactive command
6470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // and sending it can "confuse" the baseband/ril.
6480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // One reason for out of order responses can be UI glitches. For example,
6490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // if the application launch an activity, and that activity is stored
6500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // by the framework inside the history stack. That activity will be
6510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // available for relaunch using the latest application dialog
6520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // (long press on the home button). Relaunching that activity can send
6530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // the same command's result again to the CatService and can cause it to
6540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // get out of sync with the SIM.
6550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!validateResponse(resMsg)) {
6560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return;
6570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ResponseData resp = null;
6590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean helpRequired = false;
6600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CommandDetails cmdDet = resMsg.getCmdDetails();
6610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        switch (resMsg.resCode) {
6630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case HELP_INFO_REQUIRED:
6640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            helpRequired = true;
6650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // fall through
6660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case OK:
6670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case PRFRMD_WITH_PARTIAL_COMPREHENSION:
6680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case PRFRMD_WITH_MISSING_INFO:
6690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case PRFRMD_WITH_ADDITIONAL_EFS_READ:
6700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case PRFRMD_ICON_NOT_DISPLAYED:
6710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case PRFRMD_MODIFIED_BY_NAA:
6720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case PRFRMD_LIMITED_SERVICE:
6730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case PRFRMD_WITH_MODIFICATION:
6740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case PRFRMD_NAA_NOT_ACTIVE:
6750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case PRFRMD_TONE_NOT_PLAYED:
6762d7aad7791b92186dabc779b3ab43794aceebcdaGuillaume Lucas        case TERMINAL_CRNTLY_UNABLE_TO_PROCESS:
6770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            switch (AppInterface.CommandType.fromInt(cmdDet.typeOfCommand)) {
6780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case SET_UP_MENU:
6790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                helpRequired = resMsg.resCode == ResultCode.HELP_INFO_REQUIRED;
6800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                sendMenuSelection(resMsg.usersMenuSelection, helpRequired);
6810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return;
6820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case SELECT_ITEM:
6830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                resp = new SelectItemResponseData(resMsg.usersMenuSelection);
6840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
6850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case GET_INPUT:
6860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case GET_INKEY:
6870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                Input input = mCurrntCmd.geInput();
6880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (!input.yesNo) {
6890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // when help is requested there is no need to send the text
6900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // string object.
6910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (!helpRequired) {
6920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        resp = new GetInkeyInputResponseData(resMsg.usersInput,
6930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                input.ucs2, input.packed);
6940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
6950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else {
6960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    resp = new GetInkeyInputResponseData(
6970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            resMsg.usersYesNoSelection);
6980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
6990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
7000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case DISPLAY_TEXT:
7010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case LAUNCH_BROWSER:
7020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
7030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case SET_UP_CALL:
7040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mCmdIf.handleCallSetupRequestFromSim(resMsg.usersConfirm, null);
7050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // No need to send terminal response for SET UP CALL. The user's
7060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // confirmation result is send back using a dedicated ril message
7070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // invoked by the CommandInterface call above.
7080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mCurrntCmd = null;
7090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return;
710cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville            default:
711cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville                break;
7120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
7130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
7140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case NO_RESPONSE_FROM_USER:
7150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case UICC_SESSION_TERM_BY_USER:
7160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case BACKWARD_MOVE_BY_USER:
7170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case USER_NOT_ACCEPT:
7180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            resp = null;
7190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
7200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        default:
7210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return;
7220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
7232d7aad7791b92186dabc779b3ab43794aceebcdaGuillaume Lucas        sendTerminalResponse(cmdDet, resMsg.resCode, resMsg.includeAdditionalInfo,
7242d7aad7791b92186dabc779b3ab43794aceebcdaGuillaume Lucas                resMsg.additionalInfo, resp);
7250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCurrntCmd = null;
7260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
7270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean isStkAppInstalled() {
7290825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Intent intent = new Intent(AppInterface.CAT_CMD_ACTION);
7300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        PackageManager pm = mContext.getPackageManager();
7310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        List<ResolveInfo> broadcastReceivers =
7320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            pm.queryBroadcastReceivers(intent, PackageManager.GET_META_DATA);
7330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int numReceiver = broadcastReceivers == null ? 0 : broadcastReceivers.size();
7340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return (numReceiver > 0);
7360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
7370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
738