diff options
author | Wink Saville <wink@google.com> | 2012-07-11 15:41:29 -0700 |
---|---|---|
committer | Jean-Baptiste Queru <jbq@google.com> | 2012-07-17 12:23:13 -0700 |
commit | c38bb60d867c5d61d90b7179a9ed2b2d1848124f (patch) | |
tree | 1d22c162b785b6e6663419f28d2c4d7afd97086d /src/java/com/android/internal/telephony/RIL.java | |
parent | f4ba68aa88637e9df034fce94971535852cc0a7b (diff) | |
download | frameworks_opt_telephony-c38bb60d867c5d61d90b7179a9ed2b2d1848124f.zip frameworks_opt_telephony-c38bb60d867c5d61d90b7179a9ed2b2d1848124f.tar.gz frameworks_opt_telephony-c38bb60d867c5d61d90b7179a9ed2b2d1848124f.tar.bz2 |
Create telephony-common - DO NOT MERGE
telephony-common was created by moving some of
frameworks/base/telephony
to:
frameworks/opt/telephony
Change-Id: I32cbb5eec1fa239c1587e055c8f7ef4fc48fb62c
Diffstat (limited to 'src/java/com/android/internal/telephony/RIL.java')
-rw-r--r-- | src/java/com/android/internal/telephony/RIL.java | 3861 |
1 files changed, 3861 insertions, 0 deletions
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java new file mode 100644 index 0000000..b14f6c8 --- /dev/null +++ b/src/java/com/android/internal/telephony/RIL.java @@ -0,0 +1,3861 @@ +/* + * Copyright (C) 2006 The Android Open Source 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 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 android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.net.ConnectivityManager; +import android.net.LocalSocket; +import android.net.LocalSocketAddress; +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.SystemProperties; +import android.os.PowerManager.WakeLock; +import android.telephony.NeighboringCellInfo; +import android.telephony.PhoneNumberUtils; +import android.telephony.SmsManager; +import android.telephony.SmsMessage; +import android.text.TextUtils; +import android.util.Log; + +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 com.android.internal.telephony.IccRefreshResponse; + +import java.io.ByteArrayInputStream; +import java.io.DataInputStream; +import java.io.FileDescriptor; +import java.io.IOException; +import java.io.InputStream; +import java.io.PrintWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.concurrent.atomic.AtomicBoolean; + +/** + * {@hide} + */ +class RILRequest { + static final String LOG_TAG = "RILJ"; + + //***** Class Variables + static int sNextSerial = 0; + static Object sSerialMonitor = new Object(); + private static Object sPoolSync = new Object(); + private static RILRequest sPool = null; + private static int sPoolSize = 0; + private static final int MAX_POOL_SIZE = 4; + + //***** Instance Variables + int mSerial; + int mRequest; + Message mResult; + Parcel mp; + RILRequest mNext; + + /** + * Retrieves a new RILRequest instance from the pool. + * + * @param request RIL_REQUEST_* + * @param result sent when operation completes + * @return a RILRequest instance from the pool. + */ + static RILRequest obtain(int request, Message result) { + RILRequest rr = null; + + synchronized(sPoolSync) { + if (sPool != null) { + rr = sPool; + sPool = rr.mNext; + rr.mNext = null; + sPoolSize--; + } + } + + if (rr == null) { + rr = new RILRequest(); + } + + synchronized(sSerialMonitor) { + rr.mSerial = sNextSerial++; + } + rr.mRequest = request; + rr.mResult = result; + rr.mp = Parcel.obtain(); + + if (result != null && result.getTarget() == null) { + throw new NullPointerException("Message target must not be null"); + } + + // first elements in any RIL Parcel + rr.mp.writeInt(request); + rr.mp.writeInt(rr.mSerial); + + return rr; + } + + /** + * Returns a RILRequest instance to the pool. + * + * Note: This should only be called once per use. + */ + void release() { + synchronized (sPoolSync) { + if (sPoolSize < MAX_POOL_SIZE) { + this.mNext = sPool; + sPool = this; + sPoolSize++; + mResult = null; + } + } + } + + private RILRequest() { + } + + static void + resetSerial() { + synchronized(sSerialMonitor) { + sNextSerial = 0; + } + } + + String + serialString() { + //Cheesy way to do %04d + StringBuilder sb = new StringBuilder(8); + String sn; + + sn = Integer.toString(mSerial); + + //sb.append("J["); + sb.append('['); + for (int i = 0, s = sn.length() ; i < 4 - s; i++) { + sb.append('0'); + } + + sb.append(sn); + sb.append(']'); + return sb.toString(); + } + + void + onError(int error, Object ret) { + CommandException ex; + + ex = CommandException.fromRilErrno(error); + + if (RIL.RILJ_LOGD) Log.d(LOG_TAG, serialString() + "< " + + RIL.requestToString(mRequest) + + " error: " + ex); + + if (mResult != null) { + AsyncResult.forMessage(mResult, ret, ex); + mResult.sendToTarget(); + } + + if (mp != null) { + mp.recycle(); + mp = null; + } + } +} + + +/** + * RIL implementation of the CommandsInterface. + * FIXME public only for testing + * + * {@hide} + */ +public final class RIL extends BaseCommands implements CommandsInterface { + static final String LOG_TAG = "RILJ"; + static final boolean RILJ_LOGD = true; + static final boolean RILJ_LOGV = false; // STOP SHIP if true + + /** + * Wake lock timeout should be longer than the longest timeout in + * the vendor ril. + */ + private static final int DEFAULT_WAKE_LOCK_TIMEOUT = 60000; + + //***** Instance Variables + + LocalSocket mSocket; + HandlerThread mSenderThread; + RILSender mSender; + Thread mReceiverThread; + RILReceiver mReceiver; + WakeLock mWakeLock; + int mWakeLockTimeout; + // The number of requests pending to be sent out, it increases before calling + // EVENT_SEND and decreases while handling EVENT_SEND. It gets cleared while + // WAKE_LOCK_TIMEOUT occurs. + int mRequestMessagesPending; + // The number of requests sent out but waiting for response. It increases while + // sending request and decreases while handling response. It should match + // mRequestList.size() unless there are requests no replied while + // WAKE_LOCK_TIMEOUT occurs. + int mRequestMessagesWaiting; + + //I'd rather this be LinkedList or something + ArrayList<RILRequest> mRequestsList = new ArrayList<RILRequest>(); + + Object mLastNITZTimeInfo; + + // When we are testing emergency calls + AtomicBoolean mTestingEmergencyCall = new AtomicBoolean(false); + + //***** Events + + static final int EVENT_SEND = 1; + static final int EVENT_WAKE_LOCK_TIMEOUT = 2; + + //***** Constants + + // match with constant in ril.cpp + static final int RIL_MAX_COMMAND_BYTES = (8 * 1024); + static final int RESPONSE_SOLICITED = 0; + static final int RESPONSE_UNSOLICITED = 1; + + static final String SOCKET_NAME_RIL = "rild"; + + static final int SOCKET_OPEN_RETRY_MILLIS = 4 * 1000; + + // The number of the required config values for broadcast SMS stored in the C struct + // RIL_CDMA_BroadcastServiceInfo + private static final int CDMA_BSI_NO_OF_INTS_STRUCT = 3; + + private static final int CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES = 31; + + BroadcastReceiver mIntentReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + if (intent.getAction().equals(Intent.ACTION_SCREEN_ON)) { + sendScreenState(true); + } else if (intent.getAction().equals(Intent.ACTION_SCREEN_OFF)) { + sendScreenState(false); + } else { + Log.w(LOG_TAG, "RIL received unexpected Intent: " + intent.getAction()); + } + } + }; + + class RILSender extends Handler implements Runnable { + public RILSender(Looper looper) { + super(looper); + } + + // Only allocated once + byte[] dataLength = new byte[4]; + + //***** Runnable implementation + public void + run() { + //setup if needed + } + + + //***** Handler implementation + @Override public void + handleMessage(Message msg) { + RILRequest rr = (RILRequest)(msg.obj); + RILRequest req = null; + + switch (msg.what) { + case EVENT_SEND: + /** + * mRequestMessagePending++ already happened for every + * EVENT_SEND, thus we must make sure + * mRequestMessagePending-- happens once and only once + */ + boolean alreadySubtracted = false; + try { + LocalSocket s; + + s = mSocket; + + if (s == null) { + rr.onError(RADIO_NOT_AVAILABLE, null); + rr.release(); + if (mRequestMessagesPending > 0) + mRequestMessagesPending--; + alreadySubtracted = true; + return; + } + + synchronized (mRequestsList) { + mRequestsList.add(rr); + mRequestMessagesWaiting++; + } + + if (mRequestMessagesPending > 0) + mRequestMessagesPending--; + alreadySubtracted = true; + + byte[] data; + + data = rr.mp.marshall(); + rr.mp.recycle(); + rr.mp = null; + + if (data.length > RIL_MAX_COMMAND_BYTES) { + throw new RuntimeException( + "Parcel larger than max bytes allowed! " + + data.length); + } + + // parcel length in big endian + dataLength[0] = dataLength[1] = 0; + dataLength[2] = (byte)((data.length >> 8) & 0xff); + dataLength[3] = (byte)((data.length) & 0xff); + + //Log.v(LOG_TAG, "writing packet: " + data.length + " bytes"); + + s.getOutputStream().write(dataLength); + s.getOutputStream().write(data); + } catch (IOException ex) { + Log.e(LOG_TAG, "IOException", ex); + req = findAndRemoveRequestFromList(rr.mSerial); + // make sure this request has not already been handled, + // eg, if RILReceiver cleared the list. + if (req != null || !alreadySubtracted) { + rr.onError(RADIO_NOT_AVAILABLE, null); + rr.release(); + } + } catch (RuntimeException exc) { + Log.e(LOG_TAG, "Uncaught exception ", exc); + req = findAndRemoveRequestFromList(rr.mSerial); + // make sure this request has not already been handled, + // eg, if RILReceiver cleared the list. + if (req != null || !alreadySubtracted) { + rr.onError(GENERIC_FAILURE, null); + rr.release(); + } + } finally { + // Note: We are "Done" only if there are no outstanding + // requests or replies. Thus this code path will only release + // the wake lock on errors. + releaseWakeLockIfDone(); + } + + if (!alreadySubtracted && mRequestMessagesPending > 0) { + mRequestMessagesPending--; + } + + break; + + case EVENT_WAKE_LOCK_TIMEOUT: + // Haven't heard back from the last request. Assume we're + // not getting a response and release the wake lock. + synchronized (mWakeLock) { + if (mWakeLock.isHeld()) { + // The timer of WAKE_LOCK_TIMEOUT is reset with each + // new send request. So when WAKE_LOCK_TIMEOUT occurs + // all requests in mRequestList already waited at + // least DEFAULT_WAKE_LOCK_TIMEOUT but no response. + // Reset mRequestMessagesWaiting to enable + // releaseWakeLockIfDone(). + // + // Note: Keep mRequestList so that delayed response + // can still be handled when response finally comes. + if (mRequestMessagesWaiting != 0) { + Log.d(LOG_TAG, "NOTE: mReqWaiting is NOT 0 but" + + mRequestMessagesWaiting + " at TIMEOUT, reset!" + + " There still msg waitng for response"); + + mRequestMessagesWaiting = 0; + + if (RILJ_LOGD) { + synchronized (mRequestsList) { + int count = mRequestsList.size(); + Log.d(LOG_TAG, "WAKE_LOCK_TIMEOUT " + + " mRequestList=" + count); + + for (int i = 0; i < count; i++) { + rr = mRequestsList.get(i); + Log.d(LOG_TAG, i + ": [" + rr.mSerial + "] " + + requestToString(rr.mRequest)); + } + } + } + } + // mRequestMessagesPending shows how many + // requests are waiting to be sent (and before + // to be added in request list) since star the + // WAKE_LOCK_TIMEOUT timer. Since WAKE_LOCK_TIMEOUT + // is the expected time to get response, all requests + // should already sent out (i.e. + // mRequestMessagesPending is 0 )while TIMEOUT occurs. + if (mRequestMessagesPending != 0) { + Log.e(LOG_TAG, "ERROR: mReqPending is NOT 0 but" + + mRequestMessagesPending + " at TIMEOUT, reset!"); + mRequestMessagesPending = 0; + + } + mWakeLock.release(); + } + } + break; + } + } + } + + /** + * Reads in a single RIL message off the wire. A RIL message consists + * of a 4-byte little-endian length and a subsequent series of bytes. + * The final message (length header omitted) is read into + * <code>buffer</code> and the length of the final message (less header) + * is returned. A return value of -1 indicates end-of-stream. + * + * @param is non-null; Stream to read from + * @param buffer Buffer to fill in. Must be as large as maximum + * message size, or an ArrayOutOfBounds exception will be thrown. + * @return Length of message less header, or -1 on end of stream. + * @throws IOException + */ + private static int readRilMessage(InputStream is, byte[] buffer) + throws IOException { + int countRead; + int offset; + int remaining; + int messageLength; + + // First, read in the length of the message + offset = 0; + remaining = 4; + do { + countRead = is.read(buffer, offset, remaining); + + if (countRead < 0 ) { + Log.e(LOG_TAG, "Hit EOS reading message length"); + return -1; + } + + offset += countRead; + remaining -= countRead; + } while (remaining > 0); + + messageLength = ((buffer[0] & 0xff) << 24) + | ((buffer[1] & 0xff) << 16) + | ((buffer[2] & 0xff) << 8) + | (buffer[3] & 0xff); + + // Then, re-use the buffer and read in the message itself + offset = 0; + remaining = messageLength; + do { + countRead = is.read(buffer, offset, remaining); + + if (countRead < 0 ) { + Log.e(LOG_TAG, "Hit EOS reading message. messageLength=" + messageLength + + " remaining=" + remaining); + return -1; + } + + offset += countRead; + remaining -= countRead; + } while (remaining > 0); + + return messageLength; + } + + class RILReceiver implements Runnable { + byte[] buffer; + + RILReceiver() { + buffer = new byte[RIL_MAX_COMMAND_BYTES]; + } + + public void + run() { + int retryCount = 0; + + try {for (;;) { + LocalSocket s = null; + LocalSocketAddress l; + + try { + s = new LocalSocket(); + l = new LocalSocketAddress(SOCKET_NAME_RIL, + LocalSocketAddress.Namespace.RESERVED); + s.connect(l); + } catch (IOException ex){ + try { + if (s != null) { + s.close(); + } + } catch (IOException ex2) { + //ignore failure to close after failure to connect + } + + // don't print an error message after the the first time + // or after the 8th time + + if (retryCount == 8) { + Log.e (LOG_TAG, + "Couldn't find '" + SOCKET_NAME_RIL + + "' socket after " + retryCount + + " times, continuing to retry silently"); + } else if (retryCount > 0 && retryCount < 8) { + Log.i (LOG_TAG, + "Couldn't find '" + SOCKET_NAME_RIL + + "' socket; retrying after timeout"); + } + + try { + Thread.sleep(SOCKET_OPEN_RETRY_MILLIS); + } catch (InterruptedException er) { + } + + retryCount++; + continue; + } + + retryCount = 0; + + mSocket = s; + Log.i(LOG_TAG, "Connected to '" + SOCKET_NAME_RIL + "' socket"); + + int length = 0; + try { + InputStream is = mSocket.getInputStream(); + + for (;;) { + Parcel p; + + length = readRilMessage(is, buffer); + + if (length < 0) { + // End-of-stream reached + break; + } + + p = Parcel.obtain(); + p.unmarshall(buffer, 0, length); + p.setDataPosition(0); + + //Log.v(LOG_TAG, "Read packet: " + length + " bytes"); + + processResponse(p); + p.recycle(); + } + } catch (java.io.IOException ex) { + Log.i(LOG_TAG, "'" + SOCKET_NAME_RIL + "' socket closed", + ex); + } catch (Throwable tr) { + Log.e(LOG_TAG, "Uncaught exception read length=" + length + + "Exception:" + tr.toString()); + } + + Log.i(LOG_TAG, "Disconnected from '" + SOCKET_NAME_RIL + + "' socket"); + + setRadioState (RadioState.RADIO_UNAVAILABLE); + + try { + mSocket.close(); + } catch (IOException ex) { + } + + mSocket = null; + RILRequest.resetSerial(); + + // Clear request list on close + clearRequestsList(RADIO_NOT_AVAILABLE, false); + }} catch (Throwable tr) { + Log.e(LOG_TAG,"Uncaught exception", tr); + } + + /* We're disconnected so we don't know the ril version */ + notifyRegistrantsRilConnectionChanged(-1); + } + } + + + + //***** Constructors + + public RIL(Context context, int preferredNetworkType, int cdmaSubscription) { + super(context); + if (RILJ_LOGD) { + riljLog("RIL(context, preferredNetworkType=" + preferredNetworkType + + " cdmaSubscription=" + cdmaSubscription + ")"); + } + mCdmaSubscription = cdmaSubscription; + mPreferredNetworkType = preferredNetworkType; + mPhoneType = RILConstants.NO_PHONE; + + PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); + mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, LOG_TAG); + mWakeLock.setReferenceCounted(false); + mWakeLockTimeout = SystemProperties.getInt(TelephonyProperties.PROPERTY_WAKE_LOCK_TIMEOUT, + DEFAULT_WAKE_LOCK_TIMEOUT); + mRequestMessagesPending = 0; + mRequestMessagesWaiting = 0; + + mSenderThread = new HandlerThread("RILSender"); + mSenderThread.start(); + + Looper looper = mSenderThread.getLooper(); + mSender = new RILSender(looper); + + ConnectivityManager cm = (ConnectivityManager)context.getSystemService( + Context.CONNECTIVITY_SERVICE); + if (cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE) == false) { + riljLog("Not starting RILReceiver: wifi-only"); + } else { + riljLog("Starting RILReceiver"); + mReceiver = new RILReceiver(); + mReceiverThread = new Thread(mReceiver, "RILReceiver"); + mReceiverThread.start(); + + IntentFilter filter = new IntentFilter(); + filter.addAction(Intent.ACTION_SCREEN_ON); + filter.addAction(Intent.ACTION_SCREEN_OFF); + context.registerReceiver(mIntentReceiver, filter); + } + } + + //***** CommandsInterface implementation + + public void getVoiceRadioTechnology(Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_VOICE_RADIO_TECH, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + + @Override public void + setOnNITZTime(Handler h, int what, Object obj) { + super.setOnNITZTime(h, what, obj); + + // Send the last NITZ time if we have it + if (mLastNITZTimeInfo != null) { + mNITZTimeRegistrant + .notifyRegistrant( + new AsyncResult (null, mLastNITZTimeInfo, null)); + mLastNITZTimeInfo = null; + } + } + + public void + getIccCardStatus(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_GET_SIM_STATUS, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + @Override public void + supplyIccPin(String pin, Message result) { + supplyIccPinForApp(pin, null, result); + } + + @Override public void + supplyIccPinForApp(String pin, String aid, 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_ENTER_SIM_PIN, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeInt(2); + rr.mp.writeString(pin); + rr.mp.writeString(aid); + + send(rr); + } + + @Override public void + supplyIccPuk(String puk, String newPin, Message result) { + supplyIccPukForApp(puk, newPin, null, result); + } + + @Override public void + supplyIccPukForApp(String puk, String newPin, String aid, 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_ENTER_SIM_PUK, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeInt(3); + rr.mp.writeString(puk); + rr.mp.writeString(newPin); + rr.mp.writeString(aid); + + send(rr); + } + + @Override public void + supplyIccPin2(String pin, Message result) { + supplyIccPin2ForApp(pin, null, result); + } + + @Override public void + supplyIccPin2ForApp(String pin, String aid, 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_ENTER_SIM_PIN2, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeInt(2); + rr.mp.writeString(pin); + rr.mp.writeString(aid); + + send(rr); + } + + @Override public void + supplyIccPuk2(String puk2, String newPin2, Message result) { + supplyIccPuk2ForApp(puk2, newPin2, null, result); + } + + @Override public void + supplyIccPuk2ForApp(String puk, String newPin2, String aid, 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_ENTER_SIM_PUK2, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeInt(3); + rr.mp.writeString(puk); + rr.mp.writeString(newPin2); + rr.mp.writeString(aid); + + send(rr); + } + + @Override public void + changeIccPin(String oldPin, String newPin, Message result) { + changeIccPinForApp(oldPin, newPin, null, result); + } + + @Override public void + changeIccPinForApp(String oldPin, String newPin, String aid, 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_CHANGE_SIM_PIN, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeInt(3); + rr.mp.writeString(oldPin); + rr.mp.writeString(newPin); + rr.mp.writeString(aid); + + send(rr); + } + + @Override public void + changeIccPin2(String oldPin2, String newPin2, Message result) { + changeIccPin2ForApp(oldPin2, newPin2, null, result); + } + + @Override public void + changeIccPin2ForApp(String oldPin2, String newPin2, String aid, 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_CHANGE_SIM_PIN2, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeInt(3); + rr.mp.writeString(oldPin2); + rr.mp.writeString(newPin2); + rr.mp.writeString(aid); + + send(rr); + } + + public void + changeBarringPassword(String facility, String oldPwd, String newPwd, Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_CHANGE_BARRING_PASSWORD, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeInt(3); + rr.mp.writeString(facility); + rr.mp.writeString(oldPwd); + rr.mp.writeString(newPwd); + + send(rr); + } + + public void + supplyNetworkDepersonalization(String netpin, Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeInt(1); + rr.mp.writeString(netpin); + + send(rr); + } + + public void + getCurrentCalls (Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_CURRENT_CALLS, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + @Deprecated public void + getPDPContextList(Message result) { + getDataCallList(result); + } + + public void + getDataCallList(Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_DATA_CALL_LIST, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + dial (String address, int clirMode, Message result) { + dial(address, clirMode, null, result); + } + + 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); + rr.mp.writeInt(0); // UUS information is absent + + 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()); + } + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + getIMSI(Message result) { + getIMSIForApp(null, result); + } + + public void + getIMSIForApp(String aid, Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMSI, result); + + rr.mp.writeInt(1); + rr.mp.writeString(aid); + + if (RILJ_LOGD) riljLog(rr.serialString() + + "> getIMSI: " + requestToString(rr.mRequest) + + " aid: " + aid); + + send(rr); + } + + public void + getIMEI(Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMEI, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + getIMEISV(Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_IMEISV, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + + public void + hangupConnection (int gsmIndex, Message result) { + if (RILJ_LOGD) riljLog("hangupConnection: gsmIndex=" + gsmIndex); + + RILRequest rr = RILRequest.obtain(RIL_REQUEST_HANGUP, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " " + + gsmIndex); + + rr.mp.writeInt(1); + rr.mp.writeInt(gsmIndex); + + send(rr); + } + + public void + hangupWaitingOrBackground (Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND, + result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + hangupForegroundResumeBackground (Message result) { + RILRequest rr + = RILRequest.obtain( + RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND, + result); + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + switchWaitingOrHoldingAndActive (Message result) { + RILRequest rr + = RILRequest.obtain( + RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE, + result); + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + conference (Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_CONFERENCE, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + + public void setPreferredVoicePrivacy(boolean enable, Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE, + result); + + rr.mp.writeInt(1); + rr.mp.writeInt(enable ? 1:0); + + send(rr); + } + + public void getPreferredVoicePrivacy(Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE, + result); + send(rr); + } + + public void + separateConnection (int gsmIndex, Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_SEPARATE_CONNECTION, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " " + gsmIndex); + + rr.mp.writeInt(1); + rr.mp.writeInt(gsmIndex); + + send(rr); + } + + public void + acceptCall (Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_ANSWER, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + rejectCall (Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_UDUB, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + explicitCallTransfer (Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_EXPLICIT_CALL_TRANSFER, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + getLastCallFailCause (Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_LAST_CALL_FAIL_CAUSE, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + /** + * @deprecated + */ + public void + getLastPdpFailCause (Message result) { + getLastDataCallFailCause (result); + } + + /** + * The preferred new alternative to getLastPdpFailCause + */ + public void + getLastDataCallFailCause (Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + setMute (boolean enableMute, Message response) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_SET_MUTE, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " " + enableMute); + + rr.mp.writeInt(1); + rr.mp.writeInt(enableMute ? 1 : 0); + + send(rr); + } + + public void + getMute (Message response) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_GET_MUTE, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + getSignalStrength (Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_SIGNAL_STRENGTH, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + getVoiceRegistrationState (Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_VOICE_REGISTRATION_STATE, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + getDataRegistrationState (Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_DATA_REGISTRATION_STATE, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + getOperator(Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_OPERATOR, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + sendDtmf(char c, Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_DTMF, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeString(Character.toString(c)); + + send(rr); + } + + public void + startDtmf(char c, Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_DTMF_START, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeString(Character.toString(c)); + + send(rr); + } + + public void + stopDtmf(Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_DTMF_STOP, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + sendBurstDtmf(String dtmfString, int on, int off, Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_BURST_DTMF, result); + + rr.mp.writeInt(3); + rr.mp.writeString(dtmfString); + rr.mp.writeString(Integer.toString(on)); + rr.mp.writeString(Integer.toString(off)); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " : " + dtmfString); + + send(rr); + } + + public void + sendSMS (String smscPDU, String pdu, Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_SEND_SMS, result); + + rr.mp.writeInt(2); + rr.mp.writeString(smscPDU); + rr.mp.writeString(pdu); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + sendCdmaSms(byte[] pdu, Message result) { + int address_nbr_of_digits; + int subaddr_nbr_of_digits; + int bearerDataLength; + ByteArrayInputStream bais = new ByteArrayInputStream(pdu); + DataInputStream dis = new DataInputStream(bais); + + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_CDMA_SEND_SMS, result); + + try { + rr.mp.writeInt(dis.readInt()); //teleServiceId + rr.mp.writeByte((byte) dis.readInt()); //servicePresent + rr.mp.writeInt(dis.readInt()); //serviceCategory + rr.mp.writeInt(dis.read()); //address_digit_mode + rr.mp.writeInt(dis.read()); //address_nbr_mode + rr.mp.writeInt(dis.read()); //address_ton + rr.mp.writeInt(dis.read()); //address_nbr_plan + address_nbr_of_digits = (byte) dis.read(); + rr.mp.writeByte((byte) address_nbr_of_digits); + for(int i=0; i < address_nbr_of_digits; i++){ + rr.mp.writeByte(dis.readByte()); // address_orig_bytes[i] + } + rr.mp.writeInt(dis.read()); //subaddressType + rr.mp.writeByte((byte) dis.read()); //subaddr_odd + subaddr_nbr_of_digits = (byte) dis.read(); + rr.mp.writeByte((byte) subaddr_nbr_of_digits); + for(int i=0; i < subaddr_nbr_of_digits; i++){ + rr.mp.writeByte(dis.readByte()); //subaddr_orig_bytes[i] + } + + bearerDataLength = dis.read(); + rr.mp.writeInt(bearerDataLength); + for(int i=0; i < bearerDataLength; i++){ + rr.mp.writeByte(dis.readByte()); //bearerData[i] + } + }catch (IOException ex){ + if (RILJ_LOGD) riljLog("sendSmsCdma: conversion from input stream to object failed: " + + ex); + } + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void deleteSmsOnSim(int index, Message response) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_DELETE_SMS_ON_SIM, + response); + + rr.mp.writeInt(1); + rr.mp.writeInt(index); + + if (false) { + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + + requestToString(rr.mRequest) + + " " + index); + } + + send(rr); + } + + public void deleteSmsOnRuim(int index, Message response) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM, + response); + + rr.mp.writeInt(1); + rr.mp.writeInt(index); + + if (false) { + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + + requestToString(rr.mRequest) + + " " + index); + } + + send(rr); + } + + public void writeSmsToSim(int status, String smsc, String pdu, Message response) { + status = translateStatus(status); + + RILRequest rr = RILRequest.obtain(RIL_REQUEST_WRITE_SMS_TO_SIM, + response); + + rr.mp.writeInt(status); + rr.mp.writeString(pdu); + rr.mp.writeString(smsc); + + if (false) { + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + + requestToString(rr.mRequest) + + " " + status); + } + + send(rr); + } + + public void writeSmsToRuim(int status, String pdu, Message response) { + status = translateStatus(status); + + RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM, + response); + + rr.mp.writeInt(status); + rr.mp.writeString(pdu); + + if (false) { + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + + requestToString(rr.mRequest) + + " " + status); + } + + send(rr); + } + + /** + * Translates EF_SMS status bits to a status value compatible with + * SMS AT commands. See TS 27.005 3.1. + */ + private int translateStatus(int status) { + switch(status & 0x7) { + case SmsManager.STATUS_ON_ICC_READ: + return 1; + case SmsManager.STATUS_ON_ICC_UNREAD: + return 0; + case SmsManager.STATUS_ON_ICC_SENT: + return 3; + case SmsManager.STATUS_ON_ICC_UNSENT: + return 2; + } + + // Default to READ. + return 1; + } + + public void + setupDataCall(String radioTechnology, String profile, String apn, + String user, String password, String authType, String protocol, + Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_SETUP_DATA_CALL, result); + + rr.mp.writeInt(7); + + rr.mp.writeString(radioTechnology); + rr.mp.writeString(profile); + rr.mp.writeString(apn); + rr.mp.writeString(user); + rr.mp.writeString(password); + rr.mp.writeString(authType); + rr.mp.writeString(protocol); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + + requestToString(rr.mRequest) + " " + radioTechnology + " " + + profile + " " + apn + " " + user + " " + + password + " " + authType + " " + protocol); + + send(rr); + } + + public void + deactivateDataCall(int cid, int reason, Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_DEACTIVATE_DATA_CALL, result); + + rr.mp.writeInt(2); + rr.mp.writeString(Integer.toString(cid)); + rr.mp.writeString(Integer.toString(reason)); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + + requestToString(rr.mRequest) + " " + cid + " " + reason); + + send(rr); + } + + public void + setRadioPower(boolean on, Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_RADIO_POWER, result); + + rr.mp.writeInt(1); + rr.mp.writeInt(on ? 1 : 0); + + if (RILJ_LOGD) { + riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + (on ? " on" : " off")); + } + + send(rr); + } + + public void + setSuppServiceNotifications(boolean enable, Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION, result); + + rr.mp.writeInt(1); + rr.mp.writeInt(enable ? 1 : 0); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + + requestToString(rr.mRequest)); + + send(rr); + } + + public void + acknowledgeLastIncomingGsmSms(boolean success, int cause, Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_SMS_ACKNOWLEDGE, result); + + rr.mp.writeInt(2); + rr.mp.writeInt(success ? 1 : 0); + rr.mp.writeInt(cause); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " " + success + " " + cause); + + send(rr); + } + + public void + acknowledgeLastIncomingCdmaSms(boolean success, int cause, Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE, result); + + rr.mp.writeInt(success ? 0 : 1); //RIL_CDMA_SMS_ErrorClass + // cause code according to X.S004-550E + rr.mp.writeInt(cause); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " " + success + " " + cause); + + send(rr); + } + + public void + acknowledgeIncomingGsmSmsWithPdu(boolean success, String ackPdu, Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU, result); + + rr.mp.writeInt(2); + rr.mp.writeString(success ? "1" : "0"); + rr.mp.writeString(ackPdu); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + ' ' + success + " [" + ackPdu + ']'); + + send(rr); + } + + public void + iccIO (int command, int fileid, String path, int p1, int p2, int p3, + String data, String pin2, Message result) { + iccIOForApp(command, fileid, path, p1, p2, p3, data, pin2, null, result); + } + public void + iccIOForApp (int command, int fileid, String path, int p1, int p2, int p3, + String data, String pin2, String aid, 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(aid); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> iccIO: " + + requestToString(rr.mRequest) + + " 0x" + Integer.toHexString(command) + + " 0x" + Integer.toHexString(fileid) + " " + + " path: " + path + "," + + p1 + "," + p2 + "," + p3 + + " aid: " + aid); + + send(rr); + } + + public void + getCLIR(Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_GET_CLIR, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + setCLIR(int clirMode, Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_SET_CLIR, result); + + // count ints + rr.mp.writeInt(1); + + rr.mp.writeInt(clirMode); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " " + clirMode); + + send(rr); + } + + public void + queryCallWaiting(int serviceClass, Message response) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_QUERY_CALL_WAITING, response); + + rr.mp.writeInt(1); + rr.mp.writeInt(serviceClass); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " " + serviceClass); + + send(rr); + } + + public void + setCallWaiting(boolean enable, int serviceClass, Message response) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_SET_CALL_WAITING, response); + + rr.mp.writeInt(2); + rr.mp.writeInt(enable ? 1 : 0); + rr.mp.writeInt(serviceClass); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " " + enable + ", " + serviceClass); + + send(rr); + } + + public void + setNetworkSelectionModeAutomatic(Message response) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC, + response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + setNetworkSelectionModeManual(String operatorNumeric, Message response) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL, + response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " " + operatorNumeric); + + rr.mp.writeString(operatorNumeric); + + send(rr); + } + + public void + getNetworkSelectionMode(Message response) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE, + response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + getAvailableNetworks(Message response) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_QUERY_AVAILABLE_NETWORKS, + response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + setCallForward(int action, int cfReason, int serviceClass, + String number, int timeSeconds, Message response) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_SET_CALL_FORWARD, response); + + rr.mp.writeInt(action); + rr.mp.writeInt(cfReason); + rr.mp.writeInt(serviceClass); + rr.mp.writeInt(PhoneNumberUtils.toaFromString(number)); + rr.mp.writeString(number); + rr.mp.writeInt (timeSeconds); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " " + action + " " + cfReason + " " + serviceClass + + timeSeconds); + + send(rr); + } + + public void + queryCallForwardStatus(int cfReason, int serviceClass, + String number, Message response) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_QUERY_CALL_FORWARD_STATUS, response); + + rr.mp.writeInt(2); // 2 is for query action, not in used anyway + rr.mp.writeInt(cfReason); + rr.mp.writeInt(serviceClass); + rr.mp.writeInt(PhoneNumberUtils.toaFromString(number)); + rr.mp.writeString(number); + rr.mp.writeInt (0); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " " + cfReason + " " + serviceClass); + + send(rr); + } + + public void + queryCLIP(Message response) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_QUERY_CLIP, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + + public void + getBasebandVersion (Message response) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_BASEBAND_VERSION, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + @Override + public void + queryFacilityLock(String facility, String password, int serviceClass, + Message response) { + queryFacilityLockForApp(facility, password, serviceClass, null, response); + } + + @Override + public void + queryFacilityLockForApp(String facility, String password, int serviceClass, String appId, + Message response) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_QUERY_FACILITY_LOCK, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + // count strings + rr.mp.writeInt(4); + + rr.mp.writeString(facility); + rr.mp.writeString(password); + + rr.mp.writeString(Integer.toString(serviceClass)); + rr.mp.writeString(appId); + + send(rr); + } + + @Override + public void + setFacilityLock (String facility, boolean lockState, String password, + int serviceClass, Message response) { + setFacilityLockForApp(facility, lockState, password, serviceClass, null, response); + } + + @Override + public void + setFacilityLockForApp(String facility, boolean lockState, String password, + int serviceClass, String appId, Message response) { + String lockString; + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_SET_FACILITY_LOCK, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + // count strings + rr.mp.writeInt(5); + + rr.mp.writeString(facility); + lockString = (lockState)?"1":"0"; + rr.mp.writeString(lockString); + rr.mp.writeString(password); + rr.mp.writeString(Integer.toString(serviceClass)); + rr.mp.writeString(appId); + + send(rr); + + } + + public void + sendUSSD (String ussdString, Message response) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_SEND_USSD, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " " + ussdString); + + rr.mp.writeString(ussdString); + + send(rr); + } + + // inherited javadoc suffices + public void cancelPendingUssd (Message response) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_CANCEL_USSD, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + + public void resetRadio(Message result) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_RESET_RADIO, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void invokeOemRilRequestRaw(byte[] data, Message response) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_OEM_HOOK_RAW, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + "[" + IccUtils.bytesToHexString(data) + "]"); + + rr.mp.writeByteArray(data); + + send(rr); + + } + + public void invokeOemRilRequestStrings(String[] strings, Message response) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_OEM_HOOK_STRINGS, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeStringArray(strings); + + send(rr); + } + + /** + * Assign a specified band for RF configuration. + * + * @param bandMode one of BM_*_BAND + * @param response is callback message + */ + public void setBandMode (int bandMode, Message response) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_SET_BAND_MODE, response); + + rr.mp.writeInt(1); + rr.mp.writeInt(bandMode); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " " + bandMode); + + send(rr); + } + + /** + * Query the list of band mode supported by RF. + * + * @param response is callback message + * ((AsyncResult)response.obj).result is an int[] with every + * element representing one avialable BM_*_BAND + */ + public void queryAvailableBandMode (Message response) { + RILRequest rr + = RILRequest.obtain(RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE, + response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + /** + * {@inheritDoc} + */ + public void sendTerminalResponse(String contents, Message response) { + RILRequest rr = RILRequest.obtain( + RILConstants.RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeString(contents); + send(rr); + } + + /** + * {@inheritDoc} + */ + public void sendEnvelope(String contents, Message response) { + RILRequest rr = RILRequest.obtain( + RILConstants.RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + rr.mp.writeString(contents); + send(rr); + } + + /** + * {@inheritDoc} + */ + public void sendEnvelopeWithStatus(String contents, Message response) { + RILRequest rr = RILRequest.obtain( + RILConstants.RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + '[' + contents + ']'); + + rr.mp.writeString(contents); + send(rr); + } + + /** + * {@inheritDoc} + */ + public void handleCallSetupRequestFromSim( + boolean accept, Message response) { + + RILRequest rr = RILRequest.obtain( + RILConstants.RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM, + response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + int[] param = new int[1]; + param[0] = accept ? 1 : 0; + rr.mp.writeIntArray(param); + send(rr); + } + + /** + * {@inheritDoc} + */ + @Override + public void setCurrentPreferredNetworkType() { + if (RILJ_LOGD) riljLog("setCurrentPreferredNetworkType: " + mSetPreferredNetworkType); + setPreferredNetworkType(mSetPreferredNetworkType, null); + } + private int mSetPreferredNetworkType; + + /** + * {@inheritDoc} + */ + public void setPreferredNetworkType(int networkType , Message response) { + RILRequest rr = RILRequest.obtain( + RILConstants.RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, response); + + rr.mp.writeInt(1); + rr.mp.writeInt(networkType); + + mSetPreferredNetworkType = networkType; + mPreferredNetworkType = networkType; + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " : " + networkType); + + send(rr); + } + + /** + * {@inheritDoc} + */ + public void getPreferredNetworkType(Message response) { + RILRequest rr = RILRequest.obtain( + RILConstants.RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + /** + * {@inheritDoc} + */ + public void getNeighboringCids(Message response) { + RILRequest rr = RILRequest.obtain( + RILConstants.RIL_REQUEST_GET_NEIGHBORING_CELL_IDS, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + /** + * {@inheritDoc} + */ + public void setLocationUpdates(boolean enable, Message response) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_SET_LOCATION_UPDATES, response); + rr.mp.writeInt(1); + rr.mp.writeInt(enable ? 1 : 0); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + + requestToString(rr.mRequest) + ": " + enable); + + send(rr); + } + + /** + * {@inheritDoc} + */ + public void getSmscAddress(Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_GET_SMSC_ADDRESS, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + /** + * {@inheritDoc} + */ + public void setSmscAddress(String address, Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_SET_SMSC_ADDRESS, result); + + rr.mp.writeString(address); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " : " + address); + + send(rr); + } + + /** + * {@inheritDoc} + */ + public void reportSmsMemoryStatus(boolean available, Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_REPORT_SMS_MEMORY_STATUS, result); + rr.mp.writeInt(1); + rr.mp.writeInt(available ? 1 : 0); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + + requestToString(rr.mRequest) + ": " + available); + + send(rr); + } + + /** + * {@inheritDoc} + */ + public void reportStkServiceIsRunning(Message result) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING, result); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + /** + * {@inheritDoc} + */ + public void getGsmBroadcastConfig(Message response) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_GSM_GET_BROADCAST_CONFIG, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + /** + * {@inheritDoc} + */ + public void setGsmBroadcastConfig(SmsBroadcastConfigInfo[] config, Message response) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_GSM_SET_BROADCAST_CONFIG, response); + + int numOfConfig = config.length; + rr.mp.writeInt(numOfConfig); + + for(int i = 0; i < numOfConfig; i++) { + rr.mp.writeInt(config[i].getFromServiceId()); + rr.mp.writeInt(config[i].getToServiceId()); + rr.mp.writeInt(config[i].getFromCodeScheme()); + rr.mp.writeInt(config[i].getToCodeScheme()); + rr.mp.writeInt(config[i].isSelected() ? 1 : 0); + } + + if (RILJ_LOGD) { + riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " with " + numOfConfig + " configs : "); + for (int i = 0; i < numOfConfig; i++) { + riljLog(config[i].toString()); + } + } + + send(rr); + } + + /** + * {@inheritDoc} + */ + public void setGsmBroadcastActivation(boolean activate, Message response) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_GSM_BROADCAST_ACTIVATION, response); + + rr.mp.writeInt(1); + rr.mp.writeInt(activate ? 0 : 1); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + //***** Private Methods + + private void sendScreenState(boolean on) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_SCREEN_STATE, null); + rr.mp.writeInt(1); + rr.mp.writeInt(on ? 1 : 0); + + if (RILJ_LOGD) riljLog(rr.serialString() + + "> " + requestToString(rr.mRequest) + ": " + on); + + send(rr); + } + + protected void + onRadioAvailable() { + // In case screen state was lost (due to process crash), + // this ensures that the RIL knows the correct screen state. + + // TODO: Should query Power Manager and send the actual + // screen state. Just send true for now. + sendScreenState(true); + } + + private RadioState getRadioStateFromInt(int stateInt) { + RadioState state; + + /* RIL_RadioState ril.h */ + switch(stateInt) { + case 0: state = RadioState.RADIO_OFF; break; + case 1: state = RadioState.RADIO_UNAVAILABLE; break; + case 10: state = RadioState.RADIO_ON; break; + + default: + throw new RuntimeException( + "Unrecognized RIL_RadioState: " + stateInt); + } + return state; + } + + private void switchToRadioState(RadioState newState) { + setRadioState(newState); + } + + /** + * Holds a PARTIAL_WAKE_LOCK whenever + * a) There is outstanding RIL request sent to RIL deamon and no replied + * b) There is a request pending to be sent out. + * + * There is a WAKE_LOCK_TIMEOUT to release the lock, though it shouldn't + * happen often. + */ + + private void + acquireWakeLock() { + synchronized (mWakeLock) { + mWakeLock.acquire(); + mRequestMessagesPending++; + + mSender.removeMessages(EVENT_WAKE_LOCK_TIMEOUT); + Message msg = mSender.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT); + mSender.sendMessageDelayed(msg, mWakeLockTimeout); + } + } + + private void + releaseWakeLockIfDone() { + synchronized (mWakeLock) { + if (mWakeLock.isHeld() && + (mRequestMessagesPending == 0) && + (mRequestMessagesWaiting == 0)) { + mSender.removeMessages(EVENT_WAKE_LOCK_TIMEOUT); + mWakeLock.release(); + } + } + } + + private void + send(RILRequest rr) { + Message msg; + + if (mSocket == null) { + rr.onError(RADIO_NOT_AVAILABLE, null); + rr.release(); + return; + } + + msg = mSender.obtainMessage(EVENT_SEND, rr); + + acquireWakeLock(); + + msg.sendToTarget(); + } + + private void + processResponse (Parcel p) { + int type; + + type = p.readInt(); + + if (type == RESPONSE_UNSOLICITED) { + processUnsolicited (p); + } else if (type == RESPONSE_SOLICITED) { + processSolicited (p); + } + + releaseWakeLockIfDone(); + } + + /** + * Release each request in mReqeustsList then clear the list + * @param error is the RIL_Errno sent back + * @param loggable true means to print all requests in mRequestslist + */ + private void clearRequestsList(int error, boolean loggable) { + RILRequest rr; + synchronized (mRequestsList) { + int count = mRequestsList.size(); + if (RILJ_LOGD && loggable) { + Log.d(LOG_TAG, "WAKE_LOCK_TIMEOUT " + + " mReqPending=" + mRequestMessagesPending + + " mRequestList=" + count); + } + + for (int i = 0; i < count ; i++) { + rr = mRequestsList.get(i); + if (RILJ_LOGD && loggable) { + Log.d(LOG_TAG, i + ": [" + rr.mSerial + "] " + + requestToString(rr.mRequest)); + } + rr.onError(error, null); + rr.release(); + } + mRequestsList.clear(); + mRequestMessagesWaiting = 0; + } + } + + private RILRequest findAndRemoveRequestFromList(int serial) { + synchronized (mRequestsList) { + for (int i = 0, s = mRequestsList.size() ; i < s ; i++) { + RILRequest rr = mRequestsList.get(i); + + if (rr.mSerial == serial) { + mRequestsList.remove(i); + if (mRequestMessagesWaiting > 0) + mRequestMessagesWaiting--; + return rr; + } + } + } + + return null; + } + + private void + processSolicited (Parcel p) { + int serial, error; + boolean found = false; + + serial = p.readInt(); + error = p.readInt(); + + RILRequest rr; + + rr = findAndRemoveRequestFromList(serial); + + if (rr == null) { + Log.w(LOG_TAG, "Unexpected solicited response! sn: " + + serial + " error: " + error); + return; + } + + Object ret = null; + + if (error == 0 || p.dataAvail() > 0) { + // either command succeeds or command fails but with data payload + try {switch (rr.mRequest) { + /* + cat libs/telephony/ril_commands.h \ + | egrep "^ *{RIL_" \ + | sed -re 's/\{([^,]+),[^,]+,([^}]+).+/case \1: ret = \2(p); break;/' + */ + 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_NETWORK_DEPERSONALIZATION: 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: { + if (mTestingEmergencyCall.getAndSet(false)) { + if (mEmergencyCallbackModeRegistrant != null) { + riljLog("testing emergency call, notify ECM Registrants"); + mEmergencyCallbackModeRegistrant.notifyRegistrant(); + } + } + 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 = responseInts(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; + default: + throw new RuntimeException("Unrecognized solicited response: " + rr.mRequest); + //break; + }} catch (Throwable tr) { + // Exceptions here usually mean invalid RIL responses + + Log.w(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(); + } + rr.release(); + return; + } + } + + if (error != 0) { + rr.onError(error, ret); + rr.release(); + return; + } + + 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(); + } + + rr.release(); + } + + private String + retToString(int req, Object ret) { + if (ret == null) return ""; + switch (req) { + // Don't log these return values, for privacy's sake. + case RIL_REQUEST_GET_IMSI: + case RIL_REQUEST_GET_IMEI: + case RIL_REQUEST_GET_IMEISV: + if (!RILJ_LOGV) { + // If not versbose logging just return and don't display IMSI and IMEI, IMEISV + return ""; + } + } + + StringBuilder sb; + String s; + int length; + if (ret instanceof int[]){ + int[] intArray = (int[]) ret; + length = intArray.length; + sb = new StringBuilder("{"); + if (length > 0) { + int i = 0; + sb.append(intArray[i++]); + while ( i < length) { + sb.append(", ").append(intArray[i++]); + } + } + sb.append("}"); + s = sb.toString(); + } else if (ret instanceof String[]) { + String[] strings = (String[]) ret; + length = strings.length; + sb = new StringBuilder("{"); + if (length > 0) { + int i = 0; + sb.append(strings[i++]); + while ( i < length) { + sb.append(", ").append(strings[i++]); + } + } + sb.append("}"); + s = sb.toString(); + }else if (req == RIL_REQUEST_GET_CURRENT_CALLS) { + ArrayList<DriverCall> calls = (ArrayList<DriverCall>) ret; + sb = new StringBuilder(" "); + for (DriverCall dc : calls) { + sb.append("[").append(dc).append("] "); + } + s = sb.toString(); + } else if (req == RIL_REQUEST_GET_NEIGHBORING_CELL_IDS) { + ArrayList<NeighboringCellInfo> cells; + cells = (ArrayList<NeighboringCellInfo>) ret; + sb = new StringBuilder(" "); + for (NeighboringCellInfo cell : cells) { + sb.append(cell).append(" "); + } + s = sb.toString(); + } else { + s = ret.toString(); + } + return s; + } + + private void + processUnsolicited (Parcel p) { + int response; + Object ret; + + response = p.readInt(); + + try {switch(response) { +/* + cat libs/telephony/ril_unsol_commands.h \ + | egrep "^ *{RIL_" \ + | sed -re 's/\{([^,]+),[^,]+,([^}]+).+/case \1: \2(rr, p); break;/' +*/ + + case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: ret = responseVoid(p); break; + case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: ret = responseVoid(p); break; + case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED: ret = responseVoid(p); break; + case RIL_UNSOL_RESPONSE_NEW_SMS: ret = responseString(p); break; + case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT: ret = responseString(p); break; + case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM: ret = responseInts(p); break; + case RIL_UNSOL_ON_USSD: ret = responseStrings(p); break; + case RIL_UNSOL_NITZ_TIME_RECEIVED: ret = responseString(p); break; + case RIL_UNSOL_SIGNAL_STRENGTH: ret = responseSignalStrength(p); break; + case RIL_UNSOL_DATA_CALL_LIST_CHANGED: ret = responseDataCallList(p);break; + case RIL_UNSOL_SUPP_SVC_NOTIFICATION: ret = responseSuppServiceNotification(p); break; + case RIL_UNSOL_STK_SESSION_END: ret = responseVoid(p); break; + case RIL_UNSOL_STK_PROACTIVE_COMMAND: ret = responseString(p); break; + case RIL_UNSOL_STK_EVENT_NOTIFY: ret = responseString(p); break; + case RIL_UNSOL_STK_CALL_SETUP: ret = responseInts(p); break; + case RIL_UNSOL_SIM_SMS_STORAGE_FULL: ret = responseVoid(p); break; + case RIL_UNSOL_SIM_REFRESH: ret = responseSimRefresh(p); break; + case RIL_UNSOL_CALL_RING: ret = responseCallRing(p); break; + case RIL_UNSOL_RESTRICTED_STATE_CHANGED: ret = responseInts(p); break; + case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED: ret = responseVoid(p); break; + case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS: ret = responseCdmaSms(p); break; + case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS: ret = responseRaw(p); break; + case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL: ret = responseVoid(p); break; + case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break; + case RIL_UNSOL_CDMA_CALL_WAITING: ret = responseCdmaCallWaiting(p); break; + case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS: ret = responseInts(p); break; + case RIL_UNSOL_CDMA_INFO_REC: ret = responseCdmaInformationRecord(p); break; + case RIL_UNSOL_OEM_HOOK_RAW: ret = responseRaw(p); break; + case RIL_UNSOL_RINGBACK_TONE: ret = responseInts(p); break; + case RIL_UNSOL_RESEND_INCALL_MUTE: ret = responseVoid(p); break; + case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED: ret = responseInts(p); break; + case RIL_UNSOl_CDMA_PRL_CHANGED: ret = responseInts(p); break; + case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: ret = responseVoid(p); break; + case RIL_UNSOL_RIL_CONNECTED: ret = responseInts(p); break; + case RIL_UNSOL_VOICE_RADIO_TECH_CHANGED: ret = responseInts(p); break; + + default: + throw new RuntimeException("Unrecognized unsol response: " + response); + //break; (implied) + }} catch (Throwable tr) { + Log.e(LOG_TAG, "Exception processing unsol response: " + response + + "Exception:" + tr.toString()); + return; + } + + switch(response) { + case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: + /* has bonus radio state int */ + RadioState newState = getRadioStateFromInt(p.readInt()); + if (RILJ_LOGD) unsljLogMore(response, newState.toString()); + + switchToRadioState(newState); + break; + case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: + if (RILJ_LOGD) unsljLog(response); + + mCallStateRegistrants + .notifyRegistrants(new AsyncResult(null, null, null)); + break; + case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED: + if (RILJ_LOGD) unsljLog(response); + + mVoiceNetworkStateRegistrants + .notifyRegistrants(new AsyncResult(null, null, null)); + break; + case RIL_UNSOL_RESPONSE_NEW_SMS: { + if (RILJ_LOGD) unsljLog(response); + + // FIXME this should move up a layer + String a[] = new String[2]; + + a[1] = (String)ret; + + SmsMessage sms; + + sms = SmsMessage.newFromCMT(a); + if (mGsmSmsRegistrant != null) { + mGsmSmsRegistrant + .notifyRegistrant(new AsyncResult(null, sms, null)); + } + break; + } + case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mSmsStatusRegistrant != null) { + mSmsStatusRegistrant.notifyRegistrant( + new AsyncResult(null, ret, null)); + } + break; + case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM: + if (RILJ_LOGD) unsljLogRet(response, ret); + + int[] smsIndex = (int[])ret; + + if(smsIndex.length == 1) { + if (mSmsOnSimRegistrant != null) { + mSmsOnSimRegistrant. + notifyRegistrant(new AsyncResult(null, smsIndex, null)); + } + } else { + if (RILJ_LOGD) riljLog(" NEW_SMS_ON_SIM ERROR with wrong length " + + smsIndex.length); + } + break; + case RIL_UNSOL_ON_USSD: + String[] resp = (String[])ret; + + if (resp.length < 2) { + resp = new String[2]; + resp[0] = ((String[])ret)[0]; + resp[1] = null; + } + if (RILJ_LOGD) unsljLogMore(response, resp[0]); + if (mUSSDRegistrant != null) { + mUSSDRegistrant.notifyRegistrant( + new AsyncResult (null, resp, null)); + } + break; + case RIL_UNSOL_NITZ_TIME_RECEIVED: + if (RILJ_LOGD) unsljLogRet(response, ret); + + // has bonus long containing milliseconds since boot that the NITZ + // time was received + long nitzReceiveTime = p.readLong(); + + Object[] result = new Object[2]; + + result[0] = ret; + result[1] = Long.valueOf(nitzReceiveTime); + + boolean ignoreNitz = SystemProperties.getBoolean( + TelephonyProperties.PROPERTY_IGNORE_NITZ, false); + + if (ignoreNitz) { + if (RILJ_LOGD) riljLog("ignoring UNSOL_NITZ_TIME_RECEIVED"); + } else { + if (mNITZTimeRegistrant != null) { + + mNITZTimeRegistrant + .notifyRegistrant(new AsyncResult (null, result, null)); + } else { + // in case NITZ time registrant isnt registered yet + mLastNITZTimeInfo = result; + } + } + break; + + case RIL_UNSOL_SIGNAL_STRENGTH: + // Note this is set to "verbose" because it happens + // frequently + if (RILJ_LOGV) unsljLogvRet(response, ret); + + if (mSignalStrengthRegistrant != null) { + mSignalStrengthRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } + break; + case RIL_UNSOL_DATA_CALL_LIST_CHANGED: + if (RILJ_LOGD) unsljLogRet(response, ret); + + mDataNetworkStateRegistrants.notifyRegistrants(new AsyncResult(null, ret, null)); + break; + + case RIL_UNSOL_SUPP_SVC_NOTIFICATION: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mSsnRegistrant != null) { + mSsnRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_STK_SESSION_END: + if (RILJ_LOGD) unsljLog(response); + + if (mCatSessionEndRegistrant != null) { + mCatSessionEndRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_STK_PROACTIVE_COMMAND: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mCatProCmdRegistrant != null) { + mCatProCmdRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_STK_EVENT_NOTIFY: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mCatEventRegistrant != null) { + mCatEventRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_STK_CALL_SETUP: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mCatCallSetUpRegistrant != null) { + mCatCallSetUpRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_SIM_SMS_STORAGE_FULL: + if (RILJ_LOGD) unsljLog(response); + + if (mIccSmsFullRegistrant != null) { + mIccSmsFullRegistrant.notifyRegistrant(); + } + break; + + case RIL_UNSOL_SIM_REFRESH: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mIccRefreshRegistrants != null) { + mIccRefreshRegistrants.notifyRegistrants( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_CALL_RING: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mRingRegistrant != null) { + mRingRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_RESTRICTED_STATE_CHANGED: + if (RILJ_LOGD) unsljLogvRet(response, ret); + if (mRestrictedStateRegistrant != null) { + mRestrictedStateRegistrant.notifyRegistrant( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED: + if (RILJ_LOGD) unsljLog(response); + + if (mIccStatusChangedRegistrants != null) { + mIccStatusChangedRegistrants.notifyRegistrants(); + } + break; + + case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS: + if (RILJ_LOGD) unsljLog(response); + + SmsMessage sms = (SmsMessage) ret; + + if (mCdmaSmsRegistrant != null) { + mCdmaSmsRegistrant + .notifyRegistrant(new AsyncResult(null, sms, null)); + } + break; + + case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS: + if (RILJ_LOGD) unsljLog(response); + + if (mGsmBroadcastSmsRegistrant != null) { + mGsmBroadcastSmsRegistrant + .notifyRegistrant(new AsyncResult(null, ret, null)); + } + break; + + case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL: + if (RILJ_LOGD) unsljLog(response); + + if (mIccSmsFullRegistrant != null) { + mIccSmsFullRegistrant.notifyRegistrant(); + } + break; + + case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: + if (RILJ_LOGD) unsljLog(response); + + if (mEmergencyCallbackModeRegistrant != null) { + mEmergencyCallbackModeRegistrant.notifyRegistrant(); + } + break; + + case RIL_UNSOL_CDMA_CALL_WAITING: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mCallWaitingInfoRegistrants != null) { + mCallWaitingInfoRegistrants.notifyRegistrants( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mOtaProvisionRegistrants != null) { + mOtaProvisionRegistrants.notifyRegistrants( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_CDMA_INFO_REC: + ArrayList<CdmaInformationRecords> listInfoRecs; + + try { + listInfoRecs = (ArrayList<CdmaInformationRecords>)ret; + } catch (ClassCastException e) { + Log.e(LOG_TAG, "Unexpected exception casting to listInfoRecs", e); + break; + } + + for (CdmaInformationRecords rec : listInfoRecs) { + if (RILJ_LOGD) unsljLogRet(response, rec); + notifyRegistrantsCdmaInfoRec(rec); + } + break; + + case RIL_UNSOL_OEM_HOOK_RAW: + if (RILJ_LOGD) unsljLogvRet(response, IccUtils.bytesToHexString((byte[])ret)); + if (mUnsolOemHookRawRegistrant != null) { + mUnsolOemHookRawRegistrant.notifyRegistrant(new AsyncResult(null, ret, null)); + } + break; + + case RIL_UNSOL_RINGBACK_TONE: + if (RILJ_LOGD) unsljLogvRet(response, ret); + if (mRingbackToneRegistrants != null) { + boolean playtone = (((int[])ret)[0] == 1); + mRingbackToneRegistrants.notifyRegistrants( + new AsyncResult (null, playtone, null)); + } + break; + + case RIL_UNSOL_RESEND_INCALL_MUTE: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mResendIncallMuteRegistrants != null) { + mResendIncallMuteRegistrants.notifyRegistrants( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_VOICE_RADIO_TECH_CHANGED: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mVoiceRadioTechChangedRegistrants != null) { + mVoiceRadioTechChangedRegistrants.notifyRegistrants( + new AsyncResult(null, ret, null)); + } + break; + + case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mCdmaSubscriptionChangedRegistrants != null) { + mCdmaSubscriptionChangedRegistrants.notifyRegistrants( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOl_CDMA_PRL_CHANGED: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mCdmaPrlChangedRegistrants != null) { + mCdmaPrlChangedRegistrants.notifyRegistrants( + new AsyncResult (null, ret, null)); + } + break; + + case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: + if (RILJ_LOGD) unsljLogRet(response, ret); + + if (mExitEmergencyCallbackModeRegistrants != null) { + mExitEmergencyCallbackModeRegistrants.notifyRegistrants( + new AsyncResult (null, null, null)); + } + break; + + case RIL_UNSOL_RIL_CONNECTED: { + if (RILJ_LOGD) unsljLogRet(response, ret); + + // Initial conditions + setRadioPower(false, null); + setPreferredNetworkType(mPreferredNetworkType, null); + setCdmaSubscriptionSource(mCdmaSubscription, null); + notifyRegistrantsRilConnectionChanged(((int[])ret)[0]); + break; + } + } + } + + /** + * Notifiy all registrants that the ril has connected or disconnected. + * + * @param rilVer is the version of the ril or -1 if disconnected. + */ + private void notifyRegistrantsRilConnectionChanged(int rilVer) { + mRilVersion = rilVer; + if (mRilConnectedRegistrants != null) { + mRilConnectedRegistrants.notifyRegistrants( + new AsyncResult (null, new Integer(rilVer), null)); + } + } + + private Object + responseInts(Parcel p) { + int numInts; + int response[]; + + numInts = p.readInt(); + + response = new int[numInts]; + + for (int i = 0 ; i < numInts ; i++) { + response[i] = p.readInt(); + } + + return response; + } + + + private Object + responseVoid(Parcel p) { + return null; + } + + private Object + responseCallForward(Parcel p) { + int numInfos; + CallForwardInfo infos[]; + + numInfos = p.readInt(); + + infos = new CallForwardInfo[numInfos]; + + for (int i = 0 ; i < numInfos ; i++) { + infos[i] = new CallForwardInfo(); + + infos[i].status = p.readInt(); + infos[i].reason = p.readInt(); + infos[i].serviceClass = p.readInt(); + infos[i].toa = p.readInt(); + infos[i].number = p.readString(); + infos[i].timeSeconds = p.readInt(); + } + + return infos; + } + + private Object + responseSuppServiceNotification(Parcel p) { + SuppServiceNotification notification = new SuppServiceNotification(); + + notification.notificationType = p.readInt(); + notification.code = p.readInt(); + notification.index = p.readInt(); + notification.type = p.readInt(); + notification.number = p.readString(); + + return notification; + } + + private Object + responseCdmaSms(Parcel p) { + SmsMessage sms; + sms = SmsMessage.newFromParcel(p); + + return sms; + } + + private Object + responseString(Parcel p) { + String response; + + response = p.readString(); + + return response; + } + + private Object + responseStrings(Parcel p) { + int num; + String response[]; + + response = p.readStringArray(); + + if (false) { + num = p.readInt(); + + response = new String[num]; + for (int i = 0; i < num; i++) { + response[i] = p.readString(); + } + } + + return response; + } + + private Object + responseRaw(Parcel p) { + int num; + byte response[]; + + response = p.createByteArray(); + + return response; + } + + private Object + responseSMS(Parcel p) { + int messageRef, errorCode; + String ackPDU; + + messageRef = p.readInt(); + ackPDU = p.readString(); + errorCode = p.readInt(); + + SmsResponse response = new SmsResponse(messageRef, ackPDU, errorCode); + + return response; + } + + + private Object + responseICC_IO(Parcel p) { + int sw1, sw2; + byte data[] = null; + Message ret; + + sw1 = p.readInt(); + sw2 = p.readInt(); + + String s = p.readString(); + + if (RILJ_LOGV) riljLog("< iccIO: " + + " 0x" + Integer.toHexString(sw1) + + " 0x" + Integer.toHexString(sw2) + " " + + s); + + return new IccIoResult(sw1, sw2, s); + } + + private 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); + } + return status; + } + + private Object + responseSimRefresh(Parcel p) { + IccRefreshResponse response = new IccRefreshResponse(); + + response.refreshResult = p.readInt(); + response.efId = p.readInt(); + response.aid = p.readString(); + return response; + } + + private 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(); + 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; + 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; + } + + private DataCallState getDataCallState(Parcel p, int version) { + DataCallState dataCall = new DataCallState(); + + dataCall.version = version; + if (version < 5) { + dataCall.cid = p.readInt(); + dataCall.active = p.readInt(); + dataCall.type = p.readString(); + String addresses = p.readString(); + if (!TextUtils.isEmpty(addresses)) { + dataCall.addresses = addresses.split(" "); + } + } else { + dataCall.status = p.readInt(); + dataCall.suggestedRetryTime = p.readInt(); + dataCall.cid = p.readInt(); + dataCall.active = p.readInt(); + dataCall.type = p.readString(); + dataCall.ifname = p.readString(); + if ((dataCall.status == DataConnection.FailCause.NONE.getErrorCode()) && + TextUtils.isEmpty(dataCall.ifname)) { + throw new RuntimeException("getDataCallState, no ifname"); + } + String addresses = p.readString(); + if (!TextUtils.isEmpty(addresses)) { + dataCall.addresses = addresses.split(" "); + } + String dnses = p.readString(); + if (!TextUtils.isEmpty(dnses)) { + dataCall.dnses = dnses.split(" "); + } + String gateways = p.readString(); + if (!TextUtils.isEmpty(gateways)) { + dataCall.gateways = gateways.split(" "); + } + } + return dataCall; + } + + private Object + responseDataCallList(Parcel p) { + ArrayList<DataCallState> response; + + int ver = p.readInt(); + int num = p.readInt(); + riljLog("responseDataCallList ver=" + ver + " num=" + num); + + response = new ArrayList<DataCallState>(num); + for (int i = 0; i < num; i++) { + response.add(getDataCallState(p, ver)); + } + + return response; + } + + private Object + responseSetupDataCall(Parcel p) { + int ver = p.readInt(); + int num = p.readInt(); + if (RILJ_LOGV) riljLog("responseSetupDataCall ver=" + ver + " num=" + num); + + DataCallState dataCall; + + if (ver < 5) { + dataCall = new DataCallState(); + dataCall.version = ver; + dataCall.cid = Integer.parseInt(p.readString()); + dataCall.ifname = p.readString(); + if (TextUtils.isEmpty(dataCall.ifname)) { + throw new RuntimeException( + "RIL_REQUEST_SETUP_DATA_CALL response, no ifname"); + } + String addresses = p.readString(); + if (!TextUtils.isEmpty(addresses)) { + dataCall.addresses = addresses.split(" "); + } + if (num >= 4) { + String dnses = p.readString(); + if (RILJ_LOGD) riljLog("responseSetupDataCall got dnses=" + dnses); + if (!TextUtils.isEmpty(dnses)) { + dataCall.dnses = dnses.split(" "); + } + } + if (num >= 5) { + String gateways = p.readString(); + if (RILJ_LOGD) riljLog("responseSetupDataCall got gateways=" + gateways); + if (!TextUtils.isEmpty(gateways)) { + dataCall.gateways = gateways.split(" "); + } + } + } else { + if (num != 1) { + throw new RuntimeException( + "RIL_REQUEST_SETUP_DATA_CALL response expecting 1 RIL_Data_Call_response_v5" + + " got " + num); + } + dataCall = getDataCallState(p, ver); + } + + return dataCall; + } + + private Object + responseOperatorInfos(Parcel p) { + String strings[] = (String [])responseStrings(p); + ArrayList<OperatorInfo> ret; + + if (strings.length % 4 != 0) { + throw new RuntimeException( + "RIL_REQUEST_QUERY_AVAILABLE_NETWORKS: invalid response. Got " + + strings.length + " strings, expected multible of 4"); + } + + ret = new ArrayList<OperatorInfo>(strings.length / 4); + + for (int i = 0 ; i < strings.length ; i += 4) { + ret.add ( + new OperatorInfo( + strings[i+0], + strings[i+1], + strings[i+2], + strings[i+3])); + } + + return ret; + } + + private Object + responseCellList(Parcel p) { + int num, rssi; + String location; + ArrayList<NeighboringCellInfo> response; + NeighboringCellInfo cell; + + num = p.readInt(); + response = new ArrayList<NeighboringCellInfo>(); + + // Determine the radio access type + String radioString = SystemProperties.get( + TelephonyProperties.PROPERTY_DATA_NETWORK_TYPE, "unknown"); + int radioType; + if (radioString.equals("GPRS")) { + radioType = NETWORK_TYPE_GPRS; + } else if (radioString.equals("EDGE")) { + radioType = NETWORK_TYPE_EDGE; + } else if (radioString.equals("UMTS")) { + radioType = NETWORK_TYPE_UMTS; + } else if (radioString.equals("HSDPA")) { + radioType = NETWORK_TYPE_HSDPA; + } else if (radioString.equals("HSUPA")) { + radioType = NETWORK_TYPE_HSUPA; + } else if (radioString.equals("HSPA")) { + radioType = NETWORK_TYPE_HSPA; + } else { + radioType = NETWORK_TYPE_UNKNOWN; + } + + // Interpret the location based on radio access type + if (radioType != NETWORK_TYPE_UNKNOWN) { + for (int i = 0 ; i < num ; i++) { + rssi = p.readInt(); + location = p.readString(); + cell = new NeighboringCellInfo(rssi, location, radioType); + response.add(cell); + } + } + return response; + } + + private 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]; + } + return response; + } + + private Object responseGmsBroadcastConfig(Parcel p) { + int num; + ArrayList<SmsBroadcastConfigInfo> response; + SmsBroadcastConfigInfo info; + + num = p.readInt(); + response = new ArrayList<SmsBroadcastConfigInfo>(num); + + for (int i = 0; i < num; i++) { + int fromId = p.readInt(); + int toId = p.readInt(); + int fromScheme = p.readInt(); + int toScheme = p.readInt(); + boolean selected = (p.readInt() == 1); + + info = new SmsBroadcastConfigInfo(fromId, toId, fromScheme, + toScheme, selected); + response.add(info); + } + return response; + } + + private Object + responseCdmaBroadcastConfig(Parcel p) { + int numServiceCategories; + int response[]; + + numServiceCategories = p.readInt(); + + if (numServiceCategories == 0) { + // TODO: The logic of providing default values should + // not be done by this transport layer. And needs to + // be done by the vendor ril or application logic. + int numInts; + numInts = CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES * CDMA_BSI_NO_OF_INTS_STRUCT + 1; + response = new int[numInts]; + + // Faking a default record for all possible records. + response[0] = CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES; + + // Loop over CDMA_BROADCAST_SMS_NO_OF_SERVICE_CATEGORIES set 'english' as + // default language and selection status to false for all. + for (int i = 1; i < numInts; i += CDMA_BSI_NO_OF_INTS_STRUCT ) { + response[i + 0] = i / CDMA_BSI_NO_OF_INTS_STRUCT; + response[i + 1] = 1; + response[i + 2] = 0; + } + } else { + int numInts; + numInts = (numServiceCategories * CDMA_BSI_NO_OF_INTS_STRUCT) + 1; + response = new int[numInts]; + + response[0] = numServiceCategories; + for (int i = 1 ; i < numInts; i++) { + response[i] = p.readInt(); + } + } + + return response; + } + + private 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(); + } + + return response; + } + + private ArrayList<CdmaInformationRecords> + responseCdmaInformationRecord(Parcel p) { + int numberOfInfoRecs; + ArrayList<CdmaInformationRecords> response; + + /** + * Loop through all of the information records unmarshalling them + * and converting them to Java Objects. + */ + numberOfInfoRecs = p.readInt(); + response = new ArrayList<CdmaInformationRecords>(numberOfInfoRecs); + + for (int i = 0; i < numberOfInfoRecs; i++) { + CdmaInformationRecords InfoRec = new CdmaInformationRecords(p); + response.add(InfoRec); + } + + return response; + } + + private Object + responseCdmaCallWaiting(Parcel p) { + CdmaCallWaitingNotification notification = new CdmaCallWaitingNotification(); + + notification.number = p.readString(); + notification.numberPresentation = notification.presentationFromCLIP(p.readInt()); + notification.name = p.readString(); + notification.namePresentation = notification.numberPresentation; + notification.isPresent = p.readInt(); + notification.signalType = p.readInt(); + notification.alertPitch = p.readInt(); + notification.signal = p.readInt(); + notification.numberType = p.readInt(); + notification.numberPlan = p.readInt(); + + return notification; + } + + private Object + responseCallRing(Parcel p){ + char response[] = new char[4]; + + response[0] = (char) p.readInt(); // isPresent + response[1] = (char) p.readInt(); // signalType + response[2] = (char) p.readInt(); // alertPitch + response[3] = (char) p.readInt(); // signal + + return response; + } + + private void + notifyRegistrantsCdmaInfoRec(CdmaInformationRecords infoRec) { + int response = RIL_UNSOL_CDMA_INFO_REC; + if (infoRec.record instanceof CdmaInformationRecords.CdmaDisplayInfoRec) { + if (mDisplayInfoRegistrants != null) { + if (RILJ_LOGD) unsljLogRet(response, infoRec.record); + mDisplayInfoRegistrants.notifyRegistrants( + new AsyncResult (null, infoRec.record, null)); + } + } else if (infoRec.record instanceof CdmaInformationRecords.CdmaSignalInfoRec) { + if (mSignalInfoRegistrants != null) { + if (RILJ_LOGD) unsljLogRet(response, infoRec.record); + mSignalInfoRegistrants.notifyRegistrants( + new AsyncResult (null, infoRec.record, null)); + } + } else if (infoRec.record instanceof CdmaInformationRecords.CdmaNumberInfoRec) { + if (mNumberInfoRegistrants != null) { + if (RILJ_LOGD) unsljLogRet(response, infoRec.record); + mNumberInfoRegistrants.notifyRegistrants( + new AsyncResult (null, infoRec.record, null)); + } + } else if (infoRec.record instanceof CdmaInformationRecords.CdmaRedirectingNumberInfoRec) { + if (mRedirNumInfoRegistrants != null) { + if (RILJ_LOGD) unsljLogRet(response, infoRec.record); + mRedirNumInfoRegistrants.notifyRegistrants( + new AsyncResult (null, infoRec.record, null)); + } + } else if (infoRec.record instanceof CdmaInformationRecords.CdmaLineControlInfoRec) { + if (mLineControlInfoRegistrants != null) { + if (RILJ_LOGD) unsljLogRet(response, infoRec.record); + mLineControlInfoRegistrants.notifyRegistrants( + new AsyncResult (null, infoRec.record, null)); + } + } else if (infoRec.record instanceof CdmaInformationRecords.CdmaT53ClirInfoRec) { + if (mT53ClirInfoRegistrants != null) { + if (RILJ_LOGD) unsljLogRet(response, infoRec.record); + mT53ClirInfoRegistrants.notifyRegistrants( + new AsyncResult (null, infoRec.record, null)); + } + } else if (infoRec.record instanceof CdmaInformationRecords.CdmaT53AudioControlInfoRec) { + if (mT53AudCntrlInfoRegistrants != null) { + if (RILJ_LOGD) unsljLogRet(response, infoRec.record); + mT53AudCntrlInfoRegistrants.notifyRegistrants( + new AsyncResult (null, infoRec.record, null)); + } + } + } + + static String + requestToString(int request) { +/* + cat libs/telephony/ril_commands.h \ + | egrep "^ *{RIL_" \ + | sed -re 's/\{RIL_([^,]+),[^,]+,([^}]+).+/case RIL_\1: return "\1";/' +*/ + switch(request) { + case RIL_REQUEST_GET_SIM_STATUS: return "GET_SIM_STATUS"; + case RIL_REQUEST_ENTER_SIM_PIN: return "ENTER_SIM_PIN"; + case RIL_REQUEST_ENTER_SIM_PUK: return "ENTER_SIM_PUK"; + case RIL_REQUEST_ENTER_SIM_PIN2: return "ENTER_SIM_PIN2"; + case RIL_REQUEST_ENTER_SIM_PUK2: return "ENTER_SIM_PUK2"; + case RIL_REQUEST_CHANGE_SIM_PIN: return "CHANGE_SIM_PIN"; + case RIL_REQUEST_CHANGE_SIM_PIN2: return "CHANGE_SIM_PIN2"; + case RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION: return "ENTER_NETWORK_DEPERSONALIZATION"; + case RIL_REQUEST_GET_CURRENT_CALLS: return "GET_CURRENT_CALLS"; + case RIL_REQUEST_DIAL: return "DIAL"; + case RIL_REQUEST_GET_IMSI: return "GET_IMSI"; + case RIL_REQUEST_HANGUP: return "HANGUP"; + case RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND: return "HANGUP_WAITING_OR_BACKGROUND"; + case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND: return "HANGUP_FOREGROUND_RESUME_BACKGROUND"; + case RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE: return "REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE"; + case RIL_REQUEST_CONFERENCE: return "CONFERENCE"; + case RIL_REQUEST_UDUB: return "UDUB"; + case RIL_REQUEST_LAST_CALL_FAIL_CAUSE: return "LAST_CALL_FAIL_CAUSE"; + case RIL_REQUEST_SIGNAL_STRENGTH: return "SIGNAL_STRENGTH"; + case RIL_REQUEST_VOICE_REGISTRATION_STATE: return "VOICE_REGISTRATION_STATE"; + case RIL_REQUEST_DATA_REGISTRATION_STATE: return "DATA_REGISTRATION_STATE"; + case RIL_REQUEST_OPERATOR: return "OPERATOR"; + case RIL_REQUEST_RADIO_POWER: return "RADIO_POWER"; + case RIL_REQUEST_DTMF: return "DTMF"; + case RIL_REQUEST_SEND_SMS: return "SEND_SMS"; + case RIL_REQUEST_SEND_SMS_EXPECT_MORE: return "SEND_SMS_EXPECT_MORE"; + case RIL_REQUEST_SETUP_DATA_CALL: return "SETUP_DATA_CALL"; + case RIL_REQUEST_SIM_IO: return "SIM_IO"; + case RIL_REQUEST_SEND_USSD: return "SEND_USSD"; + case RIL_REQUEST_CANCEL_USSD: return "CANCEL_USSD"; + case RIL_REQUEST_GET_CLIR: return "GET_CLIR"; + case RIL_REQUEST_SET_CLIR: return "SET_CLIR"; + case RIL_REQUEST_QUERY_CALL_FORWARD_STATUS: return "QUERY_CALL_FORWARD_STATUS"; + case RIL_REQUEST_SET_CALL_FORWARD: return "SET_CALL_FORWARD"; + case RIL_REQUEST_QUERY_CALL_WAITING: return "QUERY_CALL_WAITING"; + case RIL_REQUEST_SET_CALL_WAITING: return "SET_CALL_WAITING"; + case RIL_REQUEST_SMS_ACKNOWLEDGE: return "SMS_ACKNOWLEDGE"; + case RIL_REQUEST_GET_IMEI: return "GET_IMEI"; + case RIL_REQUEST_GET_IMEISV: return "GET_IMEISV"; + case RIL_REQUEST_ANSWER: return "ANSWER"; + case RIL_REQUEST_DEACTIVATE_DATA_CALL: return "DEACTIVATE_DATA_CALL"; + case RIL_REQUEST_QUERY_FACILITY_LOCK: return "QUERY_FACILITY_LOCK"; + case RIL_REQUEST_SET_FACILITY_LOCK: return "SET_FACILITY_LOCK"; + case RIL_REQUEST_CHANGE_BARRING_PASSWORD: return "CHANGE_BARRING_PASSWORD"; + case RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE: return "QUERY_NETWORK_SELECTION_MODE"; + case RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC: return "SET_NETWORK_SELECTION_AUTOMATIC"; + case RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL: return "SET_NETWORK_SELECTION_MANUAL"; + case RIL_REQUEST_QUERY_AVAILABLE_NETWORKS : return "QUERY_AVAILABLE_NETWORKS "; + case RIL_REQUEST_DTMF_START: return "DTMF_START"; + case RIL_REQUEST_DTMF_STOP: return "DTMF_STOP"; + case RIL_REQUEST_BASEBAND_VERSION: return "BASEBAND_VERSION"; + case RIL_REQUEST_SEPARATE_CONNECTION: return "SEPARATE_CONNECTION"; + case RIL_REQUEST_SET_MUTE: return "SET_MUTE"; + case RIL_REQUEST_GET_MUTE: return "GET_MUTE"; + case RIL_REQUEST_QUERY_CLIP: return "QUERY_CLIP"; + case RIL_REQUEST_LAST_DATA_CALL_FAIL_CAUSE: return "LAST_DATA_CALL_FAIL_CAUSE"; + case RIL_REQUEST_DATA_CALL_LIST: return "DATA_CALL_LIST"; + case RIL_REQUEST_RESET_RADIO: return "RESET_RADIO"; + case RIL_REQUEST_OEM_HOOK_RAW: return "OEM_HOOK_RAW"; + case RIL_REQUEST_OEM_HOOK_STRINGS: return "OEM_HOOK_STRINGS"; + case RIL_REQUEST_SCREEN_STATE: return "SCREEN_STATE"; + case RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION: return "SET_SUPP_SVC_NOTIFICATION"; + case RIL_REQUEST_WRITE_SMS_TO_SIM: return "WRITE_SMS_TO_SIM"; + case RIL_REQUEST_DELETE_SMS_ON_SIM: return "DELETE_SMS_ON_SIM"; + case RIL_REQUEST_SET_BAND_MODE: return "SET_BAND_MODE"; + case RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE: return "QUERY_AVAILABLE_BAND_MODE"; + case RIL_REQUEST_STK_GET_PROFILE: return "REQUEST_STK_GET_PROFILE"; + case RIL_REQUEST_STK_SET_PROFILE: return "REQUEST_STK_SET_PROFILE"; + case RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND: return "REQUEST_STK_SEND_ENVELOPE_COMMAND"; + case RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE: return "REQUEST_STK_SEND_TERMINAL_RESPONSE"; + case RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM: return "REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM"; + case RIL_REQUEST_EXPLICIT_CALL_TRANSFER: return "REQUEST_EXPLICIT_CALL_TRANSFER"; + case RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE: return "REQUEST_SET_PREFERRED_NETWORK_TYPE"; + case RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE: return "REQUEST_GET_PREFERRED_NETWORK_TYPE"; + case RIL_REQUEST_GET_NEIGHBORING_CELL_IDS: return "REQUEST_GET_NEIGHBORING_CELL_IDS"; + case RIL_REQUEST_SET_LOCATION_UPDATES: return "REQUEST_SET_LOCATION_UPDATES"; + case RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE: return "RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE"; + case RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE: return "RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE"; + case RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE: return "RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE"; + case RIL_REQUEST_SET_TTY_MODE: return "RIL_REQUEST_SET_TTY_MODE"; + case RIL_REQUEST_QUERY_TTY_MODE: return "RIL_REQUEST_QUERY_TTY_MODE"; + case RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE: return "RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE"; + case RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE: return "RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE"; + case RIL_REQUEST_CDMA_FLASH: return "RIL_REQUEST_CDMA_FLASH"; + case RIL_REQUEST_CDMA_BURST_DTMF: return "RIL_REQUEST_CDMA_BURST_DTMF"; + case RIL_REQUEST_CDMA_SEND_SMS: return "RIL_REQUEST_CDMA_SEND_SMS"; + case RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE: return "RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE"; + case RIL_REQUEST_GSM_GET_BROADCAST_CONFIG: return "RIL_REQUEST_GSM_GET_BROADCAST_CONFIG"; + case RIL_REQUEST_GSM_SET_BROADCAST_CONFIG: return "RIL_REQUEST_GSM_SET_BROADCAST_CONFIG"; + case RIL_REQUEST_CDMA_GET_BROADCAST_CONFIG: return "RIL_REQUEST_CDMA_GET_BROADCAST_CONFIG"; + case RIL_REQUEST_CDMA_SET_BROADCAST_CONFIG: return "RIL_REQUEST_CDMA_SET_BROADCAST_CONFIG"; + case RIL_REQUEST_GSM_BROADCAST_ACTIVATION: return "RIL_REQUEST_GSM_BROADCAST_ACTIVATION"; + case RIL_REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY: return "RIL_REQUEST_CDMA_VALIDATE_AND_WRITE_AKEY"; + case RIL_REQUEST_CDMA_BROADCAST_ACTIVATION: return "RIL_REQUEST_CDMA_BROADCAST_ACTIVATION"; + case RIL_REQUEST_CDMA_SUBSCRIPTION: return "RIL_REQUEST_CDMA_SUBSCRIPTION"; + case RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM: return "RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM"; + case RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM: return "RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM"; + case RIL_REQUEST_DEVICE_IDENTITY: return "RIL_REQUEST_DEVICE_IDENTITY"; + case RIL_REQUEST_GET_SMSC_ADDRESS: return "RIL_REQUEST_GET_SMSC_ADDRESS"; + case RIL_REQUEST_SET_SMSC_ADDRESS: return "RIL_REQUEST_SET_SMSC_ADDRESS"; + case RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE: return "REQUEST_EXIT_EMERGENCY_CALLBACK_MODE"; + case RIL_REQUEST_REPORT_SMS_MEMORY_STATUS: return "RIL_REQUEST_REPORT_SMS_MEMORY_STATUS"; + case RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING: return "RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING"; + case RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE: return "RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE"; + case RIL_REQUEST_ISIM_AUTHENTICATION: return "RIL_REQUEST_ISIM_AUTHENTICATION"; + case RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU: return "RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU"; + case RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS: return "RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS"; + case RIL_REQUEST_VOICE_RADIO_TECH: return "RIL_REQUEST_VOICE_RADIO_TECH"; + default: return "<unknown request>"; + } + } + + static String + responseToString(int request) + { +/* + cat libs/telephony/ril_unsol_commands.h \ + | egrep "^ *{RIL_" \ + | sed -re 's/\{RIL_([^,]+),[^,]+,([^}]+).+/case RIL_\1: return "\1";/' +*/ + switch(request) { + case RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED: return "UNSOL_RESPONSE_RADIO_STATE_CHANGED"; + case RIL_UNSOL_RESPONSE_CALL_STATE_CHANGED: return "UNSOL_RESPONSE_CALL_STATE_CHANGED"; + case RIL_UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED: return "UNSOL_RESPONSE_VOICE_NETWORK_STATE_CHANGED"; + case RIL_UNSOL_RESPONSE_NEW_SMS: return "UNSOL_RESPONSE_NEW_SMS"; + case RIL_UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT: return "UNSOL_RESPONSE_NEW_SMS_STATUS_REPORT"; + case RIL_UNSOL_RESPONSE_NEW_SMS_ON_SIM: return "UNSOL_RESPONSE_NEW_SMS_ON_SIM"; + case RIL_UNSOL_ON_USSD: return "UNSOL_ON_USSD"; + case RIL_UNSOL_ON_USSD_REQUEST: return "UNSOL_ON_USSD_REQUEST"; + case RIL_UNSOL_NITZ_TIME_RECEIVED: return "UNSOL_NITZ_TIME_RECEIVED"; + case RIL_UNSOL_SIGNAL_STRENGTH: return "UNSOL_SIGNAL_STRENGTH"; + case RIL_UNSOL_DATA_CALL_LIST_CHANGED: return "UNSOL_DATA_CALL_LIST_CHANGED"; + case RIL_UNSOL_SUPP_SVC_NOTIFICATION: return "UNSOL_SUPP_SVC_NOTIFICATION"; + case RIL_UNSOL_STK_SESSION_END: return "UNSOL_STK_SESSION_END"; + case RIL_UNSOL_STK_PROACTIVE_COMMAND: return "UNSOL_STK_PROACTIVE_COMMAND"; + case RIL_UNSOL_STK_EVENT_NOTIFY: return "UNSOL_STK_EVENT_NOTIFY"; + case RIL_UNSOL_STK_CALL_SETUP: return "UNSOL_STK_CALL_SETUP"; + case RIL_UNSOL_SIM_SMS_STORAGE_FULL: return "UNSOL_SIM_SMS_STORAGE_FULL"; + case RIL_UNSOL_SIM_REFRESH: return "UNSOL_SIM_REFRESH"; + case RIL_UNSOL_CALL_RING: return "UNSOL_CALL_RING"; + case RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED: return "UNSOL_RESPONSE_SIM_STATUS_CHANGED"; + case RIL_UNSOL_RESPONSE_CDMA_NEW_SMS: return "UNSOL_RESPONSE_CDMA_NEW_SMS"; + case RIL_UNSOL_RESPONSE_NEW_BROADCAST_SMS: return "UNSOL_RESPONSE_NEW_BROADCAST_SMS"; + case RIL_UNSOL_CDMA_RUIM_SMS_STORAGE_FULL: return "UNSOL_CDMA_RUIM_SMS_STORAGE_FULL"; + case RIL_UNSOL_RESTRICTED_STATE_CHANGED: return "UNSOL_RESTRICTED_STATE_CHANGED"; + case RIL_UNSOL_ENTER_EMERGENCY_CALLBACK_MODE: return "UNSOL_ENTER_EMERGENCY_CALLBACK_MODE"; + case RIL_UNSOL_CDMA_CALL_WAITING: return "UNSOL_CDMA_CALL_WAITING"; + case RIL_UNSOL_CDMA_OTA_PROVISION_STATUS: return "UNSOL_CDMA_OTA_PROVISION_STATUS"; + case RIL_UNSOL_CDMA_INFO_REC: return "UNSOL_CDMA_INFO_REC"; + case RIL_UNSOL_OEM_HOOK_RAW: return "UNSOL_OEM_HOOK_RAW"; + case RIL_UNSOL_RINGBACK_TONE: return "UNSOL_RINGBACK_TONG"; + case RIL_UNSOL_RESEND_INCALL_MUTE: return "UNSOL_RESEND_INCALL_MUTE"; + case RIL_UNSOL_CDMA_SUBSCRIPTION_SOURCE_CHANGED: return "CDMA_SUBSCRIPTION_SOURCE_CHANGED"; + case RIL_UNSOl_CDMA_PRL_CHANGED: return "UNSOL_CDMA_PRL_CHANGED"; + case RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE: return "UNSOL_EXIT_EMERGENCY_CALLBACK_MODE"; + case RIL_UNSOL_RIL_CONNECTED: return "UNSOL_RIL_CONNECTED"; + case RIL_UNSOL_VOICE_RADIO_TECH_CHANGED: return "UNSOL_VOICE_RADIO_TECH_CHANGED"; + default: return "<unknown reponse>"; + } + } + + private void riljLog(String msg) { + Log.d(LOG_TAG, msg); + } + + private void riljLogv(String msg) { + Log.v(LOG_TAG, msg); + } + + private void unsljLog(int response) { + riljLog("[UNSL]< " + responseToString(response)); + } + + private void unsljLogMore(int response, String more) { + riljLog("[UNSL]< " + responseToString(response) + " " + more); + } + + private void unsljLogRet(int response, Object ret) { + riljLog("[UNSL]< " + responseToString(response) + " " + retToString(response, ret)); + } + + private void unsljLogvRet(int response, Object ret) { + riljLogv("[UNSL]< " + responseToString(response) + " " + retToString(response, ret)); + } + + + // ***** Methods for CDMA support + public void + getDeviceIdentity(Message response) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_DEVICE_IDENTITY, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void + getCDMASubscription(Message response) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_SUBSCRIPTION, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + @Override + public void setPhoneType(int phoneType) { // Called by CDMAPhone and GSMPhone constructor + if (RILJ_LOGD) riljLog("setPhoneType=" + phoneType + " old value=" + mPhoneType); + mPhoneType = phoneType; + } + + /** + * {@inheritDoc} + */ + public void queryCdmaRoamingPreference(Message response) { + RILRequest rr = RILRequest.obtain( + RILConstants.RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + /** + * {@inheritDoc} + */ + public void setCdmaRoamingPreference(int cdmaRoamingType, Message response) { + RILRequest rr = RILRequest.obtain( + RILConstants.RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE, response); + + rr.mp.writeInt(1); + rr.mp.writeInt(cdmaRoamingType); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " : " + cdmaRoamingType); + + send(rr); + } + + /** + * {@inheritDoc} + */ + public void setCdmaSubscriptionSource(int cdmaSubscription , Message response) { + RILRequest rr = RILRequest.obtain( + RILConstants.RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE, response); + + rr.mp.writeInt(1); + rr.mp.writeInt(cdmaSubscription); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " : " + cdmaSubscription); + + send(rr); + } + + /** + * {@inheritDoc} + */ + @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)); + + send(rr); + } + + /** + * {@inheritDoc} + */ + public void queryTTYMode(Message response) { + RILRequest rr = RILRequest.obtain( + RILConstants.RIL_REQUEST_QUERY_TTY_MODE, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + /** + * {@inheritDoc} + */ + public void setTTYMode(int ttyMode, Message response) { + RILRequest rr = RILRequest.obtain( + RILConstants.RIL_REQUEST_SET_TTY_MODE, response); + + rr.mp.writeInt(1); + rr.mp.writeInt(ttyMode); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " : " + ttyMode); + + send(rr); + } + + /** + * {@inheritDoc} + */ + public void + sendCDMAFeatureCode(String FeatureCode, Message response) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_FLASH, response); + + rr.mp.writeString(FeatureCode); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + + " : " + FeatureCode); + + send(rr); + } + + public void getCdmaBroadcastConfig(Message response) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_GET_BROADCAST_CONFIG, response); + + send(rr); + } + + // TODO: Change the configValuesArray to a RIL_BroadcastSMSConfig + public void setCdmaBroadcastConfig(int[] configValuesArray, Message response) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_SET_BROADCAST_CONFIG, response); + + for(int i = 0; i < configValuesArray.length; i++) { + rr.mp.writeInt(configValuesArray[i]); + } + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void setCdmaBroadcastActivation(boolean activate, Message response) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_CDMA_BROADCAST_ACTIVATION, response); + + rr.mp.writeInt(1); + rr.mp.writeInt(activate ? 0 :1); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + /** + * {@inheritDoc} + */ + public void exitEmergencyCallbackMode(Message response) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE, response); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + public void requestIsimAuthentication(String nonce, Message response) { + RILRequest rr = RILRequest.obtain(RIL_REQUEST_ISIM_AUTHENTICATION, response); + + rr.mp.writeString(nonce); + + if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); + + send(rr); + } + + /* (non-Javadoc) + * @see com.android.internal.telephony.BaseCommands#testingEmergencyCall() + */ + @Override + public void testingEmergencyCall() { + if (RILJ_LOGD) riljLog("testingEmergencyCall"); + mTestingEmergencyCall.set(true); + } + + public void dump(FileDescriptor fd, PrintWriter pw, String[] args) { + pw.println("RIL:"); + pw.println(" mSocket=" + mSocket); + pw.println(" mSenderThread=" + mSenderThread); + pw.println(" mSender=" + mSender); + pw.println(" mReceiverThread=" + mReceiverThread); + pw.println(" mReceiver=" + mReceiver); + pw.println(" mWakeLock=" + mWakeLock); + pw.println(" mWakeLockTimeout=" + mWakeLockTimeout); + synchronized (mRequestsList) { + pw.println(" mRequestMessagesPending=" + mRequestMessagesPending); + pw.println(" mRequestMessagesWaiting=" + mRequestMessagesWaiting); + int count = mRequestsList.size(); + pw.println(" mRequestList count=" + count); + for (int i = 0; i < count; i++) { + RILRequest rr = mRequestsList.get(i); + pw.println(" [" + rr.mSerial + "] " + requestToString(rr.mRequest)); + } + } + pw.println(" mLastNITZTimeInfo=" + mLastNITZTimeInfo); + pw.println(" mTestingEmergencyCall=" + mTestingEmergencyCall.get()); + } +} |