/* * 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 com.android.internal.util.Preconditions.checkNotNull; import android.annotation.UnsupportedAppUsage; import android.content.Context; import android.hardware.radio.V1_0.Carrier; import android.hardware.radio.V1_0.CarrierRestrictions; import android.hardware.radio.V1_0.CdmaBroadcastSmsConfigInfo; import android.hardware.radio.V1_0.CdmaSmsAck; import android.hardware.radio.V1_0.CdmaSmsMessage; import android.hardware.radio.V1_0.CdmaSmsWriteArgs; import android.hardware.radio.V1_0.DataProfileId; import android.hardware.radio.V1_0.Dial; import android.hardware.radio.V1_0.GsmBroadcastSmsConfigInfo; import android.hardware.radio.V1_0.GsmSmsMessage; import android.hardware.radio.V1_0.HardwareConfigModem; import android.hardware.radio.V1_0.IRadio; import android.hardware.radio.V1_0.IccIo; import android.hardware.radio.V1_0.ImsSmsMessage; import android.hardware.radio.V1_0.IndicationFilter; import android.hardware.radio.V1_0.LceDataInfo; import android.hardware.radio.V1_0.MvnoType; import android.hardware.radio.V1_0.NvWriteItem; import android.hardware.radio.V1_0.RadioError; import android.hardware.radio.V1_0.RadioIndicationType; import android.hardware.radio.V1_0.RadioResponseInfo; import android.hardware.radio.V1_0.RadioResponseType; import android.hardware.radio.V1_0.ResetNvType; import android.hardware.radio.V1_0.SelectUiccSub; import android.hardware.radio.V1_0.SimApdu; import android.hardware.radio.V1_0.SmsWriteArgs; import android.hardware.radio.V1_0.UusInfo; import android.hardware.radio.V1_2.AccessNetwork; import android.hardware.radio.V1_4.CarrierRestrictionsWithPriority; import android.hardware.radio.V1_4.SimLockMultiSimPolicy; import android.hardware.radio.deprecated.V1_0.IOemHook; import android.net.ConnectivityManager; import android.net.KeepalivePacketData; import android.net.LinkAddress; import android.net.LinkProperties; import android.net.NetworkUtils; import android.os.AsyncResult; import android.os.Build; import android.os.Handler; import android.os.HwBinder; import android.os.Message; import android.os.PowerManager; import android.os.PowerManager.WakeLock; import android.os.RemoteException; import android.os.SystemClock; import android.os.SystemProperties; import android.os.WorkSource; import android.provider.Settings; import android.service.carrier.CarrierIdentifier; import android.telephony.AccessNetworkConstants.AccessNetworkType; import android.telephony.CarrierRestrictionRules; import android.telephony.CellInfo; import android.telephony.ClientRequestStats; import android.telephony.ImsiEncryptionInfo; import android.telephony.ModemActivityInfo; import android.telephony.NeighboringCellInfo; import android.telephony.NetworkScanRequest; import android.telephony.PhoneNumberUtils; import android.telephony.RadioAccessFamily; import android.telephony.RadioAccessSpecifier; import android.telephony.Rlog; import android.telephony.ServiceState; import android.telephony.SmsManager; import android.telephony.TelephonyHistogram; import android.telephony.TelephonyManager; import android.telephony.TelephonyManager.PrefNetworkMode; import android.telephony.data.ApnSetting; import android.telephony.data.DataCallResponse; import android.telephony.data.DataProfile; import android.telephony.data.DataService; import android.telephony.emergency.EmergencyNumber; import android.text.TextUtils; import android.util.Log; import android.util.SparseArray; import com.android.internal.annotations.VisibleForTesting; import com.android.internal.telephony.cat.ComprehensionTlv; import com.android.internal.telephony.cat.ComprehensionTlvTag; import com.android.internal.telephony.cdma.CdmaInformationRecords; import com.android.internal.telephony.cdma.CdmaSmsBroadcastConfigInfo; import com.android.internal.telephony.gsm.SmsBroadcastConfigInfo; import com.android.internal.telephony.metrics.TelephonyMetrics; import com.android.internal.telephony.nano.TelephonyProto.SmsSession; import com.android.internal.telephony.uicc.IccUtils; import java.io.ByteArrayInputStream; import java.io.DataInputStream; import java.io.FileDescriptor; import java.io.IOException; import java.io.PrintWriter; import java.net.Inet4Address; import java.net.Inet6Address; import java.net.InetAddress; import java.util.ArrayList; import java.util.Arrays; import java.util.HashSet; import java.util.List; import java.util.NoSuchElementException; import java.util.Set; import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicLong; /** * RIL implementation of the CommandsInterface. * * {@hide} */ public class RIL extends BaseCommands implements CommandsInterface { static final String RILJ_LOG_TAG = "RILJ"; static final String RILJ_WAKELOCK_TAG = "*telephony-radio*"; // Have a separate wakelock instance for Ack static final String RILJ_ACK_WAKELOCK_NAME = "RILJ_ACK_WL"; static final boolean RILJ_LOGD = true; static final boolean RILJ_LOGV = false; // STOPSHIP if true static final int RIL_HISTOGRAM_BUCKET_COUNT = 5; /** * Wake lock timeout should be longer than the longest timeout in * the vendor ril. */ private static final int DEFAULT_WAKE_LOCK_TIMEOUT_MS = 60000; // Wake lock default timeout associated with ack private static final int DEFAULT_ACK_WAKE_LOCK_TIMEOUT_MS = 200; private static final int DEFAULT_BLOCKING_MESSAGE_RESPONSE_TIMEOUT_MS = 2000; // Variables used to differentiate ack messages from request while calling clearWakeLock() public static final int INVALID_WAKELOCK = -1; public static final int FOR_WAKELOCK = 0; public static final int FOR_ACK_WAKELOCK = 1; private final ClientWakelockTracker mClientWakelockTracker = new ClientWakelockTracker(); /** @hide */ public static final HalVersion RADIO_HAL_VERSION_UNKNOWN = HalVersion.UNKNOWN; /** @hide */ public static final HalVersion RADIO_HAL_VERSION_1_0 = new HalVersion(1, 0); /** @hide */ public static final HalVersion RADIO_HAL_VERSION_1_1 = new HalVersion(1, 1); /** @hide */ public static final HalVersion RADIO_HAL_VERSION_1_2 = new HalVersion(1, 2); /** @hide */ public static final HalVersion RADIO_HAL_VERSION_1_3 = new HalVersion(1, 3); /** @hide */ public static final HalVersion RADIO_HAL_VERSION_1_4 = new HalVersion(1, 4); // IRadio version private HalVersion mRadioVersion = RADIO_HAL_VERSION_UNKNOWN; //***** Instance Variables @UnsupportedAppUsage final WakeLock mWakeLock; // Wake lock associated with request/response final WakeLock mAckWakeLock; // Wake lock associated with ack sent final int mWakeLockTimeout; // Timeout associated with request/response final int mAckWakeLockTimeout; // Timeout associated with ack sent // The number of wakelock requests currently active. Don't release the lock // until dec'd to 0 int mWakeLockCount; // Variables used to identify releasing of WL on wakelock timeouts volatile int mWlSequenceNum = 0; volatile int mAckWlSequenceNum = 0; @UnsupportedAppUsage SparseArray mRequestList = new SparseArray(); static SparseArray mRilTimeHistograms = new SparseArray(); Object[] mLastNITZTimeInfo; // When we are testing emergency calls @UnsupportedAppUsage AtomicBoolean mTestingEmergencyCall = new AtomicBoolean(false); final Integer mPhoneId; /** * A set that records if radio service is disabled in hal for * a specific phone id slot to avoid further getService request. */ Set mDisabledRadioServices = new HashSet(); /** * A set that records if oem hook service is disabled in hal for * a specific phone id slot to avoid further getService request. */ Set mDisabledOemHookServices = new HashSet(); /* default work source which will blame phone process */ private WorkSource mRILDefaultWorkSource; /* Worksource containing all applications causing wakelock to be held */ private WorkSource mActiveWakelockWorkSource; /** Telephony metrics instance for logging metrics event */ private TelephonyMetrics mMetrics = TelephonyMetrics.getInstance(); /** Radio bug detector instance */ private RadioBugDetector mRadioBugDetector = null; boolean mIsMobileNetworkSupported; RadioResponse mRadioResponse; RadioIndication mRadioIndication; volatile IRadio mRadioProxy = null; OemHookResponse mOemHookResponse; OemHookIndication mOemHookIndication; volatile IOemHook mOemHookProxy = null; final AtomicLong mRadioProxyCookie = new AtomicLong(0); final RadioProxyDeathRecipient mRadioProxyDeathRecipient; final RilHandler mRilHandler; //***** Events static final int EVENT_WAKE_LOCK_TIMEOUT = 2; static final int EVENT_ACK_WAKE_LOCK_TIMEOUT = 4; static final int EVENT_BLOCKING_RESPONSE_TIMEOUT = 5; static final int EVENT_RADIO_PROXY_DEAD = 6; //***** Constants static final String[] HIDL_SERVICE_NAME = {"slot1", "slot2", "slot3"}; static final int IRADIO_GET_SERVICE_DELAY_MILLIS = 4 * 1000; static final String EMPTY_ALPHA_LONG = ""; static final String EMPTY_ALPHA_SHORT = ""; public static List getTelephonyRILTimingHistograms() { List list; synchronized (mRilTimeHistograms) { list = new ArrayList<>(mRilTimeHistograms.size()); for (int i = 0; i < mRilTimeHistograms.size(); i++) { TelephonyHistogram entry = new TelephonyHistogram(mRilTimeHistograms.valueAt(i)); list.add(entry); } } return list; } /** The handler used to handle the internal event of RIL. */ @VisibleForTesting public class RilHandler extends Handler { //***** Handler implementation @Override public void handleMessage(Message msg) { RILRequest rr; switch (msg.what) { 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. // 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_MS but no response. // // Note: Keep mRequestList so that delayed response // can still be handled when response finally comes. synchronized (mRequestList) { if (msg.arg1 == mWlSequenceNum && clearWakeLock(FOR_WAKELOCK)) { if (mRadioBugDetector != null) { mRadioBugDetector.processWakelockTimeout(); } if (RILJ_LOGD) { int count = mRequestList.size(); Rlog.d(RILJ_LOG_TAG, "WAKE_LOCK_TIMEOUT " + " mRequestList=" + count); for (int i = 0; i < count; i++) { rr = mRequestList.valueAt(i); Rlog.d(RILJ_LOG_TAG, i + ": [" + rr.mSerial + "] " + requestToString(rr.mRequest)); } } } } break; case EVENT_ACK_WAKE_LOCK_TIMEOUT: if (msg.arg1 == mAckWlSequenceNum && clearWakeLock(FOR_ACK_WAKELOCK)) { if (RILJ_LOGV) { Rlog.d(RILJ_LOG_TAG, "ACK_WAKE_LOCK_TIMEOUT"); } } break; case EVENT_BLOCKING_RESPONSE_TIMEOUT: int serial = msg.arg1; rr = findAndRemoveRequestFromList(serial); // If the request has already been processed, do nothing if(rr == null) { break; } //build a response if expected if (rr.mResult != null) { Object timeoutResponse = getResponseForTimedOutRILRequest(rr); AsyncResult.forMessage( rr.mResult, timeoutResponse, null); rr.mResult.sendToTarget(); mMetrics.writeOnRilTimeoutResponse(mPhoneId, rr.mSerial, rr.mRequest); } decrementWakeLock(rr); rr.release(); break; case EVENT_RADIO_PROXY_DEAD: riljLog("handleMessage: EVENT_RADIO_PROXY_DEAD cookie = " + msg.obj + " mRadioProxyCookie = " + mRadioProxyCookie.get()); if ((long) msg.obj == mRadioProxyCookie.get()) { resetProxyAndRequestList(); } break; } } } /** Return RadioBugDetector instance for testing. */ @VisibleForTesting public RadioBugDetector getRadioBugDetector() { if (mRadioBugDetector == null) { mRadioBugDetector = new RadioBugDetector(mContext, mPhoneId); } return mRadioBugDetector; } /** * In order to prevent calls to Telephony from waiting indefinitely * low-latency blocking calls will eventually time out. In the event of * a timeout, this function generates a response that is returned to the * higher layers to unblock the call. This is in lieu of a meaningful * response. * @param rr The RIL Request that has timed out. * @return A default object, such as the one generated by a normal response * that is returned to the higher layers. **/ @UnsupportedAppUsage private static Object getResponseForTimedOutRILRequest(RILRequest rr) { if (rr == null ) return null; Object timeoutResponse = null; switch(rr.mRequest) { case RIL_REQUEST_GET_ACTIVITY_INFO: timeoutResponse = new ModemActivityInfo( 0, 0, 0, new int [ModemActivityInfo.TX_POWER_LEVELS], 0, 0); break; }; return timeoutResponse; } final class RadioProxyDeathRecipient implements HwBinder.DeathRecipient { @Override public void serviceDied(long cookie) { // Deal with service going away riljLog("serviceDied"); mRilHandler.sendMessage(mRilHandler.obtainMessage(EVENT_RADIO_PROXY_DEAD, cookie)); } } private void resetProxyAndRequestList() { mRadioProxy = null; mOemHookProxy = null; // increment the cookie so that death notification can be ignored mRadioProxyCookie.incrementAndGet(); setRadioState(TelephonyManager.RADIO_POWER_UNAVAILABLE, true /* forceNotifyRegistrants */); RILRequest.resetSerial(); // Clear request list on close clearRequestList(RADIO_NOT_AVAILABLE, false); getRadioProxy(null); getOemHookProxy(null); } /** Returns a {@link IRadio} instance or null if the service is not available. */ @VisibleForTesting public synchronized IRadio getRadioProxy(Message result) { if (!mIsMobileNetworkSupported) { if (RILJ_LOGV) riljLog("getRadioProxy: Not calling getService(): wifi-only"); if (result != null) { AsyncResult.forMessage(result, null, CommandException.fromRilErrno(RADIO_NOT_AVAILABLE)); result.sendToTarget(); } return null; } if (mRadioProxy != null) { return mRadioProxy; } try { if (mDisabledRadioServices.contains(mPhoneId)) { riljLoge("getRadioProxy: mRadioProxy for " + HIDL_SERVICE_NAME[mPhoneId] + " is disabled"); } else { try { mRadioProxy = android.hardware.radio.V1_4.IRadio.getService( HIDL_SERVICE_NAME[mPhoneId], true); mRadioVersion = RADIO_HAL_VERSION_1_4; } catch (NoSuchElementException e) { } if (mRadioProxy == null) { try { mRadioProxy = android.hardware.radio.V1_3.IRadio.getService( HIDL_SERVICE_NAME[mPhoneId], true); mRadioVersion = RADIO_HAL_VERSION_1_3; } catch (NoSuchElementException e) { } } if (mRadioProxy == null) { try { mRadioProxy = android.hardware.radio.V1_2.IRadio.getService( HIDL_SERVICE_NAME[mPhoneId], true); mRadioVersion = RADIO_HAL_VERSION_1_2; } catch (NoSuchElementException e) { } } if (mRadioProxy == null) { try { mRadioProxy = android.hardware.radio.V1_1.IRadio.getService( HIDL_SERVICE_NAME[mPhoneId], true); mRadioVersion = RADIO_HAL_VERSION_1_1; } catch (NoSuchElementException e) { } } if (mRadioProxy == null) { try { mRadioProxy = android.hardware.radio.V1_0.IRadio.getService( HIDL_SERVICE_NAME[mPhoneId], true); mRadioVersion = RADIO_HAL_VERSION_1_0; } catch (NoSuchElementException e) { } } if (mRadioProxy != null) { mRadioProxy.linkToDeath(mRadioProxyDeathRecipient, mRadioProxyCookie.incrementAndGet()); mRadioProxy.setResponseFunctions(mRadioResponse, mRadioIndication); } else { mDisabledRadioServices.add(mPhoneId); riljLoge("getRadioProxy: mRadioProxy for " + HIDL_SERVICE_NAME[mPhoneId] + " is disabled"); } } } catch (RemoteException e) { mRadioProxy = null; riljLoge("RadioProxy getService/setResponseFunctions: " + e); } if (mRadioProxy == null) { // getService() is a blocking call, so this should never happen riljLoge("getRadioProxy: mRadioProxy == null"); if (result != null) { AsyncResult.forMessage(result, null, CommandException.fromRilErrno(RADIO_NOT_AVAILABLE)); result.sendToTarget(); } } return mRadioProxy; } /** Returns an {@link IOemHook} instance or null if the service is not available. */ @VisibleForTesting public synchronized IOemHook getOemHookProxy(Message result) { if (!mIsMobileNetworkSupported) { if (RILJ_LOGV) riljLog("getOemHookProxy: Not calling getService(): wifi-only"); if (result != null) { AsyncResult.forMessage(result, null, CommandException.fromRilErrno(RADIO_NOT_AVAILABLE)); result.sendToTarget(); } return null; } if (mOemHookProxy != null) { return mOemHookProxy; } try { if (mDisabledOemHookServices.contains(mPhoneId)) { riljLoge("getOemHookProxy: mOemHookProxy for " + HIDL_SERVICE_NAME[mPhoneId] + " is disabled"); } else { mOemHookProxy = IOemHook.getService(HIDL_SERVICE_NAME[mPhoneId], true); if (mOemHookProxy != null) { // not calling linkToDeath() as ril service runs in the same process and death // notification for that should be sufficient mOemHookProxy.setResponseFunctions(mOemHookResponse, mOemHookIndication); } else { mDisabledOemHookServices.add(mPhoneId); riljLoge("getOemHookProxy: mOemHookProxy for " + HIDL_SERVICE_NAME[mPhoneId] + " is disabled"); } } } catch (NoSuchElementException e) { mOemHookProxy = null; riljLoge("IOemHook service is not on the device HAL: " + e); } catch (RemoteException e) { mOemHookProxy = null; riljLoge("OemHookProxy getService/setResponseFunctions: " + e); } if (mOemHookProxy == null) { if (result != null) { AsyncResult.forMessage(result, null, CommandException.fromRilErrno(RADIO_NOT_AVAILABLE)); result.sendToTarget(); } } return mOemHookProxy; } //***** Constructors @UnsupportedAppUsage public RIL(Context context, int preferredNetworkType, int cdmaSubscription) { this(context, preferredNetworkType, cdmaSubscription, null); } @UnsupportedAppUsage public RIL(Context context, int preferredNetworkType, int cdmaSubscription, Integer instanceId) { super(context); if (RILJ_LOGD) { riljLog("RIL: init preferredNetworkType=" + preferredNetworkType + " cdmaSubscription=" + cdmaSubscription + ")"); } mContext = context; mCdmaSubscription = cdmaSubscription; mPreferredNetworkType = preferredNetworkType; mPhoneType = RILConstants.NO_PHONE; mPhoneId = instanceId == null ? 0 : instanceId; if (isRadioBugDetectionEnabled()) { mRadioBugDetector = new RadioBugDetector(context, mPhoneId); } ConnectivityManager cm = (ConnectivityManager)context.getSystemService( Context.CONNECTIVITY_SERVICE); mIsMobileNetworkSupported = cm.isNetworkSupported(ConnectivityManager.TYPE_MOBILE); mRadioResponse = new RadioResponse(this); mRadioIndication = new RadioIndication(this); mOemHookResponse = new OemHookResponse(this); mOemHookIndication = new OemHookIndication(this); mRilHandler = new RilHandler(); mRadioProxyDeathRecipient = new RadioProxyDeathRecipient(); PowerManager pm = (PowerManager)context.getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, RILJ_WAKELOCK_TAG); mWakeLock.setReferenceCounted(false); mAckWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, RILJ_ACK_WAKELOCK_NAME); mAckWakeLock.setReferenceCounted(false); mWakeLockTimeout = SystemProperties.getInt(TelephonyProperties.PROPERTY_WAKE_LOCK_TIMEOUT, DEFAULT_WAKE_LOCK_TIMEOUT_MS); mAckWakeLockTimeout = SystemProperties.getInt( TelephonyProperties.PROPERTY_WAKE_LOCK_TIMEOUT, DEFAULT_ACK_WAKE_LOCK_TIMEOUT_MS); mWakeLockCount = 0; mRILDefaultWorkSource = new WorkSource(context.getApplicationInfo().uid, context.getPackageName()); mActiveWakelockWorkSource = new WorkSource(); TelephonyDevController tdc = TelephonyDevController.getInstance(); tdc.registerRIL(this); // set radio callback; needed to set RadioIndication callback (should be done after // wakelock stuff is initialized above as callbacks are received on separate binder threads) getRadioProxy(null); getOemHookProxy(null); if (RILJ_LOGD) { riljLog("Radio HAL version: " + mRadioVersion); } } private boolean isRadioBugDetectionEnabled() { return Settings.Global.getInt( mContext.getContentResolver(), Settings.Global.ENABLE_RADIO_BUG_DETECTION, 0) != 0; } @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)); } } private void addRequest(RILRequest rr) { acquireWakeLock(rr, FOR_WAKELOCK); synchronized (mRequestList) { rr.mStartTimeMs = SystemClock.elapsedRealtime(); mRequestList.append(rr.mSerial, rr); } } private RILRequest obtainRequest(int request, Message result, WorkSource workSource) { RILRequest rr = RILRequest.obtain(request, result, workSource); addRequest(rr); return rr; } private void handleRadioProxyExceptionForRR(RILRequest rr, String caller, Exception e) { riljLoge(caller + ": " + e); resetProxyAndRequestList(); } private static String convertNullToEmptyString(String string) { return string != null ? string : ""; } @Override public void getIccCardStatus(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_GET_SIM_STATUS, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getIccCardStatus(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getIccCardStatus", e); } } } @Override public void getIccSlotsStatus(Message result) { if (result != null) { AsyncResult.forMessage(result, null, CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED)); result.sendToTarget(); } } @Override public void setLogicalToPhysicalSlotMapping(int[] physicalSlots, Message result) { if (result != null) { AsyncResult.forMessage(result, null, CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED)); result.sendToTarget(); } } @Override public void supplyIccPin(String pin, Message result) { supplyIccPinForApp(pin, null, result); } @Override public void supplyIccPinForApp(String pin, String aid, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_ENTER_SIM_PIN, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " aid = " + aid); } try { radioProxy.supplyIccPinForApp(rr.mSerial, convertNullToEmptyString(pin), convertNullToEmptyString(aid)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "supplyIccPinForApp", e); } } } @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) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_ENTER_SIM_PUK, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " aid = " + aid); } try { radioProxy.supplyIccPukForApp(rr.mSerial, convertNullToEmptyString(puk), convertNullToEmptyString(newPin), convertNullToEmptyString(aid)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "supplyIccPukForApp", e); } } } @Override public void supplyIccPin2(String pin, Message result) { supplyIccPin2ForApp(pin, null, result); } @Override public void supplyIccPin2ForApp(String pin, String aid, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_ENTER_SIM_PIN2, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " aid = " + aid); } try { radioProxy.supplyIccPin2ForApp(rr.mSerial, convertNullToEmptyString(pin), convertNullToEmptyString(aid)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "supplyIccPin2ForApp", e); } } } @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) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_ENTER_SIM_PUK2, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " aid = " + aid); } try { radioProxy.supplyIccPuk2ForApp(rr.mSerial, convertNullToEmptyString(puk), convertNullToEmptyString(newPin2), convertNullToEmptyString(aid)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "supplyIccPuk2ForApp", e); } } } @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) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CHANGE_SIM_PIN, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " oldPin = " + oldPin + " newPin = " + newPin + " aid = " + aid); } try { radioProxy.changeIccPinForApp(rr.mSerial, convertNullToEmptyString(oldPin), convertNullToEmptyString(newPin), convertNullToEmptyString(aid)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "changeIccPinForApp", e); } } } @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) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CHANGE_SIM_PIN2, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " oldPin = " + oldPin2 + " newPin = " + newPin2 + " aid = " + aid); } try { radioProxy.changeIccPin2ForApp(rr.mSerial, convertNullToEmptyString(oldPin2), convertNullToEmptyString(newPin2), convertNullToEmptyString(aid)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "changeIccPin2ForApp", e); } } } @Override public void supplyNetworkDepersonalization(String netpin, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_ENTER_NETWORK_DEPERSONALIZATION, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " netpin = " + netpin); } try { radioProxy.supplyNetworkDepersonalization(rr.mSerial, convertNullToEmptyString(netpin)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "supplyNetworkDepersonalization", e); } } } @Override public void getCurrentCalls(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_GET_CURRENT_CALLS, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } try { radioProxy.getCurrentCalls(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getCurrentCalls", e); } } } @Override public void dial(String address, boolean isEmergencyCall, EmergencyNumber emergencyNumberInfo, boolean hasKnownUserIntentEmergency, int clirMode, Message result) { dial(address, isEmergencyCall, emergencyNumberInfo, hasKnownUserIntentEmergency, clirMode, null, result); } @Override public void enableModem(boolean enable, Message result) { IRadio radioProxy = getRadioProxy(result); if (mRadioVersion.less(RADIO_HAL_VERSION_1_3)) { if (RILJ_LOGV) riljLog("enableModem: not supported."); if (result != null) { AsyncResult.forMessage(result, null, CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED)); result.sendToTarget(); } return; } android.hardware.radio.V1_3.IRadio radioProxy13 = (android.hardware.radio.V1_3.IRadio) radioProxy; if (radioProxy13 != null) { RILRequest rr = obtainRequest(RIL_REQUEST_ENABLE_MODEM, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " enable = " + enable); } try { radioProxy13.enableModem(rr.mSerial, enable); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "enableModem", e); } } } @Override public void getModemStatus(Message result) { IRadio radioProxy = getRadioProxy(result); if (mRadioVersion.less(RADIO_HAL_VERSION_1_3)) { if (RILJ_LOGV) riljLog("getModemStatus: not supported."); if (result != null) { AsyncResult.forMessage(result, null, CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED)); result.sendToTarget(); } return; } android.hardware.radio.V1_3.IRadio radioProxy13 = (android.hardware.radio.V1_3.IRadio) radioProxy; if (radioProxy13 != null) { RILRequest rr = obtainRequest(RIL_REQUEST_GET_MODEM_STATUS, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } try { radioProxy13.getModemStackStatus(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getModemStatus", e); } } } @Override public void dial(String address, boolean isEmergencyCall, EmergencyNumber emergencyNumberInfo, boolean hasKnownUserIntentEmergency, int clirMode, UUSInfo uusInfo, Message result) { if (isEmergencyCall && mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_4) && emergencyNumberInfo != null) { emergencyDial(address, emergencyNumberInfo, hasKnownUserIntentEmergency, clirMode, uusInfo, result); return; } IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_DIAL, result, mRILDefaultWorkSource); Dial dialInfo = new Dial(); dialInfo.address = convertNullToEmptyString(address); dialInfo.clir = clirMode; if (uusInfo != null) { UusInfo info = new UusInfo(); info.uusType = uusInfo.getType(); info.uusDcs = uusInfo.getDcs(); info.uusData = new String(uusInfo.getUserData()); dialInfo.uusInfo.add(info); } if (RILJ_LOGD) { // Do not log function arg for privacy riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } try { radioProxy.dial(rr.mSerial, dialInfo); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "dial", e); } } } private void emergencyDial(String address, EmergencyNumber emergencyNumberInfo, boolean hasKnownUserIntentEmergency, int clirMode, UUSInfo uusInfo, Message result) { IRadio radioProxy = getRadioProxy(result); // IRadio V1.4 android.hardware.radio.V1_4.IRadio radioProxy14 = (android.hardware.radio.V1_4.IRadio) radioProxy; if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_EMERGENCY_DIAL, result, mRILDefaultWorkSource); Dial dialInfo = new Dial(); dialInfo.address = convertNullToEmptyString(address); dialInfo.clir = clirMode; if (uusInfo != null) { UusInfo info = new UusInfo(); info.uusType = uusInfo.getType(); info.uusDcs = uusInfo.getDcs(); info.uusData = new String(uusInfo.getUserData()); dialInfo.uusInfo.add(info); } if (RILJ_LOGD) { // Do not log function arg for privacy riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } try { radioProxy14.emergencyDial(rr.mSerial, dialInfo, emergencyNumberInfo.getEmergencyServiceCategoryBitmaskInternalDial(), emergencyNumberInfo.getEmergencyUrns() != null ? new ArrayList(emergencyNumberInfo.getEmergencyUrns()) : new ArrayList<>(), emergencyNumberInfo.getEmergencyCallRouting(), hasKnownUserIntentEmergency, emergencyNumberInfo.getEmergencyNumberSourceBitmask() == EmergencyNumber.EMERGENCY_NUMBER_SOURCE_TEST); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "emergencyDial", e); } } } @Override public void getIMSI(Message result) { getIMSIForApp(null, result); } @Override public void getIMSIForApp(String aid, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_GET_IMSI, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " aid = " + aid); } try { radioProxy.getImsiForApp(rr.mSerial, convertNullToEmptyString(aid)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getIMSIForApp", e); } } } @Override public void hangupConnection(int gsmIndex, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_HANGUP, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " gsmIndex = " + gsmIndex); } try { radioProxy.hangup(rr.mSerial, gsmIndex); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "hangupConnection", e); } } } @UnsupportedAppUsage @Override public void hangupWaitingOrBackground(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_HANGUP_WAITING_OR_BACKGROUND, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.hangupWaitingOrBackground(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "hangupWaitingOrBackground", e); } } } @UnsupportedAppUsage @Override public void hangupForegroundResumeBackground(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.hangupForegroundResumeBackground(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "hangupForegroundResumeBackground", e); } } } @Override public void switchWaitingOrHoldingAndActive(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SWITCH_WAITING_OR_HOLDING_AND_ACTIVE, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.switchWaitingOrHoldingAndActive(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "switchWaitingOrHoldingAndActive", e); } } } @Override public void conference(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CONFERENCE, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.conference(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "conference", e); } } } @Override public void rejectCall(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_UDUB, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.rejectCall(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "rejectCall", e); } } } @Override public void getLastCallFailCause(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_LAST_CALL_FAIL_CAUSE, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getLastCallFailCause(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getLastCallFailCause", e); } } } @Override public void getSignalStrength(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SIGNAL_STRENGTH, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_4)) { android.hardware.radio.V1_4.IRadio radioProxy14 = (android.hardware.radio.V1_4.IRadio) radioProxy; try { radioProxy14.getSignalStrength_1_4(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getSignalStrength_1_4", e); } } else { try { radioProxy.getSignalStrength(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getSignalStrength", e); } } } } @Override public void getVoiceRegistrationState(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_VOICE_REGISTRATION_STATE, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getVoiceRegistrationState(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getVoiceRegistrationState", e); } } } @Override public void getDataRegistrationState(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_DATA_REGISTRATION_STATE, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getDataRegistrationState(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getDataRegistrationState", e); } } } @Override public void getOperator(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_OPERATOR, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getOperator(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getOperator", e); } } } @UnsupportedAppUsage @Override public void setRadioPower(boolean on, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_RADIO_POWER, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " on = " + on); } try { radioProxy.setRadioPower(rr.mSerial, on); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setRadioPower", e); } } } @Override public void sendDtmf(char c, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_DTMF, result, mRILDefaultWorkSource); if (RILJ_LOGD) { // Do not log function arg for privacy riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } try { radioProxy.sendDtmf(rr.mSerial, c + ""); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "sendDtmf", e); } } } private GsmSmsMessage constructGsmSendSmsRilRequest(String smscPdu, String pdu) { GsmSmsMessage msg = new GsmSmsMessage(); msg.smscPdu = smscPdu == null ? "" : smscPdu; msg.pdu = pdu == null ? "" : pdu; return msg; } @Override public void sendSMS(String smscPdu, String pdu, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SEND_SMS, result, mRILDefaultWorkSource); // Do not log function args for privacy if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); GsmSmsMessage msg = constructGsmSendSmsRilRequest(smscPdu, pdu); try { radioProxy.sendSms(rr.mSerial, msg); mMetrics.writeRilSendSms(mPhoneId, rr.mSerial, SmsSession.Event.Tech.SMS_GSM, SmsSession.Event.Format.SMS_FORMAT_3GPP); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "sendSMS", e); } } } @Override public void sendSMSExpectMore(String smscPdu, String pdu, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SEND_SMS_EXPECT_MORE, result, mRILDefaultWorkSource); // Do not log function arg for privacy if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); GsmSmsMessage msg = constructGsmSendSmsRilRequest(smscPdu, pdu); try { radioProxy.sendSMSExpectMore(rr.mSerial, msg); mMetrics.writeRilSendSms(mPhoneId, rr.mSerial, SmsSession.Event.Tech.SMS_GSM, SmsSession.Event.Format.SMS_FORMAT_3GPP); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "sendSMSExpectMore", e); } } } /** * Convert MVNO type string into MvnoType defined in types.hal. * @param mvnoType MVNO type * @return MVNO type in integer */ private static int convertToHalMvnoType(String mvnoType) { switch (mvnoType) { case "imsi" : return MvnoType.IMSI; case "gid" : return MvnoType.GID; case "spn" : return MvnoType.SPN; default: return MvnoType.NONE; } } /** * Convert to DataProfileInfo defined in radio/1.0/types.hal * @param dp Data profile * @return A converted data profile */ private static android.hardware.radio.V1_0.DataProfileInfo convertToHalDataProfile10( DataProfile dp) { android.hardware.radio.V1_0.DataProfileInfo dpi = new android.hardware.radio.V1_0.DataProfileInfo(); dpi.profileId = dp.getProfileId(); dpi.apn = dp.getApn(); dpi.protocol = ApnSetting.getProtocolStringFromInt(dp.getProtocolType()); dpi.roamingProtocol = ApnSetting.getProtocolStringFromInt(dp.getRoamingProtocolType()); dpi.authType = dp.getAuthType(); dpi.user = dp.getUserName(); dpi.password = dp.getPassword(); dpi.type = dp.getType(); dpi.maxConnsTime = dp.getMaxConnectionsTime(); dpi.maxConns = dp.getMaxConnections(); dpi.waitTime = dp.getWaitTime(); dpi.enabled = dp.isEnabled(); dpi.supportedApnTypesBitmap = dp.getSupportedApnTypesBitmask(); // Shift by 1 bit due to the discrepancy between // android.hardware.radio.V1_0.RadioAccessFamily and the bitmask version of // ServiceState.RIL_RADIO_TECHNOLOGY_XXXX. dpi.bearerBitmap = ServiceState.convertNetworkTypeBitmaskToBearerBitmask( dp.getBearerBitmask()) << 1; dpi.mtu = dp.getMtu(); dpi.mvnoType = MvnoType.NONE; dpi.mvnoMatchData = ""; return dpi; } /** * Convert to DataProfileInfo defined in radio/1.4/types.hal * @param dp Data profile * @return A converted data profile */ private static android.hardware.radio.V1_4.DataProfileInfo convertToHalDataProfile14( DataProfile dp) { android.hardware.radio.V1_4.DataProfileInfo dpi = new android.hardware.radio.V1_4.DataProfileInfo(); dpi.apn = dp.getApn(); dpi.protocol = dp.getProtocolType(); dpi.roamingProtocol = dp.getRoamingProtocolType(); dpi.authType = dp.getAuthType(); dpi.user = dp.getUserName(); dpi.password = dp.getPassword(); dpi.type = dp.getType(); dpi.maxConnsTime = dp.getMaxConnectionsTime(); dpi.maxConns = dp.getMaxConnections(); dpi.waitTime = dp.getWaitTime(); dpi.enabled = dp.isEnabled(); dpi.supportedApnTypesBitmap = dp.getSupportedApnTypesBitmask(); // Shift by 1 bit due to the discrepancy between // android.hardware.radio.V1_0.RadioAccessFamily and the bitmask version of // ServiceState.RIL_RADIO_TECHNOLOGY_XXXX. dpi.bearerBitmap = ServiceState.convertNetworkTypeBitmaskToBearerBitmask( dp.getBearerBitmask()) << 1; dpi.mtu = dp.getMtu(); dpi.persistent = dp.isPersistent(); dpi.preferred = dp.isPreferred(); // profile id is only meaningful when it's persistent on the modem. dpi.profileId = (dpi.persistent) ? dp.getProfileId() : DataProfileId.INVALID; return dpi; } /** * Convert NV reset type into ResetNvType defined in types.hal. * @param resetType NV reset type. * @return Converted reset type in integer or -1 if param is invalid. */ private static int convertToHalResetNvType(int resetType) { /** * resetType values * 1 - reload all NV items * 2 - erase NV reset (SCRTN) * 3 - factory reset (RTN) */ switch (resetType) { case 1: return ResetNvType.RELOAD; case 2: return ResetNvType.ERASE; case 3: return ResetNvType.FACTORY_RESET; } return -1; } @Override public void setupDataCall(int accessNetworkType, DataProfile dataProfile, boolean isRoaming, boolean allowRoaming, int reason, LinkProperties linkProperties, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SETUP_DATA_CALL, result, mRILDefaultWorkSource); ArrayList addresses = new ArrayList<>(); ArrayList dnses = new ArrayList<>(); if (linkProperties != null) { for (InetAddress address : linkProperties.getAddresses()) { addresses.add(address.getHostAddress()); } for (InetAddress dns : linkProperties.getDnsServers()) { dnses.add(dns.getHostAddress()); } } try { if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_4)) { // IRadio V1.4 android.hardware.radio.V1_4.IRadio radioProxy14 = (android.hardware.radio.V1_4.IRadio) radioProxy; // Convert to HAL data profile android.hardware.radio.V1_4.DataProfileInfo dpi = convertToHalDataProfile14(dataProfile); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + ",accessNetworkType=" + AccessNetworkType.toString(accessNetworkType) + ",isRoaming=" + isRoaming + ",allowRoaming=" + allowRoaming + "," + dataProfile + ",addresses=" + addresses + ",dnses=" + dnses); } radioProxy14.setupDataCall_1_4(rr.mSerial, accessNetworkType, dpi, allowRoaming, reason, addresses, dnses); } else if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_2)) { // IRadio V1.2 and IRadio V1.3 android.hardware.radio.V1_2.IRadio radioProxy12 = (android.hardware.radio.V1_2.IRadio) radioProxy; // Convert to HAL data profile android.hardware.radio.V1_0.DataProfileInfo dpi = convertToHalDataProfile10(dataProfile); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + ",accessNetworkType=" + AccessNetworkType.toString(accessNetworkType) + ",isRoaming=" + isRoaming + ",allowRoaming=" + allowRoaming + "," + dataProfile + ",addresses=" + addresses + ",dnses=" + dnses); } radioProxy12.setupDataCall_1_2(rr.mSerial, accessNetworkType, dpi, dataProfile.isPersistent(), allowRoaming, isRoaming, reason, addresses, dnses); } else { // IRadio V1.0 and IRadio V1.1 // Convert to HAL data profile android.hardware.radio.V1_0.DataProfileInfo dpi = convertToHalDataProfile10(dataProfile); // Getting data RAT here is just a workaround to support the older 1.0 // vendor RIL. The new data service interface passes access network type // instead of RAT for setup data request. It is impossible to convert access // network type back to RAT here, so we directly get the data RAT from // phone. int dataRat = ServiceState.RIL_RADIO_TECHNOLOGY_UNKNOWN; Phone phone = PhoneFactory.getPhone(mPhoneId); if (phone != null) { ServiceState ss = phone.getServiceState(); if (ss != null) { dataRat = ss.getRilDataRadioTechnology(); } } if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + ",dataRat=" + dataRat + ",isRoaming=" + isRoaming + ",allowRoaming=" + allowRoaming + "," + dataProfile); } radioProxy.setupDataCall(rr.mSerial, dataRat, dpi, dataProfile.isPersistent(), allowRoaming, isRoaming); } } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setupDataCall", e); } } } @Override 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); } @Override public void iccIOForApp(int command, int fileId, String path, int p1, int p2, int p3, String data, String pin2, String aid, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SIM_IO, result, mRILDefaultWorkSource); if (RILJ_LOGD) { if (Build.IS_DEBUGGABLE) { riljLog(rr.serialString() + "> iccIO: " + requestToString(rr.mRequest) + " command = 0x" + Integer.toHexString(command) + " fileId = 0x" + Integer.toHexString(fileId) + " path = " + path + " p1 = " + p1 + " p2 = " + p2 + " p3 = " + " data = " + data + " aid = " + aid); } else { riljLog(rr.serialString() + "> iccIO: " + requestToString(rr.mRequest)); } } IccIo iccIo = new IccIo(); iccIo.command = command; iccIo.fileId = fileId; iccIo.path = convertNullToEmptyString(path); iccIo.p1 = p1; iccIo.p2 = p2; iccIo.p3 = p3; iccIo.data = convertNullToEmptyString(data); iccIo.pin2 = convertNullToEmptyString(pin2); iccIo.aid = convertNullToEmptyString(aid); try { radioProxy.iccIOForApp(rr.mSerial, iccIo); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "iccIOForApp", e); } } } @Override public void sendUSSD(String ussd, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SEND_USSD, result, mRILDefaultWorkSource); if (RILJ_LOGD) { String logUssd = "*******"; if (RILJ_LOGV) logUssd = ussd; riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " ussd = " + logUssd); } try { radioProxy.sendUssd(rr.mSerial, convertNullToEmptyString(ussd)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "sendUSSD", e); } } } @Override public void cancelPendingUssd(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CANCEL_USSD, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } try { radioProxy.cancelPendingUssd(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "cancelPendingUssd", e); } } } @Override public void getCLIR(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_GET_CLIR, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getClir(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getCLIR", e); } } } @Override public void setCLIR(int clirMode, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SET_CLIR, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " clirMode = " + clirMode); } try { radioProxy.setClir(rr.mSerial, clirMode); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setCLIR", e); } } } @Override public void queryCallForwardStatus(int cfReason, int serviceClass, String number, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_QUERY_CALL_FORWARD_STATUS, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " cfreason = " + cfReason + " serviceClass = " + serviceClass); } android.hardware.radio.V1_0.CallForwardInfo cfInfo = new android.hardware.radio.V1_0.CallForwardInfo(); cfInfo.reason = cfReason; cfInfo.serviceClass = serviceClass; cfInfo.toa = PhoneNumberUtils.toaFromString(number); cfInfo.number = convertNullToEmptyString(number); cfInfo.timeSeconds = 0; try { radioProxy.getCallForwardStatus(rr.mSerial, cfInfo); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "queryCallForwardStatus", e); } } } @Override public void setCallForward(int action, int cfReason, int serviceClass, String number, int timeSeconds, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SET_CALL_FORWARD, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " action = " + action + " cfReason = " + cfReason + " serviceClass = " + serviceClass + " timeSeconds = " + timeSeconds); } android.hardware.radio.V1_0.CallForwardInfo cfInfo = new android.hardware.radio.V1_0.CallForwardInfo(); cfInfo.status = action; cfInfo.reason = cfReason; cfInfo.serviceClass = serviceClass; cfInfo.toa = PhoneNumberUtils.toaFromString(number); cfInfo.number = convertNullToEmptyString(number); cfInfo.timeSeconds = timeSeconds; try { radioProxy.setCallForward(rr.mSerial, cfInfo); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setCallForward", e); } } } @Override public void queryCallWaiting(int serviceClass, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_QUERY_CALL_WAITING, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " serviceClass = " + serviceClass); } try { radioProxy.getCallWaiting(rr.mSerial, serviceClass); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "queryCallWaiting", e); } } } @Override public void setCallWaiting(boolean enable, int serviceClass, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SET_CALL_WAITING, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " enable = " + enable + " serviceClass = " + serviceClass); } try { radioProxy.setCallWaiting(rr.mSerial, enable, serviceClass); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setCallWaiting", e); } } } @Override public void acknowledgeLastIncomingGsmSms(boolean success, int cause, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SMS_ACKNOWLEDGE, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " success = " + success + " cause = " + cause); } try { radioProxy.acknowledgeLastIncomingGsmSms(rr.mSerial, success, cause); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "acknowledgeLastIncomingGsmSms", e); } } } @Override public void acceptCall(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_ANSWER, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } try { radioProxy.acceptCall(rr.mSerial); mMetrics.writeRilAnswer(mPhoneId, rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "acceptCall", e); } } } @Override public void deactivateDataCall(int cid, int reason, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_DEACTIVATE_DATA_CALL, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " cid = " + cid + " reason = " + reason); } try { if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_2)) { android.hardware.radio.V1_2.IRadio radioProxy12 = (android.hardware.radio.V1_2.IRadio) radioProxy; radioProxy12.deactivateDataCall_1_2(rr.mSerial, cid, reason); } else { radioProxy.deactivateDataCall(rr.mSerial, cid, (reason == DataService.REQUEST_REASON_SHUTDOWN)); } mMetrics.writeRilDeactivateDataCall(mPhoneId, rr.mSerial, cid, reason); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "deactivateDataCall", e); } } } @Override public void queryFacilityLock(String facility, String password, int serviceClass, Message result) { queryFacilityLockForApp(facility, password, serviceClass, null, result); } @Override public void queryFacilityLockForApp(String facility, String password, int serviceClass, String appId, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_QUERY_FACILITY_LOCK, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " facility = " + facility + " serviceClass = " + serviceClass + " appId = " + appId); } try { radioProxy.getFacilityLockForApp(rr.mSerial, convertNullToEmptyString(facility), convertNullToEmptyString(password), serviceClass, convertNullToEmptyString(appId)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getFacilityLockForApp", e); } } } @Override public void setFacilityLock(String facility, boolean lockState, String password, int serviceClass, Message result) { setFacilityLockForApp(facility, lockState, password, serviceClass, null, result); } @Override public void setFacilityLockForApp(String facility, boolean lockState, String password, int serviceClass, String appId, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SET_FACILITY_LOCK, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " facility = " + facility + " lockstate = " + lockState + " serviceClass = " + serviceClass + " appId = " + appId); } try { radioProxy.setFacilityLockForApp(rr.mSerial, convertNullToEmptyString(facility), lockState, convertNullToEmptyString(password), serviceClass, convertNullToEmptyString(appId)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setFacilityLockForApp", e); } } } @Override public void changeBarringPassword(String facility, String oldPwd, String newPwd, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CHANGE_BARRING_PASSWORD, result, mRILDefaultWorkSource); // Do not log all function args for privacy if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + "facility = " + facility); } try { radioProxy.setBarringPassword(rr.mSerial, convertNullToEmptyString(facility), convertNullToEmptyString(oldPwd), convertNullToEmptyString(newPwd)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "changeBarringPassword", e); } } } @Override public void getNetworkSelectionMode(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_QUERY_NETWORK_SELECTION_MODE, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getNetworkSelectionMode(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getNetworkSelectionMode", e); } } } @Override public void setNetworkSelectionModeAutomatic(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SET_NETWORK_SELECTION_AUTOMATIC, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.setNetworkSelectionModeAutomatic(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setNetworkSelectionModeAutomatic", e); } } } @Override public void setNetworkSelectionModeManual(String operatorNumeric, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SET_NETWORK_SELECTION_MANUAL, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " operatorNumeric = " + operatorNumeric); } try { radioProxy.setNetworkSelectionModeManual(rr.mSerial, convertNullToEmptyString(operatorNumeric)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setNetworkSelectionModeManual", e); } } } @Override public void getAvailableNetworks(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_QUERY_AVAILABLE_NETWORKS, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getAvailableNetworks(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getAvailableNetworks", e); } } } private android.hardware.radio.V1_1.RadioAccessSpecifier convertRadioAccessSpecifierToRadioHAL( RadioAccessSpecifier ras) { android.hardware.radio.V1_1.RadioAccessSpecifier rasInHalFormat = new android.hardware.radio.V1_1.RadioAccessSpecifier(); rasInHalFormat.radioAccessNetwork = ras.getRadioAccessNetwork(); List bands = null; switch (ras.getRadioAccessNetwork()) { case AccessNetworkType.GERAN: bands = rasInHalFormat.geranBands; break; case AccessNetworkType.UTRAN: bands = rasInHalFormat.utranBands; break; case AccessNetworkType.EUTRAN: bands = rasInHalFormat.eutranBands; break; default: Log.wtf(RILJ_LOG_TAG, "radioAccessNetwork " + ras.getRadioAccessNetwork() + " not supported!"); return null; } if (ras.getBands() != null) { for (int band : ras.getBands()) { bands.add(band); } } if (ras.getChannels() != null) { for (int channel : ras.getChannels()) { rasInHalFormat.channels.add(channel); } } return rasInHalFormat; } @Override public void startNetworkScan(NetworkScanRequest nsr, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_2)) { android.hardware.radio.V1_2.NetworkScanRequest request = new android.hardware.radio.V1_2.NetworkScanRequest(); request.type = nsr.getScanType(); request.interval = nsr.getSearchPeriodicity(); request.maxSearchTime = nsr.getMaxSearchTime(); request.incrementalResultsPeriodicity = nsr.getIncrementalResultsPeriodicity(); request.incrementalResults = nsr.getIncrementalResults(); for (RadioAccessSpecifier ras : nsr.getSpecifiers()) { android.hardware.radio.V1_1.RadioAccessSpecifier rasInHalFormat = convertRadioAccessSpecifierToRadioHAL(ras); if (rasInHalFormat == null) { return; } request.specifiers.add(rasInHalFormat); } request.mccMncs.addAll(nsr.getPlmns()); RILRequest rr = obtainRequest(RIL_REQUEST_START_NETWORK_SCAN, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } try { if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_4)) { android.hardware.radio.V1_4.IRadio radioProxy14 = (android.hardware.radio.V1_4.IRadio) radioProxy; radioProxy14.startNetworkScan_1_4(rr.mSerial, request); } else { android.hardware.radio.V1_2.IRadio radioProxy12 = (android.hardware.radio.V1_2.IRadio) radioProxy; radioProxy12.startNetworkScan_1_2(rr.mSerial, request); } } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "startNetworkScan", e); } } else if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_1)) { android.hardware.radio.V1_1.IRadio radioProxy11 = (android.hardware.radio.V1_1.IRadio) radioProxy; android.hardware.radio.V1_1.NetworkScanRequest request = new android.hardware.radio.V1_1.NetworkScanRequest(); request.type = nsr.getScanType(); request.interval = nsr.getSearchPeriodicity(); for (RadioAccessSpecifier ras : nsr.getSpecifiers()) { android.hardware.radio.V1_1.RadioAccessSpecifier rasInHalFormat = convertRadioAccessSpecifierToRadioHAL(ras); if (rasInHalFormat == null) { return; } request.specifiers.add(rasInHalFormat); } RILRequest rr = obtainRequest(RIL_REQUEST_START_NETWORK_SCAN, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } try { radioProxy11.startNetworkScan(rr.mSerial, request); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "startNetworkScan", e); } } else if (result != null) { AsyncResult.forMessage(result, null, CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED)); result.sendToTarget(); } } } @Override public void stopNetworkScan(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_1)) { android.hardware.radio.V1_1.IRadio radioProxy11 = (android.hardware.radio.V1_1.IRadio) radioProxy; RILRequest rr = obtainRequest(RIL_REQUEST_STOP_NETWORK_SCAN, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } try { radioProxy11.stopNetworkScan(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "stopNetworkScan", e); } } else if (result != null) { AsyncResult.forMessage(result, null, CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED)); result.sendToTarget(); } } } @Override public void startDtmf(char c, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_DTMF_START, result, mRILDefaultWorkSource); // Do not log function arg for privacy if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.startDtmf(rr.mSerial, c + ""); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "startDtmf", e); } } } @Override public void stopDtmf(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_DTMF_STOP, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.stopDtmf(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "stopDtmf", e); } } } @Override public void separateConnection(int gsmIndex, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SEPARATE_CONNECTION, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " gsmIndex = " + gsmIndex); } try { radioProxy.separateConnection(rr.mSerial, gsmIndex); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "separateConnection", e); } } } @Override public void getBasebandVersion(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_BASEBAND_VERSION, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getBasebandVersion(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getBasebandVersion", e); } } } @Override public void setMute(boolean enableMute, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SET_MUTE, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " enableMute = " + enableMute); } try { radioProxy.setMute(rr.mSerial, enableMute); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setMute", e); } } } @Override public void getMute(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_GET_MUTE, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getMute(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getMute", e); } } } @Override public void queryCLIP(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_QUERY_CLIP, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getClip(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "queryCLIP", e); } } } /** * @deprecated */ @Override @Deprecated public void getPDPContextList(Message result) { getDataCallList(result); } @Override public void getDataCallList(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_DATA_CALL_LIST, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getDataCallList(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getDataCallList", e); } } } @UnsupportedAppUsage @Override public void invokeOemRilRequestRaw(byte[] data, Message response) { IOemHook oemHookProxy = getOemHookProxy(response); if (oemHookProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_OEM_HOOK_RAW, response, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + "[" + IccUtils.bytesToHexString(data) + "]"); } try { oemHookProxy.sendRequestRaw(rr.mSerial, primitiveArrayToArrayList(data)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "invokeOemRilRequestRaw", e); } } else { // OEM Hook service is disabled for P and later devices. // Deprecated OEM Hook APIs will perform dummy before being removed. if (RILJ_LOGD) riljLog("Radio Oem Hook Service is disabled for P and later devices. "); } } @Override public void invokeOemRilRequestStrings(String[] strings, Message result) { IOemHook oemHookProxy = getOemHookProxy(result); if (oemHookProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_OEM_HOOK_STRINGS, result, mRILDefaultWorkSource); String logStr = ""; for (int i = 0; i < strings.length; i++) { logStr = logStr + strings[i] + " "; } if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " strings = " + logStr); } try { oemHookProxy.sendRequestStrings(rr.mSerial, new ArrayList(Arrays.asList(strings))); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "invokeOemRilRequestStrings", e); } } else { // OEM Hook service is disabled for P and later devices. // Deprecated OEM Hook APIs will perform dummy before being removed. if (RILJ_LOGD) riljLog("Radio Oem Hook Service is disabled for P and later devices. "); } } @Override public void setSuppServiceNotifications(boolean enable, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SET_SUPP_SVC_NOTIFICATION, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " enable = " + enable); } try { radioProxy.setSuppServiceNotifications(rr.mSerial, enable); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setSuppServiceNotifications", e); } } } @Override public void writeSmsToSim(int status, String smsc, String pdu, Message result) { status = translateStatus(status); IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_WRITE_SMS_TO_SIM, result, mRILDefaultWorkSource); if (RILJ_LOGV) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " " + status); } SmsWriteArgs args = new SmsWriteArgs(); args.status = status; args.smsc = convertNullToEmptyString(smsc); args.pdu = convertNullToEmptyString(pdu); try { radioProxy.writeSmsToSim(rr.mSerial, args); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "writeSmsToSim", e); } } } @Override public void deleteSmsOnSim(int index, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_DELETE_SMS_ON_SIM, result, mRILDefaultWorkSource); if (RILJ_LOGV) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " index = " + index); } try { radioProxy.deleteSmsOnSim(rr.mSerial, index); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "deleteSmsOnSim", e); } } } @Override public void setBandMode(int bandMode, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SET_BAND_MODE, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " bandMode = " + bandMode); } try { radioProxy.setBandMode(rr.mSerial, bandMode); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setBandMode", e); } } } @Override public void queryAvailableBandMode(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_QUERY_AVAILABLE_BAND_MODE, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getAvailableBandModes(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "queryAvailableBandMode", e); } } } @Override public void sendEnvelope(String contents, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_STK_SEND_ENVELOPE_COMMAND, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " contents = " + contents); } try { radioProxy.sendEnvelope(rr.mSerial, convertNullToEmptyString(contents)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "sendEnvelope", e); } } } @Override public void sendTerminalResponse(String contents, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_STK_SEND_TERMINAL_RESPONSE, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " contents = " + (Build.IS_DEBUGGABLE ? contents : censoredTerminalResponse(contents))); } try { radioProxy.sendTerminalResponseToSim(rr.mSerial, convertNullToEmptyString(contents)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "sendTerminalResponse", e); } } } private String censoredTerminalResponse(String terminalResponse) { try { byte[] bytes = IccUtils.hexStringToBytes(terminalResponse); if (bytes != null) { List ctlvs = ComprehensionTlv.decodeMany(bytes, 0); int from = 0; for (ComprehensionTlv ctlv : ctlvs) { // Find text strings which might be personal information input by user, // then replace it with "********". if (ComprehensionTlvTag.TEXT_STRING.value() == ctlv.getTag()) { byte[] target = Arrays.copyOfRange(ctlv.getRawValue(), from, ctlv.getValueIndex() + ctlv.getLength()); terminalResponse = terminalResponse.toLowerCase().replace( IccUtils.bytesToHexString(target).toLowerCase(), "********"); } // The text string tag and the length field should also be hidden. from = ctlv.getValueIndex() + ctlv.getLength(); } } } catch (Exception e) { Rlog.e(RILJ_LOG_TAG, "Could not censor the terminal response: " + e); terminalResponse = null; } return terminalResponse; } @Override public void sendEnvelopeWithStatus(String contents, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_STK_SEND_ENVELOPE_WITH_STATUS, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " contents = " + contents); } try { radioProxy.sendEnvelopeWithStatus(rr.mSerial, convertNullToEmptyString(contents)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "sendEnvelopeWithStatus", e); } } } @Override public void explicitCallTransfer(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_EXPLICIT_CALL_TRANSFER, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.explicitCallTransfer(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "explicitCallTransfer", e); } } } @Override public void setPreferredNetworkType(@PrefNetworkMode int networkType , Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SET_PREFERRED_NETWORK_TYPE, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " networkType = " + networkType); } mPreferredNetworkType = networkType; mMetrics.writeSetPreferredNetworkType(mPhoneId, networkType); if (mRadioVersion.lessOrEqual(RADIO_HAL_VERSION_1_3)) { try { radioProxy.setPreferredNetworkType(rr.mSerial, networkType); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setPreferredNetworkType", e); } } else if (mRadioVersion.equals(RADIO_HAL_VERSION_1_4)) { android.hardware.radio.V1_4.IRadio radioProxy14 = (android.hardware.radio.V1_4.IRadio) radioProxy; try { radioProxy14.setPreferredNetworkTypeBitmap( rr.mSerial, convertToHalRadioAccessFamily( RadioAccessFamily.getRafFromNetworkType(networkType))); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setPreferredNetworkTypeBitmap", e); } } } } /** * convert RAF from {@link android.hardware.radio.V1_0.RadioAccessFamily} to * {@link TelephonyManager.NetworkTypeBitMask}, the bitmask represented by * {@link TelephonyManager.NetworkType}. * * @param raf {@link android.hardware.radio.V1_0.RadioAccessFamily} * @return {@link TelephonyManager.NetworkTypeBitMask} */ @TelephonyManager.NetworkTypeBitMask public static int convertToNetworkTypeBitMask(int raf) { int networkTypeRaf = 0; if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.GSM) != 0) { networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_GSM; } if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.GPRS) != 0) { networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_GPRS; } if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.EDGE) != 0) { networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_EDGE; } // convert both IS95A/IS95B to CDMA as network mode doesn't support CDMA if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.IS95A) != 0) { networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_CDMA; } if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.IS95B) != 0) { networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_CDMA; } if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.ONE_X_RTT) != 0) { networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT; } if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.EVDO_0) != 0) { networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_0; } if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.EVDO_A) != 0) { networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_A; } if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.EVDO_B) != 0) { networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_B; } if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.EHRPD) != 0) { networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_EHRPD; } if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.HSUPA) != 0) { networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_HSUPA; } if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.HSDPA) != 0) { networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_HSDPA; } if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.HSPA) != 0) { networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_HSPA; } if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.HSPAP) != 0) { networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_HSPAP; } if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.UMTS) != 0) { networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_UMTS; } if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.TD_SCDMA) != 0) { networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_TD_SCDMA; } if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.LTE) != 0) { networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_LTE; } if ((raf & android.hardware.radio.V1_0.RadioAccessFamily.LTE_CA) != 0) { networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_LTE_CA; } if ((raf & android.hardware.radio.V1_4.RadioAccessFamily.NR) != 0) { networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_NR; } // TODO: need hal definition if ((raf & (1 << ServiceState.RIL_RADIO_TECHNOLOGY_IWLAN)) != 0) { networkTypeRaf |= TelephonyManager.NETWORK_TYPE_BITMASK_IWLAN; } return (networkTypeRaf == 0) ? TelephonyManager.NETWORK_TYPE_UNKNOWN : networkTypeRaf; } // convert to android.hardware.radio.V1_0.RadioAccessFamily private static int convertToHalRadioAccessFamily( @TelephonyManager.NetworkTypeBitMask int networkTypeBitmask) { int raf = 0; if ((networkTypeBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_GSM) != 0) { raf |= android.hardware.radio.V1_0.RadioAccessFamily.GSM; } if ((networkTypeBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_GPRS) != 0) { raf |= android.hardware.radio.V1_0.RadioAccessFamily.GPRS; } if ((networkTypeBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_EDGE) != 0) { raf |= android.hardware.radio.V1_0.RadioAccessFamily.EDGE; } // convert CDMA to IS95A, consistent with ServiceState.networkTypeToRilRadioTechnology if ((networkTypeBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_CDMA) != 0) { raf |= android.hardware.radio.V1_0.RadioAccessFamily.IS95A; } if ((networkTypeBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_1xRTT) != 0) { raf |= android.hardware.radio.V1_0.RadioAccessFamily.ONE_X_RTT; } if ((networkTypeBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_0) != 0) { raf |= android.hardware.radio.V1_0.RadioAccessFamily.EVDO_0; } if ((networkTypeBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_A) != 0) { raf |= android.hardware.radio.V1_0.RadioAccessFamily.EVDO_A; } if ((networkTypeBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_EVDO_B) != 0) { raf |= android.hardware.radio.V1_0.RadioAccessFamily.EVDO_B; } if ((networkTypeBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_EHRPD) != 0) { raf |= android.hardware.radio.V1_0.RadioAccessFamily.EHRPD; } if ((networkTypeBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_HSUPA) != 0) { raf |= android.hardware.radio.V1_0.RadioAccessFamily.HSUPA; } if ((networkTypeBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_HSDPA) != 0) { raf |= android.hardware.radio.V1_0.RadioAccessFamily.HSDPA; } if ((networkTypeBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_HSPA) != 0) { raf |= android.hardware.radio.V1_0.RadioAccessFamily.HSPA; } if ((networkTypeBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_HSPAP) != 0) { raf |= android.hardware.radio.V1_0.RadioAccessFamily.HSPAP; } if ((networkTypeBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_UMTS) != 0) { raf |= android.hardware.radio.V1_0.RadioAccessFamily.UMTS; } if ((networkTypeBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_TD_SCDMA) != 0) { raf |= android.hardware.radio.V1_0.RadioAccessFamily.TD_SCDMA; } if ((networkTypeBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_LTE) != 0) { raf |= android.hardware.radio.V1_0.RadioAccessFamily.LTE; } if ((networkTypeBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_LTE_CA) != 0) { raf |= android.hardware.radio.V1_0.RadioAccessFamily.LTE_CA; } if ((networkTypeBitmask & TelephonyManager.NETWORK_TYPE_BITMASK_NR) != 0) { raf |= android.hardware.radio.V1_4.RadioAccessFamily.NR; } // TODO: need hal definition for IWLAN return (raf == 0) ? android.hardware.radio.V1_4.RadioAccessFamily.UNKNOWN : raf; } @Override public void getPreferredNetworkType(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_GET_PREFERRED_NETWORK_TYPE, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); if (mRadioVersion.lessOrEqual(RADIO_HAL_VERSION_1_3)) { try { radioProxy.getPreferredNetworkType(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getPreferredNetworkType", e); } } else if (mRadioVersion.equals(RADIO_HAL_VERSION_1_4)) { android.hardware.radio.V1_4.IRadio radioProxy14 = (android.hardware.radio.V1_4.IRadio) radioProxy; try { radioProxy14.getPreferredNetworkTypeBitmap(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getPreferredNetworkTypeBitmap", e); } } } } @Override public void setLocationUpdates(boolean enable, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SET_LOCATION_UPDATES, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " enable = " + enable); } try { radioProxy.setLocationUpdates(rr.mSerial, enable); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setLocationUpdates", e); } } } @Override public void setCdmaSubscriptionSource(int cdmaSubscription , Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CDMA_SET_SUBSCRIPTION_SOURCE, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " cdmaSubscription = " + cdmaSubscription); } try { radioProxy.setCdmaSubscriptionSource(rr.mSerial, cdmaSubscription); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setCdmaSubscriptionSource", e); } } } @Override public void queryCdmaRoamingPreference(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CDMA_QUERY_ROAMING_PREFERENCE, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getCdmaRoamingPreference(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "queryCdmaRoamingPreference", e); } } } @Override public void setCdmaRoamingPreference(int cdmaRoamingType, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CDMA_SET_ROAMING_PREFERENCE, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " cdmaRoamingType = " + cdmaRoamingType); } try { radioProxy.setCdmaRoamingPreference(rr.mSerial, cdmaRoamingType); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setCdmaRoamingPreference", e); } } } @Override public void queryTTYMode(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_QUERY_TTY_MODE, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getTTYMode(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "queryTTYMode", e); } } } @Override public void setTTYMode(int ttyMode, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SET_TTY_MODE, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " ttyMode = " + ttyMode); } try { radioProxy.setTTYMode(rr.mSerial, ttyMode); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setTTYMode", e); } } } @Override public void setPreferredVoicePrivacy(boolean enable, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CDMA_SET_PREFERRED_VOICE_PRIVACY_MODE, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " enable = " + enable); } try { radioProxy.setPreferredVoicePrivacy(rr.mSerial, enable); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setPreferredVoicePrivacy", e); } } } @Override public void getPreferredVoicePrivacy(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CDMA_QUERY_PREFERRED_VOICE_PRIVACY_MODE, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getPreferredVoicePrivacy(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getPreferredVoicePrivacy", e); } } } @Override public void sendCDMAFeatureCode(String featureCode, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CDMA_FLASH, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " featureCode = " + featureCode); } try { radioProxy.sendCDMAFeatureCode(rr.mSerial, convertNullToEmptyString(featureCode)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "sendCDMAFeatureCode", e); } } } @Override public void sendBurstDtmf(String dtmfString, int on, int off, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CDMA_BURST_DTMF, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " dtmfString = " + dtmfString + " on = " + on + " off = " + off); } try { radioProxy.sendBurstDtmf(rr.mSerial, convertNullToEmptyString(dtmfString), on, off); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "sendBurstDtmf", e); } } } private void constructCdmaSendSmsRilRequest(CdmaSmsMessage msg, byte[] pdu) { int addrNbrOfDigits; int subaddrNbrOfDigits; int bearerDataLength; ByteArrayInputStream bais = new ByteArrayInputStream(pdu); DataInputStream dis = new DataInputStream(bais); try { msg.teleserviceId = dis.readInt(); // teleServiceId msg.isServicePresent = (byte) dis.readInt() == 1 ? true : false; // servicePresent msg.serviceCategory = dis.readInt(); // serviceCategory msg.address.digitMode = dis.read(); // address digit mode msg.address.numberMode = dis.read(); // address number mode msg.address.numberType = dis.read(); // address number type msg.address.numberPlan = dis.read(); // address number plan addrNbrOfDigits = (byte) dis.read(); for (int i = 0; i < addrNbrOfDigits; i++) { msg.address.digits.add(dis.readByte()); // address_orig_bytes[i] } msg.subAddress.subaddressType = dis.read(); //subaddressType msg.subAddress.odd = (byte) dis.read() == 1 ? true : false; //subaddr odd subaddrNbrOfDigits = (byte) dis.read(); for (int i = 0; i < subaddrNbrOfDigits; i++) { msg.subAddress.digits.add(dis.readByte()); //subaddr_orig_bytes[i] } bearerDataLength = dis.read(); for (int i = 0; i < bearerDataLength; i++) { msg.bearerData.add(dis.readByte()); //bearerData[i] } } catch (IOException ex) { if (RILJ_LOGD) { riljLog("sendSmsCdma: conversion from input stream to object failed: " + ex); } } } @Override public void sendCdmaSms(byte[] pdu, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CDMA_SEND_SMS, result, mRILDefaultWorkSource); // Do not log function arg for privacy if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); CdmaSmsMessage msg = new CdmaSmsMessage(); constructCdmaSendSmsRilRequest(msg, pdu); try { radioProxy.sendCdmaSms(rr.mSerial, msg); mMetrics.writeRilSendSms(mPhoneId, rr.mSerial, SmsSession.Event.Tech.SMS_CDMA, SmsSession.Event.Format.SMS_FORMAT_3GPP2); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "sendCdmaSms", e); } } } @Override public void acknowledgeLastIncomingCdmaSms(boolean success, int cause, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CDMA_SMS_ACKNOWLEDGE, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " success = " + success + " cause = " + cause); } CdmaSmsAck msg = new CdmaSmsAck(); msg.errorClass = success ? 0 : 1; msg.smsCauseCode = cause; try { radioProxy.acknowledgeLastIncomingCdmaSms(rr.mSerial, msg); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "acknowledgeLastIncomingCdmaSms", e); } } } @Override public void getGsmBroadcastConfig(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_GSM_GET_BROADCAST_CONFIG, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getGsmBroadcastConfig(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getGsmBroadcastConfig", e); } } } @Override public void setGsmBroadcastConfig(SmsBroadcastConfigInfo[] config, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_GSM_SET_BROADCAST_CONFIG, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " with " + config.length + " configs : "); for (int i = 0; i < config.length; i++) { riljLog(config[i].toString()); } } ArrayList configs = new ArrayList<>(); int numOfConfig = config.length; GsmBroadcastSmsConfigInfo info; for (int i = 0; i < numOfConfig; i++) { info = new GsmBroadcastSmsConfigInfo(); info.fromServiceId = config[i].getFromServiceId(); info.toServiceId = config[i].getToServiceId(); info.fromCodeScheme = config[i].getFromCodeScheme(); info.toCodeScheme = config[i].getToCodeScheme(); info.selected = config[i].isSelected(); configs.add(info); } try { radioProxy.setGsmBroadcastConfig(rr.mSerial, configs); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setGsmBroadcastConfig", e); } } } @Override public void setGsmBroadcastActivation(boolean activate, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_GSM_BROADCAST_ACTIVATION, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " activate = " + activate); } try { radioProxy.setGsmBroadcastActivation(rr.mSerial, activate); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setGsmBroadcastActivation", e); } } } @Override public void getCdmaBroadcastConfig(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CDMA_GET_BROADCAST_CONFIG, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getCdmaBroadcastConfig(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getCdmaBroadcastConfig", e); } } } @Override public void setCdmaBroadcastConfig(CdmaSmsBroadcastConfigInfo[] configs, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CDMA_SET_BROADCAST_CONFIG, result, mRILDefaultWorkSource); ArrayList halConfigs = new ArrayList<>(); for (CdmaSmsBroadcastConfigInfo config: configs) { for (int i = config.getFromServiceCategory(); i <= config.getToServiceCategory(); i++) { CdmaBroadcastSmsConfigInfo info = new CdmaBroadcastSmsConfigInfo(); info.serviceCategory = i; info.language = config.getLanguage(); info.selected = config.isSelected(); halConfigs.add(info); } } if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " with " + halConfigs.size() + " configs : "); for (CdmaBroadcastSmsConfigInfo config : halConfigs) { riljLog(config.toString()); } } try { radioProxy.setCdmaBroadcastConfig(rr.mSerial, halConfigs); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setCdmaBroadcastConfig", e); } } } @Override public void setCdmaBroadcastActivation(boolean activate, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CDMA_BROADCAST_ACTIVATION, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " activate = " + activate); } try { radioProxy.setCdmaBroadcastActivation(rr.mSerial, activate); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setCdmaBroadcastActivation", e); } } } @Override public void getCDMASubscription(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CDMA_SUBSCRIPTION, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getCDMASubscription(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getCDMASubscription", e); } } } @Override public void writeSmsToRuim(int status, String pdu, Message result) { status = translateStatus(status); IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CDMA_WRITE_SMS_TO_RUIM, result, mRILDefaultWorkSource); if (RILJ_LOGV) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " status = " + status); } CdmaSmsWriteArgs args = new CdmaSmsWriteArgs(); args.status = status; constructCdmaSendSmsRilRequest(args.message, pdu.getBytes()); try { radioProxy.writeSmsToRuim(rr.mSerial, args); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "writeSmsToRuim", e); } } } @Override public void deleteSmsOnRuim(int index, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CDMA_DELETE_SMS_ON_RUIM, result, mRILDefaultWorkSource); if (RILJ_LOGV) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " index = " + index); } try { radioProxy.deleteSmsOnRuim(rr.mSerial, index); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "deleteSmsOnRuim", e); } } } @Override public void getDeviceIdentity(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_DEVICE_IDENTITY, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getDeviceIdentity(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getDeviceIdentity", e); } } } @Override public void exitEmergencyCallbackMode(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_EXIT_EMERGENCY_CALLBACK_MODE, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.exitEmergencyCallbackMode(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "exitEmergencyCallbackMode", e); } } } @Override public void getSmscAddress(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_GET_SMSC_ADDRESS, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getSmscAddress(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getSmscAddress", e); } } } @Override public void setSmscAddress(String address, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SET_SMSC_ADDRESS, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " address = " + address); } try { radioProxy.setSmscAddress(rr.mSerial, convertNullToEmptyString(address)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setSmscAddress", e); } } } @Override public void reportSmsMemoryStatus(boolean available, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_REPORT_SMS_MEMORY_STATUS, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " available = " + available); } try { radioProxy.reportSmsMemoryStatus(rr.mSerial, available); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "reportSmsMemoryStatus", e); } } } @Override public void reportStkServiceIsRunning(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_REPORT_STK_SERVICE_IS_RUNNING, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.reportStkServiceIsRunning(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "reportStkServiceIsRunning", e); } } } @Override public void getCdmaSubscriptionSource(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_CDMA_GET_SUBSCRIPTION_SOURCE, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getCdmaSubscriptionSource(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getCdmaSubscriptionSource", e); } } } @Override public void acknowledgeIncomingGsmSmsWithPdu(boolean success, String ackPdu, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " success = " + success); } try { radioProxy.acknowledgeIncomingGsmSmsWithPdu(rr.mSerial, success, convertNullToEmptyString(ackPdu)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "acknowledgeIncomingGsmSmsWithPdu", e); } } } @Override public void getVoiceRadioTechnology(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_VOICE_RADIO_TECH, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getVoiceRadioTechnology(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getVoiceRadioTechnology", e); } } } @Override public void getCellInfoList(Message result, WorkSource workSource) { workSource = getDeafultWorkSourceIfInvalid(workSource); IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_GET_CELL_INFO_LIST, result, workSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } try { radioProxy.getCellInfoList(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getCellInfoList", e); } } } @Override public void setCellInfoListRate(int rateInMillis, Message result, WorkSource workSource) { workSource = getDeafultWorkSourceIfInvalid(workSource); IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE, result, workSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " rateInMillis = " + rateInMillis); } try { radioProxy.setCellInfoListRate(rr.mSerial, rateInMillis); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setCellInfoListRate", e); } } } @Override public void setInitialAttachApn(DataProfile dataProfile, boolean isRoaming, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SET_INITIAL_ATTACH_APN, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + dataProfile); } try { if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_4)) { // v1.4 android.hardware.radio.V1_4.IRadio radioProxy14 = (android.hardware.radio.V1_4.IRadio) radioProxy; radioProxy14.setInitialAttachApn_1_4(rr.mSerial, convertToHalDataProfile14(dataProfile)); } else { // v1.3, v1.2, v1.1, and v1.0 radioProxy.setInitialAttachApn(rr.mSerial, convertToHalDataProfile10(dataProfile), dataProfile.isPersistent(), isRoaming); } } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setInitialAttachApn", e); } } } @Override public void getImsRegistrationState(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_IMS_REGISTRATION_STATE, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } try { radioProxy.getImsRegistrationState(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getImsRegistrationState", e); } } } @Override public void sendImsGsmSms(String smscPdu, String pdu, int retry, int messageRef, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_IMS_SEND_SMS, result, mRILDefaultWorkSource); // Do not log function args for privacy if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); ImsSmsMessage msg = new ImsSmsMessage(); msg.tech = RILConstants.GSM_PHONE; msg.retry = (byte) retry >= 1 ? true : false; msg.messageRef = messageRef; GsmSmsMessage gsmMsg = constructGsmSendSmsRilRequest(smscPdu, pdu); msg.gsmMessage.add(gsmMsg); try { radioProxy.sendImsSms(rr.mSerial, msg); mMetrics.writeRilSendSms(mPhoneId, rr.mSerial, SmsSession.Event.Tech.SMS_IMS, SmsSession.Event.Format.SMS_FORMAT_3GPP); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "sendImsGsmSms", e); } } } @Override public void sendImsCdmaSms(byte[] pdu, int retry, int messageRef, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_IMS_SEND_SMS, result, mRILDefaultWorkSource); // Do not log function args for privacy if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); ImsSmsMessage msg = new ImsSmsMessage(); msg.tech = RILConstants.CDMA_PHONE; msg.retry = (byte) retry >= 1 ? true : false; msg.messageRef = messageRef; CdmaSmsMessage cdmaMsg = new CdmaSmsMessage(); constructCdmaSendSmsRilRequest(cdmaMsg, pdu); msg.cdmaMessage.add(cdmaMsg); try { radioProxy.sendImsSms(rr.mSerial, msg); mMetrics.writeRilSendSms(mPhoneId, rr.mSerial, SmsSession.Event.Tech.SMS_IMS, SmsSession.Event.Format.SMS_FORMAT_3GPP2); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "sendImsCdmaSms", e); } } } private SimApdu createSimApdu(int channel, int cla, int instruction, int p1, int p2, int p3, String data) { SimApdu msg = new SimApdu(); msg.sessionId = channel; msg.cla = cla; msg.instruction = instruction; msg.p1 = p1; msg.p2 = p2; msg.p3 = p3; msg.data = convertNullToEmptyString(data); return msg; } @Override public void iccTransmitApduBasicChannel(int cla, int instruction, int p1, int p2, int p3, String data, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SIM_TRANSMIT_APDU_BASIC, result, mRILDefaultWorkSource); if (RILJ_LOGD) { if (Build.IS_DEBUGGABLE) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + String.format(" cla = 0x%02X ins = 0x%02X", cla, instruction) + String.format(" p1 = 0x%02X p2 = 0x%02X p3 = 0x%02X", p1, p2, p3) + " data = " + data); } else { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } } SimApdu msg = createSimApdu(0, cla, instruction, p1, p2, p3, data); try { radioProxy.iccTransmitApduBasicChannel(rr.mSerial, msg); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "iccTransmitApduBasicChannel", e); } } } @Override public void iccOpenLogicalChannel(String aid, int p2, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SIM_OPEN_CHANNEL, result, mRILDefaultWorkSource); if (RILJ_LOGD) { if (Build.IS_DEBUGGABLE) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " aid = " + aid + " p2 = " + p2); } else { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } } try { radioProxy.iccOpenLogicalChannel(rr.mSerial, convertNullToEmptyString(aid), p2); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "iccOpenLogicalChannel", e); } } } @Override public void iccCloseLogicalChannel(int channel, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SIM_CLOSE_CHANNEL, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " channel = " + channel); } try { radioProxy.iccCloseLogicalChannel(rr.mSerial, channel); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "iccCloseLogicalChannel", e); } } } @Override public void iccTransmitApduLogicalChannel(int channel, int cla, int instruction, int p1, int p2, int p3, String data, Message result) { if (channel <= 0) { throw new RuntimeException( "Invalid channel in iccTransmitApduLogicalChannel: " + channel); } IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL, result, mRILDefaultWorkSource); if (RILJ_LOGD) { if (Build.IS_DEBUGGABLE) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + String.format(" channel = %d", channel) + String.format(" cla = 0x%02X ins = 0x%02X", cla, instruction) + String.format(" p1 = 0x%02X p2 = 0x%02X p3 = 0x%02X", p1, p2, p3) + " data = " + data); } else { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } } SimApdu msg = createSimApdu(channel, cla, instruction, p1, p2, p3, data); try { radioProxy.iccTransmitApduLogicalChannel(rr.mSerial, msg); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "iccTransmitApduLogicalChannel", e); } } } @Override public void nvReadItem(int itemID, Message result, WorkSource workSource) { workSource = getDeafultWorkSourceIfInvalid(workSource); IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_NV_READ_ITEM, result, workSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " itemId = " + itemID); } try { radioProxy.nvReadItem(rr.mSerial, itemID); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "nvReadItem", e); } } } @Override public void nvWriteItem(int itemId, String itemValue, Message result, WorkSource workSource) { workSource = getDeafultWorkSourceIfInvalid(workSource); IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_NV_WRITE_ITEM, result, workSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " itemId = " + itemId + " itemValue = " + itemValue); } NvWriteItem item = new NvWriteItem(); item.itemId = itemId; item.value = convertNullToEmptyString(itemValue); try { radioProxy.nvWriteItem(rr.mSerial, item); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "nvWriteItem", e); } } } @Override public void nvWriteCdmaPrl(byte[] preferredRoamingList, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_NV_WRITE_CDMA_PRL, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " PreferredRoamingList = 0x" + IccUtils.bytesToHexString(preferredRoamingList)); } ArrayList arrList = new ArrayList<>(); for (int i = 0; i < preferredRoamingList.length; i++) { arrList.add(preferredRoamingList[i]); } try { radioProxy.nvWriteCdmaPrl(rr.mSerial, arrList); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "nvWriteCdmaPrl", e); } } } @Override public void nvResetConfig(int resetType, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_NV_RESET_CONFIG, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " resetType = " + resetType); } try { radioProxy.nvResetConfig(rr.mSerial, convertToHalResetNvType(resetType)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "nvResetConfig", e); } } } @Override public void setUiccSubscription(int slotId, int appIndex, int subId, int subStatus, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SET_UICC_SUBSCRIPTION, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " slot = " + slotId + " appIndex = " + appIndex + " subId = " + subId + " subStatus = " + subStatus); } SelectUiccSub info = new SelectUiccSub(); info.slot = slotId; info.appIndex = appIndex; info.subType = subId; info.actStatus = subStatus; try { radioProxy.setUiccSubscription(rr.mSerial, info); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setUiccSubscription", e); } } } @Override public void setDataAllowed(boolean allowed, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_ALLOW_DATA, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " allowed = " + allowed); } try { radioProxy.setDataAllowed(rr.mSerial, allowed); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setDataAllowed", e); } } } @Override public void getHardwareConfig(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_GET_HARDWARE_CONFIG, result, mRILDefaultWorkSource); // Do not log function args for privacy if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.getHardwareConfig(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getHardwareConfig", e); } } } @Override public void requestIccSimAuthentication(int authContext, String data, String aid, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SIM_AUTHENTICATION, result, mRILDefaultWorkSource); // Do not log function args for privacy if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy.requestIccSimAuthentication(rr.mSerial, authContext, convertNullToEmptyString(data), convertNullToEmptyString(aid)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "requestIccSimAuthentication", e); } } } @Override public void setDataProfile(DataProfile[] dps, boolean isRoaming, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = null; try { if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_4)) { // V1.4 android.hardware.radio.V1_4.IRadio radioProxy14 = (android.hardware.radio.V1_4.IRadio) radioProxy; rr = obtainRequest(RIL_REQUEST_SET_DATA_PROFILE, result, mRILDefaultWorkSource); ArrayList dpis = new ArrayList<>(); for (DataProfile dp : dps) { dpis.add(convertToHalDataProfile14(dp)); } if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " with data profiles : "); for (DataProfile profile : dps) { riljLog(profile.toString()); } } radioProxy14.setDataProfile_1_4(rr.mSerial, dpis); } else { // V1.0, 1.1, 1,2 and 1.3 ArrayList dpis = new ArrayList<>(); for (DataProfile dp : dps) { // For v1.0 to v1.2, we only send data profiles that has the persistent // (a.k.a modem cognitive) bit set to true. if (dp.isPersistent()) { dpis.add(convertToHalDataProfile10(dp)); } } if (!dpis.isEmpty()) { rr = obtainRequest(RIL_REQUEST_SET_DATA_PROFILE, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " with data profiles : "); for (DataProfile profile : dps) { riljLog(profile.toString()); } } radioProxy.setDataProfile(rr.mSerial, dpis, isRoaming); } } } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setDataProfile", e); } } } @Override public void requestShutdown(Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SHUTDOWN, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } try { radioProxy.requestShutdown(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "requestShutdown", e); } } } @Override public void getRadioCapability(Message response) { IRadio radioProxy = getRadioProxy(response); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_GET_RADIO_CAPABILITY, response, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } try { radioProxy.getRadioCapability(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getRadioCapability", e); } } } @Override public void setRadioCapability(RadioCapability rc, Message response) { IRadio radioProxy = getRadioProxy(response); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SET_RADIO_CAPABILITY, response, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " RadioCapability = " + rc.toString()); } android.hardware.radio.V1_0.RadioCapability halRc = new android.hardware.radio.V1_0.RadioCapability(); halRc.session = rc.getSession(); halRc.phase = rc.getPhase(); halRc.raf = rc.getRadioAccessFamily(); halRc.logicalModemUuid = convertNullToEmptyString(rc.getLogicalModemUuid()); halRc.status = rc.getStatus(); try { radioProxy.setRadioCapability(rr.mSerial, halRc); } catch (Exception e) { handleRadioProxyExceptionForRR(rr, "setRadioCapability", e); } } } @Override public void startLceService(int reportIntervalMs, boolean pullMode, Message result) { IRadio radioProxy = getRadioProxy(result); if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_2)) { // We have a 1.2 or later radio, so the LCE 1.0 LCE service control path is unused. // Instead the LCE functionality is always-on and provides unsolicited indications. return; } if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_START_LCE, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " reportIntervalMs = " + reportIntervalMs + " pullMode = " + pullMode); } try { radioProxy.startLceService(rr.mSerial, reportIntervalMs, pullMode); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "startLceService", e); } } } @Override public void stopLceService(Message result) { IRadio radioProxy = getRadioProxy(result); if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_2)) { // We have a 1.2 or later radio, so the LCE 1.0 LCE service control is unused. // Instead the LCE functionality is always-on and provides unsolicited indications. return; } if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_STOP_LCE, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } try { radioProxy.stopLceService(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "stopLceService", e); } } } /** * This will only be called if the LCE service is started in PULL mode, which is * only enabled when using Radio HAL versions 1.1 and earlier. * * It is still possible for vendors to override this behavior and use the 1.1 version * of LCE; however, this is strongly discouraged and this functionality will be removed * when HAL 1.x support is dropped. * * @deprecated HAL 1.2 and later use an always-on LCE that relies on indications. */ @Deprecated @Override public void pullLceData(Message response) { IRadio radioProxy = getRadioProxy(response); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_PULL_LCEDATA, response, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } try { radioProxy.pullLceData(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "pullLceData", e); } } } @Override public void getModemActivityInfo(Message result, WorkSource workSource) { workSource = getDeafultWorkSourceIfInvalid(workSource); IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_GET_ACTIVITY_INFO, result, workSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } try { radioProxy.getModemActivityInfo(rr.mSerial); Message msg = mRilHandler.obtainMessage(EVENT_BLOCKING_RESPONSE_TIMEOUT); msg.obj = null; msg.arg1 = rr.mSerial; mRilHandler.sendMessageDelayed(msg, DEFAULT_BLOCKING_MESSAGE_RESPONSE_TIMEOUT_MS); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getModemActivityInfo", e); } } } /** * Convert a list of CarrierIdentifier into a list of Carrier defined in 1.0/types.hal. * @param carriers List of CarrierIdentifier * @return List of converted objects */ @VisibleForTesting public static ArrayList createCarrierRestrictionList( List carriers) { ArrayList result = new ArrayList<>(); for (CarrierIdentifier ci : carriers) { Carrier c = new Carrier(); c.mcc = convertNullToEmptyString(ci.getMcc()); c.mnc = convertNullToEmptyString(ci.getMnc()); int matchType = CarrierIdentifier.MatchType.ALL; String matchData = null; if (!TextUtils.isEmpty(ci.getSpn())) { matchType = CarrierIdentifier.MatchType.SPN; matchData = ci.getSpn(); } else if (!TextUtils.isEmpty(ci.getImsi())) { matchType = CarrierIdentifier.MatchType.IMSI_PREFIX; matchData = ci.getImsi(); } else if (!TextUtils.isEmpty(ci.getGid1())) { matchType = CarrierIdentifier.MatchType.GID1; matchData = ci.getGid1(); } else if (!TextUtils.isEmpty(ci.getGid2())) { matchType = CarrierIdentifier.MatchType.GID2; matchData = ci.getGid2(); } c.matchType = matchType; c.matchData = convertNullToEmptyString(matchData); result.add(c); } return result; } @Override public void setAllowedCarriers(CarrierRestrictionRules carrierRestrictionRules, Message result, WorkSource workSource) { riljLog("RIL.java - setAllowedCarriers"); checkNotNull(carrierRestrictionRules, "Carrier restriction cannot be null."); workSource = getDeafultWorkSourceIfInvalid(workSource); IRadio radioProxy = getRadioProxy(result); if (radioProxy == null) { return; } RILRequest rr = obtainRequest(RIL_REQUEST_SET_ALLOWED_CARRIERS, result, workSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " params: " + carrierRestrictionRules); } // Extract multisim policy int policy = SimLockMultiSimPolicy.NO_MULTISIM_POLICY; switch (carrierRestrictionRules.getMultiSimPolicy()) { case CarrierRestrictionRules.MULTISIM_POLICY_ONE_VALID_SIM_MUST_BE_PRESENT: policy = SimLockMultiSimPolicy.ONE_VALID_SIM_MUST_BE_PRESENT; break; } if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_4)) { riljLog("RIL.java - Using IRadio 1.4 or greater"); android.hardware.radio.V1_4.IRadio radioProxy14 = (android.hardware.radio.V1_4.IRadio) radioProxy; // Prepare structure with allowed list, excluded list and priority CarrierRestrictionsWithPriority carrierRestrictions = new CarrierRestrictionsWithPriority(); carrierRestrictions.allowedCarriers = createCarrierRestrictionList(carrierRestrictionRules.getAllowedCarriers()); carrierRestrictions.excludedCarriers = createCarrierRestrictionList(carrierRestrictionRules.getExcludedCarriers()); carrierRestrictions.allowedCarriersPrioritized = (carrierRestrictionRules.getDefaultCarrierRestriction() == CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED); try { radioProxy14.setAllowedCarriers_1_4(rr.mSerial, carrierRestrictions, policy); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setAllowedCarriers_1_4", e); } } else { boolean isAllCarriersAllowed = carrierRestrictionRules.isAllCarriersAllowed(); boolean supported = (isAllCarriersAllowed || (carrierRestrictionRules.getExcludedCarriers().isEmpty() && (carrierRestrictionRules.getDefaultCarrierRestriction() == CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED))); supported = supported && (policy == SimLockMultiSimPolicy.NO_MULTISIM_POLICY); if (!supported) { // Feature is not supported by IRadio interface riljLoge("setAllowedCarriers does not support excluded list on IRadio version" + " less than 1.4"); if (result != null) { AsyncResult.forMessage(result, null, CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED)); result.sendToTarget(); } return; } riljLog("RIL.java - Using IRadio 1.3 or lower"); // Prepare structure with allowed list CarrierRestrictions carrierRestrictions = new CarrierRestrictions(); carrierRestrictions.allowedCarriers = createCarrierRestrictionList(carrierRestrictionRules.getAllowedCarriers()); try { radioProxy.setAllowedCarriers(rr.mSerial, isAllCarriersAllowed, carrierRestrictions); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setAllowedCarriers", e); } } } @Override public void getAllowedCarriers(Message result, WorkSource workSource) { workSource = getDeafultWorkSourceIfInvalid(workSource); IRadio radioProxy = getRadioProxy(result); if (radioProxy == null) { return; } RILRequest rr = obtainRequest(RIL_REQUEST_GET_ALLOWED_CARRIERS, result, workSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_4)) { riljLog("RIL.java - Using IRadio 1.4 or greater"); android.hardware.radio.V1_4.IRadio radioProxy14 = (android.hardware.radio.V1_4.IRadio) radioProxy; try { radioProxy14.getAllowedCarriers_1_4(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getAllowedCarriers_1_4", e); } } else { riljLog("RIL.java - Using IRadio 1.3 or lower"); try { radioProxy.getAllowedCarriers(rr.mSerial); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getAllowedCarriers", e); } } } @Override public void sendDeviceState(int stateType, boolean state, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SEND_DEVICE_STATE, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " " + stateType + ":" + state); } try { radioProxy.sendDeviceState(rr.mSerial, stateType, state); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "sendDeviceState", e); } } } @Override public void setUnsolResponseFilter(int filter, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SET_UNSOLICITED_RESPONSE_FILTER, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " " + filter); } if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_2)) { try { android.hardware.radio.V1_2.IRadio radioProxy12 = (android.hardware.radio.V1_2.IRadio) radioProxy; radioProxy12.setIndicationFilter_1_2(rr.mSerial, filter); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setIndicationFilter_1_2", e); } } else { try { int filter10 = filter & IndicationFilter.ALL; radioProxy.setIndicationFilter(rr.mSerial, filter10); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setIndicationFilter", e); } } } } @Override public void setSignalStrengthReportingCriteria(int hysteresisMs, int hysteresisDb, int[] thresholdsDbm, int ran, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { if (mRadioVersion.less(RADIO_HAL_VERSION_1_2)) { riljLoge("setSignalStrengthReportingCriteria ignored on IRadio version less " + "than 1.2"); return; } RILRequest rr = obtainRequest(RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } try { android.hardware.radio.V1_2.IRadio radioProxy12 = (android.hardware.radio.V1_2.IRadio) radioProxy; radioProxy12.setSignalStrengthReportingCriteria(rr.mSerial, hysteresisMs, hysteresisDb, primitiveArrayToArrayList(thresholdsDbm), convertRanToHalRan(ran)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setSignalStrengthReportingCriteria", e); } } } @Override public void setLinkCapacityReportingCriteria(int hysteresisMs, int hysteresisDlKbps, int hysteresisUlKbps, int[] thresholdsDlKbps, int[] thresholdsUlKbps, int ran, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { if (mRadioVersion.less(RADIO_HAL_VERSION_1_2)) { riljLoge("setLinkCapacityReportingCriteria ignored on IRadio version less " + "than 1.2"); return; } RILRequest rr = obtainRequest(RIL_REQUEST_SET_LINK_CAPACITY_REPORTING_CRITERIA, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } try { android.hardware.radio.V1_2.IRadio radioProxy12 = (android.hardware.radio.V1_2.IRadio) radioProxy; radioProxy12.setLinkCapacityReportingCriteria(rr.mSerial, hysteresisMs, hysteresisDlKbps, hysteresisUlKbps, primitiveArrayToArrayList(thresholdsDlKbps), primitiveArrayToArrayList(thresholdsUlKbps), convertRanToHalRan(ran)); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setLinkCapacityReportingCriteria", e); } } } private static int convertRanToHalRan(int radioAccessNetwork) { switch (radioAccessNetwork) { case AccessNetworkType.GERAN: return AccessNetwork.GERAN; case AccessNetworkType.UTRAN: return AccessNetwork.UTRAN; case AccessNetworkType.EUTRAN: return AccessNetwork.EUTRAN; case AccessNetworkType.CDMA2000: return AccessNetwork.CDMA2000; case AccessNetworkType.IWLAN: return AccessNetwork.IWLAN; case AccessNetworkType.UNKNOWN: default: return 0; } } @Override public void setSimCardPower(int state, Message result, WorkSource workSource) { workSource = getDeafultWorkSourceIfInvalid(workSource); IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_SET_SIM_CARD_POWER, result, workSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest) + " " + state); } if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_1)) { try { android.hardware.radio.V1_1.IRadio radioProxy11 = (android.hardware.radio.V1_1.IRadio) radioProxy; radioProxy11.setSimCardPower_1_1(rr.mSerial, state); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setSimCardPower", e); } } else { try { switch (state) { case TelephonyManager.CARD_POWER_DOWN: { radioProxy.setSimCardPower(rr.mSerial, false); break; } case TelephonyManager.CARD_POWER_UP: { radioProxy.setSimCardPower(rr.mSerial, true); break; } default: { if (result != null) { AsyncResult.forMessage(result, null, CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED)); result.sendToTarget(); } } } } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setSimCardPower", e); } } } } @Override public void setCarrierInfoForImsiEncryption(ImsiEncryptionInfo imsiEncryptionInfo, Message result) { checkNotNull(imsiEncryptionInfo, "ImsiEncryptionInfo cannot be null."); IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { if (mRadioVersion.greaterOrEqual(RADIO_HAL_VERSION_1_1)) { android.hardware.radio.V1_1.IRadio radioProxy11 = (android.hardware.radio.V1_1.IRadio ) radioProxy; RILRequest rr = obtainRequest(RIL_REQUEST_SET_CARRIER_INFO_IMSI_ENCRYPTION, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { android.hardware.radio.V1_1.ImsiEncryptionInfo halImsiInfo = new android.hardware.radio.V1_1.ImsiEncryptionInfo(); halImsiInfo.mnc = imsiEncryptionInfo.getMnc(); halImsiInfo.mcc = imsiEncryptionInfo.getMcc(); halImsiInfo.keyIdentifier = imsiEncryptionInfo.getKeyIdentifier(); if (imsiEncryptionInfo.getExpirationTime() != null) { halImsiInfo.expirationTime = imsiEncryptionInfo.getExpirationTime().getTime(); } for (byte b : imsiEncryptionInfo.getPublicKey().getEncoded()) { halImsiInfo.carrierKey.add(new Byte(b)); } radioProxy11.setCarrierInfoForImsiEncryption( rr.mSerial, halImsiInfo); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "setCarrierInfoForImsiEncryption", e); } } else if (result != null) { AsyncResult.forMessage(result, null, CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED)); result.sendToTarget(); } } } @Override public void startNattKeepalive( int contextId, KeepalivePacketData packetData, int intervalMillis, Message result) { checkNotNull(packetData, "KeepaliveRequest cannot be null."); IRadio radioProxy = getRadioProxy(result); if (radioProxy == null) { riljLoge("Radio Proxy object is null!"); return; } if (mRadioVersion.less(RADIO_HAL_VERSION_1_1)) { if (result != null) { AsyncResult.forMessage(result, null, CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED)); result.sendToTarget(); } return; } android.hardware.radio.V1_1.IRadio radioProxy11 = (android.hardware.radio.V1_1.IRadio) radioProxy; RILRequest rr = obtainRequest( RIL_REQUEST_START_KEEPALIVE, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { android.hardware.radio.V1_1.KeepaliveRequest req = new android.hardware.radio.V1_1.KeepaliveRequest(); req.cid = contextId; if (packetData.dstAddress instanceof Inet4Address) { req.type = android.hardware.radio.V1_1.KeepaliveType.NATT_IPV4; } else if (packetData.dstAddress instanceof Inet6Address) { req.type = android.hardware.radio.V1_1.KeepaliveType.NATT_IPV6; } else { AsyncResult.forMessage(result, null, CommandException.fromRilErrno(INVALID_ARGUMENTS)); result.sendToTarget(); return; } appendPrimitiveArrayToArrayList( packetData.srcAddress.getAddress(), req.sourceAddress); req.sourcePort = packetData.srcPort; appendPrimitiveArrayToArrayList( packetData.dstAddress.getAddress(), req.destinationAddress); req.destinationPort = packetData.dstPort; req.maxKeepaliveIntervalMillis = intervalMillis; radioProxy11.startKeepalive(rr.mSerial, req); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "startNattKeepalive", e); } } @Override public void stopNattKeepalive(int sessionHandle, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy == null) { Rlog.e(RIL.RILJ_LOG_TAG, "Radio Proxy object is null!"); return; } if (mRadioVersion.less(RADIO_HAL_VERSION_1_1)) { if (result != null) { AsyncResult.forMessage(result, null, CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED)); result.sendToTarget(); } return; } android.hardware.radio.V1_1.IRadio radioProxy11 = (android.hardware.radio.V1_1.IRadio) radioProxy; RILRequest rr = obtainRequest( RIL_REQUEST_STOP_KEEPALIVE, result, mRILDefaultWorkSource); if (RILJ_LOGD) riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); try { radioProxy11.stopKeepalive(rr.mSerial, sessionHandle); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "stopNattKeepalive", e); } } @Override public void getIMEI(Message result) { throw new RuntimeException("getIMEI not expected to be called"); } @Override public void getIMEISV(Message result) { throw new RuntimeException("getIMEISV not expected to be called"); } /** * @deprecated */ @Deprecated @Override public void getLastPdpFailCause(Message result) { throw new RuntimeException("getLastPdpFailCause not expected to be called"); } /** * The preferred new alternative to getLastPdpFailCause */ @Override public void getLastDataCallFailCause(Message result) { throw new RuntimeException("getLastDataCallFailCause not expected to be called"); } /** * 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; } @Override public void resetRadio(Message result) { throw new RuntimeException("resetRadio not expected to be called"); } /** * {@inheritDoc} */ @Override public void handleCallSetupRequestFromSim(boolean accept, Message result) { IRadio radioProxy = getRadioProxy(result); if (radioProxy != null) { RILRequest rr = obtainRequest(RIL_REQUEST_STK_HANDLE_CALL_SETUP_REQUESTED_FROM_SIM, result, mRILDefaultWorkSource); if (RILJ_LOGD) { riljLog(rr.serialString() + "> " + requestToString(rr.mRequest)); } try { radioProxy.handleStkCallSetupRequestFromSim(rr.mSerial, accept); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "getAllowedCarriers", e); } } } //***** Private Methods /** * This is a helper function to be called when a RadioIndication callback is called. * It takes care of acquiring wakelock and sending ack if needed. * @param indicationType RadioIndicationType received */ void processIndication(int indicationType) { if (indicationType == RadioIndicationType.UNSOLICITED_ACK_EXP) { sendAck(); if (RILJ_LOGD) riljLog("Unsol response received; Sending ack to ril.cpp"); } else { // ack is not expected to be sent back. Nothing is required to be done here. } } void processRequestAck(int serial) { RILRequest rr; synchronized (mRequestList) { rr = mRequestList.get(serial); } if (rr == null) { Rlog.w(RIL.RILJ_LOG_TAG, "processRequestAck: Unexpected solicited ack response! " + "serial: " + serial); } else { decrementWakeLock(rr); if (RIL.RILJ_LOGD) { riljLog(rr.serialString() + " Ack < " + RIL.requestToString(rr.mRequest)); } } } /** * This is a helper function to be called when a RadioResponse callback is called. * It takes care of acks, wakelocks, and finds and returns RILRequest corresponding to the * response if one is found. * @param responseInfo RadioResponseInfo received in response callback * @return RILRequest corresponding to the response */ @VisibleForTesting public RILRequest processResponse(RadioResponseInfo responseInfo) { int serial = responseInfo.serial; int error = responseInfo.error; int type = responseInfo.type; RILRequest rr = null; if (type == RadioResponseType.SOLICITED_ACK) { synchronized (mRequestList) { rr = mRequestList.get(serial); } if (rr == null) { Rlog.w(RILJ_LOG_TAG, "Unexpected solicited ack response! sn: " + serial); } else { decrementWakeLock(rr); if (mRadioBugDetector != null) { mRadioBugDetector.detectRadioBug(rr.mRequest, error); } if (RILJ_LOGD) { riljLog(rr.serialString() + " Ack < " + requestToString(rr.mRequest)); } } return rr; } rr = findAndRemoveRequestFromList(serial); if (rr == null) { Rlog.e(RIL.RILJ_LOG_TAG, "processResponse: Unexpected response! serial: " + serial + " error: " + error); return null; } // Time logging for RIL command and storing it in TelephonyHistogram. addToRilHistogram(rr); if (mRadioBugDetector != null) { mRadioBugDetector.detectRadioBug(rr.mRequest, error); } if (type == RadioResponseType.SOLICITED_ACK_EXP) { sendAck(); if (RIL.RILJ_LOGD) { riljLog("Response received for " + rr.serialString() + " " + RIL.requestToString(rr.mRequest) + " Sending ack to ril.cpp"); } } else { // ack sent for SOLICITED_ACK_EXP above; nothing to do for SOLICITED response } // Here and below fake RIL_UNSOL_RESPONSE_SIM_STATUS_CHANGED, see b/7255789. // This is needed otherwise we don't automatically transition to the main lock // screen when the pin or puk is entered incorrectly. switch (rr.mRequest) { case RIL_REQUEST_ENTER_SIM_PUK: case RIL_REQUEST_ENTER_SIM_PUK2: if (mIccStatusChangedRegistrants != null) { if (RILJ_LOGD) { riljLog("ON enter sim puk fakeSimStatusChanged: reg count=" + mIccStatusChangedRegistrants.size()); } mIccStatusChangedRegistrants.notifyRegistrants(); } break; case RIL_REQUEST_SHUTDOWN: setRadioState(TelephonyManager.RADIO_POWER_UNAVAILABLE, false /* forceNotifyRegistrants */); break; } if (error != RadioError.NONE) { switch (rr.mRequest) { case RIL_REQUEST_ENTER_SIM_PIN: case RIL_REQUEST_ENTER_SIM_PIN2: case RIL_REQUEST_CHANGE_SIM_PIN: case RIL_REQUEST_CHANGE_SIM_PIN2: case RIL_REQUEST_SET_FACILITY_LOCK: if (mIccStatusChangedRegistrants != null) { if (RILJ_LOGD) { riljLog("ON some errors fakeSimStatusChanged: reg count=" + mIccStatusChangedRegistrants.size()); } mIccStatusChangedRegistrants.notifyRegistrants(); } break; } } else { switch (rr.mRequest) { case RIL_REQUEST_HANGUP_FOREGROUND_RESUME_BACKGROUND: if (mTestingEmergencyCall.getAndSet(false)) { if (mEmergencyCallbackModeRegistrant != null) { riljLog("testing emergency call, notify ECM Registrants"); mEmergencyCallbackModeRegistrant.notifyRegistrant(); } } } } return rr; } /** * This is a helper function to be called at the end of all RadioResponse callbacks. * It takes care of sending error response, logging, decrementing wakelock if needed, and * releases the request from memory pool. * @param rr RILRequest for which response callback was called * @param responseInfo RadioResponseInfo received in the callback * @param ret object to be returned to request sender */ @VisibleForTesting public void processResponseDone(RILRequest rr, RadioResponseInfo responseInfo, Object ret) { if (responseInfo.error == 0) { if (RILJ_LOGD) { riljLog(rr.serialString() + "< " + requestToString(rr.mRequest) + " " + retToString(rr.mRequest, ret)); } } else { if (RILJ_LOGD) { riljLog(rr.serialString() + "< " + requestToString(rr.mRequest) + " error " + responseInfo.error); } rr.onError(responseInfo.error, ret); } mMetrics.writeOnRilSolicitedResponse(mPhoneId, rr.mSerial, responseInfo.error, rr.mRequest, ret); if (rr != null) { if (responseInfo.type == RadioResponseType.SOLICITED) { decrementWakeLock(rr); } rr.release(); } } /** * Function to send ack and acquire related wakelock */ private void sendAck() { // TODO: Remove rr and clean up acquireWakelock for response and ack RILRequest rr = RILRequest.obtain(RIL_RESPONSE_ACKNOWLEDGEMENT, null, mRILDefaultWorkSource); acquireWakeLock(rr, RIL.FOR_ACK_WAKELOCK); IRadio radioProxy = getRadioProxy(null); if (radioProxy != null) { try { radioProxy.responseAcknowledgement(); } catch (RemoteException | RuntimeException e) { handleRadioProxyExceptionForRR(rr, "sendAck", e); riljLoge("sendAck: " + e); } } else { Rlog.e(RILJ_LOG_TAG, "Error trying to send ack, radioProxy = null"); } rr.release(); } private WorkSource getDeafultWorkSourceIfInvalid(WorkSource workSource) { if (workSource == null) { workSource = mRILDefaultWorkSource; } return workSource; } /** * 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. */ @UnsupportedAppUsage private void acquireWakeLock(RILRequest rr, int wakeLockType) { synchronized (rr) { if (rr.mWakeLockType != INVALID_WAKELOCK) { Rlog.d(RILJ_LOG_TAG, "Failed to aquire wakelock for " + rr.serialString()); return; } switch(wakeLockType) { case FOR_WAKELOCK: synchronized (mWakeLock) { mWakeLock.acquire(); mWakeLockCount++; mWlSequenceNum++; String clientId = rr.getWorkSourceClientId(); if (!mClientWakelockTracker.isClientActive(clientId)) { mActiveWakelockWorkSource.add(rr.mWorkSource); mWakeLock.setWorkSource(mActiveWakelockWorkSource); } mClientWakelockTracker.startTracking(rr.mClientId, rr.mRequest, rr.mSerial, mWakeLockCount); Message msg = mRilHandler.obtainMessage(EVENT_WAKE_LOCK_TIMEOUT); msg.arg1 = mWlSequenceNum; mRilHandler.sendMessageDelayed(msg, mWakeLockTimeout); } break; case FOR_ACK_WAKELOCK: synchronized (mAckWakeLock) { mAckWakeLock.acquire(); mAckWlSequenceNum++; Message msg = mRilHandler.obtainMessage(EVENT_ACK_WAKE_LOCK_TIMEOUT); msg.arg1 = mAckWlSequenceNum; mRilHandler.sendMessageDelayed(msg, mAckWakeLockTimeout); } break; default: //WTF Rlog.w(RILJ_LOG_TAG, "Acquiring Invalid Wakelock type " + wakeLockType); return; } rr.mWakeLockType = wakeLockType; } } /** Returns the wake lock of the given type. */ @VisibleForTesting public WakeLock getWakeLock(int wakeLockType) { return wakeLockType == FOR_WAKELOCK ? mWakeLock : mAckWakeLock; } /** Returns the {@link RilHandler} instance. */ @VisibleForTesting public RilHandler getRilHandler() { return mRilHandler; } /** Returns the Ril request list. */ @VisibleForTesting public SparseArray getRilRequestList() { return mRequestList; } @UnsupportedAppUsage private void decrementWakeLock(RILRequest rr) { synchronized (rr) { switch(rr.mWakeLockType) { case FOR_WAKELOCK: synchronized (mWakeLock) { mClientWakelockTracker.stopTracking(rr.mClientId, rr.mRequest, rr.mSerial, (mWakeLockCount > 1) ? mWakeLockCount - 1 : 0); String clientId = rr.getWorkSourceClientId(); if (!mClientWakelockTracker.isClientActive(clientId)) { mActiveWakelockWorkSource.remove(rr.mWorkSource); mWakeLock.setWorkSource(mActiveWakelockWorkSource); } if (mWakeLockCount > 1) { mWakeLockCount--; } else { mWakeLockCount = 0; mWakeLock.release(); } } break; case FOR_ACK_WAKELOCK: //We do not decrement the ACK wakelock break; case INVALID_WAKELOCK: break; default: Rlog.w(RILJ_LOG_TAG, "Decrementing Invalid Wakelock type " + rr.mWakeLockType); } rr.mWakeLockType = INVALID_WAKELOCK; } } @UnsupportedAppUsage private boolean clearWakeLock(int wakeLockType) { if (wakeLockType == FOR_WAKELOCK) { synchronized (mWakeLock) { if (mWakeLockCount == 0 && !mWakeLock.isHeld()) return false; Rlog.d(RILJ_LOG_TAG, "NOTE: mWakeLockCount is " + mWakeLockCount + "at time of clearing"); mWakeLockCount = 0; mWakeLock.release(); mClientWakelockTracker.stopTrackingAll(); mActiveWakelockWorkSource = new WorkSource(); return true; } } else { synchronized (mAckWakeLock) { if (!mAckWakeLock.isHeld()) return false; mAckWakeLock.release(); return true; } } } /** * Release each request in mRequestList then clear the list * @param error is the RIL_Errno sent back * @param loggable true means to print all requests in mRequestList */ @UnsupportedAppUsage private void clearRequestList(int error, boolean loggable) { RILRequest rr; synchronized (mRequestList) { int count = mRequestList.size(); if (RILJ_LOGD && loggable) { Rlog.d(RILJ_LOG_TAG, "clearRequestList " + " mWakeLockCount=" + mWakeLockCount + " mRequestList=" + count); } for (int i = 0; i < count; i++) { rr = mRequestList.valueAt(i); if (RILJ_LOGD && loggable) { Rlog.d(RILJ_LOG_TAG, i + ": [" + rr.mSerial + "] " + requestToString(rr.mRequest)); } rr.onError(error, null); decrementWakeLock(rr); rr.release(); } mRequestList.clear(); } } @UnsupportedAppUsage private RILRequest findAndRemoveRequestFromList(int serial) { RILRequest rr = null; synchronized (mRequestList) { rr = mRequestList.get(serial); if (rr != null) { mRequestList.remove(serial); } } return rr; } private void addToRilHistogram(RILRequest rr) { long endTime = SystemClock.elapsedRealtime(); int totalTime = (int) (endTime - rr.mStartTimeMs); synchronized (mRilTimeHistograms) { TelephonyHistogram entry = mRilTimeHistograms.get(rr.mRequest); if (entry == null) { // We would have total #RIL_HISTOGRAM_BUCKET_COUNT range buckets for RIL commands entry = new TelephonyHistogram(TelephonyHistogram.TELEPHONY_CATEGORY_RIL, rr.mRequest, RIL_HISTOGRAM_BUCKET_COUNT); mRilTimeHistograms.put(rr.mRequest, entry); } entry.addTimeTaken(totalTime); } } @UnsupportedAppUsage RadioCapability makeStaticRadioCapability() { // default to UNKNOWN so we fail fast. int raf = RadioAccessFamily.RAF_UNKNOWN; String rafString = mContext.getResources().getString( com.android.internal.R.string.config_radio_access_family); if (!TextUtils.isEmpty(rafString)) { raf = RadioAccessFamily.rafTypeFromString(rafString); } RadioCapability rc = new RadioCapability(mPhoneId.intValue(), 0, 0, raf, "", RadioCapability.RC_STATUS_SUCCESS); if (RILJ_LOGD) riljLog("Faking RIL_REQUEST_GET_RADIO_CAPABILITY response using " + raf); return rc; } @UnsupportedAppUsage static 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: case RIL_REQUEST_SIM_OPEN_CHANNEL: case RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL: 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; // position 0 is IMEI in RIL_REQUEST_DEVICE_IDENTITY if (req == RIL_REQUEST_DEVICE_IDENTITY) { sb.append(Rlog.pii(RILJ_LOG_TAG, strings[i++])); } else { 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 calls = (ArrayList) ret; sb = new StringBuilder("{"); for (DriverCall dc : calls) { sb.append("[").append(dc).append("] "); } sb.append("}"); s = sb.toString(); } else if (req == RIL_REQUEST_GET_NEIGHBORING_CELL_IDS) { ArrayList cells = (ArrayList) ret; sb = new StringBuilder("{"); for (NeighboringCellInfo cell : cells) { sb.append("[").append(cell).append("] "); } sb.append("}"); s = sb.toString(); } else if (req == RIL_REQUEST_QUERY_CALL_FORWARD_STATUS) { CallForwardInfo[] cinfo = (CallForwardInfo[]) ret; length = cinfo.length; sb = new StringBuilder("{"); for (int i = 0; i < length; i++) { sb.append("[").append(cinfo[i]).append("] "); } sb.append("}"); s = sb.toString(); } else if (req == RIL_REQUEST_GET_HARDWARE_CONFIG) { ArrayList hwcfgs = (ArrayList) ret; sb = new StringBuilder(" "); for (HardwareConfig hwcfg : hwcfgs) { sb.append("[").append(hwcfg).append("] "); } s = sb.toString(); } else { s = ret.toString(); } return s; } void writeMetricsCallRing(char[] response) { mMetrics.writeRilCallRing(mPhoneId, response); } void writeMetricsSrvcc(int state) { mMetrics.writeRilSrvcc(mPhoneId, state); } void writeMetricsModemRestartEvent(String reason) { mMetrics.writeModemRestartEvent(mPhoneId, reason); } /** * Notify all registrants that the ril has connected or disconnected. * * @param rilVer is the version of the ril or -1 if disconnected. */ @UnsupportedAppUsage void notifyRegistrantsRilConnectionChanged(int rilVer) { mRilVersion = rilVer; if (mRilConnectedRegistrants != null) { mRilConnectedRegistrants.notifyRegistrants( new AsyncResult(null, new Integer(rilVer), null)); } } @UnsupportedAppUsage 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)); } } } @UnsupportedAppUsage static String requestToString(int request) { 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"; case RIL_REQUEST_GET_CELL_INFO_LIST: return "RIL_REQUEST_GET_CELL_INFO_LIST"; case RIL_REQUEST_SET_UNSOL_CELL_INFO_LIST_RATE: return "RIL_REQUEST_SET_CELL_INFO_LIST_RATE"; case RIL_REQUEST_SET_INITIAL_ATTACH_APN: return "RIL_REQUEST_SET_INITIAL_ATTACH_APN"; case RIL_REQUEST_SET_DATA_PROFILE: return "RIL_REQUEST_SET_DATA_PROFILE"; case RIL_REQUEST_IMS_REGISTRATION_STATE: return "RIL_REQUEST_IMS_REGISTRATION_STATE"; case RIL_REQUEST_IMS_SEND_SMS: return "RIL_REQUEST_IMS_SEND_SMS"; case RIL_REQUEST_SIM_TRANSMIT_APDU_BASIC: return "RIL_REQUEST_SIM_TRANSMIT_APDU_BASIC"; case RIL_REQUEST_SIM_OPEN_CHANNEL: return "RIL_REQUEST_SIM_OPEN_CHANNEL"; case RIL_REQUEST_SIM_CLOSE_CHANNEL: return "RIL_REQUEST_SIM_CLOSE_CHANNEL"; case RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL: return "RIL_REQUEST_SIM_TRANSMIT_APDU_CHANNEL"; case RIL_REQUEST_NV_READ_ITEM: return "RIL_REQUEST_NV_READ_ITEM"; case RIL_REQUEST_NV_WRITE_ITEM: return "RIL_REQUEST_NV_WRITE_ITEM"; case RIL_REQUEST_NV_WRITE_CDMA_PRL: return "RIL_REQUEST_NV_WRITE_CDMA_PRL"; case RIL_REQUEST_NV_RESET_CONFIG: return "RIL_REQUEST_NV_RESET_CONFIG"; case RIL_REQUEST_SET_UICC_SUBSCRIPTION: return "RIL_REQUEST_SET_UICC_SUBSCRIPTION"; case RIL_REQUEST_ALLOW_DATA: return "RIL_REQUEST_ALLOW_DATA"; case RIL_REQUEST_GET_HARDWARE_CONFIG: return "GET_HARDWARE_CONFIG"; case RIL_REQUEST_SIM_AUTHENTICATION: return "RIL_REQUEST_SIM_AUTHENTICATION"; case RIL_REQUEST_SHUTDOWN: return "RIL_REQUEST_SHUTDOWN"; case RIL_REQUEST_SET_RADIO_CAPABILITY: return "RIL_REQUEST_SET_RADIO_CAPABILITY"; case RIL_REQUEST_GET_RADIO_CAPABILITY: return "RIL_REQUEST_GET_RADIO_CAPABILITY"; case RIL_REQUEST_START_LCE: return "RIL_REQUEST_START_LCE"; case RIL_REQUEST_STOP_LCE: return "RIL_REQUEST_STOP_LCE"; case RIL_REQUEST_PULL_LCEDATA: return "RIL_REQUEST_PULL_LCEDATA"; case RIL_REQUEST_GET_ACTIVITY_INFO: return "RIL_REQUEST_GET_ACTIVITY_INFO"; case RIL_REQUEST_SET_ALLOWED_CARRIERS: return "RIL_REQUEST_SET_ALLOWED_CARRIERS"; case RIL_REQUEST_GET_ALLOWED_CARRIERS: return "RIL_REQUEST_GET_ALLOWED_CARRIERS"; case RIL_REQUEST_SET_SIM_CARD_POWER: return "RIL_REQUEST_SET_SIM_CARD_POWER"; case RIL_REQUEST_SEND_DEVICE_STATE: return "RIL_REQUEST_SEND_DEVICE_STATE"; case RIL_REQUEST_SET_UNSOLICITED_RESPONSE_FILTER: return "RIL_REQUEST_SET_UNSOLICITED_RESPONSE_FILTER"; case RIL_RESPONSE_ACKNOWLEDGEMENT: return "RIL_RESPONSE_ACKNOWLEDGEMENT"; case RIL_REQUEST_SET_CARRIER_INFO_IMSI_ENCRYPTION: return "RIL_REQUEST_SET_CARRIER_INFO_IMSI_ENCRYPTION"; case RIL_REQUEST_START_NETWORK_SCAN: return "RIL_REQUEST_START_NETWORK_SCAN"; case RIL_REQUEST_STOP_NETWORK_SCAN: return "RIL_REQUEST_STOP_NETWORK_SCAN"; case RIL_REQUEST_GET_SLOT_STATUS: return "RIL_REQUEST_GET_SLOT_STATUS"; case RIL_REQUEST_SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING: return "RIL_REQUEST_SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING"; case RIL_REQUEST_START_KEEPALIVE: return "RIL_REQUEST_START_KEEPALIVE"; case RIL_REQUEST_STOP_KEEPALIVE: return "RIL_REQUEST_STOP_KEEPALIVE"; case RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA: return "RIL_REQUEST_SET_SIGNAL_STRENGTH_REPORTING_CRITERIA"; case RIL_REQUEST_SET_LINK_CAPACITY_REPORTING_CRITERIA: return "RIL_REQUEST_SET_LINK_CAPACITY_REPORTING_CRITERIA"; case RIL_REQUEST_ENABLE_MODEM: return "RIL_REQUEST_ENABLE_MODEM"; case RIL_REQUEST_GET_MODEM_STATUS: return "RIL_REQUEST_GET_MODEM_STATUS"; default: return ""; } } @UnsupportedAppUsage static String responseToString(int request) { 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_NETWORK_STATE_CHANGED: return "UNSOL_RESPONSE_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_TONE"; 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"; case RIL_UNSOL_CELL_INFO_LIST: return "UNSOL_CELL_INFO_LIST"; case RIL_UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED: return "UNSOL_RESPONSE_IMS_NETWORK_STATE_CHANGED"; case RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED: return "RIL_UNSOL_UICC_SUBSCRIPTION_STATUS_CHANGED"; case RIL_UNSOL_SRVCC_STATE_NOTIFY: return "UNSOL_SRVCC_STATE_NOTIFY"; case RIL_UNSOL_HARDWARE_CONFIG_CHANGED: return "RIL_UNSOL_HARDWARE_CONFIG_CHANGED"; case RIL_UNSOL_RADIO_CAPABILITY: return "RIL_UNSOL_RADIO_CAPABILITY"; case RIL_UNSOL_ON_SS: return "UNSOL_ON_SS"; case RIL_UNSOL_STK_CC_ALPHA_NOTIFY: return "UNSOL_STK_CC_ALPHA_NOTIFY"; case RIL_UNSOL_LCEDATA_RECV: return "UNSOL_LCE_INFO_RECV"; case RIL_UNSOL_PCO_DATA: return "UNSOL_PCO_DATA"; case RIL_UNSOL_MODEM_RESTART: return "UNSOL_MODEM_RESTART"; case RIL_UNSOL_CARRIER_INFO_IMSI_ENCRYPTION: return "RIL_UNSOL_CARRIER_INFO_IMSI_ENCRYPTION"; case RIL_UNSOL_NETWORK_SCAN_RESULT: return "RIL_UNSOL_NETWORK_SCAN_RESULT"; case RIL_UNSOL_ICC_SLOT_STATUS: return "RIL_UNSOL_ICC_SLOT_STATUS"; case RIL_UNSOL_KEEPALIVE_STATUS: return "RIL_UNSOL_KEEPALIVE_STATUS"; case RIL_UNSOL_PHYSICAL_CHANNEL_CONFIG: return "RIL_UNSOL_PHYSICAL_CHANNEL_CONFIG"; default: return ""; } } @UnsupportedAppUsage void riljLog(String msg) { Rlog.d(RILJ_LOG_TAG, msg + (" [SUB" + mPhoneId + "]")); } void riljLoge(String msg) { Rlog.e(RILJ_LOG_TAG, msg + (" [SUB" + mPhoneId + "]")); } void riljLoge(String msg, Exception e) { Rlog.e(RILJ_LOG_TAG, msg + (" [SUB" + mPhoneId + "]"), e); } void riljLogv(String msg) { Rlog.v(RILJ_LOG_TAG, msg + (" [SUB" + mPhoneId + "]")); } @UnsupportedAppUsage void unsljLog(int response) { riljLog("[UNSL]< " + responseToString(response)); } @UnsupportedAppUsage void unsljLogMore(int response, String more) { riljLog("[UNSL]< " + responseToString(response) + " " + more); } @UnsupportedAppUsage void unsljLogRet(int response, Object ret) { riljLog("[UNSL]< " + responseToString(response) + " " + retToString(response, ret)); } @UnsupportedAppUsage void unsljLogvRet(int response, Object ret) { riljLogv("[UNSL]< " + responseToString(response) + " " + retToString(response, ret)); } @Override public void setPhoneType(int phoneType) { // Called by GsmCdmaPhone if (RILJ_LOGD) riljLog("setPhoneType=" + phoneType + " old value=" + mPhoneType); mPhoneType = phoneType; } /* (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: " + this); pw.println(" mWakeLock=" + mWakeLock); pw.println(" mWakeLockTimeout=" + mWakeLockTimeout); synchronized (mRequestList) { synchronized (mWakeLock) { pw.println(" mWakeLockCount=" + mWakeLockCount); } int count = mRequestList.size(); pw.println(" mRequestList count=" + count); for (int i = 0; i < count; i++) { RILRequest rr = mRequestList.valueAt(i); pw.println(" [" + rr.mSerial + "] " + requestToString(rr.mRequest)); } } pw.println(" mLastNITZTimeInfo=" + Arrays.toString(mLastNITZTimeInfo)); pw.println(" mTestingEmergencyCall=" + mTestingEmergencyCall.get()); mClientWakelockTracker.dumpClientRequestTracker(pw); } public List getClientRequestStats() { return mClientWakelockTracker.getClientRequestStats(); } /** Append the data to the end of an ArrayList */ public static void appendPrimitiveArrayToArrayList(byte[] src, ArrayList dst) { for (byte b : src) { dst.add(b); } } public static ArrayList primitiveArrayToArrayList(byte[] arr) { ArrayList arrayList = new ArrayList<>(arr.length); for (byte b : arr) { arrayList.add(b); } return arrayList; } /** Convert a primitive int array to an ArrayList. */ public static ArrayList primitiveArrayToArrayList(int[] arr) { ArrayList arrayList = new ArrayList<>(arr.length); for (int i : arr) { arrayList.add(i); } return arrayList; } /** Convert an ArrayList of Bytes to an exactly-sized primitive array */ public static byte[] arrayListToPrimitiveArray(ArrayList bytes) { byte[] ret = new byte[bytes.size()]; for (int i = 0; i < ret.length; i++) { ret[i] = bytes.get(i); } return ret; } static ArrayList convertHalHwConfigList( ArrayList hwListRil, RIL ril) { int num; ArrayList response; HardwareConfig hw; num = hwListRil.size(); response = new ArrayList(num); if (RILJ_LOGV) { ril.riljLog("convertHalHwConfigList: num=" + num); } for (android.hardware.radio.V1_0.HardwareConfig hwRil : hwListRil) { int type = hwRil.type; switch(type) { case HardwareConfig.DEV_HARDWARE_TYPE_MODEM: { hw = new HardwareConfig(type); HardwareConfigModem hwModem = hwRil.modem.get(0); hw.assignModem(hwRil.uuid, hwRil.state, hwModem.rilModel, hwModem.rat, hwModem.maxVoice, hwModem.maxData, hwModem.maxStandby); break; } case HardwareConfig.DEV_HARDWARE_TYPE_SIM: { hw = new HardwareConfig(type); hw.assignSim(hwRil.uuid, hwRil.state, hwRil.sim.get(0).modemUuid); break; } default: { throw new RuntimeException( "RIL_REQUEST_GET_HARDWARE_CONFIG invalid hardward type:" + type); } } response.add(hw); } return response; } static RadioCapability convertHalRadioCapability( android.hardware.radio.V1_0.RadioCapability rcRil, RIL ril) { int session = rcRil.session; int phase = rcRil.phase; // convert to public bitmask {@link TelephonyManager.NetworkTypeBitMask} int rat = convertToNetworkTypeBitMask(rcRil.raf); String logicModemUuid = rcRil.logicalModemUuid; int status = rcRil.status; ril.riljLog("convertHalRadioCapability: session=" + session + ", phase=" + phase + ", rat=" + rat + ", logicModemUuid=" + logicModemUuid + ", status=" + status + ", rcRil.raf=" + rcRil.raf); RadioCapability rc = new RadioCapability( ril.mPhoneId, session, phase, rat, logicModemUuid, status); return rc; } static LinkCapacityEstimate convertHalLceData(LceDataInfo halData, RIL ril) { final LinkCapacityEstimate lce = new LinkCapacityEstimate( halData.lastHopCapacityKbps, Byte.toUnsignedInt(halData.confidenceLevel), halData.lceSuspended ? LinkCapacityEstimate.STATUS_SUSPENDED : LinkCapacityEstimate.STATUS_ACTIVE); ril.riljLog("LCE capacity information received:" + lce); return lce; } static LinkCapacityEstimate convertHalLceData( android.hardware.radio.V1_2.LinkCapacityEstimate halData, RIL ril) { final LinkCapacityEstimate lce = new LinkCapacityEstimate( halData.downlinkCapacityKbps, halData.uplinkCapacityKbps); ril.riljLog("LCE capacity information received:" + lce); return lce; } /** * Convert CellInfo defined in 1.0/types.hal to CellInfo type. * @param records List of CellInfo defined in 1.0/types.hal * @return List of converted CellInfo object */ @VisibleForTesting public static ArrayList convertHalCellInfoList( ArrayList records) { ArrayList response = new ArrayList(records.size()); final long nanotime = SystemClock.elapsedRealtimeNanos(); for (android.hardware.radio.V1_0.CellInfo record : records) { record.timeStamp = nanotime; response.add(CellInfo.create(record)); } return response; } /** * Convert CellInfo defined in 1.2/types.hal to CellInfo type. * @param records List of CellInfo defined in 1.2/types.hal * @return List of converted CellInfo object */ @VisibleForTesting public static ArrayList convertHalCellInfoList_1_2( ArrayList records) { ArrayList response = new ArrayList(records.size()); final long nanotime = SystemClock.elapsedRealtimeNanos(); for (android.hardware.radio.V1_2.CellInfo record : records) { record.timeStamp = nanotime; response.add(CellInfo.create(record)); } return response; } /** * Convert CellInfo defined in 1.4/types.hal to CellInfo type. * @param records List of CellInfo defined in 1.4/types.hal. * @return List of converted CellInfo object. */ @VisibleForTesting public static ArrayList convertHalCellInfoList_1_4( ArrayList records) { ArrayList response = new ArrayList(records.size()); final long nanotime = SystemClock.elapsedRealtimeNanos(); for (android.hardware.radio.V1_4.CellInfo record : records) { response.add(CellInfo.create(record, nanotime)); } return response; } /** * Convert SetupDataCallResult defined in 1.0 or 1.4/types.hal into DataCallResponse * @param dcResult setup data call result * @return converted DataCallResponse object */ @VisibleForTesting public static DataCallResponse convertDataCallResult(Object dcResult) { if (dcResult == null) return null; int cause, suggestedRetryTime, cid, active, mtu; String ifname; int protocolType; String[] addresses = null; String[] dnses = null; String[] gateways = null; String[] pcscfs = null; if (dcResult instanceof android.hardware.radio.V1_0.SetupDataCallResult) { final android.hardware.radio.V1_0.SetupDataCallResult result = (android.hardware.radio.V1_0.SetupDataCallResult) dcResult; cause = result.status; suggestedRetryTime = result.suggestedRetryTime; cid = result.cid; active = result.active; protocolType = ApnSetting.getProtocolIntFromString(result.type); ifname = result.ifname; if (!TextUtils.isEmpty(result.addresses)) { addresses = result.addresses.split("\\s+"); } if (!TextUtils.isEmpty(result.dnses)) { dnses = result.dnses.split("\\s+"); } if (!TextUtils.isEmpty(result.gateways)) { gateways = result.gateways.split("\\s+"); } if (!TextUtils.isEmpty(result.pcscf)) { pcscfs = result.pcscf.split("\\s+"); } mtu = result.mtu; } else if (dcResult instanceof android.hardware.radio.V1_4.SetupDataCallResult) { final android.hardware.radio.V1_4.SetupDataCallResult result = (android.hardware.radio.V1_4.SetupDataCallResult) dcResult; cause = result.cause; suggestedRetryTime = result.suggestedRetryTime; cid = result.cid; active = result.active; protocolType = result.type; ifname = result.ifname; addresses = result.addresses.stream().toArray(String[]::new); dnses = result.dnses.stream().toArray(String[]::new); gateways = result.gateways.stream().toArray(String[]::new); pcscfs = result.pcscf.stream().toArray(String[]::new); mtu = result.mtu; } else { Rlog.e(RILJ_LOG_TAG, "Unsupported SetupDataCallResult " + dcResult); return null; } // Process address List laList = new ArrayList<>(); if (addresses != null) { for (String address : addresses) { address = address.trim(); if (address.isEmpty()) continue; try { LinkAddress la; // Check if the address contains prefix length. If yes, LinkAddress // can parse that. if (address.split("/").length == 2) { la = new LinkAddress(address); } else { InetAddress ia = NetworkUtils.numericToInetAddress(address); la = new LinkAddress(ia, (ia instanceof Inet4Address) ? 32 : 128); } laList.add(la); } catch (IllegalArgumentException e) { Rlog.e(RILJ_LOG_TAG, "Unknown address: " + address, e); } } } // Process dns List dnsList = new ArrayList<>(); if (dnses != null) { for (String dns : dnses) { dns = dns.trim(); InetAddress ia; try { ia = NetworkUtils.numericToInetAddress(dns); dnsList.add(ia); } catch (IllegalArgumentException e) { Rlog.e(RILJ_LOG_TAG, "Unknown dns: " + dns, e); } } } // Process gateway List gatewayList = new ArrayList<>(); if (gateways != null) { for (String gateway : gateways) { gateway = gateway.trim(); InetAddress ia; try { ia = NetworkUtils.numericToInetAddress(gateway); gatewayList.add(ia); } catch (IllegalArgumentException e) { Rlog.e(RILJ_LOG_TAG, "Unknown gateway: " + gateway, e); } } } // Process gateway List pcscfList = new ArrayList<>(); if (pcscfs != null) { for (String pcscf : pcscfs) { pcscf = pcscf.trim(); InetAddress ia; try { ia = NetworkUtils.numericToInetAddress(pcscf); pcscfList.add(ia); } catch (IllegalArgumentException e) { Rlog.e(RILJ_LOG_TAG, "Unknown pcscf: " + pcscf, e); } } } return new DataCallResponse(cause, suggestedRetryTime, cid, active, protocolType, ifname, laList, dnsList, gatewayList, pcscfList, mtu); } /** * Convert SetupDataCallResult defined in 1.0 or 1.4/types.hal into DataCallResponse * @param dataCallResultList List of SetupDataCallResult defined in 1.0 or 1.4/types.hal * @return List of converted DataCallResponse object */ @VisibleForTesting public static ArrayList convertDataCallResultList( List dataCallResultList) { ArrayList response = new ArrayList(dataCallResultList.size()); for (Object obj : dataCallResultList) { response.add(convertDataCallResult(obj)); } return response; } /** * Get the HAL version. * * @return the current HalVersion */ public HalVersion getHalVersion() { return mRadioVersion; } }