CatService.java revision 419f297bfb0cc21566d1d1110573dd9205e8f713
10825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/*
20825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Copyright (C) 2007 The Android Open Source Project
30825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
40825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Licensed under the Apache License, Version 2.0 (the "License");
50825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * you may not use this file except in compliance with the License.
60825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * You may obtain a copy of the License at
70825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
80825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *      http://www.apache.org/licenses/LICENSE-2.0
90825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Unless required by applicable law or agreed to in writing, software
110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * distributed under the License is distributed on an "AS IS" BASIS,
120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * See the License for the specific language governing permissions and
140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * limitations under the License.
150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
170825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepackage com.android.internal.telephony.cat;
180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
190825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Context;
200825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.Intent;
210825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.pm.PackageManager;
220825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.content.pm.ResolveInfo;
230825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.AsyncResult;
240825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Handler;
250825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.HandlerThread;
260825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.Message;
270825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport android.os.SystemProperties;
280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
290825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport com.android.internal.telephony.CommandsInterface;
30d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccFileHandler;
31d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccRecords;
32d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.IccUtils;
33d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.UiccCard;
34d720945f2be5ea5fe0faf67e67d9ea0e184eba67Alex Yakavenkaimport com.android.internal.telephony.uicc.UiccCardApplication;
350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
370825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.io.ByteArrayOutputStream;
380825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.List;
390825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleimport java.util.Locale;
400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
410825495a331bb44df395a0cdb79fab85e68db5d5Wink Savilleclass RilMessage {
420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    int mId;
430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    Object mData;
440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    ResultCode mResCode;
450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    RilMessage(int msgId, String rawData) {
470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mId = msgId;
480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mData = rawData;
490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    RilMessage(RilMessage other) {
5222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mId = other.mId;
5322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mData = other.mData;
5422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        mResCode = other.mResCode;
550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville/**
590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * Class that implements SIM Toolkit Telephony Service. Interacts with the RIL
600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * and application.
610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville *
620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville * {@hide}
630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville */
640825495a331bb44df395a0cdb79fab85e68db5d5Wink Savillepublic class CatService extends Handler implements AppInterface {
65cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    private static final boolean DBG = false;
660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Class members
680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static IccRecords mIccRecords;
69e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private static UiccCardApplication mUiccApplication;
700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Service members.
720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Protects singleton instance lazy initialization.
730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final Object sInstanceLock = new Object();
740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static CatService sInstance;
750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private CommandsInterface mCmdIf;
760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private Context mContext;
770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private CatCmdMessage mCurrntCmd = null;
780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private CatCmdMessage mMenuCmd = null;
790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private RilMessageDecoder mMsgDecoder = null;
810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean mStkAppInstalled = false;
820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Service constants.
840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int MSG_ID_SESSION_END              = 1;
850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int MSG_ID_PROACTIVE_COMMAND        = 2;
860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int MSG_ID_EVENT_NOTIFY             = 3;
870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int MSG_ID_CALL_SETUP               = 4;
880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int MSG_ID_REFRESH                  = 5;
890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int MSG_ID_RESPONSE                 = 6;
900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int MSG_ID_SIM_READY                = 7;
910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    static final int MSG_ID_RIL_MSG_DECODED          = 10;
930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    // Events to signal SIM presence or absent in the device.
950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int MSG_ID_ICC_RECORDS_LOADED       = 20;
960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int DEV_ID_KEYPAD      = 0x01;
980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int DEV_ID_UICC        = 0x81;
990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int DEV_ID_TERMINAL    = 0x82;
1000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private static final int DEV_ID_NETWORK     = 0x83;
1010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1022f48cebb0f3169da9d9325f7b4884872280599e5Nizar Haouati    static final String STK_DEFAULT = "Default Message";
1030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /* Intentionally private for singleton */
105e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    private CatService(CommandsInterface ci, UiccCardApplication ca, IccRecords ir,
106e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            Context context, IccFileHandler fh, UiccCard ic) {
107e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (ci == null || ca == null || ir == null || context == null || fh == null
1080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                || ic == null) {
1090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new NullPointerException(
1100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    "Service: Input parameters must not be null");
1110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
1120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCmdIf = ci;
1130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mContext = context;
1140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Get the RilMessagesDecoder for decoding the messages.
1160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mMsgDecoder = RilMessageDecoder.getInstance(this, fh);
1170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Register ril events handling.
1190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCmdIf.setOnCatSessionEnd(this, MSG_ID_SESSION_END, null);
1200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCmdIf.setOnCatProactiveCmd(this, MSG_ID_PROACTIVE_COMMAND, null);
1210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCmdIf.setOnCatEvent(this, MSG_ID_EVENT_NOTIFY, null);
1220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCmdIf.setOnCatCallSetUp(this, MSG_ID_CALL_SETUP, null);
1230825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        //mCmdIf.setOnSimRefresh(this, MSG_ID_REFRESH, null);
1240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mIccRecords = ir;
126e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mUiccApplication = ca;
1270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Register for SIM ready event.
129e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        mUiccApplication.registerForReady(this, MSG_ID_SIM_READY, null);
1300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mIccRecords.registerForRecordsLoaded(this, MSG_ID_ICC_RECORDS_LOADED, null);
1310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Check if STK application is availalbe
1330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mStkAppInstalled = isStkAppInstalled();
1340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CatLog.d(this, "Running CAT service. STK app installed:" + mStkAppInstalled);
1360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
1380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void dispose() {
1390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mIccRecords.unregisterForRecordsLoaded(this);
1400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCmdIf.unSetOnCatSessionEnd(this);
1410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCmdIf.unSetOnCatProactiveCmd(this);
1420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCmdIf.unSetOnCatEvent(this);
1430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCmdIf.unSetOnCatCallSetUp(this);
1440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
14522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        removeCallbacksAndMessages(null);
1460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
1470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
148cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
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.
18922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sendTerminalResponse(cmdParams.mCmdDet, 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                }
22922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sendTerminalResponse(cmdParams.mCmdDet, 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) {
23422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sendTerminalResponse(cmdParams.mCmdDet, 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.
24022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                cmdParams.mCmdDet.typeOfCommand = CommandType.SET_UP_IDLE_MODE_TEXT.value();
2410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
2420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case SET_UP_IDLE_MODE_TEXT:
24322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sendTerminalResponse(cmdParams.mCmdDet, ResultCode.OK, false, 0, null);
2440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
2450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case PROVIDE_LOCAL_INFORMATION:
2460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                ResponseData resp;
24722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                switch (cmdParams.mCmdDet.commandQualifier) {
2480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    case CommandParamsFactory.DTTZ_SETTING:
2490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        resp = new DTTZResponseData(null);
25022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        sendTerminalResponse(cmdParams.mCmdDet, ResultCode.OK, false, 0, resp);
2510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        break;
2520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    case CommandParamsFactory.LANGUAGE_SETTING:
2530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        resp = new LanguageResponseData(Locale.getDefault().getLanguage());
25422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        sendTerminalResponse(cmdParams.mCmdDet, ResultCode.OK, false, 0, resp);
2550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        break;
2560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    default:
25722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        sendTerminalResponse(cmdParams.mCmdDet, ResultCode.OK, false, 0, null);
2580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
2590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // No need to start STK app here.
2600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return;
2610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case LAUNCH_BROWSER:
26222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                if ((((LaunchBrowserParams) cmdParams).mConfirmMsg.text != null)
26322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        && (((LaunchBrowserParams) cmdParams).mConfirmMsg.text.equals(STK_DEFAULT))) {
2640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    message = mContext.getText(com.android.internal.R.string.launchBrowserDefault);
26522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    ((LaunchBrowserParams) cmdParams).mConfirmMsg.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:
27622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                if ((((DisplayTextParams)cmdParams).mTextMsg.text != null)
27722d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        && (((DisplayTextParams)cmdParams).mTextMsg.text.equals(STK_DEFAULT))) {
2780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    message = mContext.getText(com.android.internal.R.string.sending);
27922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    ((DisplayTextParams)cmdParams).mTextMsg.text = message.toString();
2800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
2810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
2820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case PLAY_TONE:
2830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
2840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case SET_UP_CALL:
28522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                if ((((CallSetupParams) cmdParams).mConfirmMsg.text != null)
28622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        && (((CallSetupParams) cmdParams).mConfirmMsg.text.equals(STK_DEFAULT))) {
2870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    message = mContext.getText(com.android.internal.R.string.SetupCallDefault);
28822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    ((CallSetupParams) cmdParams).mConfirmMsg.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;
29622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                if (cmd.mHasAlphaId && (cmd.mTextMsg.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) {
30022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        sendTerminalResponse(cmdParams.mCmdDet, 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) {
30822d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        sendTerminalResponse(cmdParams.mCmdDet,
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))) {
32422d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                    sendTerminalResponse(cmdParams.mCmdDet, 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);
408cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville        if (DBG) {
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    /**
5100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Used for instantiating/updating the Service from the GsmPhone or CdmaPhone constructor.
5110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
5120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param ci CommandsInterface object
5130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param context phone app context
5140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @param ic Icc card
5150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return The only Service object in the system
5160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
517e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka    public static CatService getInstance(CommandsInterface ci,
518e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            Context context, UiccCard ic) {
519e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        UiccCardApplication ca = null;
520e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        IccFileHandler fh = null;
521e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        IccRecords ir = null;
522e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        if (ic != null) {
523e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            /* Since Cat is not tied to any application, but rather is Uicc application
524e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka             * in itself - just get first FileHandler and IccRecords object
525e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka             */
526e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            ca = ic.getApplicationIndex(0);
527e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            if (ca != null) {
528e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                fh = ca.getIccFileHandler();
529e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                ir = ca.getIccRecords();
530e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka            }
531e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        }
5320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        synchronized (sInstanceLock) {
5330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (sInstance == null) {
534e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (ci == null || ca == null || ir == null || context == null || fh == null
5350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        || ic == null) {
5360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    return null;
5370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
5380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                HandlerThread thread = new HandlerThread("Cat Telephony service");
5390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                thread.start();
540e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                sInstance = new CatService(ci, ca, ir, context, fh, ic);
5410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                CatLog.d(sInstance, "NEW sInstance");
5420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else if ((ir != null) && (mIccRecords != ir)) {
543e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (mIccRecords != null) {
544e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    mIccRecords.unregisterForRecordsLoaded(sInstance);
545e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                }
546e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka
547e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                if (mUiccApplication != null) {
548e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                    mUiccApplication.unregisterForReady(sInstance);
549e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                }
550e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                CatLog.d(sInstance,
551e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                        "Reinitialize the Service with SIMRecords and UiccCardApplication");
5520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mIccRecords = ir;
553e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                mUiccApplication = ca;
5540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // re-Register for SIM ready event.
5560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mIccRecords.registerForRecordsLoaded(sInstance, MSG_ID_ICC_RECORDS_LOADED, null);
557e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka                mUiccApplication.registerForReady(sInstance, MSG_ID_SIM_READY, null);
5580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                CatLog.d(sInstance, "sr changed reinitialize and return current sInstance");
5590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            } else {
5600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                CatLog.d(sInstance, "Return current sInstance");
5610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
5620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return sInstance;
5630825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
5640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5650825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    /**
5670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * Used by application to get an AppInterface object.
5680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     *
5690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     * @return The only Service object in the system
5700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville     */
5710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public static AppInterface getInstance() {
572e287feac673ff68565b766e0e463d105fa9cef9dAlex Yakavenka        return getInstance(null, null, null);
5730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
5740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    @Override
5760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public void handleMessage(Message msg) {
5770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
5780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        switch (msg.what) {
5790825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_SESSION_END:
5800825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_PROACTIVE_COMMAND:
5810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_EVENT_NOTIFY:
5820825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_REFRESH:
5830825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            CatLog.d(this, "ril message arrived");
5840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            String data = null;
5850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (msg.obj != null) {
5860825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                AsyncResult ar = (AsyncResult) msg.obj;
5870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (ar != null && ar.result != null) {
5880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    try {
5890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        data = (String) ar.result;
5900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    } catch (ClassCastException e) {
5910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                        break;
5920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
5930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
5940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
5950825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mMsgDecoder.sendStartDecodingMessageParams(new RilMessage(msg.what, data));
5960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
5970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_CALL_SETUP:
5980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mMsgDecoder.sendStartDecodingMessageParams(new RilMessage(msg.what, null));
5990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
6000825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_ICC_RECORDS_LOADED:
6010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
6020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_RIL_MSG_DECODED:
6030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            handleRilMsg((RilMessage) msg.obj);
6040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
6050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_RESPONSE:
6060825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            handleCmdResponse((CatResponseMessage) msg.obj);
6070825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
6080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case MSG_ID_SIM_READY:
6090825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            CatLog.d(this, "SIM ready. Reporting STK service running now...");
6100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            mCmdIf.reportStkServiceIsRunning(null);
6110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
6120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        default:
6130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            throw new AssertionError("Unrecognized CAT command: " + msg.what);
6140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6150825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6160825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
617cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville    @Override
6180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    public synchronized void onCmdResponse(CatResponseMessage resMsg) {
6190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (resMsg == null) {
6200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return;
6210825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6220825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // queue a response message.
62322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        Message msg = obtainMessage(MSG_ID_RESPONSE, resMsg);
6240825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        msg.sendToTarget();
6250825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6260825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6270825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean validateResponse(CatResponseMessage resMsg) {
6280825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (mCurrntCmd != null) {
62922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville            return (resMsg.mCmdDet.compareTo(mCurrntCmd.mCmdDet));
6300825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6310825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return false;
6320825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6330825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6340825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean removeMenu(Menu menu) {
6350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        try {
6360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            if (menu.items.size() == 1 && menu.items.get(0) == null) {
6370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return true;
6380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
6390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        } catch (NullPointerException e) {
6400825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            CatLog.d(this, "Unable to get Menu's items size");
6410825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return true;
6420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return false;
6440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
6450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
6460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private void handleCmdResponse(CatResponseMessage resMsg) {
6470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // Make sure the response details match the last valid command. An invalid
6480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // response is a one that doesn't have a corresponding proactive command
6490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // and sending it can "confuse" the baseband/ril.
6500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // One reason for out of order responses can be UI glitches. For example,
6510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // if the application launch an activity, and that activity is stored
6520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // by the framework inside the history stack. That activity will be
6530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // available for relaunch using the latest application dialog
6540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // (long press on the home button). Relaunching that activity can send
6550825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // the same command's result again to the CatService and can cause it to
6560825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        // get out of sync with the SIM.
6570825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        if (!validateResponse(resMsg)) {
6580825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return;
6590825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
6600825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        ResponseData resp = null;
6610825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        boolean helpRequired = false;
6620825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        CommandDetails cmdDet = resMsg.getCmdDetails();
66314957f5b0b202fc80782944c962d282ed1866837Abhishek Adappa        AppInterface.CommandType type = AppInterface.CommandType.fromInt(cmdDet.typeOfCommand);
6640825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
66522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        switch (resMsg.mResCode) {
6660825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case HELP_INFO_REQUIRED:
6670825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            helpRequired = true;
6680825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            // fall through
6690825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case OK:
6700825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case PRFRMD_WITH_PARTIAL_COMPREHENSION:
6710825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case PRFRMD_WITH_MISSING_INFO:
6720825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case PRFRMD_WITH_ADDITIONAL_EFS_READ:
6730825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case PRFRMD_ICON_NOT_DISPLAYED:
6740825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case PRFRMD_MODIFIED_BY_NAA:
6750825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case PRFRMD_LIMITED_SERVICE:
6760825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case PRFRMD_WITH_MODIFICATION:
6770825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case PRFRMD_NAA_NOT_ACTIVE:
6780825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case PRFRMD_TONE_NOT_PLAYED:
6792d7aad7791b92186dabc779b3ab43794aceebcdaGuillaume Lucas        case TERMINAL_CRNTLY_UNABLE_TO_PROCESS:
68014957f5b0b202fc80782944c962d282ed1866837Abhishek Adappa            switch (type) {
6810825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case SET_UP_MENU:
68222d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                helpRequired = resMsg.mResCode == ResultCode.HELP_INFO_REQUIRED;
68322d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                sendMenuSelection(resMsg.mUsersMenuSelection, helpRequired);
6840825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return;
6850825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case SELECT_ITEM:
68622d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                resp = new SelectItemResponseData(resMsg.mUsersMenuSelection);
6870825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
6880825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case GET_INPUT:
6890825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case GET_INKEY:
6900825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                Input input = mCurrntCmd.geInput();
6910825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                if (!input.yesNo) {
6920825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // when help is requested there is no need to send the text
6930825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    // string object.
6940825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    if (!helpRequired) {
69522d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                        resp = new GetInkeyInputResponseData(resMsg.mUsersInput,
6960825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                                input.ucs2, input.packed);
6970825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    }
6980825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                } else {
6990825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                    resp = new GetInkeyInputResponseData(
70022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                            resMsg.mUsersYesNoSelection);
7010825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                }
7020825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
7030825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case DISPLAY_TEXT:
7040825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case LAUNCH_BROWSER:
7050825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                break;
706419f297bfb0cc21566d1d1110573dd9205e8f713Shriram Ganesh            // 3GPP TS.102.223: Open Channel alpha confirmation should not send TR
707419f297bfb0cc21566d1d1110573dd9205e8f713Shriram Ganesh            case OPEN_CHANNEL:
7080825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            case SET_UP_CALL:
70922d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                mCmdIf.handleCallSetupRequestFromSim(resMsg.mUsersConfirm, null);
7100825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // No need to send terminal response for SET UP CALL. The user's
7110825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // confirmation result is send back using a dedicated ril message
7120825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                // invoked by the CommandInterface call above.
7130825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                mCurrntCmd = null;
7140825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                return;
715cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville            default:
716cbaa45bbf2cab852b6c9c3a887e9f803d4e857eaWink Saville                break;
7170825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            }
7180825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
7190825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case BACKWARD_MOVE_BY_USER:
7200825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        case USER_NOT_ACCEPT:
72114957f5b0b202fc80782944c962d282ed1866837Abhishek Adappa            // if the user dismissed the alert dialog for a
72214957f5b0b202fc80782944c962d282ed1866837Abhishek Adappa            // setup call/open channel, consider that as the user
72314957f5b0b202fc80782944c962d282ed1866837Abhishek Adappa            // rejecting the call. Use dedicated API for this, rather than
72414957f5b0b202fc80782944c962d282ed1866837Abhishek Adappa            // sending a terminal response.
72514957f5b0b202fc80782944c962d282ed1866837Abhishek Adappa            if (type == CommandType.SET_UP_CALL || type == CommandType.OPEN_CHANNEL) {
72614957f5b0b202fc80782944c962d282ed1866837Abhishek Adappa                mCmdIf.handleCallSetupRequestFromSim(false, null);
72714957f5b0b202fc80782944c962d282ed1866837Abhishek Adappa                mCurrntCmd = null;
72814957f5b0b202fc80782944c962d282ed1866837Abhishek Adappa                return;
72914957f5b0b202fc80782944c962d282ed1866837Abhishek Adappa            } else {
73014957f5b0b202fc80782944c962d282ed1866837Abhishek Adappa                resp = null;
73114957f5b0b202fc80782944c962d282ed1866837Abhishek Adappa            }
73214957f5b0b202fc80782944c962d282ed1866837Abhishek Adappa            break;
73314957f5b0b202fc80782944c962d282ed1866837Abhishek Adappa        case NO_RESPONSE_FROM_USER:
73414957f5b0b202fc80782944c962d282ed1866837Abhishek Adappa        case UICC_SESSION_TERM_BY_USER:
7350825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            resp = null;
7360825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            break;
7370825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        default:
7380825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville            return;
7390825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        }
74022d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville        sendTerminalResponse(cmdDet, resMsg.mResCode, resMsg.mIncludeAdditionalInfo,
74122d85a8e3a575a6d01d2c788587971657dfe20c6Wink Saville                resMsg.mAdditionalInfo, resp);
7420825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        mCurrntCmd = null;
7430825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
7440825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7450825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    private boolean isStkAppInstalled() {
7460825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        Intent intent = new Intent(AppInterface.CAT_CMD_ACTION);
7470825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        PackageManager pm = mContext.getPackageManager();
7480825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        List<ResolveInfo> broadcastReceivers =
7490825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville                            pm.queryBroadcastReceivers(intent, PackageManager.GET_META_DATA);
7500825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        int numReceiver = broadcastReceivers == null ? 0 : broadcastReceivers.size();
7510825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville
7520825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville        return (numReceiver > 0);
7530825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville    }
7540825495a331bb44df395a0cdb79fab85e68db5d5Wink Saville}
755