[IRadioConfig] Applying new IRadioConfig AIDL

Bug: 198332054
Test: m -j
Change-Id: Ifc4a86e23a9f0942790f88d208e573e06502a6fe
Merged-In: Ifc4a86e23a9f0942790f88d208e573e06502a6fe
(cherry picked from commit 70a3726d029fe0f0f952460c779f7f8ade93071b)
diff --git a/Android.bp b/Android.bp
index bf70772..7439bea 100644
--- a/Android.bp
+++ b/Android.bp
@@ -105,6 +105,7 @@
         "android.hardware.radio-V1.4-java",
         "android.hardware.radio-V1.5-java",
         "android.hardware.radio-V1.6-java",
+        "android.hardware.radio.config-V1-java",
         "android.hardware.radio.data-V1-java",
         "android.hardware.radio.messaging-V1-java",
         "android.hardware.radio.modem-V1-java",
diff --git a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
index d92f96d..4d5ae40 100644
--- a/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
+++ b/src/java/com/android/internal/telephony/PhoneConfigurationManager.java
@@ -336,7 +336,7 @@
             log("switchMultiSimConfig: sending the request for switching");
             Message callback = Message.obtain(
                     mHandler, EVENT_SWITCH_DSDS_CONFIG_DONE, numOfSims, 0 /**dummy arg*/);
-            mRadioConfig.setModemsConfig(numOfSims, callback);
+            mRadioConfig.setNumOfLiveModems(numOfSims, callback);
         } else {
             log("switchMultiSimConfig: No need to switch. getNumOfActiveSims is already "
                     + numOfSims);
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 2f7a482..5aa91f7 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -183,6 +183,9 @@
     /** @hide */
     public static final HalVersion RADIO_HAL_VERSION_1_6 = new HalVersion(1, 6);
 
+    /** @hide */
+    public static final HalVersion RADIO_HAL_VERSION_2_0 = new HalVersion(2, 0);
+
     // IRadio version
     private HalVersion mRadioVersion = RADIO_HAL_VERSION_UNKNOWN;
 
diff --git a/src/java/com/android/internal/telephony/RILUtils.java b/src/java/com/android/internal/telephony/RILUtils.java
index deb4c57..35c6eb1 100644
--- a/src/java/com/android/internal/telephony/RILUtils.java
+++ b/src/java/com/android/internal/telephony/RILUtils.java
@@ -16,6 +16,14 @@
 
 package com.android.internal.telephony;
 
+import static android.telephony.TelephonyManager.CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE;
+import static android.telephony.TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED;
+import static android.telephony.TelephonyManager.CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE;
+import static android.telephony.TelephonyManager.CAPABILITY_SIM_PHONEBOOK_IN_MODEM;
+import static android.telephony.TelephonyManager.CAPABILITY_SLICING_CONFIG_SUPPORTED;
+import static android.telephony.TelephonyManager.CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING;
+import static android.telephony.TelephonyManager.CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK;
+
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_ACKNOWLEDGE_INCOMING_GSM_SMS_WITH_PDU;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_ALLOCATE_PDU_SESSION_ID;
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_ALLOW_DATA;
@@ -286,6 +294,8 @@
 import android.telephony.CellSignalStrengthWcdma;
 import android.telephony.ClosedSubscriberGroupInfo;
 import android.telephony.LinkCapacityEstimate;
+import android.telephony.ModemInfo;
+import android.telephony.PhoneCapability;
 import android.telephony.PhoneNumberUtils;
 import android.telephony.PhysicalChannelConfig;
 import android.telephony.RadioAccessSpecifier;
@@ -322,6 +332,7 @@
 import com.android.internal.telephony.uicc.AdnCapacity;
 import com.android.internal.telephony.uicc.IccCardApplicationStatus;
 import com.android.internal.telephony.uicc.IccCardStatus;
+import com.android.internal.telephony.uicc.IccSlotStatus;
 import com.android.internal.telephony.uicc.IccUtils;
 import com.android.internal.telephony.uicc.SimPhonebookRecord;
 import com.android.telephony.Rlog;
@@ -334,7 +345,9 @@
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.List;
+import java.util.Set;
 import java.util.stream.Collectors;
 
 /**
@@ -3741,6 +3754,105 @@
                 .replace(PhoneNumberUtils.WILD, '?');
     }
 
+    /**
+     * Convert array of SimSlotStatus to IccSlotStatus
+     * @param o object that represents array/list of SimSlotStatus
+     * @return ArrayList of IccSlotStatus
+     */
+    public static ArrayList<IccSlotStatus> convertHalSlotStatus(Object o) {
+        ArrayList<IccSlotStatus> response = new ArrayList<>();
+        if (o instanceof android.hardware.radio.config.SimSlotStatus[]) {
+            final android.hardware.radio.config.SimSlotStatus[] halSlotStatusArray =
+                    (android.hardware.radio.config.SimSlotStatus[]) o;
+            for (android.hardware.radio.config.SimSlotStatus slotStatus : halSlotStatusArray) {
+                IccSlotStatus iccSlotStatus = new IccSlotStatus();
+                iccSlotStatus.setCardState(slotStatus.cardState);
+                iccSlotStatus.setSlotState(slotStatus.portInfo[0].portState);
+                iccSlotStatus.logicalSlotIndex = slotStatus.portInfo[0].logicalSlotId;
+                iccSlotStatus.atr = slotStatus.atr;
+                iccSlotStatus.iccid = slotStatus.portInfo[0].iccId;
+                iccSlotStatus.eid = slotStatus.eid;
+                response.add(iccSlotStatus);
+            }
+        } else if (o instanceof ArrayList) {
+            final ArrayList<android.hardware.radio.config.V1_0.SimSlotStatus> halSlotStatusArray =
+                    (ArrayList<android.hardware.radio.config.V1_0.SimSlotStatus>) o;
+            for (android.hardware.radio.config.V1_0.SimSlotStatus slotStatus : halSlotStatusArray) {
+                IccSlotStatus iccSlotStatus = new IccSlotStatus();
+                iccSlotStatus.setCardState(slotStatus.cardState);
+                iccSlotStatus.setSlotState(slotStatus.slotState);
+                iccSlotStatus.logicalSlotIndex = slotStatus.logicalSlotId;
+                iccSlotStatus.atr = slotStatus.atr;
+                iccSlotStatus.iccid = slotStatus.iccid;
+                response.add(iccSlotStatus);
+            }
+        } else if (o instanceof ArrayList) {
+            final ArrayList<android.hardware.radio.config.V1_2.SimSlotStatus> halSlotStatusArray =
+                    (ArrayList<android.hardware.radio.config.V1_2.SimSlotStatus>) o;
+            for (android.hardware.radio.config.V1_2.SimSlotStatus slotStatus : halSlotStatusArray) {
+                IccSlotStatus iccSlotStatus = new IccSlotStatus();
+                iccSlotStatus.setCardState(slotStatus.base.cardState);
+                iccSlotStatus.setSlotState(slotStatus.base.slotState);
+                iccSlotStatus.logicalSlotIndex = slotStatus.base.logicalSlotId;
+                iccSlotStatus.atr = slotStatus.base.atr;
+                iccSlotStatus.iccid = slotStatus.base.iccid;
+                iccSlotStatus.eid = slotStatus.eid;
+                response.add(iccSlotStatus);
+            }
+        }
+        return response;
+    }
+
+    /**
+     * Convert int[] list to SlotPortMapping[]
+     * @param list int[] of slots mapping
+     * @return SlotPortMapping[] of slots mapping
+     */
+    public static android.hardware.radio.config.SlotPortMapping[] convertSimSlotsMapping(
+            int[] list) {
+        android.hardware.radio.config.SlotPortMapping[] res =
+                new android.hardware.radio.config.SlotPortMapping[list.length];
+        for (int i : list) {
+            res[i] = new android.hardware.radio.config.SlotPortMapping();
+            res[i].portId = i;
+        }
+        return res;
+    }
+
+
+    /**
+     * Convert PhoneCapability to telephony PhoneCapability.
+     * @param deviceNrCapabilities device's nr capability array
+     * @param o PhoneCapability to convert
+     * @return converted PhoneCapability
+     */
+    public static PhoneCapability convertHalPhoneCapability(int[] deviceNrCapabilities, Object o) {
+        int maxActiveVoiceCalls = 0;
+        int maxActiveData = 0;
+        boolean validationBeforeSwitchSupported = false;
+        List<ModemInfo> logicalModemList = new ArrayList<>();
+        if (o instanceof android.hardware.radio.config.PhoneCapability) {
+            final android.hardware.radio.config.PhoneCapability phoneCapability =
+                    (android.hardware.radio.config.PhoneCapability) o;
+            maxActiveData = phoneCapability.maxActiveData;
+            validationBeforeSwitchSupported = phoneCapability.isInternetLingeringSupported;
+            for (int modemId : phoneCapability.logicalModemIds) {
+                logicalModemList.add(new ModemInfo(modemId));
+            }
+        } else if (o instanceof android.hardware.radio.config.V1_1.PhoneCapability) {
+            final android.hardware.radio.config.V1_1.PhoneCapability phoneCapability =
+                    (android.hardware.radio.config.V1_1.PhoneCapability) o;
+            maxActiveData = phoneCapability.maxActiveData;
+            validationBeforeSwitchSupported = phoneCapability.isInternetLingeringSupported;
+            for (android.hardware.radio.config.V1_1.ModemInfo modemInfo :
+                    phoneCapability.logicalModemList) {
+                logicalModemList.add(new ModemInfo(modemInfo.modemId));
+            }
+        }
+        return new PhoneCapability(maxActiveVoiceCalls, maxActiveData, logicalModemList,
+                validationBeforeSwitchSupported, deviceNrCapabilities);
+    }
+
     /** Append the data to the end of an ArrayList */
     public static void appendPrimitiveArrayToArrayList(byte[] src, ArrayList<Byte> dst) {
         for (byte b : src) {
@@ -4144,7 +4256,8 @@
                 return "GET_ALLOWED_NETWORK_TYPES_BITMAP";
             case RIL_REQUEST_GET_SLICING_CONFIG:
                 return "GET_SLICING_CONFIG";
-            default: return "<unknown request>";
+            default:
+                return "<unknown request " + request + ">";
         }
     }
 
@@ -4279,4 +4392,51 @@
                 return "<unknown response>";
         }
     }
+
+    /**
+     * Create capabilities based off of the radio hal version and feature set configurations.
+     * @param radioHalVersion radio hal version
+     * @param modemReducedFeatureSet1 reduced feature set
+     * @return set of capabilities
+     */
+    @VisibleForTesting
+    public static Set<String> getCaps(HalVersion radioHalVersion, boolean modemReducedFeatureSet1) {
+        final Set<String> caps = new HashSet<>();
+
+        if (radioHalVersion.equals(RIL.RADIO_HAL_VERSION_UNKNOWN)) {
+            // If the Radio HAL is UNKNOWN, no capabilities will present themselves.
+            loge("Radio Hal Version is UNKNOWN!");
+        }
+
+        logd("Radio Hal Version = " + radioHalVersion.toString());
+        if (radioHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_6)) {
+            caps.add(CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK);
+            logd("CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK");
+
+            if (!modemReducedFeatureSet1) {
+                caps.add(CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE);
+                logd("CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE");
+                caps.add(CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE);
+                logd("CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE");
+                caps.add(CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING);
+                logd("CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING");
+                caps.add(CAPABILITY_SLICING_CONFIG_SUPPORTED);
+                logd("CAPABILITY_SLICING_CONFIG_SUPPORTED");
+                caps.add(CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
+                logd("CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED");
+            } else {
+                caps.add(CAPABILITY_SIM_PHONEBOOK_IN_MODEM);
+                logd("CAPABILITY_SIM_PHONEBOOK_IN_MODEM");
+            }
+        }
+        return caps;
+    }
+
+    private static void logd(String log) {
+        Rlog.d("RILUtils", log);
+    }
+
+    private static void loge(String log) {
+        Rlog.e("RILUtils", log);
+    }
 }
