mirror of
https://github.com/S3NEO/android_device_samsung_msm8226-common.git
synced 2024-11-06 21:55:45 +00:00
460 lines
17 KiB
Java
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);
|
|
}
|
|
}
|