From a4b66e9d931573249020ee3106bf5286f5fa8c37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C3=ABl=20Burtin?= Date: Sat, 7 Jan 2012 10:33:12 +0100 Subject: [PATCH] Add support for recent Huawei Qualcom RIL Override RIL class with some Huawei specific calls. Add a new CARDSTATE_NOT_READY state to Icc card status. Add Huawei specific EF path. Change the definition of NETWORK_LOCKED app state for Huawei RIL. Change-Id: I66e4d7a42a0a5ca416e5d9e114e41c184afe5bd7 --- .../android/internal/telephony/HuaweiRIL.java | 909 ++++++++++++++++++ .../android/internal/telephony/IccCard.java | 4 +- .../telephony/IccCardApplication.java | 5 + .../internal/telephony/IccCardStatus.java | 6 +- .../telephony/gsm/SIMFileHandler.java | 42 + 5 files changed, 964 insertions(+), 2 deletions(-) create mode 100644 telephony/java/com/android/internal/telephony/HuaweiRIL.java diff --git a/telephony/java/com/android/internal/telephony/HuaweiRIL.java b/telephony/java/com/android/internal/telephony/HuaweiRIL.java new file mode 100644 index 0000000000000..c5d736c370661 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/HuaweiRIL.java @@ -0,0 +1,909 @@ +/* + * Copyright (C) 2011 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.RIL_REQUEST_CHANGE_SIM_PIN; +import static com.android.internal.telephony.RILConstants.RIL_REQUEST_CHANGE_SIM_PIN2; +import static com.android.internal.telephony.RILConstants.RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION; +import static com.android.internal.telephony.RILConstants.RIL_REQUEST_ENTER_SIM_PIN; +import static com.android.internal.telephony.RILConstants.RIL_REQUEST_ENTER_SIM_PIN2; +import static com.android.internal.telephony.RILConstants.RIL_REQUEST_ENTER_SIM_PUK; +import static com.android.internal.telephony.RILConstants.RIL_REQUEST_ENTER_SIM_PUK2; +import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_CURRENT_CALLS; +import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_IMEI; +import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_IMEISV; +import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_IMSI; +import static com.android.internal.telephony.RILConstants.RIL_REQUEST_GET_NEIGHBORING_CELL_IDS; +import static com.android.internal.telephony.RILConstants.RIL_REQUEST_QUERY_FACILITY_LOCK; +import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SETUP_DATA_CALL; +import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SET_FACILITY_LOCK; +import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SIM_IO; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_CALL_RING; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_CDMA_CALL_WAITING; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_CDMA_INFO_REC; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_CDMA_OTA_PROVISION_STATUS; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_DATA_CALL_LIST_CHANGED; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_NITZ_TIME_RECEIVED; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_OEM_HOOK_RAW; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_ON_USSD; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_ON_USSD_REQUEST; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RESEND_INCALL_MUTE; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RESPONSE_CDMA_NEW_SMS; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RESPONSE_NEW_SMS; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RESTRICTED_STATE_CHANGED; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RINGBACK_TONE; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SIGNAL_STRENGTH; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SIM_REFRESH; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SIM_SMS_STORAGE_FULL; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_STK_CALL_SETUP; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_STK_EVENT_NOTIFY; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_STK_PROACTIVE_COMMAND; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_STK_SESSION_END; +import static com.android.internal.telephony.RILConstants.RIL_UNSOL_SUPP_SVC_NOTIFICATION; + +import android.content.Context; +import android.content.res.Resources; +import android.os.AsyncResult; +import android.os.Message; +import android.os.Parcel; +import android.telephony.NeighboringCellInfo; +import android.telephony.SmsMessage; +import android.text.TextUtils; +import android.util.Log; + +import com.android.internal.telephony.cdma.CdmaInformationRecords; + +import java.util.ArrayList; + +/** + * Custom Huawei ril {@hide} + */ +public class HuaweiRIL extends RIL implements CommandsInterface { + protected String mAid; + + // Override RILConstants + public static final int RIL_UNSOL_RESPONSE_TETHERED_MODE_STATE_CHANGED = 1032; + public static final int RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED = 1034; + public static final int RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE = 1037; + public static final int RIL_UNSOL_RIL_CONNECTED = 1031; + + + public HuaweiRIL(Context context, int networkMode, int cdmaSubscription) { + super(context, networkMode, cdmaSubscription); + } + + @Override + public void + supplyIccPin(String pin, Message result) { + // but this request is also valid for SIM and RUIM + RILRequest rr = RILRequest.obtain(RIL_REQUEST_ENTER_SIM_PIN, result); + + if (RILJ_LOGD) + riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeString(null); + rr.mp.writeString(pin); + + send(rr); + } + + @Override public void + supplyIccPin2ForApp(String pin, String aid, 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_ENTER_SIM_PIN2, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeString(null); + rr.mp.writeString(pin); + + send(rr); + } + + @Override public void + supplyIccPukForApp(String puk, String newPin, String aid, 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_ENTER_SIM_PUK, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeString(null); + rr.mp.writeString(puk); + rr.mp.writeString(newPin); + + send(rr); + } + + @Override public void + supplyIccPuk2ForApp(String puk, String newPin2, String aid, 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_ENTER_SIM_PUK2, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeString(null); + rr.mp.writeString(puk); + rr.mp.writeString(newPin2); + + send(rr); + } + + @Override + public void + getIMSI(Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMSI, result); + + if (RILJ_LOGD) + riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeString(null); + + send(rr); + } + + @Override public void + changeIccPinForApp(String oldPin, String newPin, String aid, 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_CHANGE_SIM_PIN, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeString(null); + rr.mp.writeString(oldPin); + rr.mp.writeString(newPin); + + send(rr); + } + + @Override public void + changeIccPin2ForApp(String oldPin2, String newPin2, String aid, 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_CHANGE_SIM_PIN2, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeString(null); + rr.mp.writeString(oldPin2); + rr.mp.writeString(newPin2); + + send(rr); + } + + @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 + setupDataCall(String radioTechnology, String profile, String apn, + String user, String password, String authType, String ipVersion, + Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result); + + rr.mp.writeInt(7); + + rr.mp.writeString(radioTechnology); + rr.mp.writeString(profile); + rr.mp.writeString(apn); + rr.mp.writeString(user); + rr.mp.writeString(password); + rr.mp.writeString(authType); + rr.mp.writeString("0"); // ipVersion + + if (RILJ_LOGD) + riljLog(rr.serialString() + "> " + + requestToString(rr.mRequest) + " " + radioTechnology + " " + + profile + " " + apn + " " + user + " " + + password + " " + authType + " " + ipVersion); + + send(rr); + } + + 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); + + rr.mp.writeString(mAid); + 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); + + if (RILJ_LOGD) + riljLog(rr.serialString() + "> iccIO: " + requestToString(rr.mRequest) + + " 0x" + Integer.toHexString(command) + + " 0x" + Integer.toHexString(fileid) + " " + + " path: " + path + "," + + p1 + "," + p2 + "," + p3); + + send(rr); + } + + @Override + public void + queryFacilityLock(String facility, String password, int serviceClass, + Message response) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_QUERY_FACILITY_LOCK, response); + + if (RILJ_LOGD) + riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeInt(4); + rr.mp.writeString(null); //mAid); + rr.mp.writeString(facility); + rr.mp.writeString(password); + rr.mp.writeString(Integer.toString(serviceClass)); + + send(rr); + } + + @Override + public void + setFacilityLockForApp(String facility, boolean lockState, String password, + int serviceClass, String appId, Message response) { + String lockString; + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_SET_FACILITY_LOCK, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeInt(5); + rr.mp.writeString(null); + rr.mp.writeString(facility); + lockString = (lockState)?"1":"0"; + rr.mp.writeString(lockString); + rr.mp.writeString(password); + rr.mp.writeString(Integer.toString(serviceClass)); + + send(rr); + + } + + 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()); + 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); + Log.d(LOG_TAG, "mAid " + application.aid); + mAid = application.aid; + } + return status; + } + + @Override + protected DataCallState getDataCallState(Parcel p, int version) { + DataCallState dataCall = new DataCallState(); + + riljLog("getDataCallState ver=" + version); + dataCall.version = version; + if (version < 5) { + dataCall.cid = p.readInt(); + dataCall.active = p.readInt(); + dataCall.type = p.readString(); + //p.readString(); // APN - not used + String addresses = p.readString(); + if (!TextUtils.isEmpty(addresses)) { + dataCall.addresses = addresses.split(" "); + } + // DataCallState needs an ifname. Since we don't have one use the name from the ThrottleService resource (default=rmnet0). + dataCall.ifname = Resources.getSystem().getString(com.android.internal.R.string.config_datause_iface); + } else { + 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)) { + 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(" "); + } + } + return dataCall; + } + + protected String + retToString(int req, Object ret) { + if (ret == null) return ""; + switch (req) { + // Don't log these return values, for privacy's sake. + case RIL_REQUEST_GET_IMSI: + case RIL_REQUEST_GET_IMEI: + case RIL_REQUEST_GET_IMEISV: + if (!RILJ_LOGV) { + // If not versbose logging just return and don't display IMSI and IMEI, IMEISV + return ""; + } + } + + StringBuilder sb; + String s; + int length; + if (ret instanceof int[]){ + int[] intArray = (int[]) ret; + length = intArray.length; + sb = new StringBuilder("{"); + if (length > 0) { + int i = 0; + sb.append(intArray[i++]); + while ( i < length) { + sb.append(", ").append(intArray[i++]); + } + } + sb.append("}"); + s = sb.toString(); + } else if (ret instanceof String[]) { + String[] strings = (String[]) ret; + length = strings.length; + sb = new StringBuilder("{"); + if (length > 0) { + int i = 0; + sb.append(strings[i++]); + while ( i < length) { + sb.append(", ").append(strings[i++]); + } + } + sb.append("}"); + s = sb.toString(); + }else if (req == RIL_REQUEST_GET_CURRENT_CALLS) { + ArrayList calls = (ArrayList) ret; + sb = new StringBuilder(" "); + for (DriverCall dc : calls) { + sb.append("[").append(dc).append("] "); + } + s = sb.toString(); + } else if (req == RIL_REQUEST_GET_NEIGHBORING_CELL_IDS) { + ArrayList cells; + cells = (ArrayList) ret; + sb = new StringBuilder(" "); + for (NeighboringCellInfo cell : cells) { + sb.append(cell).append(" "); + } + s = sb.toString(); + } else { + s = ret.toString(); + } + return s; + } + + protected void + processUnsolicited (Parcel p) { + int response; + Object ret; + + response = p.readInt(); + + try {switch(response) { +/* + cat libs/telephony/ril_unsol_commands.h \ + | egrep "^ *{RIL_" \ + | sed -re 's/\{([^,]+),[^,]+,([^}]+).+/case \1: \2(rr, p); break;/' +*/ + + case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: ret = responseVoid(p); break; + case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: ret = responseVoid(p); break; + case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED: ret = responseVoid(p); break; + case RIL_UNSOL_RESPONSE_NEW_SMS: ret = responseString(p); break; + case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT: ret = responseString(p); break; + case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM: ret = responseInts(p); break; + case RIL_UNSOL_ON_USSD: ret = responseStrings(p); break; + case RIL_UNSOL_NITZ_TIME_RECEIVED: ret = responseString(p); break; + case RIL_UNSOL_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break; + case RIL_UNSOL_DATA_CALL_LIST_CHANGED: ret = responseDataCallList(p);break; + case RIL_UNSOL_SUPP_SVC_NOTIFICATION: ret = responseSuppServiceNotification(p); break; + case RIL_UNSOL_STK_SESSION_END: ret = responseVoid(p); break; + case RIL_UNSOL_STK_PROACTIVE_COMMAND: ret = responseString(p); break; + case RIL_UNSOL_STK_EVENT_NOTIFY: ret = responseString(p); break; + case RIL_UNSOL_STK_CALL_SETUP: ret = responseInts(p); break; + case RIL_UNSOL_SIM_SMS_STORAGE_FULL: ret = responseVoid(p); break; + case RIL_UNSOL_SIM_REFRESH: ret = responseInts(p); break; + case RIL_UNSOL_CALL_RING: ret = responseCallRing(p); break; + case RIL_UNSOL_RESTRICTED_STATE_CHANGED: ret = responseInts(p); break; + case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED: ret = responseVoid(p); break; + case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS: ret = responseCdmaSms(p); break; + case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS: ret = responseRaw(p); break; + case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL: ret = responseVoid(p); break; + case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break; + case RIL_UNSOL_CDMA_CALL_WAITING: ret = responseCdmaCallWaiting(p); break; + case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS: ret = responseInts(p); break; + case RIL_UNSOL_CDMA_INFO_REC: ret = responseCdmaInformationRecord(p); break; + case RIL_UNSOL_OEM_HOOK_RAW: ret = responseRaw(p); break; + case RIL_UNSOL_RINGBACK_TONE: ret = responseInts(p); break; + case RIL_UNSOL_RESEND_INCALL_MUTE: ret = responseVoid(p); break; + case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED: ret = responseInts(p); break; + case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break; + case RIL_UNSOL_RIL_CONNECTED: ret = responseInts(p); break; + case RIL_UNSOL_RESPONSE_TETHERED_MODE_STATE_CHANGED: ret = responseInts(p); break; // 1032 + + default: + throw new RuntimeException("Unrecognized unsol response: " + response); + //break; (implied) + }} catch (Throwable tr) { + Log.e(LOG_TAG, "Exception processing unsol response: " + response + + "Exception:" + tr.toString()); + return; + } + + switch(response) { + case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: + /* has bonus radio state int */ + RadioState newState = getRadioStateFromInt(p.readInt()); + if (RILJ_LOGD) unsljLogMore(response, newState.toString()); + + switchToRadioState(newState); + break; + case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: + if (RILJ_LOGD) unsljLog(response); + + mCallStateRegistrants + .notifyRegistrants(new AsyncResult(null, null, null)); + break; + case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED: + if (RILJ_LOGD) unsljLog(response); + + mVoiceNetworkStateRegistrants + .notifyRegistrants(new AsyncResult(null, null, null)); + break; + case RIL_UNSOL_RESPONSE_NEW_SMS: { + if (RILJ_LOGD) unsljLog(response); + + // FIXME this should move up a layer + String a[] = new String[2]; + + a[1] = (String)ret; + + SmsMessage sms; + + sms = SmsMessage.newFromCMT(a); + if (mGsmSmsRegistrant != null) { + mGsmSmsRegistrant + .notifyRegistrant(new AsyncResult(null, sms, null)); + } + break; + } + case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mSmsStatusRegistrant != null) { + mSmsStatusRegistrant.notifyRegistrant( + new AsyncResult(null, ret, null)); + } + break; + case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM: + if (RILJ_LOGD) unsljLogRet(response, ret); + + int[] smsIndex = (int[])ret; + + if(smsIndex.length == 1) { + if (mSmsOnSimRegistrant != null) { + mSmsOnSimRegistrant. + notifyRegistrant(new AsyncResult(null, smsIndex, null)); + } + } else { + if (RILJ_LOGD) riljLog(" NEW_SMS_ON_SIM ERROR with wrong length " + + smsIndex.length); + } + break; + case RIL_UNSOL_ON_USSD: + String[] resp = (String[])ret; + + if (resp.length < 2) { + resp = new String[2]; + resp[0] = ((String[])ret)[0]; + resp[1] = null; + } + if (RILJ_LOGD) unsljLogMore(response, resp[0]); + if (mUSSDRegistrant != null) { + mUSSDRegistrant.notifyRegistrant( + new AsyncResult (null, resp, null)); + } + break; + case RIL_UNSOL_NITZ_TIME_RECEIVED: + if (RILJ_LOGD) unsljLogRet(response, ret); + + // has bonus long containing milliseconds since boot that the NITZ + // time was received + long nitzReceiveTime = p.readLong(); + + Object[] result = new Object[2]; + + result[0] = ret; + result[1] = Long.valueOf(nitzReceiveTime); + + if (mNITZTimeRegistrant != null) { + + mNITZTimeRegistrant + .notifyRegistrant(new AsyncResult (null, result, null)); + } else { + // in case NITZ time registrant isnt registered yet + mLastNITZTimeInfo = result; + } + break; + + case RIL_UNSOL_SIGNAL_STRENGTH: + // Note this is set to "verbose" because it happens + // frequently + if (RILJ_LOGV) unsljLogvRet(response, ret); + + if (mSignalStrengthRegistrant != null) { + mSignalStrengthRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } + break; + case RIL_UNSOL_DATA_CALL_LIST_CHANGED: + if (RILJ_LOGD) unsljLogRet(response, ret); + + mDataNetworkStateRegistrants.notifyRegistrants(new AsyncResult(null, ret, null)); + break; + + case RIL_UNSOL_SUPP_SVC_NOTIFICATION: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mSsnRegistrant != null) { + mSsnRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_STK_SESSION_END: + if (RILJ_LOGD) unsljLog(response); + + if (mCatSessionEndRegistrant != null) { + mCatSessionEndRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_STK_PROACTIVE_COMMAND: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mCatProCmdRegistrant != null) { + mCatProCmdRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_STK_EVENT_NOTIFY: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mCatEventRegistrant != null) { + mCatEventRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_STK_CALL_SETUP: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mCatCallSetUpRegistrant != null) { + mCatCallSetUpRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_SIM_SMS_STORAGE_FULL: + if (RILJ_LOGD) unsljLog(response); + + if (mIccSmsFullRegistrant != null) { + mIccSmsFullRegistrant.notifyRegistrant(); + } + break; + + case RIL_UNSOL_SIM_REFRESH: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mIccRefreshRegistrants != null) { + mIccRefreshRegistrants.notifyRegistrants( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_CALL_RING: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mRingRegistrant != null) { + mRingRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_RESTRICTED_STATE_CHANGED: + if (RILJ_LOGD) unsljLogvRet(response, ret); + if (mRestrictedStateRegistrant != null) { + mRestrictedStateRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED: + if (RILJ_LOGD) unsljLog(response); + + if (mIccStatusChangedRegistrants != null) { + mIccStatusChangedRegistrants.notifyRegistrants(); + } + break; + + case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS: + if (RILJ_LOGD) unsljLog(response); + + SmsMessage sms = (SmsMessage) ret; + + if (mCdmaSmsRegistrant != null) { + mCdmaSmsRegistrant + .notifyRegistrant(new AsyncResult(null, sms, null)); + } + break; + + case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS: + if (RILJ_LOGD) unsljLog(response); + + if (mGsmBroadcastSmsRegistrant != null) { + mGsmBroadcastSmsRegistrant + .notifyRegistrant(new AsyncResult(null, ret, null)); + } + break; + + case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL: + if (RILJ_LOGD) unsljLog(response); + + if (mIccSmsFullRegistrant != null) { + mIccSmsFullRegistrant.notifyRegistrant(); + } + break; + + case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: + if (RILJ_LOGD) unsljLog(response); + + if (mEmergencyCallbackModeRegistrant != null) { + mEmergencyCallbackModeRegistrant.notifyRegistrant(); + } + break; + + case RIL_UNSOL_CDMA_CALL_WAITING: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mCallWaitingInfoRegistrants != null) { + mCallWaitingInfoRegistrants.notifyRegistrants( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mOtaProvisionRegistrants != null) { + mOtaProvisionRegistrants.notifyRegistrants( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_CDMA_INFO_REC: + ArrayList listInfoRecs; + + try { + listInfoRecs = (ArrayList)ret; + } catch (ClassCastException e) { + Log.e(LOG_TAG, "Unexpected exception casting to listInfoRecs", e); + break; + } + + for (CdmaInformationRecords rec : listInfoRecs) { + if (RILJ_LOGD) unsljLogRet(response, rec); + notifyRegistrantsCdmaInfoRec(rec); + } + break; + + case RIL_UNSOL_OEM_HOOK_RAW: + if (RILJ_LOGD) unsljLogvRet(response, IccUtils.bytesToHexString((byte[])ret)); + if (mUnsolOemHookRawRegistrant != null) { + mUnsolOemHookRawRegistrant.notifyRegistrant(new AsyncResult(null, ret, null)); + } + break; + + case RIL_UNSOL_RINGBACK_TONE: + if (RILJ_LOGD) unsljLogvRet(response, ret); + if (mRingbackToneRegistrants != null) { + boolean playtone = (((int[])ret)[0] == 1); + mRingbackToneRegistrants.notifyRegistrants( + new AsyncResult (null, playtone, null)); + } + break; + + case RIL_UNSOL_RESEND_INCALL_MUTE: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mResendIncallMuteRegistrants != null) { + mResendIncallMuteRegistrants.notifyRegistrants( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mCdmaSubscriptionChangedRegistrants != null) { + mCdmaSubscriptionChangedRegistrants.notifyRegistrants( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mExitEmergencyCallbackModeRegistrants != null) { + mExitEmergencyCallbackModeRegistrants.notifyRegistrants( + new AsyncResult (null, null, null)); + } + break; + + case RIL_UNSOL_RIL_CONNECTED: { + if (RILJ_LOGD) unsljLogRet(response, ret); + + // Initial conditions + setRadioPower(false, null); + setPreferredNetworkType(mPreferredNetworkType, null); + setCdmaSubscriptionSource(mCdmaSubscription, null); + notifyRegistrantsRilConnectionChanged(((int[])ret)[0]); + break; + } + } + } + + /** + * Notifiy 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)); + } + } + + static String + responseToString(int request) + { + /* + cat libs/telephony/ril_unsol_commands.h \ + | egrep "^ *{RIL_" \ + | sed -re 's/\{RIL_([^,]+),[^,]+,([^}]+).+/case RIL_\1: return "\1";/' + */ + switch(request) { + case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: return "UNSOL_RESPONSE_RADIO_STATE_CHANGED"; + case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: return "UNSOL_RESPONSE_CALL_STATE_CHANGED"; + case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED: return "UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED"; + case RIL_UNSOL_RESPONSE_NEW_SMS: return "UNSOL_RESPONSE_NEW_SMS"; + case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT: return "UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT"; + case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM: return "UNSOL_RESPONSE_NEW_SMS_ON_SIM"; + case RIL_UNSOL_ON_USSD: return "UNSOL_ON_USSD"; + case RIL_UNSOL_ON_USSD_REQUEST: return "UNSOL_ON_USSD_REQUEST"; + case RIL_UNSOL_NITZ_TIME_RECEIVED: return "UNSOL_NITZ_TIME_RECEIVED"; + case RIL_UNSOL_SIGNAL_STRENGTH: return "UNSOL_SIGNAL_STRENGTH"; + case RIL_UNSOL_DATA_CALL_LIST_CHANGED: return "UNSOL_DATA_CALL_LIST_CHANGED"; + case RIL_UNSOL_SUPP_SVC_NOTIFICATION: return "UNSOL_SUPP_SVC_NOTIFICATION"; + case RIL_UNSOL_STK_SESSION_END: return "UNSOL_STK_SESSION_END"; + case RIL_UNSOL_STK_PROACTIVE_COMMAND: return "UNSOL_STK_PROACTIVE_COMMAND"; + case RIL_UNSOL_STK_EVENT_NOTIFY: return "UNSOL_STK_EVENT_NOTIFY"; + case RIL_UNSOL_STK_CALL_SETUP: return "UNSOL_STK_CALL_SETUP"; + case RIL_UNSOL_SIM_SMS_STORAGE_FULL: return "UNSOL_SIM_SMS_STORAGE_FULL"; + case RIL_UNSOL_SIM_REFRESH: return "UNSOL_SIM_REFRESH"; + case RIL_UNSOL_CALL_RING: return "UNSOL_CALL_RING"; + case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED: return "UNSOL_RESPONSE_SIM_STATUS_CHANGED"; + case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS: return "UNSOL_RESPONSE_CDMA_NEW_SMS"; + case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS: return "UNSOL_RESPONSE_NEW_BROADCAST_SMS"; + case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL: return "UNSOL_CDMA_RUIM_SMS_STORAGE_FULL"; + case RIL_UNSOL_RESTRICTED_STATE_CHANGED: return "UNSOL_RESTRICTED_STATE_CHANGED"; + case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: return "UNSOL_ENTER_EMERGENCY_CALLBACK_MODE"; + case RIL_UNSOL_CDMA_CALL_WAITING: return "UNSOL_CDMA_CALL_WAITING"; + case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS: return "UNSOL_CDMA_OTA_PROVISION_STATUS"; + case RIL_UNSOL_CDMA_INFO_REC: return "UNSOL_CDMA_INFO_REC"; + case RIL_UNSOL_OEM_HOOK_RAW: return "UNSOL_OEM_HOOK_RAW"; + case RIL_UNSOL_RINGBACK_TONE: return "UNSOL_RINGBACK_TONG"; + case RIL_UNSOL_RESEND_INCALL_MUTE: return "UNSOL_RESEND_INCALL_MUTE"; + case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED: return "CDMA_SUBSCRIPTION_SOURCE_CHANGED"; + case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: return "UNSOL_EXIT_EMERGENCY_CALLBACK_MODE"; + case RIL_UNSOL_RIL_CONNECTED: return "UNSOL_RIL_CONNECTED"; + case RIL_UNSOL_RESPONSE_TETHERED_MODE_STATE_CHANGED: return "RIL_UNSOL_RESPONSE_TETHERED_MODE_STATE_CHANGED"; + default: return ""; + } + } + +} diff --git a/telephony/java/com/android/internal/telephony/IccCard.java b/telephony/java/com/android/internal/telephony/IccCard.java index 955849d4699c8..88da40834c9f6 100644 --- a/telephony/java/com/android/internal/telephony/IccCard.java +++ b/telephony/java/com/android/internal/telephony/IccCard.java @@ -764,7 +764,9 @@ private State getAppState(int appIndex) { if (app.app_state.isPukRequired()) { return IccCard.State.PUK_REQUIRED; } - if (app.app_state.isSubscriptionPersoEnabled()) { + if (app.app_state.isSubscriptionPersoEnabled() && + (!(this.mPhone.mCM.getClass() == HuaweiRIL.class) || + app.perso_substate.isPersoSubStateNetworkLocked())) { return IccCard.State.NETWORK_LOCKED; } if (app.app_state.isAppReady()) { diff --git a/telephony/java/com/android/internal/telephony/IccCardApplication.java b/telephony/java/com/android/internal/telephony/IccCardApplication.java index abb740ef0c32a..3ae960380af51 100644 --- a/telephony/java/com/android/internal/telephony/IccCardApplication.java +++ b/telephony/java/com/android/internal/telephony/IccCardApplication.java @@ -94,6 +94,11 @@ public enum PersoSubState{ boolean isPersoSubStateUnknown() { return this == PERSOSUBSTATE_UNKNOWN; } + + boolean isPersoSubStateNetworkLocked() + { + return this == PERSOSUBSTATE_SIM_NETWORK; + } }; public AppType app_type; diff --git a/telephony/java/com/android/internal/telephony/IccCardStatus.java b/telephony/java/com/android/internal/telephony/IccCardStatus.java index c751a21f24de2..874727a004e4a 100644 --- a/telephony/java/com/android/internal/telephony/IccCardStatus.java +++ b/telephony/java/com/android/internal/telephony/IccCardStatus.java @@ -29,7 +29,8 @@ public class IccCardStatus { public enum CardState { CARDSTATE_ABSENT, CARDSTATE_PRESENT, - CARDSTATE_ERROR; + CARDSTATE_ERROR, + CARDSTATE_NOT_READY; boolean isCardPresent() { return this == CARDSTATE_PRESENT; @@ -82,6 +83,9 @@ public void setCardState(int state) { case 2: mCardState = CardState.CARDSTATE_ERROR; break; + case 3: + mCardState = CardState.CARDSTATE_NOT_READY; + break; default: throw new RuntimeException("Unrecognized RIL_CardState: " + state); } diff --git a/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java b/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java index e8d10f9172180..2fdf670d372b5 100644 --- a/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java +++ b/telephony/java/com/android/internal/telephony/gsm/SIMFileHandler.java @@ -19,6 +19,7 @@ import android.os.Message; import android.util.Log; +import com.android.internal.telephony.HuaweiRIL; import com.android.internal.telephony.IccCard; import com.android.internal.telephony.IccCardApplication; import com.android.internal.telephony.IccConstants; @@ -57,6 +58,12 @@ public void handleMessage(Message msg) { } protected String getEFPath(int efid) { + if (phone.mCM.getClass() == HuaweiRIL.class) { + IccCard icccard = phone.getIccCard(); + if (icccard != null && icccard.isApplicationOnIcc(IccCardApplication.AppType.APPTYPE_USIM)) + return getEFPathForUICC(efid); + } + // TODO(): DF_GSM can be 7F20 or 7F21 to handle backward compatibility. // Implement this after discussion with OEMs. switch(efid) { @@ -102,6 +109,41 @@ protected String getEFPath(int efid) { return path; } + protected String getEFPathForUICC(int efid) { + switch (efid) { + case EF_SMS: + case EF_EXT6: + case EF_MWIS: + case EF_MBI: + case EF_SPN: + case EF_AD: + case EF_MBDN: + case EF_PNN: + case EF_SPDI: + case EF_SST: + case EF_CFIS: + case EF_MAILBOX_CPHS: + case EF_VOICE_MAIL_INDICATOR_CPHS: + case EF_CFF_CPHS: + case EF_SPN_CPHS: + case EF_SPN_SHORT_CPHS: + case EF_INFO_CPHS: + case EF_PBR: + case EF_MSISDN: + case EF_FDN: + return MF_SIM + DF_ADFISIM; + + case EF_CSP_CPHS: + // we only support global phonebook. + return MF_SIM + DF_TELECOM + DF_PHONEBOOK; + + } + String path = getCommonIccEFPath(efid); + if (path == null) + Log.e(LOG_TAG, "Error: EF Path being returned in null"); + return path; + } + protected void logd(String msg) { Log.d(LOG_TAG, "[SIMFileHandler] " + msg); }