From 488effe65db1526345a38030c6890a03241355cf Mon Sep 17 00:00:00 2001 From: Giulio Cervera Date: Fri, 20 Jul 2012 16:32:04 +0200 Subject: telephony: Add Sony RIL for Qualcomm basebands Change-Id: Iae6e7c17c4892e711d6da3ef34e523cda33bcbe5 --- .../internal/telephony/SonyQualcommRIL.java | 476 +++++++++++++++++++++ 1 file changed, 476 insertions(+) create mode 100644 telephony/java/com/android/internal/telephony/SonyQualcommRIL.java diff --git a/telephony/java/com/android/internal/telephony/SonyQualcommRIL.java b/telephony/java/com/android/internal/telephony/SonyQualcommRIL.java new file mode 100644 index 0000000..ffd03e1 --- /dev/null +++ b/telephony/java/com/android/internal/telephony/SonyQualcommRIL.java @@ -0,0 +1,476 @@ +/* + * 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 java.util.ArrayList; + +/** + * Custom Qualcomm No SimReady RIL for Sony + * + * {@hide} + */ + +public class SonyQualcommRIL extends RIL implements CommandsInterface { + protected String mAid = ""; + protected HandlerThread mIccThread; + protected IccHandler mIccHandler; + 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 = 10; + + public SonyQualcommRIL(Context context, int networkMode, int cdmaSubscription) { + super(context, networkMode, cdmaSubscription); + } + + @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); + + 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: " + requestToString(rr.mRequest) + + " 0x" + Integer.toHexString(command) + + " 0x" + Integer.toHexString(fileid) + " " + + " path: " + path + "," + + p1 + "," + p2 + "," + p3); + + send(rr); + } + + @Override public void + supplyIccPin(String pin, Message result) { + supplyIccPinForApp(pin, mAid, result); + } + + @Override public void + changeIccPin(String oldPin, String newPin, Message result) { + changeIccPinForApp(oldPin, newPin, mAid, result); + } + + @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 + 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); + } + + updateIccType(status); + return status; + } + + private void updateIccType(IccCardStatus icccardstatus) + { + IccCardApplication.AppType apptype = IccCardApplication.AppType.APPTYPE_UNKNOWN; + if(icccardstatus.getNumApplications() > 0) + { + CommandsInterface.RadioState radiostate = getRadioState(); + int i; + IccCardApplication icccardapplication; + if(radiostate == CommandsInterface.RadioState.RUIM_LOCKED_OR_ABSENT || radiostate == CommandsInterface.RadioState.RUIM_NOT_READY || radiostate == CommandsInterface.RadioState.RUIM_READY) + i = icccardstatus.getCdmaSubscriptionAppIndex(); + else + i = icccardstatus.getGsmUmtsSubscriptionAppIndex(); + icccardapplication = icccardstatus.getApplication(i); + Log.i("RILJ", (new StringBuilder()).append("app_state ").append(icccardapplication.app_state).append(", perso_substate ").append(icccardapplication.perso_substate).append(", app_type ").append(icccardapplication.app_type).toString()); + mAid = icccardapplication.aid; + riljLog((new StringBuilder()).append("Will use ").append(mAid).append(" as default application id. Hopefully you wont mind").toString()); + apptype = icccardapplication.app_type; + } + SystemProperties.set("ril.icctype", Integer.toString(apptype.ordinal())); + } + + @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() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + @Override + protected Object + responseOperatorInfos(Parcel p) { + String strings[] = (String [])responseStrings(p); + ArrayList ret; + + if (strings.length % 5 != 0) { + throw new RuntimeException( + "RIL_REQUEST_QUERY_AVAILABLE_NETWORKS: invalid response. Got " + + strings.length + " strings, expected multible of 5"); + } + + ret = new ArrayList(strings.length / 4); + + for (int i = 0 ; i < strings.length ; i += 5) { + ret.add ( + new OperatorInfo( + strings[i+0], + strings[i+1], + strings[i+2], + strings[i+3])); + } + return ret; + } + + @Override + public void + dial(String address, int clirMode, UUSInfo uusInfo, Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_DIAL, result); + + rr.mp.writeString(address); + rr.mp.writeInt(clirMode); + + if (uusInfo == null) { + rr.mp.writeInt(0); // UUS information is absent + } else { + rr.mp.writeInt(1); // UUS information is present + rr.mp.writeInt(uusInfo.getType()); + rr.mp.writeInt(uusInfo.getDcs()); + rr.mp.writeByteArray(uusInfo.getUserData()); + } + rr.mp.writeInt(255); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + setNetworkSelectionMode(String operatorNumeric, Message response) { + RILRequest rr; + + if (operatorNumeric == null) + rr = RILRequest.obtain(RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC, response); + else + rr = RILRequest.obtain(RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL, response); + + rr.mp.writeString(operatorNumeric); + rr.mp.writeInt(-1); + + send(rr); + } + + @Override + public void + setNetworkSelectionModeAutomatic(Message response) { + setNetworkSelectionMode(null, response); + } + + @Override + public void + setNetworkSelectionModeManual(String operatorNumeric, Message response) { + setNetworkSelectionMode(operatorNumeric, response); + } + + @Override + protected Object + responseSignalStrength(Parcel p) { + int numInts = 12; + int response[]; + + boolean noLte = false; + + /* TODO: Add SignalStrength class to match RIL_SignalStrength */ + response = new int[numInts]; + for (int i = 0 ; i < numInts ; i++) { + if (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) { + response[i] *= -1; + } + } + + return response; + } + + @Override + protected void + processUnsolicited (Parcel p) { + Object ret; + int dataPosition = p.dataPosition(); // save off position within the Parcel + int response = p.readInt(); + + switch(response) { + case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: ret = responseVoid(p); break; + + 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; + } + } + + 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: + if (mIccHandler == null) { + handlerThread = new HandlerThread("IccHandler"); + mIccThread = handlerThread; + + mIccThread.start(); + + looper = mIccThread.getLooper(); + mIccHandler = new IccHandler(this,looper); + mIccHandler.run(); + } + if (mPhoneType == RILConstants.CDMA_PHONE) { + radioState = CommandsInterface.RadioState.RUIM_NOT_READY; + } else { + radioState = CommandsInterface.RadioState.SIM_NOT_READY; + } + break; + default: + throw new RuntimeException("Unrecognized RIL_RadioState: " + stateCode); + } + + setRadioState(radioState); + } + + class IccHandler extends Handler implements Runnable { + private static final int EVENT_GET_ICC_STATUS_DONE = 1; + private static final int EVENT_ICC_STATUS_CHANGED = 2; + private static final int EVENT_RADIO_ON = 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; + } + if (mPhoneType == RILConstants.CDMA_PHONE) { + mRil.setRadioState(CommandsInterface.RadioState.RUIM_LOCKED_OR_ABSENT); + } else { + mRil.setRadioState(CommandsInterface.RadioState.SIM_LOCKED_OR_ABSENT); + } + } 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: + mRil.setRadioState(CommandsInterface.RadioState.SIM_LOCKED_OR_ABSENT); + break; + case APPTYPE_RUIM: + mRil.setRadioState(CommandsInterface.RadioState.RUIM_LOCKED_OR_ABSENT); + 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: + mRil.setRadioState(CommandsInterface.RadioState.SIM_READY); + break; + case APPTYPE_RUIM: + mRil.setRadioState(CommandsInterface.RadioState.RUIM_READY); + 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); + } + } +} -- cgit v1.1