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