/* * Copyright (C) 2012 The CyanogenMod Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package com.android.internal.telephony; import static com.android.internal.telephony.RILConstants.*; import android.content.Context; import android.os.AsyncResult; import android.os.Handler; import android.os.HandlerThread; import android.os.Looper; import android.os.Message; import android.os.Parcel; import android.telephony.SmsMessage; import android.os.SystemProperties; import android.text.TextUtils; import android.util.Log; import com.android.internal.telephony.RILConstants; import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo; import com.android.internal.telephony.cdma.CdmaInformationRecords; import java.util.ArrayList; /** * Custom Qualcomm No SimReady RIL using the latest Uicc stack * * {@hide} */ public class QualcommSharedRIL extends RIL implements CommandsInterface { protected HandlerThread mIccThread; protected IccHandler mIccHandler; protected String mAid; protected boolean mUSIM = false; protected String[] mLastDataIface = new String[20]; boolean RILJ_LOGV = true; boolean RILJ_LOGD = true; private final int RIL_INT_RADIO_OFF = 0; private final int RIL_INT_RADIO_UNAVALIABLE = 1; private final int RIL_INT_RADIO_ON = 2; private final int RIL_INT_RADIO_ON_NG = 10; private final int RIL_INT_RADIO_ON_HTC = 13; public QualcommSharedRIL(Context context, int networkMode, int cdmaSubscription) { super(context, networkMode, cdmaSubscription); mSetPreferredNetworkType = -1; mQANElements = 5; } @Override public void supplyIccPin2(String pin, Message result) { supplyIccPin2ForApp(pin, mAid, result); } @Override public void changeIccPin2(String oldPin2, String newPin2, Message result) { changeIccPin2ForApp(oldPin2, newPin2, mAid, result); } @Override public void supplyIccPuk(String puk, String newPin, Message result) { supplyIccPukForApp(puk, newPin, mAid, result); } @Override public void supplyIccPuk2(String puk2, String newPin2, Message result) { supplyIccPuk2ForApp(puk2, newPin2, mAid, result); } @Override public void queryFacilityLock(String facility, String password, int serviceClass, Message response) { queryFacilityLockForApp(facility, password, serviceClass, mAid, response); } @Override public void setFacilityLock (String facility, boolean lockState, String password, int serviceClass, Message response) { setFacilityLockForApp(facility, lockState, password, serviceClass, mAid, response); } @Override public void getIMSI(Message result) { RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMSI, result); rr.mp.writeInt(1); rr.mp.writeString(mAid); if (RILJ_LOGD) riljLog(rr.serialString() + "> getIMSI:RIL_REQUEST_GET_IMSI " + RIL_REQUEST_GET_IMSI + " aid: " + mAid + " " + requestToString(rr.mRequest)); send(rr); } @Override public void iccIO (int command, int fileid, String path, int p1, int p2, int p3, String data, String pin2, Message result) { //Note: This RIL request has not been renamed to ICC, // but this request is also valid for SIM and RUIM RILRequest rr = RILRequest.obtain(RIL_REQUEST_SIM_IO, result); if (mUSIM) path = path.replaceAll("7F20$","7FFF"); rr.mp.writeInt(command); rr.mp.writeInt(fileid); rr.mp.writeString(path); rr.mp.writeInt(p1); rr.mp.writeInt(p2); rr.mp.writeInt(p3); rr.mp.writeString(data); rr.mp.writeString(pin2); rr.mp.writeString(mAid); if (RILJ_LOGD) riljLog(rr.serialString() + "> iccIO: " + " aid: " + mAid + " " + requestToString(rr.mRequest) + " 0x" + Integer.toHexString(command) + " 0x" + Integer.toHexString(fileid) + " " + " path: " + path + "," + p1 + "," + p2 + "," + p3); send(rr); } @Override protected Object responseIccCardStatus(Parcel p) { IccCardApplication ca; IccCardStatus status = new IccCardStatus(); status.setCardState(p.readInt()); status.setUniversalPinState(p.readInt()); status.setGsmUmtsSubscriptionAppIndex(p.readInt()); status.setCdmaSubscriptionAppIndex(p.readInt()); status.setImsSubscriptionAppIndex(p.readInt()); int numApplications = p.readInt(); // limit to maximum allowed applications if (numApplications > IccCardStatus.CARD_MAX_APPS) { numApplications = IccCardStatus.CARD_MAX_APPS; } status.setNumApplications(numApplications); for (int i = 0; i < numApplications; i++) { ca = new IccCardApplication(); ca.app_type = ca.AppTypeFromRILInt(p.readInt()); ca.app_state = ca.AppStateFromRILInt(p.readInt()); ca.perso_substate = ca.PersoSubstateFromRILInt(p.readInt()); ca.aid = p.readString(); ca.app_label = p.readString(); ca.pin1_replaced = p.readInt(); ca.pin1 = ca.PinStateFromRILInt(p.readInt()); ca.pin2 = ca.PinStateFromRILInt(p.readInt()); p.readInt(); //remaining_count_pin1 p.readInt(); //remaining_count_puk1 p.readInt(); //remaining_count_pin2 p.readInt(); //remaining_count_puk2 status.addApplication(ca); } int appIndex = -1; if (mPhoneType == RILConstants.CDMA_PHONE) { appIndex = status.getCdmaSubscriptionAppIndex(); Log.d(LOG_TAG, "This is a CDMA PHONE " + appIndex); } else { appIndex = status.getGsmUmtsSubscriptionAppIndex(); Log.d(LOG_TAG, "This is a GSM PHONE " + appIndex); } if (numApplications > 0) { IccCardApplication application = status.getApplication(appIndex); mAid = application.aid; mUSIM = application.app_type == IccCardApplication.AppType.APPTYPE_USIM; mSetPreferredNetworkType = mPreferredNetworkType; if (TextUtils.isEmpty(mAid)) mAid = ""; Log.d(LOG_TAG, "mAid " + mAid); } return status; } @Override protected DataCallState getDataCallState(Parcel p, int version) { DataCallState dataCall = new DataCallState(); boolean oldRil = needsOldRilFeature("datacall"); if (!oldRil && version < 5) { return super.getDataCallState(p, version); } else if (!oldRil) { dataCall.version = version; dataCall.status = p.readInt(); dataCall.suggestedRetryTime = p.readInt(); dataCall.cid = p.readInt(); dataCall.active = p.readInt(); dataCall.type = p.readString(); dataCall.ifname = p.readString(); if ((dataCall.status == DataConnection.FailCause.NONE.getErrorCode()) && TextUtils.isEmpty(dataCall.ifname) && dataCall.active != 0) { throw new RuntimeException("getDataCallState, no ifname"); } String addresses = p.readString(); if (!TextUtils.isEmpty(addresses)) { dataCall.addresses = addresses.split(" "); } String dnses = p.readString(); if (!TextUtils.isEmpty(dnses)) { dataCall.dnses = dnses.split(" "); } String gateways = p.readString(); if (!TextUtils.isEmpty(gateways)) { dataCall.gateways = gateways.split(" "); } } else { dataCall.version = 4; // was dataCall.version = version; dataCall.cid = p.readInt(); dataCall.active = p.readInt(); dataCall.type = p.readString(); dataCall.ifname = mLastDataIface[dataCall.cid]; p.readString(); // skip APN if (TextUtils.isEmpty(dataCall.ifname)) { dataCall.ifname = mLastDataIface[0]; } String addresses = p.readString(); if (!TextUtils.isEmpty(addresses)) { dataCall.addresses = addresses.split(" "); } p.readInt(); // RadioTechnology p.readInt(); // inactiveReason dataCall.dnses = new String[2]; dataCall.dnses[0] = SystemProperties.get("net."+dataCall.ifname+".dns1"); dataCall.dnses[1] = SystemProperties.get("net."+dataCall.ifname+".dns2"); } return dataCall; } @Override protected Object responseSetupDataCall(Parcel p) { DataCallState dataCall; boolean oldRil = needsOldRilFeature("datacall"); if (!oldRil) return super.responseSetupDataCall(p); dataCall = new DataCallState(); dataCall.version = 4; dataCall.cid = 0; // Integer.parseInt(p.readString()); p.readString(); dataCall.ifname = p.readString(); if ((dataCall.status == DataConnection.FailCause.NONE.getErrorCode()) && TextUtils.isEmpty(dataCall.ifname) && dataCall.active != 0) { throw new RuntimeException( "RIL_REQUEST_SETUP_DATA_CALL response, no ifname"); } /* Use the last digit of the interface id as the cid */ if (!needsOldRilFeature("singlepdp")) { dataCall.cid = Integer.parseInt(dataCall.ifname.substring(dataCall.ifname.length() - 1)); } mLastDataIface[dataCall.cid] = dataCall.ifname; String addresses = p.readString(); if (!TextUtils.isEmpty(addresses)) { dataCall.addresses = addresses.split(" "); } dataCall.dnses = new String[2]; dataCall.dnses[0] = SystemProperties.get("net."+dataCall.ifname+".dns1"); dataCall.dnses[1] = SystemProperties.get("net."+dataCall.ifname+".dns2"); dataCall.active = 1; dataCall.status = 0; return dataCall; } @Override public void getNeighboringCids(Message response) { if (!getRadioState().isOn()) return; RILRequest rr = RILRequest.obtain( RILConstants.RIL_REQUEST_GET_NEIGHBORING_CELL_IDS, response); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); send(rr); } @Override public void setCurrentPreferredNetworkType() { if (RILJ_LOGD) riljLog("setCurrentPreferredNetworkType: " + mSetPreferredNetworkType); setPreferredNetworkType(mSetPreferredNetworkType, null); } @Override public void setPreferredNetworkType(int networkType , Message response) { /** * If not using a USIM, ignore LTE mode and go to 3G */ if (!mUSIM && networkType == RILConstants.NETWORK_MODE_LTE_GSM_WCDMA && mSetPreferredNetworkType >= RILConstants.NETWORK_MODE_WCDMA_PREF) { networkType = RILConstants.NETWORK_MODE_WCDMA_PREF; } mSetPreferredNetworkType = networkType; super.setPreferredNetworkType(networkType, response); } @Override protected Object responseSignalStrength(Parcel p) { int numInts = 12; int response[]; boolean oldRil = needsOldRilFeature("signalstrength"); boolean noLte = false; /* TODO: Add SignalStrength class to match RIL_SignalStrength */ response = new int[numInts]; for (int i = 0 ; i < numInts ; i++) { if ((oldRil || noLte) && i > 6 && i < 12) { response[i] = -1; } else { response[i] = p.readInt(); } if (i == 7 && response[i] == 99) { response[i] = -1; noLte = true; } if (i == 8 && !(noLte || oldRil)) { response[i] *= -1; } } return response; } @Override protected void processSolicited (Parcel p) { int serial, error; boolean found = false; serial = p.readInt(); error = p.readInt(); RILRequest rr; rr = findAndRemoveRequestFromList(serial); if (rr == null) { Log.w(LOG_TAG, "Unexpected solicited response! sn: " + serial + " error: " + error); return; } Object ret = null; if (error == 0 || p.dataAvail() > 0) { /* Convert RIL_REQUEST_GET_MODEM_VERSION back */ if (SystemProperties.get("ro.cm.device").indexOf("e73") == 0 && rr.mRequest == 220) { rr.mRequest = RIL_REQUEST_BASEBAND_VERSION; } // either command succeeds or command fails but with data payload try {switch (rr.mRequest) { /* cat libs/telephony/ril_commands.h \ | egrep "^ *{RIL_" \ | sed -re 's/\{([^,]+),[^,]+,([^}]+).+/case \1: ret = \2(p); break;/' */ case RIL_REQUEST_GET_SIM_STATUS: ret = responseIccCardStatus(p); break; case RIL_REQUEST_ENTER_SIM_PIN: ret = responseInts(p); break; case RIL_REQUEST_ENTER_SIM_PUK: ret = responseInts(p); break; case RIL_REQUEST_ENTER_SIM_PIN2: ret = responseInts(p); break; case RIL_REQUEST_ENTER_SIM_PUK2: ret = responseInts(p); break; case RIL_REQUEST_CHANGE_SIM_PIN: ret = responseInts(p); break; case RIL_REQUEST_CHANGE_SIM_PIN2: ret = responseInts(p); break; case RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION: ret = responseInts(p); break; case RIL_REQUEST_GET_CURRENT_CALLS: ret = responseCallList(p); break; case RIL_REQUEST_DIAL: ret = responseVoid(p); break; case RIL_REQUEST_GET_IMSI: ret = responseString(p); break; case RIL_REQUEST_HANGUP: ret = responseVoid(p); break; case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND: ret = responseVoid(p); break; case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND: ret = responseVoid(p); break; case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE: ret = responseVoid(p); break; case RIL_REQUEST_CONFERENCE: ret = responseVoid(p); break; case RIL_REQUEST_UDUB: ret = responseVoid(p); break; case RIL_REQUEST_LAST_CALL_FAIL_CAUSE: ret = responseInts(p); break; case RIL_REQUEST_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break; case RIL_REQUEST_VOICE_REGISTRATION_STATE: ret = responseStrings(p); break; case RIL_REQUEST_DATA_REGISTRATION_STATE: ret = responseStrings(p); break; case RIL_REQUEST_OPERATOR: ret = responseStrings(p); break; case RIL_REQUEST_RADIO_POWER: ret = responseVoid(p); break; case RIL_REQUEST_DTMF: ret = responseVoid(p); break; case RIL_REQUEST_SEND_SMS: ret = responseSMS(p); break; case RIL_REQUEST_SEND_SMS_EXPECT_MORE: ret = responseSMS(p); break; case RIL_REQUEST_SETUP_DATA_CALL: ret = responseSetupDataCall(p); break; case RIL_REQUEST_SIM_IO: ret = responseICC_IO(p); break; case RIL_REQUEST_SEND_USSD: ret = responseVoid(p); break; case RIL_REQUEST_CANCEL_USSD: ret = responseVoid(p); break; case RIL_REQUEST_GET_CLIR: ret = responseInts(p); break; case RIL_REQUEST_SET_CLIR: ret = responseVoid(p); break; case RIL_REQUEST_QUERY_CALL_FORWARD_STATUS: ret = responseCallForward(p); break; case RIL_REQUEST_SET_CALL_FORWARD: ret = responseVoid(p); break; case RIL_REQUEST_QUERY_CALL_WAITING: ret = responseInts(p); break; case RIL_REQUEST_SET_CALL_WAITING: ret = responseVoid(p); break; case RIL_REQUEST_SMS_ACKNOWLEDGE: ret = responseVoid(p); break; case RIL_REQUEST_GET_IMEI: ret = responseString(p); break; case RIL_REQUEST_GET_IMEISV: ret = responseString(p); break; case RIL_REQUEST_ANSWER: ret = responseVoid(p); break; case RIL_REQUEST_DEACTIVATE_DATA_CALL: ret = responseVoid(p); break; case RIL_REQUEST_QUERY_FACILITY_LOCK: ret = responseInts(p); break; case RIL_REQUEST_SET_FACILITY_LOCK: ret = responseInts(p); break; case RIL_REQUEST_CHANGE_BARRING_PASSWORD: ret = responseVoid(p); break; case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE: ret = responseInts(p); break; case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC: ret = responseVoid(p); break; case RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL: ret = responseVoid(p); break; case RIL_REQUEST_QUERY_AVAILABLE_NETWORKS : ret = responseOperatorInfos(p); break; case RIL_REQUEST_DTMF_START: ret = responseVoid(p); break; case RIL_REQUEST_DTMF_STOP: ret = responseVoid(p); break; case RIL_REQUEST_BASEBAND_VERSION: ret = responseString(p); break; case RIL_REQUEST_SEPARATE_CONNECTION: ret = responseVoid(p); break; case RIL_REQUEST_SET_MUTE: ret = responseVoid(p); break; case RIL_REQUEST_GET_MUTE: ret = responseInts(p); break; case RIL_REQUEST_QUERY_CLIP: ret = responseInts(p); break; case RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE: ret = responseInts(p); break; case RIL_REQUEST_DATA_CALL_LIST: ret = responseDataCallList(p); break; case RIL_REQUEST_RESET_RADIO: ret = responseVoid(p); break; case RIL_REQUEST_OEM_HOOK_RAW: ret = responseRaw(p); break; case RIL_REQUEST_OEM_HOOK_STRINGS: ret = responseStrings(p); break; case RIL_REQUEST_SCREEN_STATE: ret = responseVoid(p); break; case RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION: ret = responseVoid(p); break; case RIL_REQUEST_WRITE_SMS_TO_SIM: ret = responseInts(p); break; case RIL_REQUEST_DELETE_SMS_ON_SIM: ret = responseVoid(p); break; case RIL_REQUEST_SET_BAND_MODE: ret = responseVoid(p); break; case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE: ret = responseInts(p); break; case RIL_REQUEST_STK_GET_PROFILE: ret = responseString(p); break; case RIL_REQUEST_STK_SET_PROFILE: ret = responseVoid(p); break; case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND: ret = responseString(p); break; case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE: ret = responseVoid(p); break; case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM: ret = responseInts(p); break; case RIL_REQUEST_EXPLICIT_CALL_TRANSFER: ret = responseVoid(p); break; case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE: ret = responseVoid(p); break; case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE: ret = responseGetPreferredNetworkType(p); break; case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS: ret = responseCellList(p); break; case RIL_REQUEST_SET_LOCATION_UPDATES: ret = responseVoid(p); break; case RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE: ret = responseVoid(p); break; case RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE: ret = responseVoid(p); break; case RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE: ret = responseInts(p); break; case RIL_REQUEST_SET_TTY_MODE: ret = responseVoid(p); break; case RIL_REQUEST_QUERY_TTY_MODE: ret = responseInts(p); break; case RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE: ret = responseVoid(p); break; case RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE: ret = responseInts(p); break; case RIL_REQUEST_CDMA_FLASH: ret = responseVoid(p); break; case RIL_REQUEST_CDMA_BURST_DTMF: ret = responseVoid(p); break; case RIL_REQUEST_CDMA_SEND_SMS: ret = responseSMS(p); break; case RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE: ret = responseVoid(p); break; case RIL_REQUEST_GSM_GET_BROADCAST_CONFIG: ret = responseGmsBroadcastConfig(p); break; case RIL_REQUEST_GSM_SET_BROADCAST_CONFIG: ret = responseVoid(p); break; case RIL_REQUEST_GSM_BROADCAST_ACTIVATION: ret = responseVoid(p); break; case RIL_REQUEST_CDMA_GET_BROADCAST_CONFIG: ret = responseCdmaBroadcastConfig(p); break; case RIL_REQUEST_CDMA_SET_BROADCAST_CONFIG: ret = responseVoid(p); break; case RIL_REQUEST_CDMA_BROADCAST_ACTIVATION: ret = responseVoid(p); break; case RIL_REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY: ret = responseVoid(p); break; case RIL_REQUEST_CDMA_SUBSCRIPTION: ret = responseStrings(p); break; case RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM: ret = responseInts(p); break; case RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM: ret = responseVoid(p); break; case RIL_REQUEST_DEVICE_IDENTITY: ret = responseStrings(p); break; case RIL_REQUEST_GET_SMSC_ADDRESS: ret = responseString(p); break; case RIL_REQUEST_SET_SMSC_ADDRESS: ret = responseVoid(p); break; case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break; case RIL_REQUEST_REPORT_SMS_MEMORY_STATUS: ret = responseVoid(p); break; case RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING: ret = responseVoid(p); break; case 104: ret = responseInts(p); break; // RIL_REQUEST_VOICE_RADIO_TECH case 105: ret = responseInts(p); break; // RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE case 106: ret = responseStrings(p); break; // RIL_REQUEST_CDMA_PRL_VERSION case 107: ret = responseInts(p); break; // RIL_REQUEST_IMS_REGISTRATION_STATE case RIL_REQUEST_VOICE_RADIO_TECH: ret = responseInts(p); break; default: throw new RuntimeException("Unrecognized solicited response: " + rr.mRequest); //break; }} catch (Throwable tr) { // Exceptions here usually mean invalid RIL responses Log.w(LOG_TAG, rr.serialString() + "< " + requestToString(rr.mRequest) + " exception, possible invalid RIL response", tr); if (rr.mResult != null) { AsyncResult.forMessage(rr.mResult, null, tr); rr.mResult.sendToTarget(); } rr.release(); return; } } if (error != 0) { rr.onError(error, ret); rr.release(); return; } if (RILJ_LOGD) riljLog(rr.serialString() + "< " + requestToString(rr.mRequest) + " " + retToString(rr.mRequest, ret)); if (rr.mResult != null) { AsyncResult.forMessage(rr.mResult, ret, null); rr.mResult.sendToTarget(); } rr.release(); } @Override protected void processUnsolicited (Parcel p) { Object ret; int dataPosition = p.dataPosition(); // save off position within the Parcel int response = p.readInt(); /* Assume devices needing the "datacall" GB-compatibility flag are * running GB RILs, so skip 1031-1034 for those */ if (needsOldRilFeature("datacall")) { switch(response) { case 1031: case 1032: case 1033: case 1034: ret = responseVoid(p); return; } } switch(response) { //case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: ret = responseVoid(p); break; case RIL_UNSOL_RIL_CONNECTED: ret = responseInts(p); break; case 1035: ret = responseVoid(p); break; // RIL_UNSOL_VOICE_RADIO_TECH_CHANGED case 1036: ret = responseVoid(p); break; // RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED case 1037: ret = responseVoid(p); break; // RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE case 1038: ret = responseVoid(p); break; // RIL_UNSOL_DATA_NETWORK_STATE_CHANGED default: // Rewind the Parcel p.setDataPosition(dataPosition); // Forward responses that we are not overriding to the super class super.processUnsolicited(p); return; } switch(response) { case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: int state = p.readInt(); setRadioStateFromRILInt(state); break; case RIL_UNSOL_RIL_CONNECTED: if (RILJ_LOGD) unsljLogRet(response, ret); notifyRegistrantsRilConnectionChanged(((int[])ret)[0]); break; case 1035: case 1036: break; case 1037: // RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE if (RILJ_LOGD) unsljLogRet(response, ret); if (mExitEmergencyCallbackModeRegistrants != null) { mExitEmergencyCallbackModeRegistrants.notifyRegistrants( new AsyncResult (null, null, null)); } break; case 1038: break; } } /** * Notify all registrants that the ril has connected or disconnected. * * @param rilVer is the version of the ril or -1 if disconnected. */ private void notifyRegistrantsRilConnectionChanged(int rilVer) { mRilVersion = rilVer; if (mRilConnectedRegistrants != null) { mRilConnectedRegistrants.notifyRegistrants( new AsyncResult (null, new Integer(rilVer), null)); } } private void setRadioStateFromRILInt (int stateCode) { CommandsInterface.RadioState radioState; HandlerThread handlerThread; Looper looper; IccHandler iccHandler; switch (stateCode) { case RIL_INT_RADIO_OFF: radioState = CommandsInterface.RadioState.RADIO_OFF; if (mIccHandler != null) { mIccThread = null; mIccHandler = null; } break; case RIL_INT_RADIO_UNAVALIABLE: radioState = CommandsInterface.RadioState.RADIO_UNAVAILABLE; break; case RIL_INT_RADIO_ON: case RIL_INT_RADIO_ON_NG: case RIL_INT_RADIO_ON_HTC: if (mIccHandler == null) { handlerThread = new HandlerThread("IccHandler"); mIccThread = handlerThread; mIccThread.start(); looper = mIccThread.getLooper(); mIccHandler = new IccHandler(this,looper); mIccHandler.run(); } radioState = CommandsInterface.RadioState.RADIO_ON; break; default: throw new RuntimeException("Unrecognized RIL_RadioState: " + stateCode); } setRadioState (radioState); } class IccHandler extends Handler implements Runnable { private static final int EVENT_RADIO_ON = 1; private static final int EVENT_ICC_STATUS_CHANGED = 2; private static final int EVENT_GET_ICC_STATUS_DONE = 3; private static final int EVENT_RADIO_OFF_OR_UNAVAILABLE = 4; private RIL mRil; private boolean mRadioOn = false; public IccHandler (RIL ril, Looper looper) { super (looper); mRil = ril; } public void handleMessage (Message paramMessage) { switch (paramMessage.what) { case EVENT_RADIO_ON: mRadioOn = true; Log.d(LOG_TAG, "Radio on -> Forcing sim status update"); sendMessage(obtainMessage(EVENT_ICC_STATUS_CHANGED)); break; case EVENT_GET_ICC_STATUS_DONE: AsyncResult asyncResult = (AsyncResult) paramMessage.obj; if (asyncResult.exception != null) { Log.e (LOG_TAG, "IccCardStatusDone shouldn't return exceptions!", asyncResult.exception); break; } IccCardStatus status = (IccCardStatus) asyncResult.result; if (status.getNumApplications() == 0) { if (!mRil.getRadioState().isOn()) { break; } mRil.setRadioState(CommandsInterface.RadioState.RADIO_ON); } else { int appIndex = -1; if (mPhoneType == RILConstants.CDMA_PHONE) { appIndex = status.getCdmaSubscriptionAppIndex(); Log.d(LOG_TAG, "This is a CDMA PHONE " + appIndex); } else { appIndex = status.getGsmUmtsSubscriptionAppIndex(); Log.d(LOG_TAG, "This is a GSM PHONE " + appIndex); } IccCardApplication application = status.getApplication(appIndex); IccCardApplication.AppState app_state = application.app_state; IccCardApplication.AppType app_type = application.app_type; switch (app_state) { case APPSTATE_PIN: case APPSTATE_PUK: switch (app_type) { case APPTYPE_SIM: case APPTYPE_USIM: case APPTYPE_RUIM: mRil.setRadioState(CommandsInterface.RadioState.RADIO_ON); break; default: Log.e(LOG_TAG, "Currently we don't handle SIMs of type: " + app_type); return; } break; case APPSTATE_READY: switch (app_type) { case APPTYPE_SIM: case APPTYPE_USIM: case APPTYPE_RUIM: mRil.setRadioState(CommandsInterface.RadioState.RADIO_ON); break; default: Log.e(LOG_TAG, "Currently we don't handle SIMs of type: " + app_type); return; } break; default: return; } } break; case EVENT_ICC_STATUS_CHANGED: if (mRadioOn) { Log.d(LOG_TAG, "Received EVENT_ICC_STATUS_CHANGED, calling getIccCardStatus"); mRil.getIccCardStatus(obtainMessage(EVENT_GET_ICC_STATUS_DONE, paramMessage.obj)); } else { Log.d(LOG_TAG, "Received EVENT_ICC_STATUS_CHANGED while radio is not ON. Ignoring"); } break; case EVENT_RADIO_OFF_OR_UNAVAILABLE: mRadioOn = false; // disposeCards(); // to be verified; default: Log.e(LOG_TAG, " Unknown Event " + paramMessage.what); break; } } public void run () { mRil.registerForIccStatusChanged(this, EVENT_ICC_STATUS_CHANGED, null); Message msg = obtainMessage(EVENT_RADIO_ON); mRil.getIccCardStatus(msg); } } @Override public void supplyNetworkDepersonalization(String netpin, Message result) { RILRequest rr = RILRequest.obtain(RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION, result); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); rr.mp.writeInt(3); rr.mp.writeString(netpin); send(rr); } @Override public void setNetworkSelectionModeManual(String operatorNumeric, Message response) { RILRequest rr = RILRequest.obtain(RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL, response); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " " + operatorNumeric); rr.mp.writeInt(2); rr.mp.writeString(operatorNumeric); rr.mp.writeString("NOCHANGE"); send(rr); } }