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