blob: 775b15e194d2d921718a1d2b3696a255cf16d749 [file] [log] [blame]
/*
* Copyright (C) 2011 The CyanogenMod Project <http://www.cyanogenmod.org>
* Copyright (C) 2014 MaclawStudio
*
* 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 static android.telephony.TelephonyManager.NETWORK_TYPE_UNKNOWN;
import static android.telephony.TelephonyManager.NETWORK_TYPE_EDGE;
import static android.telephony.TelephonyManager.NETWORK_TYPE_GPRS;
import static android.telephony.TelephonyManager.NETWORK_TYPE_UMTS;
import static android.telephony.TelephonyManager.NETWORK_TYPE_HSDPA;
import static android.telephony.TelephonyManager.NETWORK_TYPE_HSUPA;
import static android.telephony.TelephonyManager.NETWORK_TYPE_HSPA;
import com.android.internal.telephony.CommandException;
import com.android.internal.telephony.dataconnection.DataCallResponse;
import com.android.internal.telephony.dataconnection.DcFailCause;
import com.android.internal.telephony.RILConstants;
import com.android.internal.telephony.cdma.CdmaInformationRecords.CdmaSignalInfoRec;
import com.android.internal.telephony.cdma.SignalToneUtil;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.res.Resources;
import android.net.ConnectivityManager;
import android.net.LocalSocket;
import android.net.LocalSocketAddress;
import android.net.NetworkInfo;
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.os.PowerManager;
import android.os.PowerManager.WakeLock;
import android.telephony.NeighboringCellInfo;
import android.telephony.PhoneNumberUtils;
import android.telephony.SignalStrength;
import android.telephony.SmsManager;
import android.telephony.SmsMessage;
import android.text.TextUtils;
import android.telephony.Rlog;
import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo;
import com.android.internal.telephony.gsm.SuppServiceNotification;
import com.android.internal.telephony.cdma.CdmaCallWaitingNotification;
import com.android.internal.telephony.cdma.CdmaInformationRecords;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.Runtime;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
public class SamsungRIL extends RIL implements CommandsInterface {
//SAMSUNG STATES
static final int RIL_REQUEST_GET_CELL_BROADCAST_CONFIG = 10002;
static final int RIL_REQUEST_SEND_ENCODED_USSD = 10005;
static final int RIL_REQUEST_SET_PDA_MEMORY_STATUS = 10006;
static final int RIL_REQUEST_GET_PHONEBOOK_STORAGE_INFO = 10007;
static final int RIL_REQUEST_GET_PHONEBOOK_ENTRY = 10008;
static final int RIL_REQUEST_ACCESS_PHONEBOOK_ENTRY = 10009;
static final int RIL_REQUEST_DIAL_VIDEO_CALL = 10010;
static final int RIL_REQUEST_CALL_DEFLECTION = 10011;
static final int RIL_REQUEST_READ_SMS_FROM_SIM = 10012;
static final int RIL_REQUEST_USIM_PB_CAPA = 10013;
static final int RIL_REQUEST_LOCK_INFO = 10014;
static final int RIL_REQUEST_DIAL_EMERGENCY = 10016;
static final int RIL_REQUEST_GET_STOREAD_MSG_COUNT = 10017;
static final int RIL_REQUEST_STK_SIM_INIT_EVENT = 10018;
static final int RIL_REQUEST_GET_LINE_ID = 10019;
static final int RIL_REQUEST_SET_LINE_ID = 10020;
static final int RIL_REQUEST_GET_SERIAL_NUMBER = 10021;
static final int RIL_REQUEST_GET_MANUFACTURE_DATE_NUMBER = 10022;
static final int RIL_REQUEST_GET_BARCODE_NUMBER = 10023;
static final int RIL_REQUEST_UICC_GBA_AUTHENTICATE_BOOTSTRAP = 10024;
static final int RIL_REQUEST_UICC_GBA_AUTHENTICATE_NAF = 10025;
static final int RIL_REQUEST_SIM_TRANSMIT_BASIC = 10026;
static final int RIL_REQUEST_SIM_OPEN_CHANNEL = 10027;
static final int RIL_REQUEST_SIM_CLOSE_CHANNEL = 10028;
static final int RIL_REQUEST_SIM_TRANSMIT_CHANNEL = 10029;
static final int RIL_REQUEST_SIM_AUTH = 10030;
static final int RIL_REQUEST_PS_ATTACH = 10031;
static final int RIL_REQUEST_PS_DETACH = 10032;
static final int RIL_REQUEST_ACTIVATE_DATA_CALL = 10033;
static final int RIL_REQUEST_CHANGE_SIM_PERSO = 10034;
static final int RIL_REQUEST_ENTER_SIM_PERSO = 10035;
static final int RIL_REQUEST_GET_TIME_INFO = 10036;
static final int RIL_REQUEST_OMADM_SETUP_SESSION = 10037;
static final int RIL_REQUEST_OMADM_SERVER_START_SESSION = 10038;
static final int RIL_REQUEST_OMADM_CLIENT_START_SESSION = 10039;
static final int RIL_REQUEST_OMADM_SEND_DATA = 10040;
static final int RIL_REQUEST_CDMA_GET_DATAPROFILE = 10041;
static final int RIL_REQUEST_CDMA_SET_DATAPROFILE = 10042;
static final int RIL_REQUEST_CDMA_GET_SYSTEMPROPERTIES = 10043;
static final int RIL_REQUEST_CDMA_SET_SYSTEMPROPERTIES = 10044;
static final int RIL_REQUEST_SEND_SMS_COUNT = 10045;
static final int RIL_REQUEST_SEND_SMS_MSG = 10046;
static final int RIL_REQUEST_SEND_SMS_MSG_READ_STATUS = 10047;
static final int RIL_REQUEST_MODEM_HANGUP = 10048;
static final int RIL_REQUEST_SET_SIM_POWER = 10049;
static final int RIL_REQUEST_SET_PREFERRED_NETWORK_LIST = 10050;
static final int RIL_REQUEST_GET_PREFERRED_NETWORK_LIST = 10051;
static final int RIL_REQUEST_HANGUP_VT = 10052;
static final int RIL_UNSOL_RELEASE_COMPLETE_MESSAGE = 11001;
static final int RIL_UNSOL_STK_SEND_SMS_RESULT = 11002;
static final int RIL_UNSOL_STK_CALL_CONTROL_RESULT = 11003;
static final int RIL_UNSOL_DUN_CALL_STATUS = 11004;
static final int RIL_UNSOL_O2_HOME_ZONE_INFO = 11007;
static final int RIL_UNSOL_DEVICE_READY_NOTI = 11008;
static final int RIL_UNSOL_GPS_NOTI = 11009;
static final int RIL_UNSOL_AM = 11010;
static final int RIL_UNSOL_DUN_PIN_CONTROL_SIGNAL = 11011;
static final int RIL_UNSOL_DATA_SUSPEND_RESUME = 11012;
static final int RIL_UNSOL_SAP = 11013;
static final int RIL_UNSOL_SIM_SMS_STORAGE_AVAILALE = 11015;
static final int RIL_UNSOL_HSDPA_STATE_CHANGED = 11016;
static final int RIL_UNSOL_TWO_MIC_STATE = 11018;
static final int RIL_UNSOL_DHA_STATE = 11019;
static final int RIL_UNSOL_UART = 11020;
static final int RIL_UNSOL_RESPONSE_HANDOVER = 11021;
static final int RIL_UNSOL_IPV6_ADDR = 11022;
static final int RIL_UNSOL_NWK_INIT_DISC_REQUEST = 11023;
static final int RIL_UNSOL_RTS_INDICATION = 11024;
static final int RIL_UNSOL_OMADM_SEND_DATA = 11025;
static final int RIL_UNSOL_DUN = 11026;
static final int RIL_UNSOL_SYSTEM_REBOOT = 11027;
static final int RIL_UNSOL_VOICE_PRIVACY_CHANGED = 11028;
static final int RIL_UNSOL_UTS_GETSMSCOUNT = 11029;
static final int RIL_UNSOL_UTS_GETSMSMSG = 11030;
static final int RIL_UNSOL_UTS_GET_UNREAD_SMS_STATUS = 11031;
static final int RIL_UNSOL_MIP_CONNECT_STATUS = 11032;
protected HandlerThread mSamsungRILThread;
protected ConnectivityHandler mSamsungRILHandler;
public SamsungRIL(Context context, int networkMode, int cdmaSubscription) {
super(context, networkMode, cdmaSubscription);
mQANElements = 5;
}
static String
requestToString(int request) {
switch (request) {
case RIL_REQUEST_DIAL_EMERGENCY: return "DIAL_EMERGENCY";
default: return RIL.requestToString(request);
}
}
@Override
public void setCurrentPreferredNetworkType() {
if (RILJ_LOGD) riljLog("setCurrentPreferredNetworkType IGNORED");
/* Google added this as a fix for crespo loosing network type after
* taking an OTA. This messes up the data connection state for us
* due to the way we handle network type change (disable data
* then change then re-enable).
*/
}
private boolean NeedReconnect()
{
ConnectivityManager cm =
(ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
NetworkInfo ni_active = cm.getActiveNetworkInfo();
return ni_active != null && ni_active.getTypeName().equalsIgnoreCase( "mobile" ) &&
ni_active.isConnected() && cm.getMobileDataEnabled();
}
@Override
public void setPreferredNetworkType(int networkType , Message response) {
/* Samsung modem implementation does bad things when a datacall is running
* while switching the preferred networktype.
*/
HandlerThread handlerThread;
Looper looper;
if(NeedReconnect())
{
if (mSamsungRILHandler == null) {
handlerThread = new HandlerThread("mSamsungRILThread");
mSamsungRILThread = handlerThread;
mSamsungRILThread.start();
looper = mSamsungRILThread.getLooper();
mSamsungRILHandler = new ConnectivityHandler(mContext, looper);
}
mSamsungRILHandler.setPreferedNetworkType(networkType, response);
} else {
if (mSamsungRILHandler != null) {
mSamsungRILThread = null;
mSamsungRILHandler = null;
}
sendPreferedNetworktype(networkType, response);
}
}
//Sends the real RIL request to the modem.
private void sendPreferedNetworktype(int networkType, Message response) {
RILRequest rr = RILRequest.obtain(
RILConstants.RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, response);
rr.mParcel.writeInt(1);
rr.mParcel.writeInt(networkType);
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)
+ " : " + networkType);
send(rr);
}
/* private class that does the handling for the dataconnection
* dataconnection is done async, so we send the request for disabling it,
* wait for the response, set the prefered networktype and notify the
* real sender with its result.
*/
private class ConnectivityHandler extends Handler{
private static final int MESSAGE_SET_PREFERRED_NETWORK_TYPE = 30;
private Context mContext;
private int mDesiredNetworkType;
//the original message, we need it for calling back the original caller when done
private Message mNetworktypeResponse;
private ConnectivityBroadcastReceiver mConnectivityReceiver = new ConnectivityBroadcastReceiver();
public ConnectivityHandler(Context context, Looper looper)
{
super (looper);
mContext = context;
}
private void startListening() {
IntentFilter filter = new IntentFilter();
filter.addAction(ConnectivityManager.CONNECTIVITY_ACTION);
mContext.registerReceiver(mConnectivityReceiver, filter);
}
private synchronized void stopListening() {
mContext.unregisterReceiver(mConnectivityReceiver);
}
public void setPreferedNetworkType(int networkType, Message response)
{
Rlog.d(RILJ_LOG_TAG, "Mobile Dataconnection is online setting it down");
mDesiredNetworkType = networkType;
mNetworktypeResponse = response;
ConnectivityManager cm =
(ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
//start listening for the connectivity change broadcast
startListening();
cm.setMobileDataEnabled(false);
}
@Override
public void handleMessage(Message msg) {
switch(msg.what) {
//networktype was set, now we can enable the dataconnection again
case MESSAGE_SET_PREFERRED_NETWORK_TYPE:
ConnectivityManager cm =
(ConnectivityManager)mContext.getSystemService(Context.CONNECTIVITY_SERVICE);
Rlog.d(RILJ_LOG_TAG, "preferred NetworkType set upping Mobile Dataconnection");
cm.setMobileDataEnabled(true);
//everything done now call back that we have set the networktype
AsyncResult.forMessage(mNetworktypeResponse, null, null);
mNetworktypeResponse.sendToTarget();
mNetworktypeResponse = null;
break;
default:
throw new RuntimeException("unexpected event not handled");
}
}
private class ConnectivityBroadcastReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (!action.equals(ConnectivityManager.CONNECTIVITY_ACTION)) {
Rlog.w(RILJ_LOG_TAG, "onReceived() called with " + intent);
return;
}
boolean noConnectivity =
intent.getBooleanExtra(ConnectivityManager.EXTRA_NO_CONNECTIVITY, false);
if (noConnectivity) {
//Ok dataconnection is down, now set the networktype
Rlog.w(RILJ_LOG_TAG, "Mobile Dataconnection is now down setting preferred NetworkType");
stopListening();
sendPreferedNetworktype(mDesiredNetworkType, obtainMessage(MESSAGE_SET_PREFERRED_NETWORK_TYPE));
mDesiredNetworkType = -1;
}
}
}
}
@Override
protected RILRequest findAndRemoveRequestFromList(int serial) {
long removalTime = System.currentTimeMillis();
long timeDiff = 0;
RILRequest rr = null;
synchronized (mRequestList) {
rr = mRequestList.get(serial);
if (rr != null) {
mRequestList.remove(serial);
return rr;
}
else
{
// We need some special code here for the Samsung RIL,
// which isn't responding to some requests.
// We will print a list of such stale requests which
// haven't yet received a response. If the timeout fires
// first, then the wakelock is released without debugging.
timeDiff = removalTime - rr.creationTime;
if ( timeDiff > mWakeLockTimeout ) {
Rlog.d(RILJ_LOG_TAG, "No response for [" + rr.mSerial + "] " +
requestToString(rr.mRequest) + " after " + timeDiff + " milliseconds.");
/* Don't actually remove anything for now. Consider uncommenting this to
purge stale requests */
/*
itr.remove();
if (mRequestMessagesWaiting > 0) {
mRequestMessagesWaiting--;
}
// We don't handle the callback (ie. rr.mResult) for
// RIL_REQUEST_SET_TTY_MODE, which is
// RIL_REQUEST_QUERY_TTY_MODE. The reason for not doing
// so is because it will also not get a response from the
// Samsung RIL
rr.release();
*/
}
}
}
return null;
}
@Override
protected RILRequest processSolicited (Parcel p) {
int serial, error;
boolean found = false;
serial = p.readInt();
error = p.readInt();
RILRequest rr;
rr = findAndRemoveRequestFromList(serial);
if (rr == null) {
Rlog.w(RILJ_LOG_TAG, "Unexpected solicited response! sn: "
+ serial + " error: " + error);
return null;
}
Object ret = null;
if (error == 0 || p.dataAvail() > 0) {
// either command succeeds or command fails but with data payload
try {switch (rr.mRequest) {
case RIL_REQUEST_GET_SIM_STATUS: ret = responseIccCardStatus(p); break;
case RIL_REQUEST_ENTER_SIM_PIN: ret = responseInts(p); break;
case RIL_REQUEST_ENTER_SIM_PUK: ret = responseInts(p); break;
case RIL_REQUEST_ENTER_SIM_PIN2: ret = responseInts(p); break;
case RIL_REQUEST_ENTER_SIM_PUK2: ret = responseInts(p); break;
case RIL_REQUEST_CHANGE_SIM_PIN: ret = responseInts(p); break;
case RIL_REQUEST_CHANGE_SIM_PIN2: ret = responseInts(p); break;
case RIL_REQUEST_ENTER_DEPERSONALIZATION_CODE: ret = responseInts(p); break;
case RIL_REQUEST_GET_CURRENT_CALLS: ret = responseCallList(p); break;
case RIL_REQUEST_DIAL: ret = responseVoid(p); break;
case RIL_REQUEST_GET_IMSI: ret = responseString(p); break;
case RIL_REQUEST_HANGUP: ret = responseVoid(p); break;
case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND: ret = responseVoid(p); break;
case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND: ret = responseVoid(p); break;
case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE: ret = responseVoid(p); break;
case RIL_REQUEST_CONFERENCE: ret = responseVoid(p); break;
case RIL_REQUEST_UDUB: ret = responseVoid(p); break;
case RIL_REQUEST_LAST_CALL_FAIL_CAUSE: ret = responseInts(p); break;
case RIL_REQUEST_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break;
case RIL_REQUEST_VOICE_REGISTRATION_STATE: ret = responseStrings(p); break;
case RIL_REQUEST_DATA_REGISTRATION_STATE: ret = responseStrings(p); break;
case RIL_REQUEST_OPERATOR: ret = responseStrings(p); break;
case RIL_REQUEST_RADIO_POWER: ret = responseVoid(p); break;
case RIL_REQUEST_DTMF: ret = responseVoid(p); break;
case RIL_REQUEST_SEND_SMS: ret = responseSMS(p); break;
case RIL_REQUEST_SEND_SMS_EXPECT_MORE: ret = responseSMS(p); break;
case RIL_REQUEST_SETUP_DATA_CALL: ret = responseSetupDataCall(p); break;
case RIL_REQUEST_SIM_IO: ret = responseICC_IO(p); break;
case RIL_REQUEST_SEND_USSD: ret = responseVoid(p); break;
case RIL_REQUEST_CANCEL_USSD: ret = responseVoid(p); break;
case RIL_REQUEST_GET_CLIR: ret = responseInts(p); break;
case RIL_REQUEST_SET_CLIR: ret = responseVoid(p); break;
case RIL_REQUEST_QUERY_CALL_FORWARD_STATUS: ret = responseCallForward(p); break;
case RIL_REQUEST_SET_CALL_FORWARD: ret = responseVoid(p); break;
case RIL_REQUEST_QUERY_CALL_WAITING: ret = responseInts(p); break;
case RIL_REQUEST_SET_CALL_WAITING: ret = responseVoid(p); break;
case RIL_REQUEST_SMS_ACKNOWLEDGE: ret = responseVoid(p); break;
case RIL_REQUEST_GET_IMEI: ret = responseString(p); break;
case RIL_REQUEST_GET_IMEISV: ret = responseString(p); break;
case RIL_REQUEST_ANSWER: ret = responseVoid(p); break;
case RIL_REQUEST_DEACTIVATE_DATA_CALL: ret = responseVoid(p); break;
case RIL_REQUEST_QUERY_FACILITY_LOCK: ret = responseInts(p); break;
case RIL_REQUEST_SET_FACILITY_LOCK: ret = responseInts(p); break;
case RIL_REQUEST_CHANGE_BARRING_PASSWORD: ret = responseVoid(p); break;
case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE: ret = responseInts(p); break;
case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC: ret = responseVoid(p); break;
case RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL: ret = responseVoid(p); break;
case RIL_REQUEST_QUERY_AVAILABLE_NETWORKS : ret = responseOperatorInfos(p); break;
case RIL_REQUEST_DTMF_START: ret = responseVoid(p); break;
case RIL_REQUEST_DTMF_STOP: ret = responseVoid(p); break;
case RIL_REQUEST_BASEBAND_VERSION: ret = responseString(p); break;
case RIL_REQUEST_SEPARATE_CONNECTION: ret = responseVoid(p); break;
case RIL_REQUEST_SET_MUTE: ret = responseVoid(p); break;
case RIL_REQUEST_GET_MUTE: ret = responseInts(p); break;
case RIL_REQUEST_QUERY_CLIP: ret = responseInts(p); break;
case RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE: ret = responseInts(p); break;
case RIL_REQUEST_DATA_CALL_LIST: ret = responseDataCallList(p); break;
case RIL_REQUEST_RESET_RADIO: ret = responseVoid(p); break;
case RIL_REQUEST_OEM_HOOK_RAW: ret = responseRaw(p); break;
case RIL_REQUEST_OEM_HOOK_STRINGS: ret = responseStrings(p); break;
case RIL_REQUEST_SCREEN_STATE: ret = responseVoid(p); break;
case RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION: ret = responseVoid(p); break;
case RIL_REQUEST_WRITE_SMS_TO_SIM: ret = responseInts(p); break;
case RIL_REQUEST_DELETE_SMS_ON_SIM: ret = responseVoid(p); break;
case RIL_REQUEST_SET_BAND_MODE: ret = responseVoid(p); break;
case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE: ret = responseInts(p); break;
case RIL_REQUEST_STK_GET_PROFILE: ret = responseString(p); break;
case RIL_REQUEST_STK_SET_PROFILE: ret = responseVoid(p); break;
case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND: ret = responseString(p); break;
case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE: ret = responseVoid(p); break;
case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM: ret = responseInts(p); break;
case RIL_REQUEST_EXPLICIT_CALL_TRANSFER: ret = responseVoid(p); break;
case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE: ret = responseVoid(p); break;
case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE: ret = responseGetPreferredNetworkType(p); break;
case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS: ret = responseCellList(p); break;
case RIL_REQUEST_SET_LOCATION_UPDATES: ret = responseVoid(p); break;
case RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE: ret = responseVoid(p); break;
case RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE: ret = responseVoid(p); break;
case RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE: ret = responseInts(p); break;
case RIL_REQUEST_SET_TTY_MODE: ret = responseVoid(p); break;
case RIL_REQUEST_QUERY_TTY_MODE: ret = responseInts(p); break;
case RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE: ret = responseVoid(p); break;
case RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE: ret = responseInts(p); break;
case RIL_REQUEST_CDMA_FLASH: ret = responseVoid(p); break;
case RIL_REQUEST_CDMA_BURST_DTMF: ret = responseVoid(p); break;
case RIL_REQUEST_CDMA_SEND_SMS: ret = responseSMS(p); break;
case RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE: ret = responseVoid(p); break;
case RIL_REQUEST_GSM_GET_BROADCAST_CONFIG: ret = responseGmsBroadcastConfig(p); break;
case RIL_REQUEST_GSM_SET_BROADCAST_CONFIG: ret = responseVoid(p); break;
case RIL_REQUEST_GSM_BROADCAST_ACTIVATION: ret = responseVoid(p); break;
case RIL_REQUEST_CDMA_GET_BROADCAST_CONFIG: ret = responseCdmaBroadcastConfig(p); break;
case RIL_REQUEST_CDMA_SET_BROADCAST_CONFIG: ret = responseVoid(p); break;
case RIL_REQUEST_CDMA_BROADCAST_ACTIVATION: ret = responseVoid(p); break;
case RIL_REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY: ret = responseVoid(p); break;
case RIL_REQUEST_CDMA_SUBSCRIPTION: ret = responseStrings(p); break;
case RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM: ret = responseInts(p); break;
case RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM: ret = responseVoid(p); break;
case RIL_REQUEST_DEVICE_IDENTITY: ret = responseStrings(p); break;
case RIL_REQUEST_GET_SMSC_ADDRESS: ret = responseString(p); break;
case RIL_REQUEST_SET_SMSC_ADDRESS: ret = responseVoid(p); break;
case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break;
case RIL_REQUEST_REPORT_SMS_MEMORY_STATUS: ret = responseVoid(p); break;
case RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING: ret = responseVoid(p); break;
case RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE: ret = responseVoid(p); break;
case RIL_REQUEST_ISIM_AUTHENTICATION: ret = responseString(p); break;
case RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU: ret = responseVoid(p); break;
case RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS: ret = responseICC_IO(p); break;
case RIL_REQUEST_VOICE_RADIO_TECH: ret = responseInts(p); break;
case RIL_REQUEST_DIAL_EMERGENCY: ret = responseVoid(p); break;
default:
throw new RuntimeException("Unrecognized solicited response: " + rr.mRequest);
//break;
}} catch (Throwable tr) {
// Exceptions here usually mean invalid RIL responses
Rlog.w(RILJ_LOG_TAG, rr.serialString() + "< "
+ requestToString(rr.mRequest)
+ " exception, possible invalid RIL response", tr);
if (rr.mResult != null) {
AsyncResult.forMessage(rr.mResult, null, tr);
rr.mResult.sendToTarget();
}
return rr;
}
}
if (error != 0) {
//ugly fix for Samsung messing up SMS_SEND request fail in binary RIL
if(!(error == -1 && rr.mRequest == RIL_REQUEST_SEND_SMS))
{
rr.onError(error, ret);
return rr;
} else {
try
{
ret = responseSMS(p);
} catch (Throwable tr) {
Rlog.w(RILJ_LOG_TAG, rr.serialString() + "< "
+ requestToString(rr.mRequest)
+ " exception, Processing Samsung SMS fix ", tr);
rr.onError(error, ret);
return rr;
}
}
}
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;
}
@Override
public void
dial(String address, int clirMode, UUSInfo uusInfo, Message result) {
RILRequest rr;
if (PhoneNumberUtils.isEmergencyNumber(address)) {
dialEmergencyCall(address, clirMode, result);
return;
}
rr = RILRequest.obtain(RIL_REQUEST_DIAL, result);
rr.mParcel.writeString(address);
rr.mParcel.writeInt(clirMode);
rr.mParcel.writeInt(0); // UUS information is absent
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);
}
public 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);
rr.mParcel.writeInt(0);
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
send(rr);
}
@Override
protected void
processUnsolicited (Parcel p) {
Object ret;
int dataPosition = p.dataPosition();
int response = p.readInt();
switch (response) {
case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: ret = responseVoid(p); break;
case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS: ret = responseString(p); break;
case RIL_UNSOL_RIL_CONNECTED: ret = responseInts(p); break;
// SAMSUNG STATES
case RIL_UNSOL_AM: ret = responseString(p); break;
case RIL_UNSOL_DUN_PIN_CONTROL_SIGNAL: ret = responseVoid(p); break;
case RIL_UNSOL_DATA_SUSPEND_RESUME: ret = responseInts(p); break;
case RIL_UNSOL_STK_CALL_CONTROL_RESULT: ret = responseVoid(p); break;
case RIL_UNSOL_TWO_MIC_STATE: ret = responseInts(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:
/* has bonus radio state int */
int state = p.readInt();
Rlog.d(RILJ_LOG_TAG, "Radio state: " + state);
switch (state) {
case 2:
// RADIO_UNAVAILABLE
state = 1;
break;
case 3:
// RADIO_ON
state = 10;
break;
case 4:
// RADIO_ON
state = 10;
// When SIM is PIN-unlocked, RIL doesn't respond with RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED.
// We notify the system here.
Rlog.d(RILJ_LOG_TAG, "SIM is PIN-unlocked now");
if (mIccStatusChangedRegistrants != null) {
mIccStatusChangedRegistrants.notifyRegistrants();
}
break;
}
RadioState newState = getRadioStateFromInt(state);
Rlog.d(RILJ_LOG_TAG, "New Radio state: " + state + " (" + newState.toString() + ")");
switchToRadioState(newState);
break;
case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS:
if (RILJ_LOGD) unsljLogRet(response, ret);
if (mGsmBroadcastSmsRegistrant != null) {
mGsmBroadcastSmsRegistrant
.notifyRegistrant(new AsyncResult(null, ret, null));
}
break;
case RIL_UNSOL_RIL_CONNECTED:
if (RILJ_LOGD) unsljLogRet(response, ret);
// Initial conditions
setRadioPower(false, null);
sendPreferedNetworktype(mPreferredNetworkType, null);
setCdmaSubscriptionSource(mCdmaSubscription, null);
notifyRegistrantsRilConnectionChanged(((int[])ret)[0]);
break;
// SAMSUNG STATES
case RIL_UNSOL_AM:
if (RILJ_LOGD) samsungUnsljLogRet(response, ret);
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 RIL_UNSOL_DUN_PIN_CONTROL_SIGNAL:
if (RILJ_LOGD) samsungUnsljLogRet(response, ret);
break;
case RIL_UNSOL_DATA_SUSPEND_RESUME:
if (RILJ_LOGD) samsungUnsljLogRet(response, ret);
break;
case RIL_UNSOL_STK_CALL_CONTROL_RESULT:
if (RILJ_LOGD) samsungUnsljLogRet(response, ret);
break;
case RIL_UNSOL_TWO_MIC_STATE:
if (RILJ_LOGD) samsungUnsljLogRet(response, ret);
break;
}
}
static String
samsungResponseToString(int request)
{
switch(request) {
// SAMSUNG STATES
case RIL_UNSOL_AM: return "RIL_UNSOL_AM";
case RIL_UNSOL_DUN_PIN_CONTROL_SIGNAL: return "RIL_UNSOL_DUN_PIN_CONTROL_SIGNAL";
case RIL_UNSOL_DATA_SUSPEND_RESUME: return "RIL_UNSOL_DATA_SUSPEND_RESUME";
case RIL_UNSOL_STK_CALL_CONTROL_RESULT: return "RIL_UNSOL_STK_CALL_CONTROL_RESULT";
case RIL_UNSOL_TWO_MIC_STATE: return "RIL_UNSOL_TWO_MIC_STATE";
default: return "<unknown response: "+request+">";
}
}
protected void samsungUnsljLog(int response) {
riljLog("[UNSL]< " + samsungResponseToString(response));
}
protected void samsungUnsljLogMore(int response, String more) {
riljLog("[UNSL]< " + samsungResponseToString(response) + " " + more);
}
protected void samsungUnsljLogRet(int response, Object ret) {
riljLog("[UNSL]< " + samsungResponseToString(response) + " " + retToString(response, ret));
}
protected void samsungUnsljLogvRet(int response, Object ret) {
riljLogv("[UNSL]< " + samsungResponseToString(response) + " " + retToString(response, ret));
}
@Override
protected Object
responseCallList(Parcel p) {
int num;
boolean isVideo;
ArrayList<DriverCall> response;
DriverCall dc;
int dataAvail = p.dataAvail();
int pos = p.dataPosition();
int size = p.dataSize();
Rlog.d(RILJ_LOG_TAG, "Parcel size = " + size);
Rlog.d(RILJ_LOG_TAG, "Parcel pos = " + pos);
Rlog.d(RILJ_LOG_TAG, "Parcel dataAvail = " + dataAvail);
//Samsung changes
num = p.readInt();
Rlog.d(RILJ_LOG_TAG, "num = " + num);
response = new ArrayList<DriverCall>(num);
for (int i = 0 ; i < num ; i++) {
dc = new DriverCall();
dc.state = DriverCall.stateFromCLCC(p.readInt());
dc.index = p.readInt();
dc.TOA = p.readInt();
dc.isMpty = (0 != p.readInt());
dc.isMT = (0 != p.readInt());
dc.als = p.readInt();
dc.isVoice = (0 != p.readInt());
isVideo = (0 != p.readInt());
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();
Rlog.d(RILJ_LOG_TAG, "state = " + dc.state);
Rlog.d(RILJ_LOG_TAG, "index = " + dc.index);
Rlog.d(RILJ_LOG_TAG, "state = " + dc.TOA);
Rlog.d(RILJ_LOG_TAG, "isMpty = " + dc.isMpty);
Rlog.d(RILJ_LOG_TAG, "isMT = " + dc.isMT);
Rlog.d(RILJ_LOG_TAG, "als = " + dc.als);
Rlog.d(RILJ_LOG_TAG, "isVoice = " + dc.isVoice);
Rlog.d(RILJ_LOG_TAG, "isVideo = " + isVideo);
Rlog.d(RILJ_LOG_TAG, "number = " + dc.number);
Rlog.d(RILJ_LOG_TAG, "np = " + np);
Rlog.d(RILJ_LOG_TAG, "name = " + dc.name);
Rlog.d(RILJ_LOG_TAG, "namePresentation = " + dc.namePresentation);
Rlog.d(RILJ_LOG_TAG, "uusInfoPresent = " + uusInfoPresent);
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);
Rlog.v(RILJ_LOG_TAG, String.format("Incoming UUS : type=%d, dcs=%d, length=%d",
dc.uusInfo.getType(), dc.uusInfo.getDcs(),
dc.uusInfo.getUserData().length));
Rlog.v(RILJ_LOG_TAG, "Incoming UUS : data (string)="
+ new String(dc.uusInfo.getUserData()));
Rlog.v(RILJ_LOG_TAG, "Incoming UUS : data (hex): "
+ IccUtils.bytesToHexString(dc.uusInfo.getUserData()));
} else {
Rlog.v(RILJ_LOG_TAG, "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();
Rlog.d(RILJ_LOG_TAG, "InCall VoicePrivacy is enabled");
} else {
mVoicePrivacyOffRegistrants.notifyRegistrants();
Rlog.d(RILJ_LOG_TAG, "InCall VoicePrivacy is disabled");
}
}
Collections.sort(response);
return response;
}
@Override
protected Object responseGetPreferredNetworkType(Parcel p) {
int [] response = (int[]) responseInts(p);
if (response.length >= 1) {
// Since this is the response for getPreferredNetworkType
// we'll assume that it should be the value we want the
// vendor ril to take if we reestablish a connection to it.
mPreferredNetworkType = response[0];
}
// When the modem responds Phone.NT_MODE_GLOBAL, it means Phone.NT_MODE_WCDMA_PREF
if (response[0] == Phone.NT_MODE_GLOBAL) {
Rlog.d(RILJ_LOG_TAG, "Overriding network type response from GLOBAL to WCDMA preferred");
response[0] = Phone.NT_MODE_WCDMA_PREF;
}
return response;
}
@Override
protected Object
responseSignalStrength(Parcel p) {
int numInts = 12;
int response[];
/* TODO: Add SignalStrength class to match RIL_SignalStrength */
response = new int[numInts];
for (int i = 0 ; i < numInts ; i++) {
response[i] = p.readInt();
}
/* Matching Samsung signal strength to asu.
Method taken from Samsungs cdma/gsmSignalStateTracker */
response[0] = ((response[0] & 0xFF00) >> 8) * 3; //gsmDbm
response[1] = -1; //gsmEcio
response[2] = (response[2] < 0)?-120:-response[2]; //cdmaDbm
response[3] = (response[3] < 0)?-160:-response[3]; //cdmaEcio
response[4] = (response[4] < 0)?-120:-response[4]; //evdoRssi
response[5] = (response[5] < 0)?-1:-response[5]; //evdoEcio
if(response[6] < 0 || response[6] > 8)
response[6] = -1;
SignalStrength signalStrength = new SignalStrength(
response[0], response[1], response[2], response[3], response[4],
response[5], response[6], true);
return signalStrength;
}
@Override public void
getVoiceRadioTechnology(Message result) {
RILRequest rr = RILRequest.obtain(RIL_REQUEST_VOICE_RADIO_TECH, result);
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
// RIL versions below 7 do not support this request
if (mRilVersion >= 7)
send(rr);
else
Rlog.d(RILJ_LOG_TAG, "RIL_REQUEST_VOICE_RADIO_TECH blocked!!!");
}
@Override
public void getCdmaSubscriptionSource(Message response) {
RILRequest rr = RILRequest.obtain(
RILConstants.RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE, response);
if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest));
Rlog.d(RILJ_LOG_TAG, "RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE blocked!!!");
//send(rr);
}
}