/*
* 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.HandlerThread;
import android.os.Looper;
import android.os.Message;
import android.os.Parcel;
import android.text.TextUtils;
import android.util.Log;
import java.util.ArrayList;
/**
* Qualcomm RIL class for basebands that do not send the SIM status
* piggybacked in RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED. Instead,
* these radios will send radio state and we have to query for SIM
* status separately.
*
* {@hide}
*/
public class HTCQualcommRIL extends QualcommSharedRIL implements CommandsInterface {
private final int RIL_INT_RADIO_OFF = 0;
private final int RIL_INT_RADIO_UNAVAILABLE = 1;
private final int RIL_INT_RADIO_ON = 13;
public HTCQualcommRIL(Context context, int networkMode, int cdmaSubscription) {
super(context, networkMode, cdmaSubscription);
}
@Override
protected Object
responseIccCardStatus(Parcel p) {
IccCardApplication ca;
// use old needsOldRilFeature method for feature. it would be redundant to make
// a new method just for naming sake.
boolean subscriptionFromSource = needsOldRilFeature("subscriptionFromSource");
boolean oldRil = needsOldRilFeature("icccardstatus");
IccCardStatus status = new IccCardStatus();
status.setCardState(p.readInt());
status.setUniversalPinState(p.readInt());
status.setGsmUmtsSubscriptionAppIndex(p.readInt());
status.setCdmaSubscriptionAppIndex(p.readInt());
if (!oldRil)
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());
if ((ca.app_state == IccCardApplication.AppState.APPSTATE_SUBSCRIPTION_PERSO) &&
((ca.perso_substate == IccCardApplication.PersoSubState.PERSOSUBSTATE_READY) ||
(ca.perso_substate == IccCardApplication.PersoSubState.PERSOSUBSTATE_UNKNOWN))) {
// ridiculous HTC hack
ca.app_state = IccCardApplication.AppState.APPSTATE_UNKNOWN;
Log.d(LOG_TAG, "ca.app_state == AppState.APPSTATE_SUBSCRIPTION_PERSO");
Log.d(LOG_TAG, "ca.perso_substate == PersoSubState.PERSOSUBSTATE_READY");
}
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);
}
// use ril response to determine subscription source
if (subscriptionFromSource)
return status;
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 Object
responseSignalStrength(Parcel p) {
int numInts = 14;
int response[];
/* HTC signal strength format:
* 0: GW_SignalStrength
* 1: GW_SignalStrength.bitErrorRate
* 2: CDMA_SignalStrength.dbm
* 3: CDMA_SignalStrength.ecio
* 4: EVDO_SignalStrength.dbm
* 5: EVDO_SignalStrength.ecio
* 6: EVDO_SignalStrength.signalNoiseRatio
* 7: ATT_SignalStrength.dbm
* 8: ATT_SignalStrength.ecno
* 9: LTE_SignalStrength.signalStrength
* 10: LTE_SignalStrength.rsrp
* 11: LTE_SignalStrength.rsrq
* 12: LTE_SignalStrength.rssnr
* 13: LTE_SignalStrength.cqi
*/
response = new int[numInts];
for (int i = 0; i < numInts; i++) {
if (i > 8) {
response[i-2] = p.readInt();
response[i] = -1;
} else {
response[i] = p.readInt();
}
}
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;
case 21004: ret = responseVoid(p); break; // RIL_UNSOL_VOICE_RADIO_TECH_CHANGED
case 21005: ret = responseVoid(p); break; // RIL_UNSOL_IMS_NETWORK_STATE_CHANGED
case 21007: 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 21004:
case 21005:
case 21007:
if (RILJ_LOGD) unsljLogRet(response, ret);
if (mExitEmergencyCallbackModeRegistrants != null) {
mExitEmergencyCallbackModeRegistrants.notifyRegistrants(
new AsyncResult (null, null, null));
}
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_UNAVAILABLE:
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();
}
radioState = CommandsInterface.RadioState.RADIO_ON;
break;
default:
throw new RuntimeException("Unrecognized RIL_RadioState: " + stateCode);
}
setRadioState(radioState);
}
}