diff --git a/src/java/com/android/internal/telephony/RadioConfig.java b/src/java/com/android/internal/telephony/RadioConfig.java
index 32b24fe..d9a2608 100644
--- a/src/java/com/android/internal/telephony/RadioConfig.java
+++ b/src/java/com/android/internal/telephony/RadioConfig.java
@@ -29,21 +29,18 @@
 import static com.android.internal.telephony.RILConstants.RIL_REQUEST_SWITCH_DUAL_SIM_CONFIG;
 
 import android.content.Context;
-import android.hardware.radio.V1_0.RadioResponseInfo;
-import android.hardware.radio.V1_0.RadioResponseType;
-import android.hardware.radio.config.V1_0.IRadioConfig;
-import android.hardware.radio.config.V1_1.ModemsConfig;
 import android.os.AsyncResult;
 import android.os.Handler;
 import android.os.HwBinder;
+import android.os.IBinder;
 import android.os.Message;
 import android.os.Registrant;
 import android.os.RemoteException;
+import android.os.ServiceManager;
 import android.os.WorkSource;
 import android.telephony.TelephonyManager;
 import android.util.SparseArray;
 
-import com.android.internal.telephony.uicc.IccSlotStatus;
 import com.android.telephony.Rlog;
 
 import java.util.ArrayList;
@@ -59,35 +56,33 @@
     private static final String TAG = "RadioConfig";
     private static final boolean DBG = true;
     private static final boolean VDBG = false;   //STOPSHIP if true
-
     private static final int EVENT_SERVICE_DEAD = 1;
+    private static final Object sLock = new Object();
 
-    private static final HalVersion RADIO_CONFIG_HAL_VERSION_UNKNOWN = new HalVersion(-1, -1);
-
-    private static final HalVersion RADIO_CONFIG_HAL_VERSION_1_0 = new HalVersion(1, 0);
-
-    private static final HalVersion RADIO_CONFIG_HAL_VERSION_1_1 = new HalVersion(1, 1);
-
-    private static final HalVersion RADIO_CONFIG_HAL_VERSION_1_3 = new HalVersion(1, 3);
+    static final HalVersion RADIO_CONFIG_HAL_VERSION_UNKNOWN = new HalVersion(-1, -1);
+    static final HalVersion RADIO_CONFIG_HAL_VERSION_1_0 = new HalVersion(1, 0);
+    static final HalVersion RADIO_CONFIG_HAL_VERSION_1_1 = new HalVersion(1, 1);
+    static final HalVersion RADIO_CONFIG_HAL_VERSION_1_3 = new HalVersion(1, 3);
+    static final HalVersion RADIO_CONFIG_HAL_VERSION_2_0 = new HalVersion(2, 0);
 
     private final boolean mIsMobileNetworkSupported;
-    private volatile IRadioConfig mRadioConfigProxy = null;
-    // IRadioConfig version
-    private HalVersion mRadioConfigVersion = RADIO_CONFIG_HAL_VERSION_UNKNOWN;
-    private final ServiceDeathRecipient mServiceDeathRecipient;
-    private final AtomicLong mRadioConfigProxyCookie = new AtomicLong(0);
+    private final HwServiceDeathRecipient mHwServiceDeathRecipient;
+    private final BinderServiceDeathRecipient mBinderServiceDeathRecipient;
     private final RadioConfigResponse mRadioConfigResponse;
     private final RadioConfigIndication mRadioConfigIndication;
-    private final SparseArray<RILRequest> mRequestList = new SparseArray<RILRequest>();
+    private final SparseArray<RILRequest> mRequestList = new SparseArray<>();
     /* default work source which will blame phone process */
     private final WorkSource mDefaultWorkSource;
     private final int[] mDeviceNrCapabilities;
+    private final AtomicLong mRadioConfigProxyCookie = new AtomicLong(0);
+
     private static RadioConfig sRadioConfig;
-    private static final Object sLock = new Object();
+
+    private final RadioConfigProxy mRadioConfigProxy = new RadioConfigProxy();
 
     protected Registrant mSimSlotStatusRegistrant;
 
