android_device_samsung_msm8.../ril/SamsungMSM8226DSRIL.java
2015-06-11 14:36:14 +02:00

460 lines
17 KiB
Java

/*
* Copyright (c) 2014, The CyanogenMod Project. All rights reserved.
*
* 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.media.AudioManager;
import android.os.AsyncResult;
import android.os.Message;
import android.os.Parcel;
import android.os.SystemProperties;
import android.telephony.Rlog;
import android.telephony.SignalStrength;
import android.telephony.PhoneNumberUtils;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import com.android.internal.telephony.uicc.IccCardApplicationStatus;
import com.android.internal.telephony.uicc.IccCardStatus;
/**
* Qualcomm RIL for Samsung MSM8226 Dual-sim devices
* {@hide}
*/
public class SamsungMSM8226DSRIL extends RIL {
private AudioManager mAudioManager;
public SamsungMSM8226DSRIL(Context context, int preferredNetworkType,
int cdmaSubscription, Integer instanceId) {
super(context, preferredNetworkType, cdmaSubscription, instanceId);
mAudioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
mQANElements = 6;
}
public SamsungMSM8226DSRIL(Context context, int networkMode,
int cdmaSubscription) {
super(context, networkMode, cdmaSubscription);
mAudioManager = (AudioManager)mContext.getSystemService(Context.AUDIO_SERVICE);
mQANElements = 6;
}
@Override
public void acceptCall(Message result) {
RILRequest rr = RILRequest.obtain(RIL_REQUEST_ANSWER, result);
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
rr.mParcel.writeInt(1);
rr.mParcel.writeInt(0);
send(rr);
}
@Override
protected Object
responseIccCardStatus(Parcel p) {
IccCardApplicationStatus appStatus;
IccCardStatus cardStatus = new IccCardStatus();
cardStatus.setCardState(p.readInt());
cardStatus.setUniversalPinState(p.readInt());
cardStatus.mGsmUmtsSubscriptionAppIndex = p.readInt();
cardStatus.mCdmaSubscriptionAppIndex = p.readInt();
cardStatus.mImsSubscriptionAppIndex = p.readInt();
int numApplications = p.readInt();
// limit to maximum allowed applications
if (numApplications > IccCardStatus.CARD_MAX_APPS) {
numApplications = IccCardStatus.CARD_MAX_APPS;
}
cardStatus.mApplications = new IccCardApplicationStatus[numApplications];
for (int i = 0 ; i < numApplications ; i++) {
appStatus = new IccCardApplicationStatus();
appStatus.app_type = appStatus.AppTypeFromRILInt(p.readInt());
appStatus.app_state = appStatus.AppStateFromRILInt(p.readInt());
appStatus.perso_substate = appStatus.PersoSubstateFromRILInt(p.readInt());
appStatus.aid = p.readString();
appStatus.app_label = p.readString();
appStatus.pin1_replaced = p.readInt();
appStatus.pin1 = appStatus.PinStateFromRILInt(p.readInt());
appStatus.pin2 = appStatus.PinStateFromRILInt(p.readInt());
p.readInt(); // remaining_count_pin1 - pin1_num_retries
p.readInt(); // remaining_count_puk1 - puk1_num_retries
p.readInt(); // remaining_count_pin2 - pin2_num_retries
p.readInt(); // remaining_count_puk2 - puk2_num_retries
p.readInt(); // - perso_unblock_retries
cardStatus.mApplications[i] = appStatus;
}
return cardStatus;
}
@Override
protected Object
responseSignalStrength(Parcel p) {
int gsmSignalStrength = (p.readInt() & 0xff00)/85;
int gsmBitErrorRate = p.readInt();
int cdmaDbm = p.readInt();
int cdmaEcio = p.readInt();
int evdoDbm = p.readInt();
int evdoEcio = p.readInt();
int evdoSnr = p.readInt();
int lteSignalStrength = p.readInt();
int lteRsrp = p.readInt();
int lteRsrq = p.readInt();
int lteRssnr = p.readInt();
int lteCqi = p.readInt();
int tdScdmaRscp = p.readInt();
// constructor sets default true, makeSignalStrengthFromRilParcel does not set it
boolean isGsm = true;
if ((lteSignalStrength & 0xff) == 255 || lteSignalStrength == 99) {
lteSignalStrength = 99;
lteRsrp = SignalStrength.INVALID;
lteRsrq = SignalStrength.INVALID;
lteRssnr = SignalStrength.INVALID;
lteCqi = SignalStrength.INVALID;
} else {
lteSignalStrength &= 0xff;
}
if (RILJ_LOGD)
riljLog("gsmSignalStrength:" + gsmSignalStrength + " gsmBitErrorRate:" + gsmBitErrorRate +
" cdmaDbm:" + cdmaDbm + " cdmaEcio:" + cdmaEcio + " evdoDbm:" + evdoDbm +
" evdoEcio: " + evdoEcio + " evdoSnr:" + evdoSnr +
" lteSignalStrength:" + lteSignalStrength + " lteRsrp:" + lteRsrp +
" lteRsrq:" + lteRsrq + " lteRssnr:" + lteRssnr + " lteCqi:" + lteCqi +
" tdScdmaRscp:" + tdScdmaRscp + " isGsm:" + (isGsm ? "true" : "false"));
return new SignalStrength(gsmSignalStrength, gsmBitErrorRate, cdmaDbm, cdmaEcio, evdoDbm,
evdoEcio, evdoSnr, lteSignalStrength, lteRsrp, lteRsrq, lteRssnr, lteCqi,
tdScdmaRscp, isGsm);
}
@Override
protected Object
responseCallList(Parcel p) {
int num;
int voiceSettings;
ArrayList<DriverCall> response;
DriverCall dc;
num = p.readInt();
response = new ArrayList<DriverCall>(num);
if (RILJ_LOGV) {
riljLog("responseCallList: num=" + num +
" mEmergencyCallbackModeRegistrant=" + mEmergencyCallbackModeRegistrant +
" mTestingEmergencyCall=" + mTestingEmergencyCall.get());
}
for (int i = 0 ; i < num ; i++) {
dc = new DriverCall();
dc.state = DriverCall.stateFromCLCC(p.readInt());
dc.index = p.readInt() & 0xff;
dc.TOA = p.readInt();
dc.isMpty = (0 != p.readInt());
dc.isMT = (0 != p.readInt());
dc.als = p.readInt();
voiceSettings = p.readInt();
dc.isVoice = (0 == voiceSettings) ? false : true;
p.readInt(); // is video
p.readInt(); // samsung call detail
p.readInt(); // samsung call detail
p.readString(); // samsung call detail
dc.isVoicePrivacy = (0 != p.readInt());
dc.number = p.readString();
int np = p.readInt();
dc.numberPresentation = DriverCall.presentationFromCLIP(np);
dc.name = p.readString();
dc.namePresentation = p.readInt();
int uusInfoPresent = p.readInt();
if (uusInfoPresent == 1) {
dc.uusInfo = new UUSInfo();
dc.uusInfo.setType(p.readInt());
dc.uusInfo.setDcs(p.readInt());
byte[] userData = p.createByteArray();
dc.uusInfo.setUserData(userData);
riljLogv(String.format("Incoming UUS : type=%d, dcs=%d, length=%d",
dc.uusInfo.getType(), dc.uusInfo.getDcs(),
dc.uusInfo.getUserData().length));
riljLogv("Incoming UUS : data (string)="
+ new String(dc.uusInfo.getUserData()));
riljLogv("Incoming UUS : data (hex): "
+ IccUtils.bytesToHexString(dc.uusInfo.getUserData()));
} else {
riljLogv("Incoming UUS : NOT present!");
}
// Make sure there's a leading + on addresses with a TOA of 145
dc.number = PhoneNumberUtils.stringFromStringAndTOA(dc.number, dc.TOA);
response.add(dc);
if (dc.isVoicePrivacy) {
mVoicePrivacyOnRegistrants.notifyRegistrants();
riljLog("InCall VoicePrivacy is enabled");
} else {
mVoicePrivacyOffRegistrants.notifyRegistrants();
riljLog("InCall VoicePrivacy is disabled");
}
}
Collections.sort(response);
if ((num == 0) && mTestingEmergencyCall.getAndSet(false)) {
if (mEmergencyCallbackModeRegistrant != null) {
riljLog("responseCallList: call ended, testing emergency call," +
" notify ECM Registrants");
mEmergencyCallbackModeRegistrant.notifyRegistrant();
}
}
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) {
// SAMSUNG STATES
case 11010: // RIL_UNSOL_AM:
ret = responseString(p);
String amString = (String) ret;
Rlog.d(RILJ_LOG_TAG, "Executing AM: " + amString);
try {
Runtime.getRuntime().exec("am " + amString);
} catch (IOException e) {
e.printStackTrace();
Rlog.e(RILJ_LOG_TAG, "am " + amString + " could not be executed.");
}
break;
case 11021: // RIL_UNSOL_RESPONSE_HANDOVER:
ret = responseVoid(p);
break;
case 1036:
ret = responseVoid(p);
break;
case 11017: // RIL_UNSOL_WB_AMR_STATE:
ret = responseInts(p);
setWbAmr(((int[])ret)[0]);
break;
default:
// Rewind the Parcel
p.setDataPosition(dataPosition);
// Forward responses that we are not overriding to the super class
super.processUnsolicited(p);
return;
}
}
@Override
protected RILRequest
processSolicited (Parcel p) {
int serial, error;
boolean found = false;
int dataPosition = p.dataPosition(); // save off position within the Parcel
serial = p.readInt();
error = p.readInt();
RILRequest rr = null;
/* Pre-process the reply before popping it */
synchronized (mRequestList) {
RILRequest tr = mRequestList.get(serial);
if (tr != null && tr.mSerial == serial) {
if (error == 0 || p.dataAvail() > 0) {
try {switch (tr.mRequest) {
/* Get those we're interested in */
case RIL_REQUEST_DATA_REGISTRATION_STATE:
rr = tr;
break;
}} catch (Throwable thr) {
// Exceptions here usually mean invalid RIL responses
if (tr.mResult != null) {
AsyncResult.forMessage(tr.mResult, null, thr);
tr.mResult.sendToTarget();
}
return tr;
}
}
}
}
if (rr == null) {
/* Nothing we care about, go up */
p.setDataPosition(dataPosition);
// Forward responses that we are not overriding to the super class
return super.processSolicited(p);
}
rr = findAndRemoveRequestFromList(serial);
if (rr == null) {
return rr;
}
Object ret = null;
if (error == 0 || p.dataAvail() > 0) {
switch (rr.mRequest) {
case RIL_REQUEST_DATA_REGISTRATION_STATE: ret = responseDataRegistrationState(p); break;
default:
throw new RuntimeException("Unrecognized solicited response: " + rr.mRequest);
}
//break;
}
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();
}
return rr;
}
private Object
responseDataRegistrationState(Parcel p) {
String response[] = (String[])responseStrings(p); // all data from parcell get popped
/* DANGER WILL ROBINSON
* In some cases from Vodaphone we are receiving a RAT of 102
* while in tunnels of the metro. Lets Assume that if we
* receive 102 we actually want a RAT of 2 for EDGE service */
if (response.length > 4 &&
response[0].equals("1") &&
response[3].equals("102")) {
response[3] = "2";
}
return response;
}
/**
* Set audio parameter "wb_amr" for HD-Voice (Wideband AMR).
*
* @param state: 0 = unsupported, 1 = supported.
*/
private void setWbAmr(int state) {
if (state == 1) {
Rlog.d(RILJ_LOG_TAG, "setWbAmr(): setting audio parameter - wb_amr=on");
mAudioManager.setParameters("wide_voice_enable=true");
}else if (state == 0) {
Rlog.d(RILJ_LOG_TAG, "setWbAmr(): setting audio parameter - wb_amr=off");
mAudioManager.setParameters("wide_voice_enable=false");
}
}
@Override
public void
dial(String address, int clirMode, UUSInfo uusInfo, Message result) {
if (PhoneNumberUtils.isEmergencyNumber(address)) {
dialEmergencyCall(address, clirMode, result);
return;
}
RILRequest rr = RILRequest.obtain(RIL_REQUEST_DIAL, result);
rr.mParcel.writeString(address);
rr.mParcel.writeInt(clirMode);
rr.mParcel.writeInt(0);
rr.mParcel.writeInt(1);
rr.mParcel.writeString("");
if (uusInfo == null) {
rr.mParcel.writeInt(0); // UUS information is absent
} else {
rr.mParcel.writeInt(1); // UUS information is present
rr.mParcel.writeInt(uusInfo.getType());
rr.mParcel.writeInt(uusInfo.getDcs());
rr.mParcel.writeByteArray(uusInfo.getUserData());
}
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
static final int RIL_REQUEST_DIAL_EMERGENCY = 10016;
private void
dialEmergencyCall(String address, int clirMode, Message result) {
RILRequest rr;
Rlog.v(RILJ_LOG_TAG, "Emergency dial: " + address);
rr = RILRequest.obtain(RIL_REQUEST_DIAL_EMERGENCY, result);
rr.mParcel.writeString(address + "/");
rr.mParcel.writeInt(clirMode);
rr.mParcel.writeInt(0); // UUS information is absent
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@Override
public void setUiccSubscription(int slotId, int appIndex, int subId,
int subStatus, Message result) {
//Note: This RIL request is also valid for SIM and RUIM (ICC card)
RILRequest rr = RILRequest.obtain(115, result);
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ " slot: " + slotId + " appIndex: " + appIndex
+ " subId: " + subId + " subStatus: " + subStatus);
rr.mParcel.writeInt(slotId);
rr.mParcel.writeInt(appIndex);
rr.mParcel.writeInt(subId);
rr.mParcel.writeInt(subStatus);
send(rr);
}
@Override
public void setDataAllowed(boolean allowed, Message result) {
int req = 123;
RILRequest rr;
if (allowed)
{
req = 116;
rr = RILRequest.obtain(req, result);
}
else
{
rr = RILRequest.obtain(req, result);
rr.mParcel.writeInt(1);
rr.mParcel.writeInt(allowed ? 1 : 0);
}
send(rr);
}
private void logParcel(Parcel p) {
StringBuffer s = new StringBuffer();
byte [] bytes = p.marshall();
for (int i = 0; i < bytes.length; i++) {
if (i > 0) s.append(" ");
if (i == p.dataPosition()) s.append("*** ");
s.append(bytes[i]);
}
riljLog("parcel position=" + p.dataPosition() + ": " + s);
}
}