-    final class ServiceDeathRecipient implements HwBinder.DeathRecipient {
+    final class HwServiceDeathRecipient implements HwBinder.DeathRecipient {
         @Override
         public void serviceDied(long cookie) {
             // Deal with service going away
@@ -96,23 +91,201 @@
         }
     }
 
+    final class BinderServiceDeathRecipient implements IBinder.DeathRecipient {
+        private IBinder mBinder;
+
+        public void linkToDeath(IBinder service) throws RemoteException {
+            if (service != null) {
+                mBinder = service;
+                mBinder.linkToDeath(this, (int) mRadioConfigProxyCookie.incrementAndGet());
+            }
+        }
+
+        public synchronized void unlinkToDeath() {
+            if (mBinder != null) {
+                mBinder.unlinkToDeath(this, 0);
+                mBinder = null;
+            }
+        }
+
+        @Override
+        public void binderDied() {
+            logd("RadioConfigService has died.");
+            unlinkToDeath();
+        }
+
+    }
+
+    private final class RadioConfigProxy {
+        private boolean mIsAidl;
+
+        private volatile android.hardware.radio.config.V1_0.IRadioConfig mRadioConfigProxyV1 = null;
+        private volatile android.hardware.radio.config.IRadioConfig mRadioConfigProxyV2 = null;
+        private HalVersion mHalVersion = RADIO_CONFIG_HAL_VERSION_UNKNOWN;
+
+        public boolean isV2OrHigher() {
+            return mIsAidl;
+        }
+
+        public void setV1(
+                HalVersion halVersion, android.hardware.radio.config.V1_0.IRadioConfig config) {
+            mHalVersion = halVersion;
+            mRadioConfigProxyV1 = config;
+            mIsAidl = false;
+        }
+
+        public android.hardware.radio.config.V1_0.IRadioConfig getV1() {
+            return mRadioConfigProxyV1;
+        }
+
+        public void setV2(
+                HalVersion halVersion, android.hardware.radio.config.IRadioConfig config) {
+            mHalVersion = halVersion;
+            mRadioConfigProxyV2 = config;
+            mIsAidl = true;
+        }
+
+        public android.hardware.radio.config.IRadioConfig getV2() {
+            return mRadioConfigProxyV2;
+        }
+
+        public void clear() {
+            mHalVersion = RADIO_CONFIG_HAL_VERSION_UNKNOWN;
+            mRadioConfigProxyV1 = null;
+            mRadioConfigProxyV2 = null;
+        }
+
+        public boolean isEmpty() {
+            return mRadioConfigProxyV1 == null && mRadioConfigProxyV2 == null;
+        }
+
+        public void linkToDeath() {
+            if (isEmpty()) return;
+
+            if (isV2OrHigher()) {
+                try {
+                    // Link to death
+                    mBinderServiceDeathRecipient.linkToDeath(mRadioConfigProxyV2.asBinder());
+
+                    // Set response. If fails, set proxy to null and return.
+                    mRadioConfigProxyV2.setResponseFunctions(
+                            mRadioConfigResponse.getV2(), mRadioConfigIndication.getV2());
+                } catch (RemoteException | RuntimeException e) {
+                    mRadioConfigProxyV2 = null;
+                    loge("getRadioConfigProxyV2: RadioConfigProxy setResponseFunctions: " + e);
+                }
+            } else {
+                try {
+                    // Link to death recipient and set response.
+                    // If fails, set proxy to null and return.
+                    mRadioConfigProxyV1.linkToDeath(
+                            mHwServiceDeathRecipient, mRadioConfigProxyCookie.incrementAndGet());
+                    mRadioConfigProxyV1.setResponseFunctions(
+                            mRadioConfigResponse.getV1(), mRadioConfigIndication.getV1());
+                } catch (RemoteException | RuntimeException e) {
+                    mRadioConfigProxyV1 = null;
+                    loge("getRadioConfigProxyV1: RadioConfigProxy setResponseFunctions: " + e);
+                }
+            }
+        }
+
+        public void getPhoneCapability(int serial) throws RemoteException {
+            if (isEmpty()) return;
+            if (mHalVersion.less(RADIO_CONFIG_HAL_VERSION_1_1)) return;
+
+            if (isV2OrHigher()) {
+                mRadioConfigProxyV2.getPhoneCapability(serial);
+            } else {
+                ((android.hardware.radio.config.V1_1.IRadioConfig) mRadioConfigProxyV1)
+                        .getPhoneCapability(serial);
+            }
+        }
+
+        public void getSimSlotsStatus(int serial) throws RemoteException {
+            if (isEmpty()) return;
+
+            if (isV2OrHigher()) {
+                mRadioConfigProxyV2.getSimSlotsStatus(serial);
+            } else {
+                mRadioConfigProxyV1.getSimSlotsStatus(serial);
+            }
+        }
+
+        public void setPreferredDataModem(int serial, byte modemId) throws RemoteException {
+            if (isEmpty()) return;
+            if (mHalVersion.less(RADIO_CONFIG_HAL_VERSION_1_1)) return;
+
+            if (isV2OrHigher()) {
+                mRadioConfigProxyV2.setPreferredDataModem(serial, modemId);
+            } else {
+                ((android.hardware.radio.config.V1_1.IRadioConfig) mRadioConfigProxyV1)
+                        .setPreferredDataModem(serial, modemId);
+            }
+        }
+
+        public void setSimSlotsMapping(int serial, int[] list)
+                throws RemoteException {
+            if (isEmpty()) return;
+
+            if (isV2OrHigher()) {
+                mRadioConfigProxyV2.setSimSlotsMapping(serial,
+                        RILUtils.convertSimSlotsMapping(list));
+            } else {
+                mRadioConfigProxyV1.setSimSlotsMapping(serial,
+                        RILUtils.primitiveArrayToArrayList(list));
+            }
+        }
+
+        public void setModemsConfig(
+                int serial,
+                android.hardware.radio.config.V1_1.ModemsConfig modemsConfig)
+                throws RemoteException {
+            if (isEmpty()) return;
+            if (mHalVersion.less(RADIO_CONFIG_HAL_VERSION_1_1)) return;
+            if (mHalVersion.greaterOrEqual(RADIO_CONFIG_HAL_VERSION_2_0)) return;
+
+            ((android.hardware.radio.config.V1_1.IRadioConfig) mRadioConfigProxyV1)
+                    .setModemsConfig(serial, modemsConfig);
+        }
+
+        public void setNumOfLiveModems(int serial, byte numOfLiveModems) throws RemoteException {
+            if (isEmpty()) return;
+            if (mHalVersion.less(RADIO_CONFIG_HAL_VERSION_2_0)) return;
+
+            mRadioConfigProxyV2.setNumOfLiveModems(serial, numOfLiveModems);
+        }
+
+        public HalVersion getVersion() {
+            return mHalVersion;
+        }
+
+        public void getHalDeviceCapabilities(int serial) throws RemoteException {
+            if (isEmpty()) return;
+            if (mHalVersion.less(RADIO_CONFIG_HAL_VERSION_1_3)) return;
+
+            if (isV2OrHigher()) {
+                mRadioConfigProxyV2.getHalDeviceCapabilities(serial);
+            } else {
+                ((android.hardware.radio.config.V1_3.IRadioConfig) mRadioConfigProxyV1)
+                        .getHalDeviceCapabilities(serial);
+            }
+        }
+    }
+
     private boolean isMobileDataCapable(Context context) {
         final TelephonyManager tm = context.getSystemService(TelephonyManager.class);
-        if (tm == null) {
-            return false;
-        }
-        return tm.isDataCapable();
+        return tm != null && tm.isDataCapable();
     }
 
     private RadioConfig(Context context, HalVersion radioHalVersion) {
         mIsMobileNetworkSupported = isMobileDataCapable(context);
 
         mRadioConfigResponse = new RadioConfigResponse(this, radioHalVersion);
-        mRadioConfigIndication = new RadioConfigIndication(this);
-        mServiceDeathRecipient = new ServiceDeathRecipient();
-
-        mDefaultWorkSource = new WorkSource(context.getApplicationInfo().uid,
-                context.getPackageName());
+        mRadioConfigIndication = new RadioConfigIndication(this, radioHalVersion);
+        mHwServiceDeathRecipient = new HwServiceDeathRecipient();
+        mBinderServiceDeathRecipient = new BinderServiceDeathRecipient();
+        mDefaultWorkSource = new WorkSource(
+                context.getApplicationInfo().uid, context.getPackageName());
 
         boolean is5gStandalone = context.getResources().getBoolean(
                 com.android.internal.R.bool.config_telephony5gStandalone);
@@ -161,14 +334,12 @@
 
     @Override
     public void handleMessage(Message message) {
-        switch (message.what) {
-            case EVENT_SERVICE_DEAD:
-                logd("handleMessage: EVENT_SERVICE_DEAD cookie = " + message.obj
-                        + " mRadioConfigProxyCookie = " + mRadioConfigProxyCookie.get());
-                if ((long) message.obj == mRadioConfigProxyCookie.get()) {
-                    resetProxyAndRequestList("EVENT_SERVICE_DEAD", null);
-                }
-                break;
+        if (message.what == EVENT_SERVICE_DEAD) {
+            logd("handleMessage: EVENT_SERVICE_DEAD cookie = " + message.obj
+                    + " mRadioConfigProxyCookie = " + mRadioConfigProxyCookie.get());
+            if ((long) message.obj == mRadioConfigProxyCookie.get()) {
+                resetProxyAndRequestList("EVENT_SERVICE_DEAD", null);
+            }
         }
     }
 
@@ -188,7 +359,7 @@
             for (int i = 0; i < count; i++) {
                 rr = mRequestList.valueAt(i);
                 if (DBG && loggable) {
-                    logd(i + ": [" + rr.mSerial + "] " + requestToString(rr.mRequest));
+                    logd(i + ": [" + rr.mSerial + "] " + RILUtils.requestToString(rr.mRequest));
                 }
                 rr.onError(error, null);
                 rr.release();
@@ -199,7 +370,7 @@
 
     private void resetProxyAndRequestList(String caller, Exception e) {
         loge(caller + ": " + e);
-        mRadioConfigProxy = null;
+        mRadioConfigProxy.clear();
 
         // increment the cookie so that death notification can be ignored
         mRadioConfigProxyCookie.incrementAndGet();
@@ -211,8 +382,13 @@
         getRadioConfigProxy(null);
     }
 
-    /** Returns a {@link IRadioConfig} instance or null if the service is not available. */
-    public IRadioConfig getRadioConfigProxy(Message result) {
+    /**
+     * Returns a holder that has either:
+     * - getV1() -> {@link android.hardware.radio.config.V1_0.IRadioConfig}
+     * - getV2() -> {@link android.hardware.radio.config.IRadioConfig}
+     * that returns corresponding hal implementation
+     */
+    public RadioConfigProxy getRadioConfigProxy(Message result) {
         if (!mIsMobileNetworkSupported) {
             if (VDBG) logd("getRadioConfigProxy: Not calling getService(): wifi-only");
             if (result != null) {
@@ -223,69 +399,65 @@
             return null;
         }
 
-        if (mRadioConfigProxy != null) {
+        if (!mRadioConfigProxy.isEmpty()) {
             return mRadioConfigProxy;
         }
 
         updateRadioConfigProxy();
+        mRadioConfigProxy.linkToDeath();
 
-        if (mRadioConfigProxy == null) {
-            if (result != null) {
-                AsyncResult.forMessage(result, null,
-                        CommandException.fromRilErrno(RADIO_NOT_AVAILABLE));
-                result.sendToTarget();
-            }
+        if (mRadioConfigProxy.isEmpty() && result != null) {
+            AsyncResult.forMessage(
+                    result, null, CommandException.fromRilErrno(RADIO_NOT_AVAILABLE));
+            result.sendToTarget();
         }
 
         return mRadioConfigProxy;
     }
 
     private void updateRadioConfigProxy() {
-        try {
+        // Try to get service from different versions.
 
-            // Try to get service from different versions.
-            try {
-                mRadioConfigProxy = android.hardware.radio.config.V1_3.IRadioConfig.getService(
-                        true);
-                mRadioConfigVersion = RADIO_CONFIG_HAL_VERSION_1_3;
-            } catch (NoSuchElementException e) {
-            }
+        // Try to get AIDL variant first
+        IBinder service = ServiceManager.waitForDeclaredService(
+                android.hardware.radio.config.IRadioConfig.DESCRIPTOR + "/default");
 
-
-            if (mRadioConfigProxy == null) {
-                // Try to get service from different versions.
-                try {
-                    mRadioConfigProxy = android.hardware.radio.config.V1_1.IRadioConfig.getService(
-                            true);
-                    mRadioConfigVersion = RADIO_CONFIG_HAL_VERSION_1_1;
-                } catch (NoSuchElementException e) {
-                }
-            }
-
-            if (mRadioConfigProxy == null) {
-                try {
-                    mRadioConfigProxy = android.hardware.radio.config.V1_0
-                            .IRadioConfig.getService(true);
-                    mRadioConfigVersion = RADIO_CONFIG_HAL_VERSION_1_0;
-                } catch (NoSuchElementException e) {
-                }
-            }
-
-            if (mRadioConfigProxy == null) {
-                loge("getRadioConfigProxy: mRadioConfigProxy == null");
-                return;
-            }
-
-            // Link to death recipient and set response. If fails, set proxy to null and return.
-            mRadioConfigProxy.linkToDeath(mServiceDeathRecipient,
-                    mRadioConfigProxyCookie.incrementAndGet());
-            mRadioConfigProxy.setResponseFunctions(mRadioConfigResponse,
-                    mRadioConfigIndication);
-        } catch (RemoteException | RuntimeException e) {
-            mRadioConfigProxy = null;
-            loge("getRadioConfigProxy: RadioConfigProxy setResponseFunctions: " + e);
+        if (service != null) {
+            mRadioConfigProxy.setV2(
+                    RADIO_CONFIG_HAL_VERSION_2_0,
+                    android.hardware.radio.config.IRadioConfig.Stub.asInterface(service));
             return;
         }
+
+        // Now HIDL 1.3
+        try {
+            mRadioConfigProxy.setV1(
+                    RADIO_CONFIG_HAL_VERSION_1_3,
+                    android.hardware.radio.config.V1_3.IRadioConfig.getService(true));
+            return;
+        } catch (NoSuchElementException | RemoteException ignored) {
+        }
+
+        // HIDL 1.1
+        try {
+            mRadioConfigProxy.setV1(
+                    RADIO_CONFIG_HAL_VERSION_1_1,
+                    android.hardware.radio.config.V1_1.IRadioConfig.getService(true));
+            return;
+        } catch (NoSuchElementException | RemoteException ignored) {
+        }
+
+        // HIDL 1.0
+        try {
+            mRadioConfigProxy.setV1(
+                    RADIO_CONFIG_HAL_VERSION_1_0,
+                    android.hardware.radio.config.V1_0.IRadioConfig.getService(true));
+            return;
+        } catch (NoSuchElementException | RemoteException ignored) {
+        }
+
+        // Couldn't bind to anything!
+        loge("getRadioConfigProxy: mRadioConfigProxyHolder == null");
     }
 
     private RILRequest obtainRequest(int request, Message result, WorkSource workSource) {
@@ -314,12 +486,36 @@
      * @param responseInfo RadioResponseInfo received in response callback
      * @return RILRequest corresponding to the response
      */
-    public RILRequest processResponse(RadioResponseInfo responseInfo) {
+    public RILRequest processResponse(android.hardware.radio.RadioResponseInfo responseInfo) {
         int serial = responseInfo.serial;
         int error = responseInfo.error;
         int type = responseInfo.type;
 
-        if (type != RadioResponseType.SOLICITED) {
+        if (type != android.hardware.radio.RadioResponseType.SOLICITED) {
+            loge("processResponse: Unexpected response type " + type);
+        }
+
+        RILRequest rr = findAndRemoveRequestFromList(serial);
+        if (rr == null) {
+            loge("processResponse: Unexpected response! serial: " + serial + " error: " + error);
+            return null;
+        }
+
+        return rr;
+    }
+
+    /**
+     * This is a helper function to be called when a RadioConfigResponse callback is called.
+     * It 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
+     */
+    public RILRequest processResponse(android.hardware.radio.V1_0.RadioResponseInfo responseInfo) {
+        int serial = responseInfo.serial;
+        int error = responseInfo.error;
+        int type = responseInfo.type;
+
+        if (type != android.hardware.radio.RadioResponseType.SOLICITED) {
             loge("processResponse: Unexpected response type " + type);
         }
 
@@ -343,8 +539,7 @@
         int serial = responseInfo.serial;
         int error = responseInfo.error;
         int type = responseInfo.type;
-
-        if (type != RadioResponseType.SOLICITED) {
+        if (type != android.hardware.radio.RadioResponseType.SOLICITED) {
             loge("processResponse: Unexpected response type " + type);
         }
 
@@ -361,16 +556,17 @@
      * Wrapper function for IRadioConfig.getSimSlotsStatus().
      */
     public void getSimSlotsStatus(Message result) {
-        IRadioConfig radioConfigProxy = getRadioConfigProxy(result);
-        if (radioConfigProxy != null) {
+        RadioConfigProxy proxy = getRadioConfigProxy(result);
+
+        if (!proxy.isEmpty()) {
             RILRequest rr = obtainRequest(RIL_REQUEST_GET_SLOT_STATUS, result, mDefaultWorkSource);
 
             if (DBG) {
-                logd(rr.serialString() + "> " + requestToString(rr.mRequest));
+                logd(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
             }
 
             try {
-                radioConfigProxy.getSimSlotsStatus(rr.mSerial);
+                proxy.getSimSlotsStatus(rr.mSerial);
             } catch (RemoteException | RuntimeException e) {
                 resetProxyAndRequestList("getSimSlotsStatus", e);
             }
@@ -381,6 +577,7 @@
      * Wrapper function for IRadioConfig.setPreferredDataModem(int modemId).
      */
     public void setPreferredDataModem(int modemId, Message result) {
+        RadioConfigProxy proxy = getRadioConfigProxy(null);
         if (!isSetPreferredDataCommandSupported()) {
             if (result != null) {
                 AsyncResult.forMessage(result, null,
@@ -392,14 +589,12 @@
 
         RILRequest rr = obtainRequest(RIL_REQUEST_SET_PREFERRED_DATA_MODEM,
                 result, mDefaultWorkSource);
-
         if (DBG) {
-            logd(rr.serialString() + "> " + requestToString(rr.mRequest));
+            logd(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
         }
 
         try {
-            ((android.hardware.radio.config.V1_1.IRadioConfig) mRadioConfigProxy)
-                    .setPreferredDataModem(rr.mSerial, (byte) modemId);
+            proxy.setPreferredDataModem(rr.mSerial, (byte) modemId);
         } catch (RemoteException | RuntimeException e) {
             resetProxyAndRequestList("setPreferredDataModem", e);
         }
@@ -409,8 +604,8 @@
      * Wrapper function for IRadioConfig.getPhoneCapability().
      */
     public void getPhoneCapability(Message result) {
-        IRadioConfig radioConfigProxy = getRadioConfigProxy(null);
-        if (radioConfigProxy == null || mRadioConfigVersion.less(RADIO_CONFIG_HAL_VERSION_1_1)) {
+        RadioConfigProxy proxy = getRadioConfigProxy(null);
+        if (proxy.isEmpty() || proxy.getVersion().less(RADIO_CONFIG_HAL_VERSION_1_1)) {
             if (result != null) {
                 AsyncResult.forMessage(result, null,
                         CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
@@ -422,12 +617,11 @@
         RILRequest rr = obtainRequest(RIL_REQUEST_GET_PHONE_CAPABILITY, result, mDefaultWorkSource);
 
         if (DBG) {
-            logd(rr.serialString() + "> " + requestToString(rr.mRequest));
+            logd(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
         }
 
         try {
-            ((android.hardware.radio.config.V1_1.IRadioConfig) mRadioConfigProxy)
-                    .getPhoneCapability(rr.mSerial);
+            proxy.getPhoneCapability(rr.mSerial);
         } catch (RemoteException | RuntimeException e) {
             resetProxyAndRequestList("getPhoneCapability", e);
         }
@@ -440,91 +634,71 @@
      * See PhoneSwitcher for more details.
      */
     public boolean isSetPreferredDataCommandSupported() {
-        IRadioConfig radioConfigProxy = getRadioConfigProxy(null);
-        return radioConfigProxy != null && mRadioConfigVersion
-                .greaterOrEqual(RADIO_CONFIG_HAL_VERSION_1_1);
+        RadioConfigProxy proxy = getRadioConfigProxy(null);
+        return !proxy.isEmpty() && proxy.getVersion().greaterOrEqual(RADIO_CONFIG_HAL_VERSION_1_1);
     }
 
     /**
      * Wrapper function for IRadioConfig.setSimSlotsMapping(int32_t serial, vec<uint32_t> slotMap).
+     * TODO(ag/15898089): Interface for setSimSlotsMapping was changes but underlying implementation
+     *                    was not provided. Need to update this with proper implementation.
      */
     public void setSimSlotsMapping(int[] physicalSlots, Message result) {
-        IRadioConfig radioConfigProxy = getRadioConfigProxy(result);
-        if (radioConfigProxy != null) {
+        RadioConfigProxy proxy = getRadioConfigProxy(result);
+        if (!proxy.isEmpty()) {
             RILRequest rr = obtainRequest(RIL_REQUEST_SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING, result,
                     mDefaultWorkSource);
 
             if (DBG) {
-                logd(rr.serialString() + "> " + requestToString(rr.mRequest)
+                logd(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest)
                         + " " + Arrays.toString(physicalSlots));
             }
 
             try {
-                radioConfigProxy.setSimSlotsMapping(rr.mSerial,
-                        primitiveArrayToArrayList(physicalSlots));
+                proxy.setSimSlotsMapping(rr.mSerial, physicalSlots);
             } catch (RemoteException | RuntimeException e) {
                 resetProxyAndRequestList("setSimSlotsMapping", e);
             }
         }
     }
 
-    private static ArrayList<Integer> primitiveArrayToArrayList(int[] arr) {
-        ArrayList<Integer> arrayList = new ArrayList<>(arr.length);
-        for (int i : arr) {
-            arrayList.add(i);
-        }
-        return arrayList;
-    }
-
-    static String requestToString(int request) {
-        switch (request) {
-            case RIL_REQUEST_GET_PHONE_CAPABILITY:
-                return "GET_PHONE_CAPABILITY";
-            case RIL_REQUEST_GET_SLOT_STATUS:
-                return "GET_SLOT_STATUS";
-            case RIL_REQUEST_SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING:
-                return "SET_LOGICAL_TO_PHYSICAL_SLOT_MAPPING";
-            case RIL_REQUEST_SET_PREFERRED_DATA_MODEM:
-                return "SET_PREFERRED_DATA_MODEM";
-            case RIL_REQUEST_SWITCH_DUAL_SIM_CONFIG:
-                return "SWITCH_DUAL_SIM_CONFIG";
-            case RIL_REQUEST_GET_HAL_DEVICE_CAPABILITIES:
-                return "GET_HAL_DEVICE_CAPABILITIES";
-            default:
-                return "<unknown request " + request + ">";
-        }
-    }
-
     /**
-     * Wrapper function for using IRadioConfig.setModemsConfig(int32_t serial,
-     * ModemsConfig modemsConfig) to switch between single-sim and multi-sim.
+     * Wrapper function for using IRadioConfig.setNumOfLiveModems(int32_t serial,
+     * byte numOfLiveModems) to switch between single-sim and multi-sim.
      */
-    public void setModemsConfig(int numOfLiveModems, Message result) {
-        IRadioConfig radioConfigProxy = getRadioConfigProxy(result);
-        if (radioConfigProxy != null
-                && mRadioConfigVersion.greaterOrEqual(RADIO_CONFIG_HAL_VERSION_1_1)) {
-            android.hardware.radio.config.V1_1.IRadioConfig radioConfigProxy11 =
-                    (android.hardware.radio.config.V1_1.IRadioConfig) radioConfigProxy;
-            RILRequest rr = obtainRequest(RIL_REQUEST_SWITCH_DUAL_SIM_CONFIG,
-                    result, mDefaultWorkSource);
-
-            if (DBG) {
-                logd(rr.serialString() + "> " + requestToString(rr.mRequest)
-                        + ", numOfLiveModems = " + numOfLiveModems);
+    public void setNumOfLiveModems(int numOfLiveModems, Message result) {
+        RadioConfigProxy proxy = getRadioConfigProxy(result);
+        if (proxy.isEmpty() || proxy.getVersion().less(RADIO_CONFIG_HAL_VERSION_1_1)) {
+            if (result != null) {
+                AsyncResult.forMessage(
+                        result, null, CommandException.fromRilErrno(REQUEST_NOT_SUPPORTED));
+                result.sendToTarget();
             }
-
-            try {
-                ModemsConfig modemsConfig = new ModemsConfig();
-                modemsConfig.numOfLiveModems = (byte) numOfLiveModems;
-                radioConfigProxy11.setModemsConfig(rr.mSerial, modemsConfig);
-            } catch (RemoteException | RuntimeException e) {
-                resetProxyAndRequestList("setModemsConfig", e);
-            }
+            return;
         }
-    }
 
-    // TODO: not needed for now, but if we don't want to use System Properties any more,
-    // we need to implement a wrapper function for getModemsConfig as well
+        RILRequest rr = obtainRequest(RIL_REQUEST_SWITCH_DUAL_SIM_CONFIG,
+                result, mDefaultWorkSource);
+
+        if (DBG) {
+            logd(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest)
+                    + ", numOfLiveModems = " + numOfLiveModems);
+        }
+
+        try {
+            if (proxy.getVersion().greaterOrEqual(RADIO_CONFIG_HAL_VERSION_2_0)) {
+                proxy.setNumOfLiveModems(rr.mSerial, (byte) numOfLiveModems);
+            } else {
+                android.hardware.radio.config.V1_1.ModemsConfig modemsConfig =
+                        new android.hardware.radio.config.V1_1.ModemsConfig();
+                modemsConfig.numOfLiveModems = (byte) numOfLiveModems;
+                proxy.setModemsConfig(rr.mSerial, modemsConfig);
+            }
+        } catch (RemoteException | RuntimeException e) {
+            resetProxyAndRequestList("setModemsConfig", e);
+        }
+
+    }
 
     /**
      * Register a handler to get SIM slot status changed notifications.
@@ -547,26 +721,8 @@
      * Gets the hal capabilities from the device.
      */
     public void getHalDeviceCapabilities(Message result) {
-        IRadioConfig radioConfigProxy = getRadioConfigProxy(Message.obtain(result));
-        if (radioConfigProxy != null
-                && mRadioConfigVersion.greaterOrEqual(RADIO_CONFIG_HAL_VERSION_1_3)) {
-            android.hardware.radio.config.V1_3.IRadioConfig radioConfigProxy13 =
-                    (android.hardware.radio.config.V1_3.IRadioConfig) radioConfigProxy;
-            RILRequest rr = obtainRequest(RIL_REQUEST_GET_HAL_DEVICE_CAPABILITIES,
-                    result, mDefaultWorkSource);
-
-            if (DBG) {
-                logd(rr.serialString() + "> " + requestToString(rr.mRequest));
-            }
-
-            try {
-                mRadioConfigVersion = RADIO_CONFIG_HAL_VERSION_1_3;
-                radioConfigProxy13.getHalDeviceCapabilities(rr.mSerial);
-
-            } catch (RemoteException | RuntimeException e) {
-                resetProxyAndRequestList("getHalDeviceCapabilities", e);
-            }
-        } else {
+        RadioConfigProxy proxy = getRadioConfigProxy(Message.obtain(result));
+        if (proxy.isEmpty() || proxy.getVersion().less(RADIO_CONFIG_HAL_VERSION_1_3)) {
             if (result != null) {
                 if (DBG) {
                     logd("RIL_REQUEST_GET_HAL_DEVICE_CAPABILITIES > REQUEST_NOT_SUPPORTED");
@@ -583,6 +739,20 @@
                             + "on complete message not set.");
                 }
             }
+            return;
+        }
+
+        RILRequest rr = obtainRequest(RIL_REQUEST_GET_HAL_DEVICE_CAPABILITIES,
+                result, mDefaultWorkSource);
+
+        if (DBG) {
+            logd(rr.serialString() + "> " + RILUtils.requestToString(rr.mRequest));
+        }
+
+        try {
+            proxy.getHalDeviceCapabilities(rr.mSerial);
+        } catch (RemoteException | RuntimeException e) {
+            resetProxyAndRequestList("getHalDeviceCapabilities", e);
         }
     }
 
@@ -593,37 +763,6 @@
         return mDeviceNrCapabilities;
     }
 
-    static ArrayList<IccSlotStatus> convertHalSlotStatus(
-            ArrayList<android.hardware.radio.config.V1_0.SimSlotStatus> halSlotStatusList) {
-        ArrayList<IccSlotStatus> response = new ArrayList<IccSlotStatus>(halSlotStatusList.size());
-        for (android.hardware.radio.config.V1_0.SimSlotStatus slotStatus : halSlotStatusList) {
-            IccSlotStatus iccSlotStatus = new IccSlotStatus();
-            iccSlotStatus.setCardState(slotStatus.cardState);
-            iccSlotStatus.setSlotState(slotStatus.slotState);
-            iccSlotStatus.logicalSlotIndex = slotStatus.logicalSlotId;
-            iccSlotStatus.atr = slotStatus.atr;
-            iccSlotStatus.iccid = slotStatus.iccid;
-            response.add(iccSlotStatus);
-        }
-        return response;
-    }
-
-    static ArrayList<IccSlotStatus> convertHalSlotStatus_1_2(
-            ArrayList<android.hardware.radio.config.V1_2.SimSlotStatus> halSlotStatusList) {
-        ArrayList<IccSlotStatus> response = new ArrayList<IccSlotStatus>(halSlotStatusList.size());
-        for (android.hardware.radio.config.V1_2.SimSlotStatus slotStatus : halSlotStatusList) {
-            IccSlotStatus iccSlotStatus = new IccSlotStatus();
-            iccSlotStatus.setCardState(slotStatus.base.cardState);
-            iccSlotStatus.setSlotState(slotStatus.base.slotState);
-            iccSlotStatus.logicalSlotIndex = slotStatus.base.logicalSlotId;
-            iccSlotStatus.atr = slotStatus.base.atr;
-            iccSlotStatus.iccid = slotStatus.base.iccid;
-            iccSlotStatus.eid = slotStatus.eid;
-            response.add(iccSlotStatus);
-        }
-        return response;
-    }
-
     private static void logd(String log) {
         Rlog.d(TAG, log);
     }
diff --git a/src/java/com/android/internal/telephony/RadioConfigIndication.java b/src/java/com/android/internal/telephony/RadioConfigIndication.java
index 639272c..f88a9d2 100644
--- a/src/java/com/android/internal/telephony/RadioConfigIndication.java
+++ b/src/java/com/android/internal/telephony/RadioConfigIndication.java
@@ -16,48 +16,26 @@
 
 package com.android.internal.telephony;
 
-import android.hardware.radio.config.V1_2.IRadioConfigIndication;
-import android.os.AsyncResult;
-
-import com.android.internal.telephony.uicc.IccSlotStatus;
-import com.android.telephony.Rlog;
-
-import java.util.ArrayList;
-
 /**
  * This class is the implementation of IRadioConfigIndication interface.
  */
-public class RadioConfigIndication extends IRadioConfigIndication.Stub {
-    private final RadioConfig mRadioConfig;
-    private static final String TAG = "RadioConfigIndication";
+public class RadioConfigIndication {
+    private RadioConfigIndicationHidl mRadioConfigIndicationHidl;
+    private RadioConfigIndicationAidl mRadioConfigIndicationAidl;
 
-    public RadioConfigIndication(RadioConfig radioConfig) {
-        mRadioConfig = radioConfig;
-    }
-
-    /**
-     * Unsolicited indication for slot status changed
-     */
-    public void simSlotsStatusChanged(int indicationType,
-            ArrayList<android.hardware.radio.config.V1_0.SimSlotStatus> slotStatus) {
-        ArrayList<IccSlotStatus> ret = RadioConfig.convertHalSlotStatus(slotStatus);
-        Rlog.d(TAG, "[UNSL]< " + " UNSOL_SIM_SLOT_STATUS_CHANGED " + ret.toString());
-        if (mRadioConfig.mSimSlotStatusRegistrant != null) {
-            mRadioConfig.mSimSlotStatusRegistrant.notifyRegistrant(
-                    new AsyncResult(null, ret, null));
+    public RadioConfigIndication(RadioConfig radioConfig, HalVersion halVersion) {
+        if (halVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_2_0)) {
+            mRadioConfigIndicationAidl = new RadioConfigIndicationAidl(radioConfig);
+        } else {
+            mRadioConfigIndicationHidl = new RadioConfigIndicationHidl(radioConfig);
         }
     }
 
-    /**
-     * Unsolicited indication for slot status changed
-     */
-    public void simSlotsStatusChanged_1_2(int indicationType,
-            ArrayList<android.hardware.radio.config.V1_2.SimSlotStatus> slotStatus) {
-        ArrayList<IccSlotStatus> ret = RadioConfig.convertHalSlotStatus_1_2(slotStatus);
-        Rlog.d(TAG, "[UNSL]< " + " UNSOL_SIM_SLOT_STATUS_CHANGED " + ret.toString());
-        if (mRadioConfig.mSimSlotStatusRegistrant != null) {
-            mRadioConfig.mSimSlotStatusRegistrant.notifyRegistrant(
-                    new AsyncResult(null, ret, null));
-        }
+    public android.hardware.radio.config.V1_2.IRadioConfigIndication getV1() {
+        return mRadioConfigIndicationHidl;
+    }
+
+    public android.hardware.radio.config.IRadioConfigIndication getV2() {
+        return mRadioConfigIndicationAidl;
     }
 }
diff --git a/src/java/com/android/internal/telephony/RadioConfigIndicationAidl.java b/src/java/com/android/internal/telephony/RadioConfigIndicationAidl.java
new file mode 100644
index 0000000..aecb5c0
--- /dev/null
+++ b/src/java/com/android/internal/telephony/RadioConfigIndicationAidl.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2018 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 android.os.AsyncResult;
+
+import com.android.internal.telephony.uicc.IccSlotStatus;
+import com.android.telephony.Rlog;
+
+import java.util.ArrayList;
+
+/**
+ * This class is the AIDL implementation of IRadioConfigIndication interface.
+ */
+public class RadioConfigIndicationAidl extends
+        android.hardware.radio.config.IRadioConfigIndication.Stub {
+    private static final String TAG = "RadioConfigIndicationAidl";
+
+    private final RadioConfig mRadioConfig;
+
+    public RadioConfigIndicationAidl(RadioConfig radioConfig) {
+        mRadioConfig = radioConfig;
+    }
+
+    /**
+     * Unsolicited indication for slot status changed
+     */
+    @Override
+    public void simSlotsStatusChanged(
+            int type, android.hardware.radio.config.SimSlotStatus[] slotStatus) {
+        ArrayList<IccSlotStatus> ret = RILUtils.convertHalSlotStatus(slotStatus);
+        logd("[UNSL]< UNSOL_SIM_SLOT_STATUS_CHANGED " + ret.toString());
+        if (mRadioConfig.mSimSlotStatusRegistrant != null) {
+            mRadioConfig.mSimSlotStatusRegistrant.notifyRegistrant(
+                    new AsyncResult(null, ret, null));
+        }
+    }
+
+    private static void logd(String log) {
+        Rlog.d(TAG, log);
+    }
+}
diff --git a/src/java/com/android/internal/telephony/RadioConfigIndicationHidl.java b/src/java/com/android/internal/telephony/RadioConfigIndicationHidl.java
new file mode 100644
index 0000000..23a676b
--- /dev/null
+++ b/src/java/com/android/internal/telephony/RadioConfigIndicationHidl.java
@@ -0,0 +1,68 @@
+/*
+ * Copyright (C) 2018 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 android.os.AsyncResult;
+
+import com.android.internal.telephony.uicc.IccSlotStatus;
+import com.android.telephony.Rlog;
+
+import java.util.ArrayList;
+
+/**
+ * This class is the HIDL implementation of IRadioConfigIndication interface.
+ */
+public class RadioConfigIndicationHidl extends
+        android.hardware.radio.config.V1_2.IRadioConfigIndication.Stub {
+    private static final String TAG = "RadioConfigIndicationHidl";
+
+    private final RadioConfig mRadioConfig;
+
+    public RadioConfigIndicationHidl(RadioConfig radioConfig) {
+        mRadioConfig = radioConfig;
+    }
+
+    /**
+     * Unsolicited indication for slot status changed
+     */
+    public void simSlotsStatusChanged(int indicationType,
+            ArrayList<android.hardware.radio.config.V1_0.SimSlotStatus> slotStatus) {
+        ArrayList<IccSlotStatus> ret = RILUtils.convertHalSlotStatus(slotStatus);
+        logd("[UNSL]< UNSOL_SIM_SLOT_STATUS_CHANGED " + ret.toString());
+        if (mRadioConfig.mSimSlotStatusRegistrant != null) {
+            mRadioConfig.mSimSlotStatusRegistrant.notifyRegistrant(
+                    new AsyncResult(null, ret, null));
+        }
+    }
+
+    /**
+     * Unsolicited indication for slot status changed
+     */
+    public void simSlotsStatusChanged_1_2(int indicationType,
+            ArrayList<android.hardware.radio.config.V1_2.SimSlotStatus> slotStatus) {
+        ArrayList<IccSlotStatus> ret = RILUtils.convertHalSlotStatus(slotStatus);
+        logd("[UNSL]< UNSOL_SIM_SLOT_STATUS_CHANGED " + ret.toString());
+        if (mRadioConfig.mSimSlotStatusRegistrant != null) {
+            mRadioConfig.mSimSlotStatusRegistrant.notifyRegistrant(
+                    new AsyncResult(null, ret, null));
+        }
+    }
+
+    private static void logd(String log) {
+        Rlog.d(TAG, log);
+    }
+}
diff --git a/src/java/com/android/internal/telephony/RadioConfigResponse.java b/src/java/com/android/internal/telephony/RadioConfigResponse.java
index 3829c16..a1938bd 100644
--- a/src/java/com/android/internal/telephony/RadioConfigResponse.java
+++ b/src/java/com/android/internal/telephony/RadioConfigResponse.java
@@ -16,261 +16,37 @@
 
 package com.android.internal.telephony;
 
-import static android.telephony.TelephonyManager
-        .CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE;
-import static android.telephony.TelephonyManager.CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED;
-import static android.telephony.TelephonyManager.CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE;
-import static android.telephony.TelephonyManager.CAPABILITY_SIM_PHONEBOOK_IN_MODEM;
-import static android.telephony.TelephonyManager.CAPABILITY_SLICING_CONFIG_SUPPORTED;
-import static android.telephony.TelephonyManager.CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING;
-import static android.telephony.TelephonyManager.CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK;
-import static android.telephony.TelephonyManager.RadioInterfaceCapability;
+import android.telephony.TelephonyManager;
 
-import android.hardware.radio.V1_0.RadioError;
-import android.hardware.radio.V1_0.RadioResponseInfo;
-import android.hardware.radio.config.V1_1.ModemsConfig;
-import android.hardware.radio.config.V1_3.IRadioConfigResponse;
-import android.telephony.ModemInfo;
-import android.telephony.PhoneCapability;
-
-import com.android.internal.annotations.VisibleForTesting;
-import com.android.internal.telephony.uicc.IccSlotStatus;
-import com.android.telephony.Rlog;
-
-import java.util.ArrayList;
-import java.util.HashSet;
-import java.util.List;
 import java.util.Set;
 
 /**
  * This class is the implementation of IRadioConfigResponse interface.
  */
-public class RadioConfigResponse extends IRadioConfigResponse.Stub {
+public class RadioConfigResponse {
     private static final String TAG = "RadioConfigResponse";
 
-    private final RadioConfig mRadioConfig;
-    private final HalVersion mRadioHalVersion;
+    private final HalVersion mHalVersion;
 
-    public RadioConfigResponse(RadioConfig radioConfig, HalVersion radioHalVersion) {
-        mRadioConfig = radioConfig;
-        mRadioHalVersion = radioHalVersion;
-    }
+    private RadioConfigResponseAidl mRadioConfigResponseAidl = null;
+    private RadioConfigResponseHidl mRadioConfigResponseHidl = null;
 
-    /**
-     * Response function for IRadioConfig.getSimSlotsStatus().
-     */
-    public void getSimSlotsStatusResponse(RadioResponseInfo responseInfo,
-            ArrayList<android.hardware.radio.config.V1_0.SimSlotStatus> slotStatus) {
-        RILRequest rr = mRadioConfig.processResponse(responseInfo);
+    public RadioConfigResponse(RadioConfig radioConfig, HalVersion halVersion) {
+        mHalVersion = halVersion;
 
-        if (rr != null) {
-            ArrayList<IccSlotStatus> ret = RadioConfig.convertHalSlotStatus(slotStatus);
-            if (responseInfo.error == RadioError.NONE) {
-                // send response
-                RadioResponse.sendMessageResponse(rr.mResult, ret);
-                Rlog.d(TAG, rr.serialString() + "< "
-                        + mRadioConfig.requestToString(rr.mRequest) + " " + ret.toString());
-            } else {
-                rr.onError(responseInfo.error, ret);
-                Rlog.e(TAG, rr.serialString() + "< "
-                        + mRadioConfig.requestToString(rr.mRequest) + " error "
-                        + responseInfo.error);
-            }
-
+        if (mHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_2_0)) {
+            mRadioConfigResponseAidl = new RadioConfigResponseAidl(radioConfig, halVersion);
         } else {
-            Rlog.e(TAG, "getSimSlotsStatusResponse: Error " + responseInfo.toString());
+            mRadioConfigResponseHidl = new RadioConfigResponseHidl(radioConfig, halVersion);
         }
     }
 
-    /**
-     * Response function for IRadioConfig.getSimSlotsStatus().
-     */
-    public void getSimSlotsStatusResponse_1_2(RadioResponseInfo responseInfo,
-            ArrayList<android.hardware.radio.config.V1_2.SimSlotStatus> slotStatus) {
-        RILRequest rr = mRadioConfig.processResponse(responseInfo);
-
-        if (rr != null) {
-            ArrayList<IccSlotStatus> ret = RadioConfig.convertHalSlotStatus_1_2(slotStatus);
-            if (responseInfo.error == RadioError.NONE) {
-                // send response
-                RadioResponse.sendMessageResponse(rr.mResult, ret);
-                Rlog.d(TAG, rr.serialString() + "< "
-                        + mRadioConfig.requestToString(rr.mRequest) + " " + ret.toString());
-            } else {
-                rr.onError(responseInfo.error, ret);
-                Rlog.e(TAG, rr.serialString() + "< "
-                        + mRadioConfig.requestToString(rr.mRequest) + " error "
-                        + responseInfo.error);
-            }
-        } else {
-            Rlog.e(TAG, "getSimSlotsStatusResponse_1_2: Error " + responseInfo.toString());
-        }
+    public android.hardware.radio.config.V1_3.IRadioConfigResponse getV1() {
+        return mRadioConfigResponseHidl;
     }
 
-    /**
-     * Response function for IRadioConfig.setSimSlotsMapping().
-     */
-    public void setSimSlotsMappingResponse(RadioResponseInfo responseInfo) {
-        RILRequest rr = mRadioConfig.processResponse(responseInfo);
-
-        if (rr != null) {
-            if (responseInfo.error == RadioError.NONE) {
-                // send response
-                RadioResponse.sendMessageResponse(rr.mResult, null);
-                Rlog.d(TAG, rr.serialString() + "< "
-                        + mRadioConfig.requestToString(rr.mRequest));
-            } else {
-                rr.onError(responseInfo.error, null);
-                Rlog.e(TAG, rr.serialString() + "< "
-                        + mRadioConfig.requestToString(rr.mRequest) + " error "
-                        + responseInfo.error);
-            }
-        } else {
-            Rlog.e(TAG, "setSimSlotsMappingResponse: Error " + responseInfo.toString());
-        }
-    }
-
-    private PhoneCapability convertHalPhoneCapability(
-            android.hardware.radio.config.V1_1.PhoneCapability phoneCapability) {
-        // TODO b/121394331: clean up V1_1.PhoneCapability fields.
-        int maxActiveVoiceCalls = 0;
-        int maxActiveData = phoneCapability.maxActiveData;
-        boolean validationBeforeSwitchSupported = phoneCapability.isInternetLingeringSupported;
-        List<ModemInfo> logicalModemList = new ArrayList();
-
-        for (android.hardware.radio.config.V1_1.ModemInfo
-                modemInfo : phoneCapability.logicalModemList) {
-            logicalModemList.add(new ModemInfo(modemInfo.modemId));
-        }
-
-        return new PhoneCapability(maxActiveVoiceCalls, maxActiveData, logicalModemList,
-                validationBeforeSwitchSupported, mRadioConfig.getDeviceNrCapabilities());
-    }
-    /**
-     * Response function for IRadioConfig.getPhoneCapability().
-     */
-    public void getPhoneCapabilityResponse(RadioResponseInfo responseInfo,
-            android.hardware.radio.config.V1_1.PhoneCapability phoneCapability) {
-        RILRequest rr = mRadioConfig.processResponse(responseInfo);
-
-        if (rr != null) {
-            PhoneCapability ret = convertHalPhoneCapability(phoneCapability);
-            if (responseInfo.error == RadioError.NONE) {
-                // send response
-                RadioResponse.sendMessageResponse(rr.mResult, ret);
-                Rlog.d(TAG, rr.serialString() + "< "
-                        + mRadioConfig.requestToString(rr.mRequest) + " " + ret.toString());
-            } else {
-                rr.onError(responseInfo.error, ret);
-                Rlog.e(TAG, rr.serialString() + "< "
-                        + mRadioConfig.requestToString(rr.mRequest) + " error "
-                        + responseInfo.error);
-            }
-        } else {
-            Rlog.e(TAG, "getPhoneCapabilityResponse: Error " + responseInfo.toString());
-        }
-    }
-
-    /**
-     * Response function for IRadioConfig.setPreferredDataModem().
-     */
-    public void setPreferredDataModemResponse(RadioResponseInfo responseInfo) {
-        RILRequest rr = mRadioConfig.processResponse(responseInfo);
-
-        if (rr != null) {
-            if (responseInfo.error == RadioError.NONE) {
-                // send response
-                RadioResponse.sendMessageResponse(rr.mResult, null);
-                Rlog.d(TAG, rr.serialString() + "< "
-                        + mRadioConfig.requestToString(rr.mRequest));
-            } else {
-                rr.onError(responseInfo.error, null);
-                Rlog.e(TAG, rr.serialString() + "< "
-                        + mRadioConfig.requestToString(rr.mRequest) + " error "
-                        + responseInfo.error);
-            }
-        } else {
-            Rlog.e(TAG, "setPreferredDataModemResponse: Error " + responseInfo.toString());
-        }
-    }
-
-    /**
-     * Response function for IRadioConfig.setModemsConfigResponse()
-     * Currently this is being used as the callback for RadioConfig.setModemsConfig() method
-     */
-    public void setModemsConfigResponse(RadioResponseInfo responseInfo) {
-        RILRequest rr = mRadioConfig.processResponse(responseInfo);
-
-        if (rr != null) {
-            if (responseInfo.error == RadioError.NONE) {
-                // send response
-                RadioResponse.sendMessageResponse(rr.mResult, rr.mRequest);
-                Rlog.d(TAG, rr.serialString() + "< "
-                        + mRadioConfig.requestToString(rr.mRequest));
-            } else {
-                rr.onError(responseInfo.error, null);
-                Rlog.e(TAG, rr.serialString() + "< "
-                        + mRadioConfig.requestToString(rr.mRequest) + " error "
-                        + responseInfo.error);
-            }
-        } else {
-            Rlog.e(TAG, "setModemsConfigResponse: Error " + responseInfo.toString());
-        }
-    }
-
-    /**
-     * Response function for IRadioConfig.getModemsConfigResponse()
-     */
-    public void getModemsConfigResponse(RadioResponseInfo responseInfo, ModemsConfig modemsConfig) {
-        RILRequest rr = mRadioConfig.processResponse(responseInfo);
-
-        if (rr != null) {
-            if (responseInfo.error == RadioError.NONE) {
-                // send response
-                RadioResponse.sendMessageResponse(rr.mResult, modemsConfig);
-                Rlog.d(TAG, rr.serialString() + "< "
-                        + mRadioConfig.requestToString(rr.mRequest));
-            } else {
-                rr.onError(responseInfo.error, modemsConfig);
-                Rlog.e(TAG, rr.serialString() + "< "
-                        + mRadioConfig.requestToString(rr.mRequest) + " error "
-                        + responseInfo.error);
-            }
-        } else {
-            Rlog.e(TAG, "getModemsConfigResponse: Error " + responseInfo.toString());
-        }
-    }
-
-    /**
-     * Response function IRadioConfig.getHalDeviceCapabilities()
-     */
-    public void getHalDeviceCapabilitiesResponse(
-            android.hardware.radio.V1_6.RadioResponseInfo responseInfo,
-            boolean modemReducedFeatureSet1) {
-
-        // convert hal device capabilities to RadioInterfaceCapabilities
-
-        RILRequest rr = mRadioConfig.processResponse_1_6(responseInfo);
-        if (rr != null) {
-            // The response is compatible with Radio 1.6, it means the modem
-            // supports setAllowedNetworkTypeBitmap.
-
-            final Set<String> ret = getCaps(mRadioHalVersion, modemReducedFeatureSet1);
-
-            if (responseInfo.error == RadioError.NONE) {
-                // send response
-                RadioResponse.sendMessageResponse(rr.mResult, ret);
-                Rlog.d(TAG, rr.serialString() + "< "
-                        + mRadioConfig.requestToString(rr.mRequest));
-            } else {
-                rr.onError(responseInfo.error, ret);
-                Rlog.e(TAG, rr.serialString() + "< "
-                        + mRadioConfig.requestToString(rr.mRequest) + " error "
-                        + responseInfo.error);
-            }
-        } else {
-            Rlog.e(TAG, "getHalDeviceCapabilities: Error " + responseInfo.toString());
-        }
+    public android.hardware.radio.config.IRadioConfigResponse getV2() {
+        return mRadioConfigResponseAidl;
     }
 
     /**
@@ -280,45 +56,8 @@
      *
      * @return all capabilities
      */
-    @RadioInterfaceCapability
+    @TelephonyManager.RadioInterfaceCapability
     public Set<String> getFullCapabilitySet() {
-        return getCaps(mRadioHalVersion, false);
-    }
-
-    /**
-     * Create capabilities based off of the radio hal version and feature set configurations.
-     */
-    @VisibleForTesting
-    public static Set<String> getCaps(HalVersion radioHalVersion,
-            boolean modemReducedFeatureSet1) {
-        final Set<String> caps = new HashSet<>();
-
-        if (radioHalVersion.equals(RIL.RADIO_HAL_VERSION_UNKNOWN)) {
-            // If the Radio HAL is UNKNOWN, no capabilities will present themselves.
-            Rlog.e(TAG, "Radio Hal Version is UNKNOWN!");
-        }
-
-        Rlog.d(TAG, "Radio Hal Version = " + radioHalVersion.toString());
-        if (radioHalVersion.greaterOrEqual(RIL.RADIO_HAL_VERSION_1_6)) {
-            caps.add(CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK);
-            Rlog.d(TAG, "CAPABILITY_USES_ALLOWED_NETWORK_TYPES_BITMASK");
-
-            if (!modemReducedFeatureSet1) {
-                caps.add(CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE);
-                Rlog.d(TAG, "CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE");
-                caps.add(CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE);
-                Rlog.d(TAG, "CAPABILITY_NR_DUAL_CONNECTIVITY_CONFIGURATION_AVAILABLE");
-                caps.add(CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING);
-                Rlog.d(TAG, "CAPABILITY_THERMAL_MITIGATION_DATA_THROTTLING");
-                caps.add(CAPABILITY_SLICING_CONFIG_SUPPORTED);
-                Rlog.d(TAG, "CAPABILITY_SLICING_CONFIG_SUPPORTED");
-                caps.add(CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED);
-                Rlog.d(TAG, "CAPABILITY_PHYSICAL_CHANNEL_CONFIG_1_6_SUPPORTED");
-            } else {
-                caps.add(CAPABILITY_SIM_PHONEBOOK_IN_MODEM);
-                Rlog.d(TAG, "CAPABILITY_SIM_PHONEBOOK_IN_MODEM");
-            }
-        }
-        return caps;
+        return RILUtils.getCaps(mHalVersion, false);
     }
 }
diff --git a/src/java/com/android/internal/telephony/RadioConfigResponseAidl.java b/src/java/com/android/internal/telephony/RadioConfigResponseAidl.java
new file mode 100644
index 0000000..26975d8
--- /dev/null
+++ b/src/java/com/android/internal/telephony/RadioConfigResponseAidl.java
@@ -0,0 +1,217 @@
+/*
+ * Copyright (C) 2018 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 android.os.RemoteException;
+import android.telephony.PhoneCapability;
+
+import com.android.internal.telephony.uicc.IccSlotStatus;
+import com.android.telephony.Rlog;
+
+import java.util.ArrayList;
+import java.util.Set;
+
+/**
+ * This class is the AIDL implementation of IRadioConfigResponse interface.
+ */
+public class RadioConfigResponseAidl extends
+        android.hardware.radio.config.IRadioConfigResponse.Stub {
+    private static final String TAG = "RadioConfigResponseAidl";
+
+    private final RadioConfig mRadioConfig;
+    private final HalVersion mHalVersion;
+
+    public RadioConfigResponseAidl(RadioConfig radioConfig, HalVersion halVersion) {
+        mRadioConfig = radioConfig;
+        mHalVersion = halVersion;
+    }
+
+    /**
+     * Response function IRadioConfig.getHalDeviceCapabilities()
+     */
+    @Override
+    public void getHalDeviceCapabilitiesResponse(
+            android.hardware.radio.RadioResponseInfo info,
+            boolean modemReducedFeatureSet1) throws RemoteException {
+        // convert hal device capabilities to RadioInterfaceCapabilities
+        RILRequest rr = mRadioConfig.processResponse(info);
+        if (rr != null) {
+            final Set<String> ret = RILUtils.getCaps(mHalVersion, modemReducedFeatureSet1);
+            if (info.error == android.hardware.radio.RadioError.NONE) {
+                // send response
+                RadioResponse.sendMessageResponse(rr.mResult, ret);
+                logd(rr, RILUtils.requestToString(rr.mRequest));
+            } else {
+                rr.onError(info.error, ret);
+                loge(rr, RILUtils.requestToString(rr.mRequest) + " error " + info.error);
+            }
+        } else {
+            loge("getHalDeviceCapabilities: Error " + info.toString());
+        }
+    }
+
+    /**
+     * Response function for IRadioConfig.getNumOfLiveModemsResponse()
+     */
+    @Override
+    public void getNumOfLiveModemsResponse(
+            android.hardware.radio.RadioResponseInfo info, byte numOfLiveModems)
+            throws RemoteException {
+        RILRequest rr = mRadioConfig.processResponse(info);
+        if (rr != null) {
+            if (info.error == android.hardware.radio.RadioError.NONE) {
+                // send response
+                RadioResponse.sendMessageResponse(rr.mResult, numOfLiveModems);
+                logd(rr, RILUtils.requestToString(rr.mRequest));
+            } else {
+                rr.onError(info.error, numOfLiveModems);
+                loge(rr, RILUtils.requestToString(rr.mRequest) + " error " + info.error);
+            }
+        } else {
+            loge("getNumOfLiveModemsResponse: Error " + info.toString());
+        }
+    }
+
+    /**
+     * Response function for IRadioConfig.getPhoneCapability().
+     */
+    @Override
+    public void getPhoneCapabilityResponse(
+            android.hardware.radio.RadioResponseInfo info,
+            android.hardware.radio.config.PhoneCapability phoneCapability)
+            throws RemoteException {
+        RILRequest rr = mRadioConfig.processResponse(info);
+        if (rr != null) {
+            PhoneCapability ret = RILUtils.convertHalPhoneCapability(
+                    mRadioConfig.getDeviceNrCapabilities(), phoneCapability);
+            if (info.error == android.hardware.radio.RadioError.NONE) {
+                // send response
+                RadioResponse.sendMessageResponse(rr.mResult, ret);
+                logd(rr, RILUtils.requestToString(rr.mRequest) + " " + ret.toString());
+            } else {
+                rr.onError(info.error, ret);
+                loge(rr, RILUtils.requestToString(rr.mRequest) + " error " + info.error);
+            }
+        } else {
+            loge("getPhoneCapabilityResponse: Error " + info.toString());
+        }
+    }
+
+    /**
+     * Response function for IRadioConfig.getSimSlotsStatus().
+     */
+    @Override
+    public void getSimSlotsStatusResponse(
+            android.hardware.radio.RadioResponseInfo info,
+            android.hardware.radio.config.SimSlotStatus[] slotStatus)
+            throws RemoteException {
+        RILRequest rr = mRadioConfig.processResponse(info);
+        if (rr != null) {
+            ArrayList<IccSlotStatus> ret = RILUtils.convertHalSlotStatus(slotStatus);
+            if (info.error == android.hardware.radio.RadioError.NONE) {
+                // send response
+                RadioResponse.sendMessageResponse(rr.mResult, ret);
+                logd(rr, RILUtils.requestToString(rr.mRequest) + " " + ret.toString());
+            } else {
+                rr.onError(info.error, ret);
+                loge(rr, RILUtils.requestToString(rr.mRequest) + " error " + info.error);
+            }
+        } else {
+            loge("getSimSlotsStatusResponse: Error " + info.toString());
+        }
+    }
+
+    /**
+     * Response function for IRadioConfig.setNumOfLiveModemsResponse()
+     * Currently this is being used as the callback for RadioConfig.setNumOfLiveModems() method
+     */
+    @Override
+    public void setNumOfLiveModemsResponse(
+            android.hardware.radio.RadioResponseInfo info) throws RemoteException {
+        RILRequest rr = mRadioConfig.processResponse(info);
+        if (rr != null) {
+            if (info.error == android.hardware.radio.RadioError.NONE) {
+                // send response
+                RadioResponse.sendMessageResponse(rr.mResult, rr.mRequest);
+                logd(rr, RILUtils.requestToString(rr.mRequest));
+            } else {
+                rr.onError(info.error, null);
+                loge(rr, RILUtils.requestToString(rr.mRequest) + " error " + info.error);
+            }
+        } else {
+            loge("setModemsConfigResponse: Error " + info.toString());
+        }
+    }
+
+    /**
+     * Response function for IRadioConfig.setPreferredDataModem().
+     */
+    @Override
+    public void setPreferredDataModemResponse(
+            android.hardware.radio.RadioResponseInfo info) throws RemoteException {
+        RILRequest rr = mRadioConfig.processResponse(info);
+        if (rr != null) {
+            if (info.error == android.hardware.radio.RadioError.NONE) {
+                // send response
+                RadioResponse.sendMessageResponse(rr.mResult, null);
+                logd(rr, RILUtils.requestToString(rr.mRequest));
+            } else {
+                rr.onError(info.error, null);
+                loge(rr, RILUtils.requestToString(rr.mRequest) + " error " + info.error);
+            }
+        } else {
+            loge("setPreferredDataModemResponse: Error " + info.toString());
+        }
+    }
+
+    /**
+     * Response function for IRadioConfig.setSimSlotsMapping().
+     */
+    @Override
+    public void setSimSlotsMappingResponse(
+            android.hardware.radio.RadioResponseInfo info) throws RemoteException {
+        RILRequest rr = mRadioConfig.processResponse(info);
+        if (rr != null) {
+            if (info.error == android.hardware.radio.RadioError.NONE) {
+                // send response
+                RadioResponse.sendMessageResponse(rr.mResult, null);
+                logd(rr, RILUtils.requestToString(rr.mRequest));
+            } else {
+                rr.onError(info.error, null);
+                loge(rr, RILUtils.requestToString(rr.mRequest) + " error " + info.error);
+            }
+        } else {
+            loge("setSimSlotsMappingResponse: Error " + info.toString());
+        }
+    }
+
+    private static void logd(String log) {
+        Rlog.d(TAG, log);
+    }
+
+    private static void loge(String log) {
+        Rlog.e(TAG, log);
+    }
+
+    private static void logd(RILRequest rr, String log) {
+        logd(rr.serialString() + "< " + log);
+    }
+
+    private static void loge(RILRequest rr, String log) {
+        loge(rr.serialString() + "< " + log);
+    }
+}
diff --git a/src/java/com/android/internal/telephony/RadioConfigResponseHidl.java b/src/java/com/android/internal/telephony/RadioConfigResponseHidl.java
new file mode 100644
index 0000000..a6ae258
--- /dev/null
+++ b/src/java/com/android/internal/telephony/RadioConfigResponseHidl.java
@@ -0,0 +1,244 @@
+/*
+ * Copyright (C) 2018 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 android.os.RemoteException;
+import android.telephony.PhoneCapability;
+
+import com.android.internal.telephony.uicc.IccSlotStatus;
+import com.android.telephony.Rlog;
+
+import java.util.ArrayList;
+import java.util.Set;
+
+/**
+ * This class is the AIDL implementation of IRadioConfigResponse interface.
+ */
+public class RadioConfigResponseHidl extends
+        android.hardware.radio.config.V1_3.IRadioConfigResponse.Stub {
+    private static final String TAG = "RadioConfigResponse";
+
+    private final RadioConfig mRadioConfig;
+    private final HalVersion mHalVersion;
+
+    public RadioConfigResponseHidl(RadioConfig radioConfig, HalVersion halVersion) {
+        mRadioConfig = radioConfig;
+        mHalVersion = halVersion;
+    }
+
+    /**
+     * Response function for IRadioConfig.getSimSlotsStatus().
+     */
+    @Override
+    public void getSimSlotsStatusResponse(
+            android.hardware.radio.V1_0.RadioResponseInfo info,
+            ArrayList<android.hardware.radio.config.V1_0.SimSlotStatus> slotStatus)
+            throws RemoteException {
+        RILRequest rr = mRadioConfig.processResponse(info);
+
+        if (rr != null) {
+            ArrayList<IccSlotStatus> ret = RILUtils.convertHalSlotStatus(slotStatus);
+            if (info.error == android.hardware.radio.V1_0.RadioError.NONE) {
+                // send response
+                RadioResponse.sendMessageResponse(rr.mResult, ret);
+                logd(rr, RILUtils.requestToString(rr.mRequest) + " " + ret.toString());
+            } else {
+                rr.onError(info.error, ret);
+                loge(rr, RILUtils.requestToString(rr.mRequest) + " error " + info.error);
+            }
+        } else {
+            loge("getSimSlotsStatusResponse: Error " + info.toString());
+        }
+    }
+
+    /**
+     * Response function for IRadioConfig.setSimSlotsMapping().
+     */
+    @Override
+    public void setSimSlotsMappingResponse(android.hardware.radio.V1_0.RadioResponseInfo info)
+            throws RemoteException {
+        RILRequest rr = mRadioConfig.processResponse(info);
+        if (rr != null) {
+            if (info.error == android.hardware.radio.V1_0.RadioError.NONE) {
+                // send response
+                RadioResponse.sendMessageResponse(rr.mResult, null);
+                logd(rr, RILUtils.requestToString(rr.mRequest));
+            } else {
+                rr.onError(info.error, null);
+                loge(rr, RILUtils.requestToString(rr.mRequest) + " error " + info.error);
+            }
+        } else {
+            loge("setSimSlotsMappingResponse: Error " + info.toString());
+        }
+    }
+
+    /**
+     * Response function for IRadioConfig.getPhoneCapability().
+     */
+    @Override
+    public void getPhoneCapabilityResponse(android.hardware.radio.V1_0.RadioResponseInfo info,
+            android.hardware.radio.config.V1_1.PhoneCapability phoneCapability)
+            throws RemoteException {
+        RILRequest rr = mRadioConfig.processResponse(info);
+        if (rr != null) {
+            PhoneCapability ret = RILUtils.convertHalPhoneCapability(
+                    mRadioConfig.getDeviceNrCapabilities(), phoneCapability);
+            if (info.error == android.hardware.radio.V1_0.RadioError.NONE) {
+                // send response
+                RadioResponse.sendMessageResponse(rr.mResult, ret);
+                logd(rr, RILUtils.requestToString(rr.mRequest) + " " + ret.toString());
+            } else {
+                rr.onError(info.error, ret);
+                loge(rr, RILUtils.requestToString(rr.mRequest) + " error " + info.error);
+            }
+        } else {
+            loge("getPhoneCapabilityResponse: Error " + info.toString());
+        }
+    }
+
+    /**
+     * Response function for IRadioConfig.setPreferredDataModem().
+     */
+    @Override
+    public void setPreferredDataModemResponse(
+            android.hardware.radio.V1_0.RadioResponseInfo info) throws RemoteException {
+        RILRequest rr = mRadioConfig.processResponse(info);
+        if (rr != null) {
+            if (info.error == android.hardware.radio.V1_0.RadioError.NONE) {
+                // send response
+                RadioResponse.sendMessageResponse(rr.mResult, null);
+                logd(rr, RILUtils.requestToString(rr.mRequest));
+            } else {
+                rr.onError(info.error, null);
+                loge(rr, RILUtils.requestToString(rr.mRequest) + " error " + info.error);
+            }
+        } else {
+            loge("setPreferredDataModemResponse: Error " + info.toString());
+        }
+    }
+
+    /**
+     * Response function for IRadioConfig.setModemsConfigResponse()
+     * Currently this is being used as the callback for RadioConfig.setModemsConfig() method
+     */
+    @Override
+    public void setModemsConfigResponse(android.hardware.radio.V1_0.RadioResponseInfo info)
+            throws RemoteException {
+        RILRequest rr = mRadioConfig.processResponse(info);
+        if (rr != null) {
+            if (info.error == android.hardware.radio.V1_0.RadioError.NONE) {
+                // send response
+                RadioResponse.sendMessageResponse(rr.mResult, rr.mRequest);
+                logd(rr, RILUtils.requestToString(rr.mRequest));
+            } else {
+                rr.onError(info.error, null);
+                loge(rr, RILUtils.requestToString(rr.mRequest) + " error " + info.error);
+            }
+        } else {
+            loge("setModemsConfigResponse: Error " + info.toString());
+        }
+    }
+
+    /**
+     * Response function for IRadioConfig.getModemsConfigResponse()
+     */
+    @Override
+    public void getModemsConfigResponse(android.hardware.radio.V1_0.RadioResponseInfo info,
+            android.hardware.radio.config.V1_1.ModemsConfig modemsConfig)
+            throws RemoteException {
+        RILRequest rr = mRadioConfig.processResponse(info);
+        if (rr != null) {
+            if (info.error == android.hardware.radio.V1_0.RadioError.NONE) {
+                // send response
+                RadioResponse.sendMessageResponse(rr.mResult, modemsConfig);
+                logd(rr, RILUtils.requestToString(rr.mRequest));
+            } else {
+                rr.onError(info.error, modemsConfig);
+                loge(rr, RILUtils.requestToString(rr.mRequest) + " error " + info.error);
+            }
+        } else {
+            loge("getModemsConfigResponse: Error " + info.toString());
+        }
+    }
+
+    /**
+     * Response function for IRadioConfig.getSimSlotsStatus().
+     */
+    @Override
+    public void getSimSlotsStatusResponse_1_2(
+            android.hardware.radio.V1_0.RadioResponseInfo info,
+            ArrayList<android.hardware.radio.config.V1_2.SimSlotStatus> slotStatus)
+            throws RemoteException {
+        RILRequest rr = mRadioConfig.processResponse(info);
+        if (rr != null) {
+            ArrayList<IccSlotStatus> ret = RILUtils.convertHalSlotStatus(slotStatus);
+            if (info.error == android.hardware.radio.V1_0.RadioError.NONE) {
+                // send response
+                RadioResponse.sendMessageResponse(rr.mResult, ret);
+                logd(rr, RILUtils.requestToString(rr.mRequest) + " " + ret.toString());
+            } else {
+                rr.onError(info.error, ret);
+                loge(rr, RILUtils.requestToString(rr.mRequest) + " error " + info.error);
+            }
+        } else {
+            loge("getSimSlotsStatusResponse_1_2: Error " + info.toString());
+        }
+    }
+
+    /**
+     * Response function IRadioConfig.getHalDeviceCapabilities()
+     */
+    @Override
+    public void getHalDeviceCapabilitiesResponse(
+            android.hardware.radio.V1_6.RadioResponseInfo info, boolean modemReducedFeatureSet1)
+            throws RemoteException {
+        // convert hal device capabilities to RadioInterfaceCapabilities
+        RILRequest rr = mRadioConfig.processResponse_1_6(info);
+        if (rr != null) {
+            // The response is compatible with Radio 1.6, it means the modem
+            // supports setAllowedNetworkTypeBitmap.
+            final Set<String> ret = RILUtils.getCaps(mHalVersion,
+                    modemReducedFeatureSet1);
+            if (info.error == android.hardware.radio.V1_0.RadioError.NONE) {
+                // send response
+                RadioResponse.sendMessageResponse(rr.mResult, ret);
+                logd(rr, RILUtils.requestToString(rr.mRequest));
+            } else {
+                rr.onError(info.error, ret);
+                loge(rr, RILUtils.requestToString(rr.mRequest) + " error " + info.error);
+            }
+        } else {
+            loge("getHalDeviceCapabilities: Error " + info.toString());
+        }
+    }
+
+    private static void logd(String log) {
+        Rlog.d(TAG, log);
+    }
+
+    private static void loge(String log) {
+        Rlog.e(TAG, log);
+    }
+
+    private static void logd(RILRequest rr, String log) {
+        logd(rr.serialString() + "< " + log);
+    }
+
+    private static void loge(RILRequest rr, String log) {
+        loge(rr.serialString() + "< " + log);
+    }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java b/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java
index a702aac..a468dcd 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/PhoneConfigurationManagerTest.java
@@ -140,7 +140,7 @@
 
         // Try switching to dual SIM. Shouldn't work as we haven't indicated DSDS is supported.
         mPcm.switchMultiSimConfig(2);
-        verify(mMockRadioConfig, never()).setModemsConfig(anyInt(), any());
+        verify(mMockRadioConfig, never()).setNumOfLiveModems(anyInt(), any());
     }
 
     @Test
@@ -155,7 +155,7 @@
 
         // Try switching to dual SIM. Shouldn't work as we haven't indicated DSDS is supported.
         mPcm.switchMultiSimConfig(2);
-        verify(mMockRadioConfig, never()).setModemsConfig(anyInt(), any());
+        verify(mMockRadioConfig, never()).setNumOfLiveModems(anyInt(), any());
 
         // Send static capability back to indicate DSDS is supported.
         clearInvocations(mMockRadioConfig);
@@ -169,7 +169,7 @@
         replaceInstance(PhoneFactory.class, "sPhones", null, mPhones);
         mPcm.switchMultiSimConfig(2);
         ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
-        verify(mMockRadioConfig).setModemsConfig(eq(2), captor.capture());
+        verify(mMockRadioConfig).setNumOfLiveModems(eq(2), captor.capture());
 
         // Send message back to indicate switch success.
         Message message = captor.getValue();
@@ -221,7 +221,7 @@
         setRebootRequiredForConfigSwitch(false);
         mPcm.switchMultiSimConfig(1);
         ArgumentCaptor<Message> captor = ArgumentCaptor.forClass(Message.class);
-        verify(mMockRadioConfig).setModemsConfig(eq(1), captor.capture());
+        verify(mMockRadioConfig).setNumOfLiveModems(eq(1), captor.capture());
 
         // Send message back to indicate switch success.
         Message message = captor.getValue();
diff --git a/tests/telephonytests/src/com/android/internal/telephony/RadioConfigResponseTest.java b/tests/telephonytests/src/com/android/internal/telephony/RadioConfigResponseTest.java
index d529d67..281c900 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/RadioConfigResponseTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/RadioConfigResponseTest.java
@@ -44,7 +44,7 @@
 
     @Test
     public void testVersion_1_5() {
-        Set<String> caps = RadioConfigResponse.getCaps(RIL.RADIO_HAL_VERSION_1_5, false);
+        Set<String> caps = RILUtils.getCaps(RIL.RADIO_HAL_VERSION_1_5, false);
         assertFalse(
                 caps.contains(TelephonyManager.CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE));
         assertFalse(
@@ -60,7 +60,7 @@
 
     @Test
     public void testReducedFeatureSet() {
-        Set<String> caps = RadioConfigResponse.getCaps(RIL.RADIO_HAL_VERSION_1_6, true);
+        Set<String> caps = RILUtils.getCaps(RIL.RADIO_HAL_VERSION_1_6, true);
         assertFalse(
                 caps.contains(TelephonyManager.CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE));
         assertTrue(
@@ -78,7 +78,7 @@
 
     @Test
     public void testNonReducedFeatureSet() {
-        Set<String> caps = RadioConfigResponse.getCaps(RIL.RADIO_HAL_VERSION_1_6, false);
+        Set<String> caps = RILUtils.getCaps(RIL.RADIO_HAL_VERSION_1_6, false);
         assertTrue(
                 caps.contains(TelephonyManager.CAPABILITY_SECONDARY_LINK_BANDWIDTH_VISIBLE));
         assertTrue(