Merge remote-tracking branch 'origin/atel-sys.lnx.13.0' into HEAD

Upmerge till:
  commit <fe770da76c89396b4d5e5131977f4f8541deaa21 >

Change-Id: I9310417ada592231eb5b5ed9b0bd4d72060a13b2
diff --git a/extphone/src/com/qti/extphone/CiwlanConfig.aidl b/extphone/src/com/qti/extphone/CiwlanConfig.aidl
new file mode 100644
index 0000000..c0d5380
--- /dev/null
+++ b/extphone/src/com/qti/extphone/CiwlanConfig.aidl
@@ -0,0 +1,8 @@
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package com.qti.extphone;
+
+parcelable CiwlanConfig;
diff --git a/extphone/src/com/qti/extphone/CiwlanConfig.java b/extphone/src/com/qti/extphone/CiwlanConfig.java
new file mode 100644
index 0000000..2da5906
--- /dev/null
+++ b/extphone/src/com/qti/extphone/CiwlanConfig.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package com.qti.extphone;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class CiwlanConfig implements Parcelable {
+
+    private static final String TAG = "CiwlanConfig";
+
+    // On targets that support C_IWLAN modes, when there is a C_IWLAN status change from UI or UE
+    // moves between home and roaming, there will be a brief moment when the mode will be INVALID.
+    public static final int INVALID = -1;
+    public static final int ONLY = 0;
+    public static final int PREFERRED = 1;
+    // On targets that do not support C_IWLAN modes, UNSUPPORTED will be returned.
+    public static final int UNSUPPORTED = 2;
+
+    private int mHomeMode = INVALID;
+    private int mRoamMode = INVALID;
+
+    public CiwlanConfig(int homeMode, int roamMode) {
+        mHomeMode = homeMode;
+        mRoamMode = roamMode;
+    }
+
+    public CiwlanConfig(Parcel in) {
+        mHomeMode = in.readInt();
+        mRoamMode = in.readInt();
+    }
+
+    public String getHomeCiwlanMode() {
+        switch (mHomeMode) {
+            case ONLY:
+                return "ONLY";
+            case PREFERRED:
+                return "PREFERRED";
+            case UNSUPPORTED:
+                return "UNSUPPORTED";
+            default:
+                return "INVALID";
+        }
+    }
+
+    public String getRoamCiwlanMode() {
+        switch (mRoamMode) {
+            case ONLY:
+                return "ONLY";
+            case PREFERRED:
+                return "PREFERRED";
+            case UNSUPPORTED:
+                return "UNSUPPORTED";
+            default:
+                return "INVALID";
+        }
+    }
+
+    public boolean isCiwlanOnlyInHome() {
+        return mHomeMode == ONLY;
+    }
+
+    public boolean isCiwlanOnlyInRoam() {
+        return mRoamMode == ONLY;
+    }
+
+    public boolean isCiwlanModeSupported() {
+        return (mHomeMode != UNSUPPORTED && mRoamMode != UNSUPPORTED);
+    }
+
+    public boolean isValid() {
+        return (mHomeMode != INVALID && mRoamMode != INVALID);
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mHomeMode);
+        out.writeInt(mRoamMode);
+    }
+
+    public static final Parcelable.Creator<CiwlanConfig> CREATOR = new Parcelable.Creator() {
+        @Override
+        public CiwlanConfig createFromParcel(Parcel in) {
+            return new CiwlanConfig(in);
+        }
+
+        @Override
+        public CiwlanConfig[] newArray(int size) {
+            return new CiwlanConfig[size];
+        }
+    };
+
+    @Override
+    public String toString() {
+        return TAG + " homeMode = " + getHomeCiwlanMode() + ", roamMode = " + getRoamCiwlanMode();
+    }
+}
diff --git a/extphone/src/com/qti/extphone/DualDataRecommendation.aidl b/extphone/src/com/qti/extphone/DualDataRecommendation.aidl
new file mode 100644
index 0000000..5c3d8f9
--- /dev/null
+++ b/extphone/src/com/qti/extphone/DualDataRecommendation.aidl
@@ -0,0 +1,8 @@
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package com.qti.extphone;
+
+parcelable DualDataRecommendation;
diff --git a/extphone/src/com/qti/extphone/DualDataRecommendation.java b/extphone/src/com/qti/extphone/DualDataRecommendation.java
new file mode 100644
index 0000000..c39282b
--- /dev/null
+++ b/extphone/src/com/qti/extphone/DualDataRecommendation.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package com.qti.extphone;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class DualDataRecommendation implements Parcelable {
+
+    private static final String TAG = "DualDataRecommendation";
+
+    // Recommended SUB
+    public static final int DDS = 1;
+    public static final int NON_DDS = 2;
+
+    // Action
+    public static final int ACTION_DATA_NOT_ALLOW = 0;
+    public static final int ACTION_DATA_ALLOW = 1;
+
+    private int mSub;
+    private int mAction;
+
+    public DualDataRecommendation(int sub, int action) {
+        mSub = sub;
+        mAction = action;
+    }
+
+    public DualDataRecommendation(Parcel in) {
+        mSub = in.readInt();
+        mAction = in.readInt();
+    }
+
+    public int getRecommendedSub() {
+        return mSub;
+    }
+
+    public int getAction() {
+        return mAction;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mSub);
+        out.writeInt(mAction);
+    }
+
+    public static final Parcelable.Creator<DualDataRecommendation> CREATOR
+            = new Parcelable.Creator() {
+        public DualDataRecommendation createFromParcel(Parcel in) {
+            return new DualDataRecommendation(in);
+        }
+
+        public DualDataRecommendation[] newArray(int size) {
+            return new DualDataRecommendation[size];
+        }
+    };
+
+    @Override
+    public String toString() {
+        return TAG + ": getRecommendedSub(): " + getRecommendedSub()
+                + " getAction: " + getAction();
+    }
+}
diff --git a/extphone/src/com/qti/extphone/ExtPhoneCallbackBase.java b/extphone/src/com/qti/extphone/ExtPhoneCallbackBase.java
index 38bb777..cc31b58 100644
--- a/extphone/src/com/qti/extphone/ExtPhoneCallbackBase.java
+++ b/extphone/src/com/qti/extphone/ExtPhoneCallbackBase.java
@@ -30,7 +30,7 @@
 /*
  * Changes from Qualcomm Innovation Center are provided under the following license:
  *
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  * SPDX-License-Identifier: BSD-3-Clause-Clear
  */
 
@@ -41,6 +41,7 @@
 import android.util.Log;
 import com.qti.extphone.BearerAllocationStatus;
 import com.qti.extphone.DcParam;
+import com.qti.extphone.DualDataRecommendation;
 import com.qti.extphone.IExtPhoneCallback;
 import com.qti.extphone.NetworkSelectionMode;
 import com.qti.extphone.NrConfig;
@@ -269,4 +270,24 @@
     @Override
     public void onSimTypeChanged(QtiSimType[] simtype) throws RemoteException {
     }
+
+    @Override
+    public void onDualDataCapabilityChanged(Token token, Status status, boolean support)
+            throws RemoteException {
+    }
+
+    @Override
+    public void setDualDataUserPreferenceResponse(Token token, Status status)
+            throws RemoteException {
+    }
+
+    @Override
+    public void onDualDataRecommendation(DualDataRecommendation rec)
+            throws RemoteException {
+    }
+
+    @Override
+    public void onSimPersoUnlockStatusChange(int slotId, QtiPersoUnlockStatus persoUnlockStatus)
+            throws RemoteException {
+    }
 }
diff --git a/extphone/src/com/qti/extphone/ExtPhoneCallbackListener.java b/extphone/src/com/qti/extphone/ExtPhoneCallbackListener.java
new file mode 100644
index 0000000..d4b006e
--- /dev/null
+++ b/extphone/src/com/qti/extphone/ExtPhoneCallbackListener.java
@@ -0,0 +1,1083 @@
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package com.qti.extphone;
+
+import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.os.RemoteException;
+import android.telephony.CellInfo;
+import android.util.Log;
+
+import com.qti.extphone.BearerAllocationStatus;
+import com.qti.extphone.DcParam;
+import com.qti.extphone.DualDataRecommendation;
+import com.qti.extphone.IExtPhoneCallback;
+import com.qti.extphone.NetworkSelectionMode;
+import com.qti.extphone.NrConfig;
+import com.qti.extphone.NrConfigType;
+import com.qti.extphone.NrIconType;
+import com.qti.extphone.QRadioResponseInfo;
+import com.qti.extphone.QtiPersoUnlockStatus;
+import com.qti.extphone.SignalStrength;
+import com.qti.extphone.Status;
+import com.qti.extphone.Token;
+import com.qti.extphone.UpperLayerIndInfo;
+
+import java.lang.ref.WeakReference;
+import java.util.List;
+
+public class ExtPhoneCallbackListener {
+    private static final String TAG = "ExtPhoneCallbackListener";
+    private static final boolean DBG = true;
+
+    public static final int EVENT_ALL = 0;
+    public static final int EVENT_GET_FACILITY_LOCK_FOR_APP_RESPONSE = 1;
+    public static final int EVENT_GET_NETWORK_SELECTION_MODE_RESPONSE = 2;
+    public static final int EVENT_GET_QOS_PARAMETERS_RESPONSE =3 ;
+    public static final int EVENT_GET_QTIRADIO_CAPABILITY_RESPONSE = 4;
+    public static final int EVENT_GET_SECURE_MODE_STATUS_RESPONSE = 5;
+    public static final int EVENT_NETWORK_SCAN_RESULT = 6;
+    public static final int EVENT_ON_5G_CONFIG_INFO = 7;
+    public static final int EVENT_ON_5G_STATUS = 8;
+    public static final int EVENT_ON_ANY_NR_BEARER_ALLOCATION = 9;
+    public static final int EVENT_ON_DATA_DEACTIVATE_DELAY_TIME = 10;
+    public static final int EVENT_ON_DDS_SWITCH_CAPABILITY_CHANGE = 11;
+    public static final int EVENT_ON_DDS_SWITCH_CRITERIA_CHANGE = 12;
+    public static final int EVENT_ON_DDS_SWITCH_RECOMMENDATION = 13;
+    public static final int EVENT_ON_ENABLE_ENDC = 14;
+    public static final int EVENT_ON_ENDC_STATUS = 15;
+    public static final int EVENT_ON_EPDG_OVER_CELLULAR_DATA_SUPPORTED = 16;
+    public static final int EVENT_ON_IMEI_TYPE_CHANGED = 17;
+    public static final int EVENT_ON_NR_CONFIG_STATUS = 18;
+    public static final int EVENT_ON_NR_DC_PARAM = 19;
+    public static final int EVENT_ON_NR_ICON_TYPE = 20;
+    public static final int EVENT_ON_QOS_PARAMETERS_CHANGED = 21;
+    public static final int EVENT_ON_SECURE_MODE_STATUS_CHANGE = 22;
+    public static final int EVENT_ON_SEND_USER_PREFERENCE_FOR_DATA_DURING_VOICE_CALL = 23;
+    public static final int EVENT_ON_SET_NR_CONFIG = 24;
+    public static final int EVENT_ON_SIGNAL_STRENGTH = 25;
+    public static final int EVENT_ON_SIM_TYPE_CHANGED = 26;
+    public static final int EVENT_ON_UPPER_LAYER_IND_INFO = 27;
+    public static final int EVENT_QUERY_CALL_FORWARD_STATUS_RESPONSE = 28;
+    public static final int EVENT_SEND_CDMA_SMS_RESPONSE = 29;
+    public static final int EVENT_SET_CARRIER_INFO_FOR_IMSI_ENCRYPTION_RESPONSE = 30;
+    public static final int EVENT_SET_MSIM_PREFERENCE_RESPONSE = 31;
+    public static final int EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_RESPONSE = 32;
+    public static final int EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_RESPONSE = 33;
+    public static final int EVENT_SET_SIM_TYPE_RESPONSE = 34;
+    public static final int EVENT_SET_SMART_DDS_SWITCH_TOGGLE_RESPONSE = 35;
+    public static final int EVENT_START_NETWORK_SCAN_RESPONSE = 36;
+    public static final int EVENT_STOP_NETWORK_SCAN_RESPONSE = 37;
+    public static final int EVENT_ON_CIWLAN_CAPABILITY_CHANGE = 38;
+    public static final int EVENT_ON_DUAL_DATA_CAPABILITY_CHANGED = 39;
+    public static final int EVENT_SET_DUAL_DATA_USER_PREFERENCE_RESPONSE = 40;
+    public static final int EVENT_ON_DUAL_DATA_RECOMMENDATION = 41;
+    public static final int EVENT_ON_SIM_PERSO_UNLOCK_STATUS_CHANGE = 42;
+
+    private Handler mHandler;
+    IExtPhoneCallback mCallback = new IExtPhoneCallbackStub(this);
+
+    public ExtPhoneCallbackListener() {
+        HandlerThread headlerThread = new HandlerThread(TAG);
+        headlerThread.start();
+        Looper looper = headlerThread.getLooper();
+        init(looper);
+    }
+
+    public ExtPhoneCallbackListener(Looper looper) {
+        init(looper);
+    }
+
+    private void init(Looper looper) {
+        mHandler = new Handler(looper) {
+            public void handleMessage(Message msg) {
+                Log.d(TAG, "handleMessage");
+                if (DBG) {
+                    Log.d(TAG, " what=0x" + Integer.toHexString(msg.what) + " msg=" + msg);
+                }
+                switch (msg.what) {
+                    case EVENT_GET_FACILITY_LOCK_FOR_APP_RESPONSE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.getFacilityLockForAppResponse(
+                                    result.mStatus, (int[]) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_GET_FACILITY_LOCK_FOR_APP_RESPONSE : Exception = " +
+                                    e);
+                        }
+                        break;
+                    case EVENT_GET_NETWORK_SELECTION_MODE_RESPONSE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.getNetworkSelectionModeResponse(
+                                    result.mSlotId, result.mToken, result.mStatus,
+                                    (NetworkSelectionMode) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_GET_NETWORK_SELECTION_MODE_RESPONSE : Exception = " +
+                                    e);
+                        }
+                        break;
+                    case EVENT_GET_QOS_PARAMETERS_RESPONSE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.getQosParametersResponse(result.mSlotId,
+                                    result.mToken, result.mStatus,
+                                    (QosParametersResult) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_GET_QOS_PARAMETERS_RESPONSE : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_GET_QTIRADIO_CAPABILITY_RESPONSE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.getQtiRadioCapabilityResponse(
+                                    result.mSlotId, result.mToken, result.mStatus,
+                                    (int) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_GET_QTIRADIO_CAPABILITY_RESPONSE : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_GET_SECURE_MODE_STATUS_RESPONSE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.getSecureModeStatusResponse(result.mToken,
+                                    result.mStatus, (boolean) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_GET_SECURE_MODE_STATUS_RESPONSE : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_NETWORK_SCAN_RESULT:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.networkScanResult(result.mSlotId,
+                                    result.mToken, result.mStatus.get(), result.mError,
+                                    (List<CellInfo>) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_NETWORK_SCAN_RESULT : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_5G_CONFIG_INFO:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.on5gConfigInfo(result.mSlotId,
+                                    result.mToken, result.mStatus, (NrConfigType) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_5G_CONFIG_INFO : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_5G_STATUS:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.on5gStatus(result.mSlotId, result.mToken,
+                                    result.mStatus, (boolean) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_5G_STATUS : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_ANY_NR_BEARER_ALLOCATION:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onAnyNrBearerAllocation(result.mSlotId,
+                                    result.mToken, result.mStatus,
+                                    (BearerAllocationStatus) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_ANY_NR_BEARER_ALLOCATION : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_DATA_DEACTIVATE_DELAY_TIME:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onDataDeactivateDelayTime(result.mSlotId,
+                                    (long) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_DATA_DEACTIVATE_DELAY_TIME : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_DDS_SWITCH_CAPABILITY_CHANGE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onDdsSwitchCapabilityChange(
+                                    result.mSlotId, result.mToken, result.mStatus,
+                                    (boolean) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_DDS_SWITCH_CAPABILITY_CHANGE : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_DDS_SWITCH_CRITERIA_CHANGE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onDdsSwitchCriteriaChange(result.mSlotId,
+                                    (boolean) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_DDS_SWITCH_CRITERIA_CHANGE : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_DDS_SWITCH_RECOMMENDATION:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onDdsSwitchRecommendation(result.mSlotId,
+                                    (int) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_DDS_SWITCH_RECOMMENDATION : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_ENABLE_ENDC:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onEnableEndc(result.mSlotId,
+                                    result.mToken, result.mStatus);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_ENABLE_ENDC : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_ENDC_STATUS:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onEndcStatus(result.mSlotId,
+                                    result.mToken, result.mStatus, (boolean) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_ENDC_STATUS : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_EPDG_OVER_CELLULAR_DATA_SUPPORTED:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onEpdgOverCellularDataSupported(
+                                    result.mSlotId, (boolean) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_EPDG_OVER_CELLULAR_DATA_SUPPORTED : Exception = "
+                                    + e);
+                        }
+                        break;
+                    case EVENT_ON_IMEI_TYPE_CHANGED:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onImeiTypeChanged(
+                                    (QtiImeiInfo[]) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_IMEI_TYPE_CHANGED : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_NR_CONFIG_STATUS:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onNrConfigStatus(result.mSlotId,
+                                    result.mToken, result.mStatus, (NrConfig) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_NR_CONFIG_STATUS : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_NR_DC_PARAM:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onNrDcParam(result.mSlotId,
+                                    result.mToken, result.mStatus, (DcParam) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_NR_DC_PARAM : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_NR_ICON_TYPE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onNrIconType(result.mSlotId,
+                                    result.mToken, result.mStatus, (NrIconType) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_NR_ICON_TYPE : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_QOS_PARAMETERS_CHANGED:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onQosParametersChanged(result.mSlotId,
+                                    result.mError, (QosParametersResult) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_QOS_PARAMETERS_CHANGED : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_SECURE_MODE_STATUS_CHANGE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onSecureModeStatusChange(
+                                    (boolean) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_SECURE_MODE_STATUS_CHANGE : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_SEND_USER_PREFERENCE_FOR_DATA_DURING_VOICE_CALL:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.
+                                    onSendUserPreferenceForDataDuringVoiceCall(result.mSlotId,
+                                    result.mToken, result.mStatus);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_SEND_USER_PREFERENCE_FOR_DATA_DURING_VOICE_CALL : "
+                                    + "Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_SET_NR_CONFIG:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onSetNrConfig(result.mSlotId,
+                                    result.mToken, result.mStatus);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_SET_NR_CONFIG : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_SIGNAL_STRENGTH:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onSignalStrength(result.mSlotId,
+                                    result.mToken, result.mStatus, (SignalStrength) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_SIGNAL_STRENGTH : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_SIM_TYPE_CHANGED:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onSimTypeChanged(
+                                    (QtiSimType[]) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_SIM_TYPE_CHANGED : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_UPPER_LAYER_IND_INFO:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onUpperLayerIndInfo(result.mSlotId,
+                                    result.mToken, result.mStatus,
+                                    (UpperLayerIndInfo) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_UPPER_LAYER_IND_INFO : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_QUERY_CALL_FORWARD_STATUS_RESPONSE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.queryCallForwardStatusResponse(
+                                    result.mStatus, (QtiCallForwardInfo[]) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_QUERY_CALL_FORWARD_STATUS_RESPONSE : Exception = " +
+                                    e);
+                        }
+                        break;
+                    case EVENT_SEND_CDMA_SMS_RESPONSE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.sendCdmaSmsResponse(result.mSlotId,
+                                    result.mToken, result.mStatus, (SmsResult) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_SEND_CDMA_SMS_RESPONSE : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_SET_CARRIER_INFO_FOR_IMSI_ENCRYPTION_RESPONSE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.setCarrierInfoForImsiEncryptionResponse(
+                                    result.mSlotId, result.mToken,
+                                    (QRadioResponseInfo) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_SET_CARRIER_INFO_FOR_IMSI_ENCRYPTION_RESPONSE : " +
+                                    "Exception = " + e);
+                        }
+                        break;
+                    case EVENT_SET_MSIM_PREFERENCE_RESPONSE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.setMsimPreferenceResponse(result.mToken,
+                                    result.mStatus);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_SET_MSIM_PREFERENCE_RESPONSE : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_RESPONSE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.setNetworkSelectionModeAutomaticResponse(
+                                    result.mSlotId, result.mToken, result.mError);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_RESPONSE : " +
+                                    "Exception = " + e);
+                        }
+                        break;
+                    case EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_RESPONSE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.setNetworkSelectionModeManualResponse(
+                                    result.mSlotId, result.mToken, result.mError);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_RESPONSE : " +
+                                    "Exception = " + e);
+                        }
+                        break;
+                    case EVENT_SET_SIM_TYPE_RESPONSE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.setSimTypeResponse(result.mToken,
+                                    result.mStatus);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_SET_SIM_TYPE_RESPONSE : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_SET_SMART_DDS_SWITCH_TOGGLE_RESPONSE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.setSmartDdsSwitchToggleResponse(
+                                    result.mToken, (boolean) result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_SET_SMART_DDS_SWITCH_TOGGLE_RESPONSE : Exception = " +
+                                    e);
+                        }
+                        break;
+                    case EVENT_START_NETWORK_SCAN_RESPONSE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                        ExtPhoneCallbackListener.this.startNetworkScanResponse(result.mSlotId,
+                                result.mToken, result.mError);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_START_NETWORK_SCAN_RESPONSE : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_STOP_NETWORK_SCAN_RESPONSE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.stopNetworkScanResponse(result.mSlotId,
+                                    result.mToken, result.mError);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_STOP_NETWORK_SCAN_RESPONSE : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_DUAL_DATA_CAPABILITY_CHANGED:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onDualDataCapabilityChanged(
+                                    result.mToken, result.mStatus, (boolean)result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_DUAL_DATA_CAPABILITY_CHANGED : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_SET_DUAL_DATA_USER_PREFERENCE_RESPONSE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.setDualDataUserPreferenceResponse(
+                                    result.mToken, result.mStatus);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_SET_DUAL_DATA_USER_PREFERENCE_RESPONSE :" +
+                                    "Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_DUAL_DATA_RECOMMENDATION:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onDualDataRecommendation(
+                                    (DualDataRecommendation)result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG, "EVENT_ON_DUAL_DATA_RECOMMENDATION : Exception = " + e);
+                        }
+                        break;
+                    case EVENT_ON_SIM_PERSO_UNLOCK_STATUS_CHANGE:
+                        try {
+                            IExtPhoneCallbackStub.Result result =
+                                    (IExtPhoneCallbackStub.Result) msg.obj;
+                            ExtPhoneCallbackListener.this.onSimPersoUnlockStatusChange(
+                                    result.mSlotId, (QtiPersoUnlockStatus)result.mData);
+                        } catch (RemoteException e) {
+                            Log.e(TAG,
+                                    "EVENT_ON_SIM_PERSO_UNLOCK_STATUS_CHANGE : Exception = " + e);
+                        }
+                        break;
+                    default :
+                        Log.d(TAG, "default : " + msg.what);
+                }
+            }
+        };
+    }
+
+    public void onNrIconType(int slotId, Token token, Status status, NrIconType nrIconType) throws
+            RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onNrIconType: slotId = " + slotId + " token = " + token +
+                " status = " + status + " NrIconType = " + nrIconType);
+    }
+
+    public void onEnableEndc(int slotId, Token token, Status status) throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onEnableEndc: slotId = " + slotId + " token = " + token +
+                " status = " + status);
+    }
+
+    public void onEndcStatus(int slotId, Token token, Status status, boolean enableStatus) throws
+            RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onEndcStatus: slotId = " + slotId + " token = " + token +
+                " status = " + status + " enableStatus = " + enableStatus);
+    }
+
+    public void onSetNrConfig(int slotId, Token token, Status status) throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onSetNrConfig: slotId = " + slotId + " token = " + token +
+                " status = " +status);
+    }
+
+    public void onNrConfigStatus(int slotId, Token token, Status status, NrConfig nrConfig) throws
+            RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onNrConfigStatus: slotId = " + slotId + " token = " + token +
+                " status = " + status + " NrConfig = " + nrConfig);
+    }
+
+    public void sendCdmaSmsResponse(int slotId, Token token, Status status, SmsResult sms) throws
+            RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: sendCdmaSmsResponse: slotId = " + slotId +
+                " token = " + token + " status = " + status + " SmsResult = " + sms);
+    }
+
+    public void on5gStatus(int slotId, Token token, Status status, boolean enableStatus) throws
+            RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: on5gStatus: slotId = " + slotId + " token = " + token +
+                " status" + status + " enableStatus = " + enableStatus);
+    }
+
+    public void onAnyNrBearerAllocation(int slotId, Token token, Status status,
+            BearerAllocationStatus bearerStatus) throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onAnyNrBearerAllocation: slotId = " + slotId +
+                " token = " + token + " status = " + status + " bearerStatus = " + bearerStatus);
+    }
+
+    public void getQtiRadioCapabilityResponse(int slotId, Token token, Status status, int raf)
+            throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: getQtiRadioCapabilityResponse: slotId = " + slotId +
+                " token = " + token + " status" + status + " raf = " + raf);
+    }
+
+    public void getQosParametersResponse(int slotId, Token token, Status status,
+                QosParametersResult result) throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: getQosParametersResponse: slotId = " + slotId +
+                " token = " + token + " status" + status + " result = " + result);
+    }
+
+    public void onNrDcParam(int slotId, Token token, Status status, DcParam dcParam) throws
+            RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onNrDcParam: slotId = " + slotId +
+                " token = " + token + " status" + status + " dcParam = " + dcParam);
+    }
+
+    public void onUpperLayerIndInfo(int slotId, Token token, Status status,
+            UpperLayerIndInfo uilInfo) throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onUpperLayerIndInfo: slotId = " + slotId +
+                " token = " + token + " " + "status" + status +
+                " UpperLayerIndInfo = " + uilInfo);
+    }
+
+    public void on5gConfigInfo(int slotId, Token token, Status status, NrConfigType nrConfigType)
+            throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: on5gConfigInfo: slotId = " + slotId + " token = " +
+                token + " " + "status" + status + " NrConfigType = " + nrConfigType);
+    }
+
+    public void onSignalStrength(int slotId, Token token, Status status,
+            SignalStrength signalStrength) throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onSignalStrength: slotId = " + slotId +
+                " token = " + token + " " + "status" + status +
+                " signalStrength = " + signalStrength);
+    }
+
+    public void setCarrierInfoForImsiEncryptionResponse(int slotId, Token token,
+            QRadioResponseInfo info) throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: setCarrierInfoForImsiEncryptionResponse: slotId = " + slotId +
+                " token = " + token + " info = " + info);
+    }
+
+    public void queryCallForwardStatusResponse(Status status, QtiCallForwardInfo[] infos) throws
+            RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: queryCallForwardStatusResponse: status = " + status +
+                " CallForwardInfo = " + infos);
+    }
+
+    public void getFacilityLockForAppResponse(Status status, int[] response) throws
+            RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: getFacilityLockForAppResponse: status = " + status +
+                " response = " + response);
+    }
+
+    public void setSmartDdsSwitchToggleResponse(Token token, boolean result) throws
+            RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: setSmartDdsSwitchToggleResponse: token = " + token +
+                " result = " + result);
+    }
+
+    public void onImeiTypeChanged(QtiImeiInfo[] imeiInfo) throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onImeiTypeChanged: imeiInfo = " + imeiInfo);
+    }
+
+    public void onSendUserPreferenceForDataDuringVoiceCall(int slotId, Token token, Status status)
+            throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onSendUserPreferenceForDataDuringVoiceCall: slotId = " + slotId +
+                " token = " + token + " status = " + status);
+    }
+
+    public void onDdsSwitchCapabilityChange(int slotId, Token token, Status status, boolean support)
+            throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onDdsSwitchCapabilityChange: slotId = " + slotId + " token = " +
+                token + " status = " + status + " support = " + support);
+    }
+
+    public void onDdsSwitchCriteriaChange(int slotId, boolean telephonyDdsSwitch)
+            throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onDdsSwitchCriteriaChange: slotId = " + slotId +
+                " telephonyDdsSwitch = " + telephonyDdsSwitch);
+    }
+
+    public void onDdsSwitchRecommendation(int slotId, int recommendedSlotId)
+            throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onDdsSwitchRecommendation: slotId = " + slotId +
+                " recommendedSlotId = " + recommendedSlotId);
+    }
+
+    public void onDataDeactivateDelayTime(int slotId, long delayTimeMilliSecs)
+            throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onDataDeactivateDelayTime: slotId = " + slotId +
+                " delayTimeMilliSecs = " + delayTimeMilliSecs);
+    }
+
+    public void onEpdgOverCellularDataSupported(int slotId, boolean support)
+            throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onEpdgOverCellularDataSupported: slotId = " + slotId +
+                " support = " + support);
+    }
+
+    public void getSecureModeStatusResponse(Token token, Status status, boolean enableStatus)
+            throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: getSecureModeStatusResponse: token = " + token + " status = " +
+                status + " enableStatus = " + enableStatus);
+    }
+
+    public void onSecureModeStatusChange(boolean enabled) throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onSecureModeStatusChange: enabled = " + enabled);
+    }
+
+    public void startNetworkScanResponse(int slotId, Token token, int errorCode) throws
+            RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: startNetworkScanResponse: slotId = " + slotId +
+                " token = " + token + " errorCode = " + errorCode);
+    }
+
+    public void stopNetworkScanResponse(int slotId, Token token, int errorCode) throws
+            RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: stopNetworkScanResponse: slotId = " + slotId +
+                " token = " + token + " errorCode = " + errorCode);
+    }
+
+    public void setNetworkSelectionModeManualResponse(int slotId, Token token, int errorCode) throws
+            RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: setNetworkSelectionModeManualResponse: slotId = " + slotId +
+                " token = " + token + " errorCode = " + errorCode);
+    }
+
+    public void setNetworkSelectionModeAutomaticResponse(int slotId, Token token, int errorCode)
+            throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: setNetworkSelectionModeAutomaticResponse: slotId = " + slotId +
+                " token = " + token + " errorCode = " + errorCode);
+    }
+
+    public void getNetworkSelectionModeResponse(int slotId, Token token, Status status,
+            NetworkSelectionMode modes) throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: getNetworkSelectionModeResponse: slotId = " + slotId +
+                " token = " + token + " status = " + status + " modes = " + modes);
+    }
+
+    public void networkScanResult(int slotId, Token token, int status, int error,
+            List<CellInfo> cellInfos) throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: networkScanResult: slotId = " + slotId +
+                " token = " + token + " status = " + status + " error = " + error +
+                " cellInfos = " + cellInfos);
+    }
+
+    public void setMsimPreferenceResponse(Token token, Status status) throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: setMsimPreferenceResponse: token = " + token +
+                " status = " + status);
+    }
+
+    public void onQosParametersChanged(int slotId, int cid, QosParametersResult result)
+            throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onQosParametersChanged: slotId = " + slotId +
+                " cid = " + cid + " result = " + result);
+    }
+
+    public void setSimTypeResponse(Token token, Status status) throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: setSimTypeResponse: token = " + token + " status = " + status);
+    }
+
+    public void onSimTypeChanged(QtiSimType[] simtype) throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onSimTypeChanged: simtype = " + simtype);
+    }
+
+    public void onDualDataCapabilityChanged(Token token, Status status, boolean support)
+            throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onDualDataCapabilityChanged: support = " + support);
+    }
+
+    public void setDualDataUserPreferenceResponse(Token token, Status status)
+            throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: setDualDataUserPreferenceResponse: token = "
+                + token + " status = " + status);
+    }
+
+    public void onDualDataRecommendation(DualDataRecommendation rec)
+            throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onDualDataRecommendation: rec = " + rec);
+    }
+
+    public void onSimPersoUnlockStatusChange(int slotId, QtiPersoUnlockStatus persoUnlockStatus)
+            throws RemoteException {
+        Log.d(TAG, "UNIMPLEMENTED: onSimPersoUnlockStatusChange: slotId = "
+                + slotId + " persoUnlockStatus = " + persoUnlockStatus);
+    }
+
+    private static class IExtPhoneCallbackStub extends IExtPhoneCallback.Stub {
+        private WeakReference<ExtPhoneCallbackListener> mExtPhoneCallbackListenerWeakRef;
+
+        public IExtPhoneCallbackStub(ExtPhoneCallbackListener extPhoneCallbackListener) {
+            mExtPhoneCallbackListenerWeakRef =
+                    new WeakReference<ExtPhoneCallbackListener>(extPhoneCallbackListener);
+        }
+
+        private void send(int what, int arg1, int arg2, Object obj) {
+            ExtPhoneCallbackListener listener = mExtPhoneCallbackListenerWeakRef.get();
+            if (listener != null) {
+                Message.obtain(listener.mHandler, what, arg1, arg2, obj).sendToTarget();
+            } else {
+                if (DBG) {
+                    Log.d(TAG, " listener is null");
+                }
+            }
+        }
+
+        @Override
+        public void onNrIconType(int slotId, Token token, Status status, NrIconType nrIconType)
+                throws RemoteException {
+            send(EVENT_ON_NR_ICON_TYPE, 0, 0, new Result(slotId, token, status, 0, nrIconType));
+        }
+
+        @Override
+        public void onEnableEndc(int slotId, Token token, Status status) throws RemoteException {
+            send(EVENT_ON_ENABLE_ENDC, 0, 0, new Result(slotId, token, status, 0, null));
+        }
+
+        @Override
+        public void onEndcStatus(int slotId, Token token, Status status, boolean enableStatus)
+                throws RemoteException {
+            send(EVENT_ON_ENDC_STATUS, 0, 0, new Result(slotId, token, status, 0, enableStatus));
+        }
+
+        @Override
+        public void onSetNrConfig(int slotId, Token token, Status status) throws RemoteException {
+            send(EVENT_ON_SET_NR_CONFIG, 0, 0, new Result(slotId, token, status, 0, null));
+        }
+
+        @Override
+        public void onNrConfigStatus(int slotId, Token token, Status status, NrConfig nrConfig)
+                throws RemoteException {
+            send(EVENT_ON_NR_CONFIG_STATUS, 0, 0, new Result(slotId, token, status, 0, nrConfig));
+        }
+
+        @Override
+        public void sendCdmaSmsResponse(int slotId, Token token, Status status, SmsResult sms)
+                throws RemoteException {
+            send(EVENT_SEND_CDMA_SMS_RESPONSE, 0, 0, new Result(slotId, token, status, 0, sms));
+        }
+
+        @Override
+        public void on5gStatus(int slotId, Token token, Status status, boolean enableStatus) throws
+                RemoteException {
+            send(EVENT_ON_5G_STATUS, 0, 0, new Result(slotId, token, status, 0, enableStatus));
+        }
+
+        @Override
+        public void onAnyNrBearerAllocation(int slotId, Token token, Status status,
+                BearerAllocationStatus bearerStatus) throws RemoteException {
+            send(EVENT_ON_ANY_NR_BEARER_ALLOCATION, 0, 0, new Result(slotId, token, status, 0,
+                    bearerStatus));
+        }
+
+        @Override
+        public void getQtiRadioCapabilityResponse(int slotId, Token token, Status status, int raf)
+                throws RemoteException {
+            send(EVENT_GET_QTIRADIO_CAPABILITY_RESPONSE, 0, 0, new Result(slotId, token, status, 0,
+                    raf));
+        }
+
+        @Override
+        public void getQosParametersResponse(int slotId, Token token, Status status,
+                    QosParametersResult result) throws RemoteException {
+            send(EVENT_GET_QOS_PARAMETERS_RESPONSE, 0, 0, new Result(slotId, token, status, 0,
+                    result));
+        }
+
+        public void onNrDcParam(int slotId, Token token, Status status, DcParam dcParam) throws
+                RemoteException {
+            send(EVENT_ON_NR_DC_PARAM, 0, 0, new Result(slotId, token, status, 0, dcParam));
+        }
+
+        @Override
+        public void onUpperLayerIndInfo(int slotId, Token token, Status status,
+                UpperLayerIndInfo uilInfo) throws RemoteException {
+            send(EVENT_ON_UPPER_LAYER_IND_INFO, 0, 0, new Result(slotId, token, status, 0,
+                    uilInfo));
+        }
+
+        @Override
+        public void on5gConfigInfo(int slotId, Token token, Status status,
+                NrConfigType nrConfigType) throws RemoteException {
+            send(EVENT_ON_5G_CONFIG_INFO, 0, 0, new Result(slotId, token, status, 0,
+                    nrConfigType));
+        }
+
+        @Override
+        public void onSignalStrength(int slotId, Token token, Status status,
+                SignalStrength signalStrength) throws RemoteException {
+            send(EVENT_ON_SIGNAL_STRENGTH, 0, 0, new Result(slotId, token, status, 0,
+                    signalStrength));
+        }
+
+        @Override
+        public void setCarrierInfoForImsiEncryptionResponse(int slotId, Token token,
+                QRadioResponseInfo info) throws RemoteException {
+            send(EVENT_SET_CARRIER_INFO_FOR_IMSI_ENCRYPTION_RESPONSE, 0, 0, new Result(slotId,
+                    token, null, 0, info));
+        }
+
+        @Override
+        public void queryCallForwardStatusResponse(Status status, QtiCallForwardInfo[] infos) throws
+                RemoteException {
+            send(EVENT_QUERY_CALL_FORWARD_STATUS_RESPONSE, 0, 0, new Result(0, null, status, 0,
+                    infos));
+        }
+
+        @Override
+        public void getFacilityLockForAppResponse(Status status, int[] response) throws
+                RemoteException {
+            send(EVENT_GET_FACILITY_LOCK_FOR_APP_RESPONSE, 0, 0, new Result(0, null, status, 0,
+                    response));
+        }
+
+        @Override
+        public void setSmartDdsSwitchToggleResponse(Token token, boolean result) throws
+                RemoteException {
+            send(EVENT_SET_SMART_DDS_SWITCH_TOGGLE_RESPONSE, 0, 0, new Result(0, token, null, 0,
+                    result));
+        }
+
+        @Override
+        public void onImeiTypeChanged(QtiImeiInfo[] imeiInfo) throws RemoteException {
+            send(EVENT_ON_IMEI_TYPE_CHANGED, 0, 0, new Result(-1 , null, null, -1, imeiInfo));
+        }
+
+        public void onSendUserPreferenceForDataDuringVoiceCall(int slotId, Token token,
+                Status status) throws RemoteException {
+            send(EVENT_ON_SEND_USER_PREFERENCE_FOR_DATA_DURING_VOICE_CALL, 0, 0, new Result(slotId,
+                    token, status, 0, null));
+        }
+
+        @Override
+        public void onDdsSwitchCapabilityChange(int slotId, Token token, Status status,
+                boolean support) throws RemoteException {
+            send(EVENT_ON_DDS_SWITCH_CAPABILITY_CHANGE, 0, 0, new Result(slotId, token, status, 0,
+                    support));
+        }
+
+        @Override
+        public void onDdsSwitchCriteriaChange(int slotId, boolean telephonyDdsSwitch)
+                throws RemoteException {
+            send(EVENT_ON_DDS_SWITCH_CRITERIA_CHANGE, 0, 0,
+                    new Result(slotId , null, null, -1, telephonyDdsSwitch));
+        }
+
+        @Override
+        public void onDdsSwitchRecommendation(int slotId, int recommendedSlotId)
+                throws RemoteException {
+            send(EVENT_ON_DDS_SWITCH_RECOMMENDATION, 0, 0,
+                    new Result(slotId , null, null, -1, recommendedSlotId));
+        }
+
+        @Override
+        public void onDataDeactivateDelayTime(int slotId, long delayTimeMilliSecs)
+                throws RemoteException {
+            send(EVENT_ON_DATA_DEACTIVATE_DELAY_TIME, 0, 0,
+                    new Result(slotId , null, null, -1, delayTimeMilliSecs));
+        }
+
+        @Override
+        public void onEpdgOverCellularDataSupported(int slotId, boolean support)
+                throws RemoteException {
+            send(EVENT_ON_EPDG_OVER_CELLULAR_DATA_SUPPORTED, 0, 0,
+                    new Result(slotId , null, null, -1, support));
+        }
+
+        @Override
+        public void getSecureModeStatusResponse(Token token, Status status, boolean enableStatus)
+                throws RemoteException {
+            send(EVENT_GET_SECURE_MODE_STATUS_RESPONSE, 0, 0, new Result(0, token, status, 0,
+                    enableStatus));
+        }
+
+        @Override
+        public void onSecureModeStatusChange(boolean enabled) throws RemoteException {
+            send(EVENT_ON_SECURE_MODE_STATUS_CHANGE, 0, 0, new Result(-1, null, null, -1, enabled));
+        }
+
+        @Override
+        public void startNetworkScanResponse(int slotId, Token token, int errorCode) throws
+                RemoteException {
+            send(EVENT_START_NETWORK_SCAN_RESPONSE, 0, 0, new Result(slotId, token, null, errorCode,
+                    null));
+        }
+
+        @Override
+        public void stopNetworkScanResponse(int slotId, Token token, int errorCode) throws
+                RemoteException {
+            send(EVENT_STOP_NETWORK_SCAN_RESPONSE, 0, 0, new Result(slotId, token, null, errorCode,
+                    null));
+        }
+
+        @Override
+        public void setNetworkSelectionModeManualResponse(int slotId, Token token, int errorCode)
+                throws RemoteException {
+            send(EVENT_SET_NETWORK_SELECTION_MODE_MANUAL_RESPONSE, 0, 0, new Result(slotId, token,
+                    null, errorCode, null));
+        }
+
+        @Override
+        public void setNetworkSelectionModeAutomaticResponse(int slotId, Token token, int errorCode)
+                throws RemoteException {
+            send(EVENT_SET_NETWORK_SELECTION_MODE_AUTOMATIC_RESPONSE, 0, 0, new Result(slotId,
+                    token, null, errorCode, null));
+        }
+
+        @Override
+        public void getNetworkSelectionModeResponse(int slotId, Token token, Status status,
+                NetworkSelectionMode modes) throws RemoteException {
+            send(EVENT_GET_NETWORK_SELECTION_MODE_RESPONSE, 0, 0, new Result(slotId, token,
+                    status, 0, modes));
+        }
+
+        @Override
+        public void networkScanResult(int slotId, Token token, int status, int error,
+                List<CellInfo> cellInfos) throws RemoteException {
+            send(EVENT_NETWORK_SCAN_RESULT, 0, 0, new Result(slotId, token, new Status(status),
+                    error, cellInfos));
+        }
+
+        @Override
+        public void setMsimPreferenceResponse(Token token, Status status) throws RemoteException {
+            send(EVENT_SET_MSIM_PREFERENCE_RESPONSE, 0, 0, new Result(0, token, status, 0, null));
+        }
+
+        @Override
+        public void onQosParametersChanged(int slotId, int cid, QosParametersResult result)
+                throws RemoteException {
+            send(EVENT_ON_QOS_PARAMETERS_CHANGED, 0, 0,
+                    new Result(slotId, null, null, cid, result));
+        }
+
+        @Override
+        public void setSimTypeResponse(Token token, Status status) throws RemoteException {
+            send(EVENT_SET_SIM_TYPE_RESPONSE, 0, 0, new Result(0, token, status, 0, null));
+        }
+
+        @Override
+        public void onSimTypeChanged(QtiSimType[] simtype) throws RemoteException {
+            send(EVENT_ON_SIM_TYPE_CHANGED, 0, 0, new Result(-1, null, null, -1, simtype));
+        }
+
+        @Override
+        public void onDualDataCapabilityChanged(Token token, Status status, boolean support)
+                throws RemoteException {
+            send(EVENT_ON_DUAL_DATA_CAPABILITY_CHANGED, 0, 0,
+                    new Result(-1, token, status, -1, support));
+        }
+
+        @Override
+        public void setDualDataUserPreferenceResponse(Token token, Status status)
+                throws RemoteException {
+            send(EVENT_SET_DUAL_DATA_USER_PREFERENCE_RESPONSE, 0, 0,
+                    new Result(-1, token, status, -1, null));
+        }
+
+        @Override
+        public void onDualDataRecommendation(DualDataRecommendation rec)
+                throws RemoteException {
+            send(EVENT_ON_DUAL_DATA_RECOMMENDATION, 0, 0,
+                    new Result(-1, null, null, -1, rec));
+        }
+
+        @Override
+        public void onSimPersoUnlockStatusChange(int slotId, QtiPersoUnlockStatus persoUnlockStatus)
+                throws RemoteException {
+            send(EVENT_ON_SIM_PERSO_UNLOCK_STATUS_CHANGE, 0, 0,
+                    new Result(slotId, null, null, -1, persoUnlockStatus));
+        }
+
+        class Result {
+            int mSlotId;
+            Token mToken;
+            Status mStatus;
+            int mError;
+            Object mData;
+
+            public Result(int mSlotId, Token mToken, Status mStatus, int mError, Object mData) {
+                this.mSlotId = mSlotId;
+                this.mToken = mToken;
+                this.mStatus = mStatus;
+                this.mError = mError;
+                this.mData = mData;
+            }
+
+            @Override
+            public String toString() {
+                return "Result{" + "mSlotId=" + mSlotId + ", mToken=" + mToken + ", mStatus=" +
+                        mStatus + ", mError=" + mError + ", mData=" + mData + "}";
+            }
+        }
+    }
+}
diff --git a/extphone/src/com/qti/extphone/ExtTelephonyManager.java b/extphone/src/com/qti/extphone/ExtTelephonyManager.java
index 525589f..b77a58d 100644
--- a/extphone/src/com/qti/extphone/ExtTelephonyManager.java
+++ b/extphone/src/com/qti/extphone/ExtTelephonyManager.java
@@ -30,7 +30,7 @@
 /*
  * Changes from Qualcomm Innovation Center are provided under the following license:
  *
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  * SPDX-License-Identifier: BSD-3-Clause-Clear
  */
 
@@ -1085,6 +1085,78 @@
         return null;
     }
 
+    public CiwlanConfig getCiwlanConfig(int slotId) throws RemoteException {
+        CiwlanConfig config = null;
+        if (!isServiceConnected()) {
+            Log.e(LOG_TAG, "service not connected!");
+            return config;
+        }
+        try {
+            config = mExtTelephonyService.getCiwlanConfig(slotId);
+        } catch (RemoteException e) {
+            Log.e(LOG_TAG, "getCiwlanConfig ended in remote exception", e);
+        }
+        return config;
+    }
+
+    /**
+     * Request dual data capability.
+     * It is a static modem capability.
+     *
+     * @return - boolean TRUE/FALSE based on modem supporting dual data capability feature.
+     */
+    public boolean getDualDataCapability() {
+        if (isServiceConnected()) {
+            try {
+                return mExtTelephonyService.getDualDataCapability();
+            } catch (RemoteException ex) {
+                Log.e(LOG_TAG, "getDualDataCapability Failed.", ex);
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Set dual data user preference.
+     * In a multi-SIM device, inform modem if user wants dual data feature or not.
+     * Modem will not send any recommendations to HLOS to support dual data
+     * if user does not opt in the feature even if UE is dual data capable.
+     *
+     * @param client - Client registered with package name to receive callbacks.
+     * @param enable - Dual data selection opted by user. True if preference is enabled.
+     * @return - Integer Token can be used to compare with the response, null Token value
+     *        can be returned if request cannot be processed.
+     *
+     * Response function is IExtPhoneCallback#setDualDataUserPreferenceResponse().
+     */
+    public Token setDualDataUserPreference(Client client, boolean enable) throws RemoteException {
+        Token token = null;
+        if (!isServiceConnected()) {
+            Log.e(LOG_TAG, "service not connected!");
+            return token;
+        }
+        try {
+            token = mExtTelephonyService.setDualDataUserPreference(client, enable);
+        } catch (RemoteException e) {
+            Log.e(LOG_TAG, "setDualDataUserPreference ended in remote exception", e);
+        }
+        return token;
+    }
+
+    public QtiPersoUnlockStatus getSimPersoUnlockStatus(int slotId) {
+        QtiPersoUnlockStatus persoUnlockStatus = null;
+        if (!isServiceConnected()) {
+            Log.e(LOG_TAG, "service not connected!");
+            return persoUnlockStatus;
+        }
+        try {
+            persoUnlockStatus = mExtTelephonyService.getSimPersoUnlockStatus(slotId);
+        } catch (RemoteException e) {
+            Log.e(LOG_TAG, "Remote exception for getSimPersoUnlockStatus", e);
+        }
+        return persoUnlockStatus;
+    }
+
     public Client registerCallback(String packageName, IExtPhoneCallback callback) {
         Client client = null;
         if (!isServiceConnected()) {
@@ -1099,6 +1171,22 @@
         return client;
     }
 
+    public Client registerCallbackWithEvents(String packageName, ExtPhoneCallbackListener callback,
+            int[] events) {
+        Client client = null;
+        if (!isServiceConnected()) {
+            Log.e(LOG_TAG, "service not connected!");
+            return client;
+        }
+        try {
+            client = mExtTelephonyService.registerCallbackWithEvents(packageName,
+                    callback.mCallback, events);
+        } catch (RemoteException e) {
+            Log.e(LOG_TAG, "registerCallbackWithEvents, remote exception", e);
+        }
+        return client;
+    }
+
     public void unRegisterCallback(IExtPhoneCallback callback) {
         if (!isServiceConnected()) {
             Log.e(LOG_TAG, "service not connected!");
@@ -1111,6 +1199,10 @@
         }
     }
 
+    public void unregisterCallback(ExtPhoneCallbackListener callback) {
+        unRegisterCallback(callback.mCallback);
+    }
+
     public Client registerQtiRadioConfigCallback(String packageName, IExtPhoneCallback callback) {
         Client client = null;
         if (!isServiceConnected()) {
diff --git a/extphone/src/com/qti/extphone/IExtPhone.aidl b/extphone/src/com/qti/extphone/IExtPhone.aidl
index 5c5a0c6..72641ce 100644
--- a/extphone/src/com/qti/extphone/IExtPhone.aidl
+++ b/extphone/src/com/qti/extphone/IExtPhone.aidl
@@ -30,7 +30,7 @@
 /*
  * Changes from Qualcomm Innovation Center are provided under the following license:
  *
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  * SPDX-License-Identifier: BSD-3-Clause-Clear
  */
 
@@ -38,15 +38,17 @@
 
 import android.telephony.ImsiEncryptionInfo;
 
-import com.qti.extphone.Token;
+import com.qti.extphone.CiwlanConfig;
 import com.qti.extphone.Client;
 import com.qti.extphone.IDepersoResCallback;
 import com.qti.extphone.IExtPhoneCallback;
 import com.qti.extphone.MsimPreference;
 import com.qti.extphone.NrConfig;
 import com.qti.extphone.QtiImeiInfo;
+import com.qti.extphone.QtiPersoUnlockStatus;
 import com.qti.extphone.QtiSetNetworkSelectionMode;
 import com.qti.extphone.QtiSimType;
+import com.qti.extphone.Token;
 
 interface IExtPhone {
 
@@ -244,25 +246,41 @@
     Token queryEndcStatus(int slotId, in Client client);
 
     /**
-    * Async api
+    * @param - packageName
+    * @param - callback the IExtPhoneCallback to register.
+    * @return Client that is registered.
     * Requires permission: android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE
     */
     Client registerCallback(String packageName, IExtPhoneCallback callback);
 
     /**
-    * Async api
+    * @param - packageName
+    * @param - callback the IExtPhoneCallback to register.
+    * @param - events that client want to listen.
+    * @return Client that is registered.
+    * Requires permission: android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE
+    */
+    Client registerCallbackWithEvents(String packageName, IExtPhoneCallback callback,
+            in int[] events);
+
+    /**
+    * @param - callback the IExtPhoneCallback to unregister.
+    * @return void
     * Requires permission: android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE
     */
     void unRegisterCallback(IExtPhoneCallback callback);
 
     /**
-    * Async api
+    * @param - packageName
+    * @param - callback the IExtPhoneCallback to register.
+    * @return Client that is registered.
     * Requires permission: android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE
     */
     Client registerQtiRadioConfigCallback(String packageName, IExtPhoneCallback callback);
 
     /**
-    * Async api
+    * @param - callback the IExtPhoneCallback to unregister.
+    * @return void
     * Requires permission: android.Manifest.permission.READ_PRIVILEGED_PHONE_STATE
     */
     void unregisterQtiRadioConfigCallback(IExtPhoneCallback callback);
@@ -568,4 +586,43 @@
      * @return - Integer Token can be used to compare with the response.
      */
     Token setSimType(in Client client, in QtiSimType[] simType);
+
+    /**
+     * Query the C_IWLAN mode
+     *
+     * @param - slotId slot ID
+     * @return - The C_IWLAN configuration (only vs preferred) for home and roaming
+     */
+    CiwlanConfig getCiwlanConfig(int slotId);
+
+    /**
+     * Request dual data capability.
+     * It is a static modem capability.
+     *
+     * @return - boolean TRUE/FALSE based on modem supporting dual data capability feature.
+     */
+     boolean getDualDataCapability();
+
+    /**
+     * Set dual data user preference.
+     * In a multi-SIM device, inform modem if user wants dual data feature or not.
+     * Modem will not send any recommendations to HLOS to support dual data
+     * if user does not opt in the feature even if UE is dual data capable.
+     *
+     * @param client - Client registered with package name to receive callbacks.
+     * @param enable - Dual data selection opted by user. True if preference is enabled.
+     * @return - Integer Token can be used to compare with the response, null Token value
+     *        can be returned if request cannot be processed.
+     *
+     * Response function is IExtPhoneCallback#setDualDataUserPreferenceResponse().
+     */
+    Token setDualDataUserPreference(in Client client, in boolean enable);
+
+    /**
+     * Query the SIM Perso unlock Status
+     *
+     * @param - slotId slot ID
+     * @return - persoUnlockStatus which can be generally temporary or permanent.
+     */
+    QtiPersoUnlockStatus getSimPersoUnlockStatus(int slotId);
 }
diff --git a/extphone/src/com/qti/extphone/IExtPhoneCallback.aidl b/extphone/src/com/qti/extphone/IExtPhoneCallback.aidl
index 484cedd..5434618 100644
--- a/extphone/src/com/qti/extphone/IExtPhoneCallback.aidl
+++ b/extphone/src/com/qti/extphone/IExtPhoneCallback.aidl
@@ -30,7 +30,7 @@
 /*
  * Changes from Qualcomm Innovation Center are provided under the following license:
  *
- * Copyright (c) 2022 Qualcomm Innovation Center, Inc. All rights reserved.
+ * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
  * SPDX-License-Identifier: BSD-3-Clause-Clear
  */
 
@@ -39,6 +39,7 @@
 import android.telephony.CellInfo;
 import com.qti.extphone.BearerAllocationStatus;
 import com.qti.extphone.DcParam;
+import com.qti.extphone.DualDataRecommendation;
 import com.qti.extphone.NetworkSelectionMode;
 import com.qti.extphone.NrConfig;
 import com.qti.extphone.NrConfigType;
@@ -47,6 +48,7 @@
 import com.qti.extphone.QosParametersResult;
 import com.qti.extphone.QtiCallForwardInfo;
 import com.qti.extphone.QtiImeiInfo;
+import com.qti.extphone.QtiPersoUnlockStatus;
 import com.qti.extphone.SignalStrength;
 import com.qti.extphone.QtiSimType;
 import com.qti.extphone.SmsResult;
@@ -270,7 +272,7 @@
 
     /**
      * Response to getSecureModeStatus
-     * @param - token is the same token which is received in setSmartDdsSwitchToggle
+     * @param - token is the same token which is passed in from getSecureModeStatus
      * @param - status SUCCESS/FAILURE based on RIL data module response
      * @param - enableStatus Secure Mode status - true: enabled, false: disabled
      */
@@ -359,4 +361,47 @@
      * @param - simtype array contains the current Sim Type on each Slot
      */
     void onSimTypeChanged(in QtiSimType[] simtype);
+
+    /**
+     * Response to getDualDataCapability and also called when dual data capability changes
+     *         in Modem.
+     *
+     * @param token to match request/response. Response must include same token as in request,
+     *         otherwise token is set to -1.
+     * @param status SUCCESS/FAILURE based on the modem result code
+     * @param support True if modem supports dual data feature.
+     */
+    void onDualDataCapabilityChanged(in Token token, in Status status, in boolean support);
+
+    /**
+     * Response to setDualDataUserPreference
+     * @param - token is the same token which is recived in
+     *          sendUserPreferenceForDataDuringVoiceCall
+     * @param - status SUCCESS/FAILURE based on RIL data module response
+     */
+    void setDualDataUserPreferenceResponse(in Token token, in Status status);
+
+    /**
+     * Received in the following conditions to allow/disallow internet pdn on nDDS
+     * after dual data user preference is sent as true
+     * to modem through IQtiRadioConfig#setDualDataUserPreference().
+     * Condition to send onDualDataRecommendation(NON_DDS and DATA_ALLOW):
+     *    1)UE is in DSDA sub-mode and in full concurrent condition
+     * Conditions to send onDualDataRecommendation(NON_DDS and DATA_DISALLOW):
+     *    1)UE is in DSDS sub-mode
+     *    2)UE is in TX sharing condition
+     *    3)IRAT is initiated on nDDS when UE is in L+NR RAT combo
+     *    4)nDDS is OOS
+     *
+     * @param rec <DualDataRecommendation> to allow/disallow internet pdn on nDDS.
+     */
+    void onDualDataRecommendation(in DualDataRecommendation rec);
+
+    /**
+     * Indication received when persoSubState is unlocked either temporarily or permanently
+     *
+     * @param - slotId on which the persoSubState changed
+     * @param - persoUnlockStatus which can be generally temporary or permanent.
+     */
+    void onSimPersoUnlockStatusChange(int slotId, in QtiPersoUnlockStatus persoUnlockStatus);
 }
diff --git a/extphone/src/com/qti/extphone/QtiPersoUnlockStatus.aidl b/extphone/src/com/qti/extphone/QtiPersoUnlockStatus.aidl
new file mode 100644
index 0000000..bfad957
--- /dev/null
+++ b/extphone/src/com/qti/extphone/QtiPersoUnlockStatus.aidl
@@ -0,0 +1,8 @@
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package com.qti.extphone;
+
+parcelable QtiPersoUnlockStatus;
\ No newline at end of file
diff --git a/extphone/src/com/qti/extphone/QtiPersoUnlockStatus.java b/extphone/src/com/qti/extphone/QtiPersoUnlockStatus.java
new file mode 100644
index 0000000..9d86524
--- /dev/null
+++ b/extphone/src/com/qti/extphone/QtiPersoUnlockStatus.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (c) 2023 Qualcomm Innovation Center, Inc. All rights reserved.
+ * SPDX-License-Identifier: BSD-3-Clause-Clear
+ */
+
+package com.qti.extphone;
+
+import android.os.Parcel;
+import android.os.Parcelable;
+
+public class QtiPersoUnlockStatus implements Parcelable {
+    private static final String TAG = "QtiPersoUnlockStatus";
+
+    public static final int UNKNOWN = 0;
+    public static final int TEMPORARY_UNLOCKED  = 1;
+    public static final int PERMANENT_UNLOCKED  = 2;
+
+    private int mPersoUnlockStatus;
+
+    public QtiPersoUnlockStatus(int status) {
+        mPersoUnlockStatus = status;
+    }
+
+    public QtiPersoUnlockStatus(Parcel in) {
+        mPersoUnlockStatus = in.readInt();
+    }
+
+    public int get() {
+        return mPersoUnlockStatus;
+    }
+
+    @Override
+    public int describeContents() {
+        return 0;
+    }
+
+    @Override
+    public void writeToParcel(Parcel out, int flags) {
+        out.writeInt(mPersoUnlockStatus);
+    }
+
+    public static final Parcelable.Creator<QtiPersoUnlockStatus> CREATOR =
+            new Parcelable.Creator() {
+        public QtiPersoUnlockStatus createFromParcel(Parcel in) {
+            return new QtiPersoUnlockStatus(in);
+        }
+
+        public QtiPersoUnlockStatus[] newArray(int size) {
+            return new QtiPersoUnlockStatus[size];
+        }
+    };
+
+    @Override
+    public String toString() {
+        return TAG + ": " + get();
+    }
+}
diff --git a/ims/ims-ext-common/src/org/codeaurora/ims/CrsCrbtControllerBase.java b/ims/ims-ext-common/src/org/codeaurora/ims/CrsCrbtControllerBase.java
index ab75505..e1d6708 100644
--- a/ims/ims-ext-common/src/org/codeaurora/ims/CrsCrbtControllerBase.java
+++ b/ims/ims-ext-common/src/org/codeaurora/ims/CrsCrbtControllerBase.java
@@ -32,36 +32,60 @@
 import android.os.RemoteException;
 import org.codeaurora.ims.internal.ICrsCrbtListener;
 import org.codeaurora.ims.internal.ICrsCrbtController;
+import org.codeaurora.ims.utils.QtiImsExtUtils;
 
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.Executor;
+
+// Check the permission of the calling process
 public abstract class CrsCrbtControllerBase {
     public final class CrsCrbtBinder extends ICrsCrbtController.Stub {
 
         @Override
         public void setCrsCrbtListener(ICrsCrbtListener listener)
-            throws RemoteException{
-            CrsCrbtControllerBase.this.onSetCrsCrbtListener(listener);
+                throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() -> {
+                try {
+                    CrsCrbtControllerBase.this.onSetCrsCrbtListener(listener);
+                } catch (RemoteException e) {
+                    throw new CompletionException(e);
+                }
+            }, "setCrsCrbtListener", mExecutor,
+            QtiImsExtUtils.MODIFY_PHONE_STATE, mContext);
         }
 
         @Override
         public void removeCrsCrbtListener(ICrsCrbtListener listener)
-            throws RemoteException{
-            CrsCrbtControllerBase.this.onRemoveCrsCrbtListener(listener);
+                throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    CrsCrbtControllerBase.this.onRemoveCrsCrbtListener(listener),
+                    "removeCrsCrbtListener", mExecutor,
+                    QtiImsExtUtils.MODIFY_PHONE_STATE, mContext);
         }
 
         @Override
         public boolean isPreparatorySession(String callId)
-            throws RemoteException {
-            return CrsCrbtControllerBase.this.onIsPreparatorySession(callId);
+                throws RemoteException {
+            return QtiImsExtUtils.executeMethodAsyncForResult(() ->
+                    CrsCrbtControllerBase.this.onIsPreparatorySession(callId),
+                    "isPreparatorySession", mExecutor, QtiImsExtUtils.MODIFY_PHONE_STATE,
+                    mContext);
         }
 
         @Override
         public void sendSipDtmf(String requestCode)
-            throws RemoteException {
-            CrsCrbtControllerBase.this.onSendSipDtmf(requestCode);
+                throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    CrsCrbtControllerBase.this.onSendSipDtmf(requestCode),
+                    "sendSipDtmf", mExecutor, QtiImsExtUtils.MODIFY_PHONE_STATE,
+                    mContext);
         }
+
     }
 
     private ICrsCrbtController mBinder;
+    private Executor mExecutor;
+    private Context mContext;
 
     public ICrsCrbtController getBinder() {
         if (mBinder == null) {
@@ -70,24 +94,26 @@
         return mBinder;
     }
 
+    public CrsCrbtControllerBase(Executor executor, Context context) {
+        mExecutor = executor;
+        mContext = context;
+    }
+
     protected void onSetCrsCrbtListener(ICrsCrbtListener listener)
         throws RemoteException {
         //no-op
     }
 
-    protected void onRemoveCrsCrbtListener(ICrsCrbtListener listener)
-        throws RemoteException {
+    protected void onRemoveCrsCrbtListener(ICrsCrbtListener listener) {
         //no-op
     }
 
-    protected boolean onIsPreparatorySession(String callId)
-        throws RemoteException {
+    protected boolean onIsPreparatorySession(String callId) {
         //no-op
         return false;
     }
 
-    protected void onSendSipDtmf(String requestCode)
-        throws RemoteException {
+    protected void onSendSipDtmf(String requestCode) {
         //no-op
     }
 }
diff --git a/ims/ims-ext-common/src/org/codeaurora/ims/ImsMultiIdentityControllerBase.java b/ims/ims-ext-common/src/org/codeaurora/ims/ImsMultiIdentityControllerBase.java
index 05cf4e2..0615458 100644
--- a/ims/ims-ext-common/src/org/codeaurora/ims/ImsMultiIdentityControllerBase.java
+++ b/ims/ims-ext-common/src/org/codeaurora/ims/ImsMultiIdentityControllerBase.java
@@ -34,33 +34,55 @@
 import org.codeaurora.ims.MultiIdentityLineInfo;
 import org.codeaurora.ims.internal.IImsMultiIdentityListener;
 import org.codeaurora.ims.internal.IImsMultiIdentityInterface;
+import org.codeaurora.ims.utils.QtiImsExtUtils;
 import java.util.List;
 import java.util.ArrayList;
 
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.Executor;
+
 public abstract class ImsMultiIdentityControllerBase {
     public final class MultiIdentityBinder extends IImsMultiIdentityInterface.Stub {
 
         @Override
         public void setMultiIdentityListener(
-                IImsMultiIdentityListener listener) throws RemoteException{
-            ImsMultiIdentityControllerBase.this.
-                setMultiIdentityListener(listener);
+                IImsMultiIdentityListener listener) throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() -> {
+                    try {
+                        ImsMultiIdentityControllerBase.this.
+                            setMultiIdentityListener(listener);
+                    } catch (RemoteException e) {
+                        throw new CompletionException(e);
+                    }}, "setMultiIdentityListener", mExecutor,
+                    QtiImsExtUtils.MODIFY_PHONE_STATE, mContext);
         }
 
         @Override
-        public void updateRegistrationStatus(List<MultiIdentityLineInfo> linesInfo) {
-            ImsMultiIdentityControllerBase.this.
-                updateRegistrationStatus(linesInfo);
+        public void updateRegistrationStatus(List<MultiIdentityLineInfo> linesInfo)
+                throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    ImsMultiIdentityControllerBase.this.
+                    updateRegistrationStatus(linesInfo),
+                    "updateRegistrationStatus", mExecutor,
+                    QtiImsExtUtils.MODIFY_PHONE_STATE, mContext);
         }
 
         @Override
-        public void queryVirtualLineInfo(String msisdn) throws RemoteException{
-           ImsMultiIdentityControllerBase.this.
-               queryVirtualLineInfo(msisdn);
+        public void queryVirtualLineInfo(String msisdn) throws RemoteException {
+            if (msisdn == null) {
+                throw new RemoteException("queryVirtualLineInfo :: msisdn is null");
+            }
+            QtiImsExtUtils.executeMethodAsync(() ->
+                        ImsMultiIdentityControllerBase.this.
+                        queryVirtualLineInfo(msisdn),
+                        "queryVirtualLineInfo", mExecutor,
+                        QtiImsExtUtils.READ_PHONE_STATE, mContext);
         }
     }
 
     private IImsMultiIdentityInterface mBinder;
+    private Executor mExecutor;
+    private Context mContext;
 
     public IImsMultiIdentityInterface getBinder() {
         if (mBinder == null) {
@@ -69,8 +91,13 @@
         return mBinder;
     }
 
+    public ImsMultiIdentityControllerBase(Executor executor, Context context) {
+        mExecutor = executor;
+        mContext = context;
+    }
+
     protected void setMultiIdentityListener(
-            IImsMultiIdentityListener listener) throws RemoteException{
+            IImsMultiIdentityListener listener) throws RemoteException {
         //no-op
     }
 
@@ -79,7 +106,7 @@
         //no-op
     }
 
-    protected void queryVirtualLineInfo(String msisdn) throws RemoteException{
+    protected void queryVirtualLineInfo(String msisdn) {
         //no-op
     }
 }
diff --git a/ims/ims-ext-common/src/org/codeaurora/ims/ImsScreenShareControllerBase.java b/ims/ims-ext-common/src/org/codeaurora/ims/ImsScreenShareControllerBase.java
index 7109f55..1af3293 100644
--- a/ims/ims-ext-common/src/org/codeaurora/ims/ImsScreenShareControllerBase.java
+++ b/ims/ims-ext-common/src/org/codeaurora/ims/ImsScreenShareControllerBase.java
@@ -32,28 +32,47 @@
 import android.os.RemoteException;
 import org.codeaurora.ims.internal.IImsScreenShareListener;
 import org.codeaurora.ims.internal.IImsScreenShareController;
+import org.codeaurora.ims.utils.QtiImsExtUtils;
+
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.Executor;
 
 public abstract class ImsScreenShareControllerBase {
     public final class ScreenShareBinder extends IImsScreenShareController.Stub {
 
         @Override
         public void setScreenShareListener(
-                IImsScreenShareListener listener) throws RemoteException{
-            ImsScreenShareControllerBase.this.onSetScreenShareListener(listener);
+                IImsScreenShareListener listener) throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() -> {
+                    try {
+                        ImsScreenShareControllerBase.this.onSetScreenShareListener(listener);
+                    } catch (RemoteException e) {
+                        throw new CompletionException(e);
+                    }},
+                    "setScreenShareListener", mExecutor,
+                    QtiImsExtUtils.MODIFY_PHONE_STATE, mContext);
         }
 
         @Override
         public void startScreenShare(int width, int height) throws RemoteException{
-            ImsScreenShareControllerBase.this.onStartScreenShare(width, height);
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    ImsScreenShareControllerBase.this.onStartScreenShare(width, height),
+                    "startScreenShare", mExecutor, QtiImsExtUtils.MODIFY_PHONE_STATE,
+                    mContext);
         }
 
         @Override
         public void stopScreenShare() throws RemoteException{
-           ImsScreenShareControllerBase.this.onStopScreenShare();
+           QtiImsExtUtils.executeMethodAsync(() ->
+                    ImsScreenShareControllerBase.this.onStopScreenShare(),
+                    "stopScreenShare", mExecutor,
+                    QtiImsExtUtils.MODIFY_PHONE_STATE, mContext);
         }
     }
 
     private IImsScreenShareController mBinder;
+    private Executor mExecutor;
+    private Context mContext;
 
     public IImsScreenShareController getBinder() {
         if (mBinder == null) {
@@ -62,16 +81,21 @@
         return mBinder;
     }
 
+    public ImsScreenShareControllerBase(Executor executor, Context context) {
+        mExecutor = executor;
+        mContext = context;
+    }
+
     protected void onSetScreenShareListener(
             IImsScreenShareListener listener) throws RemoteException{
         //no-op
     }
 
-    protected void onStartScreenShare(int width, int height) throws RemoteException{
+    protected void onStartScreenShare(int width, int height) {
         //no-op
     }
 
-    protected void onStopScreenShare() throws RemoteException{
+    protected void onStopScreenShare() {
         //no-op
     }
 }
diff --git a/ims/ims-ext-common/src/org/codeaurora/ims/QtiCallConstants.java b/ims/ims-ext-common/src/org/codeaurora/ims/QtiCallConstants.java
index b6c0002..b107e2d 100755
--- a/ims/ims-ext-common/src/org/codeaurora/ims/QtiCallConstants.java
+++ b/ims/ims-ext-common/src/org/codeaurora/ims/QtiCallConstants.java
@@ -143,6 +143,15 @@
      * CODE_CONCURRENT_CALLS_NOT_POSSIBLE} */
     public static final int CODE_CONCURRENT_CALLS_NOT_POSSIBLE = 3002;
 
+    /* Call fail error code to EPSFB failure */
+    public static final int CODE_EPSFB_FAILURE = 3003;
+
+    /* Call fail error code to TWAIT_EXPIRED */
+    public static final int CODE_TWAIT_EXPIRED = 3004;
+
+    /* Call fail error code to TCP_CONNECTION_REQ */
+    public static final int CODE_TCP_CONNECTION_REQ = 3005;
+
     // Default code to use for additional call info code.
     public static final int CODE_UNSPECIFIED = -1;
 
@@ -554,6 +563,21 @@
     public static final String EXTRA_DATA_CHANNEL_MODEM_CALL_ID = "modemCallId";
     public static final String EXTRA_IS_DATA_CHANNEL_CALL = "isDcCall";
 
+    // Intent action broadcasted when essential records are loaded.
+    // requires permission "com.qti.permission.RECEIVE_ESSENTIAL_RECORDS_LOADED".
+    public static final String ACTION_ESSENTIAL_RECORDS_LOADED =
+        "org.codeaurora.intent.action.ESSENTIAL_RECORDS_LOADED";
+
     // Video online service
     public static final String EXTRA_VIDEO_ONLINE_SERVICE_SUPPORTED = "isVosSupported";
+
+    /**
+     * The value of voice/video/text is defined according to the SRTP categories
+     * and the name in the extra is defined by QC IMS service.
+     */
+    public static final String EXTRAS_SRTP_ENCRYPTION_CATEGORY = "srtpEncryptionCategory";
+    public static final int SRTP_CATEGORY_UNENCRYPTED = 0;
+    public static final int SRTP_CATEGORY_VOICE = 1 << 0;
+    public static final int SRTP_CATEGORY_VIDEO = 1 << 1;
+    public static final int SRTP_CATEGORY_TEXT = 1 << 2;
 }
diff --git a/ims/ims-ext-common/src/org/codeaurora/ims/QtiImsExtBase.java b/ims/ims-ext-common/src/org/codeaurora/ims/QtiImsExtBase.java
index dee1a72..fdfeac6 100644
--- a/ims/ims-ext-common/src/org/codeaurora/ims/QtiImsExtBase.java
+++ b/ims/ims-ext-common/src/org/codeaurora/ims/QtiImsExtBase.java
@@ -31,7 +31,9 @@
  */
 package org.codeaurora.ims;
 
+import android.content.Context;
 import android.os.Bundle;
+import android.os.RemoteException;
 import android.telephony.ims.feature.ImsFeature;
 
 import org.codeaurora.ims.internal.ICrsCrbtController;
@@ -39,10 +41,17 @@
 import org.codeaurora.ims.internal.IQtiImsExtListener;
 import org.codeaurora.ims.internal.IImsMultiIdentityInterface;
 import org.codeaurora.ims.internal.IImsScreenShareController;
+import org.codeaurora.ims.utils.QtiImsExtUtils;
 import org.codeaurora.ims.QtiCallConstants;
 import org.codeaurora.ims.VosActionInfo;
+
+import java.util.concurrent.Executor;
+
 /**
  * Base implementation for IQtiImsExt.
+ * Introduce Executor pattern where API(s) will be called on the executor thread.
+ * Except for non-oneway API(s) which call into ImsConfigImpl as setConfig/getConfig
+ * are blocking AIDL calls.
  */
 public abstract class QtiImsExtBase {
 
@@ -54,168 +63,258 @@
         @Override
         public void setCallForwardUncondTimer(int phoneId, int startHour, int startMinute,
                 int endHour, int endMinute, int action, int condition, int serviceClass,
-                String number, IQtiImsExtListener listener) {
-            onSetCallForwardUncondTimer(phoneId, startHour, startMinute, endHour, endMinute, action,
-                condition, serviceClass, number, listener);
+                String number, IQtiImsExtListener listener) throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() -> QtiImsExtBase.this.onSetCallForwardUncondTimer(
+                    phoneId, startHour, startMinute, endHour, endMinute, action,
+                    condition, serviceClass, number, listener),
+                    "setCallForwardUncondTimer", mExecutor,
+                    QtiImsExtUtils.MODIFY_PHONE_STATE, mContext);
         }
 
         @Override
         public void getCallForwardUncondTimer(int phoneId, int reason, int serviceClass,
-                IQtiImsExtListener listener) {
-            onGetCallForwardUncondTimer(phoneId, reason, serviceClass, listener);
+                IQtiImsExtListener listener) throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    QtiImsExtBase.this.onGetCallForwardUncondTimer(phoneId, reason,
+                    serviceClass, listener), "getCallForwardUncondTimer", mExecutor,
+                    QtiImsExtUtils.READ_PHONE_STATE, mContext);
         }
 
         @Override
-        public void resumePendingCall(int phoneId, int videoState) {
-            onResumePendingCall(phoneId, videoState);
+        public void resumePendingCall(int phoneId, int videoState) throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    QtiImsExtBase.this.onResumePendingCall(phoneId, videoState),
+                    "resumePendingCall", mExecutor, QtiImsExtUtils.MODIFY_PHONE_STATE, mContext);
         }
 
         @Override
-        public void sendCancelModifyCall(int phoneId, IQtiImsExtListener listener) {
-            onSendCancelModifyCall(phoneId, listener);
+        public void sendCancelModifyCall(int phoneId, IQtiImsExtListener listener)
+                throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    QtiImsExtBase.this.onSendCancelModifyCall(phoneId, listener),
+                    "sendCancelModifyCall", mExecutor, QtiImsExtUtils.MODIFY_PHONE_STATE, mContext);
         }
 
         @Override
-        public void queryVopsStatus(int phoneId, IQtiImsExtListener listener) {
-            onQueryVopsStatus(phoneId, listener);
+        public void queryVopsStatus(int phoneId, IQtiImsExtListener listener)
+                throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    QtiImsExtBase.this.onQueryVopsStatus(phoneId, listener),
+                    "queryVopsStatus", mExecutor, QtiImsExtUtils.READ_PHONE_STATE, mContext);
         }
 
         @Override
-        public void querySsacStatus(int phoneId, IQtiImsExtListener listener) {
-            onQuerySsacStatus(phoneId, listener);
+        public void querySsacStatus(int phoneId, IQtiImsExtListener listener)
+                throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    QtiImsExtBase.this.onQuerySsacStatus(phoneId, listener),
+                    "querySsacStatus", mExecutor, QtiImsExtUtils.READ_PHONE_STATE, mContext);
         }
 
         @Override
-        public void registerForParticipantStatusInfo(int phoneId, IQtiImsExtListener listener) {
-            onRegisterForParticipantStatusInfo(phoneId, listener);
+        public void registerForParticipantStatusInfo(int phoneId, IQtiImsExtListener listener)
+                throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    QtiImsExtBase.this.onRegisterForParticipantStatusInfo(phoneId, listener),
+                    "registerForParticipantStatusInfo", mExecutor,
+                    QtiImsExtUtils.MODIFY_PHONE_STATE, mContext);
         }
 
         @Override
         public void updateVoltePreference(int phoneId, int preference,
-                IQtiImsExtListener listener) {
-            onUpdateVoltePreference(phoneId, preference, listener);
+                IQtiImsExtListener listener) throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    QtiImsExtBase.this.onUpdateVoltePreference(phoneId, preference, listener),
+                    "updateVoltePreference", mExecutor,
+                    QtiImsExtUtils.MODIFY_PHONE_STATE, mContext);
         }
 
         @Override
-        public void queryVoltePreference(int phoneId, IQtiImsExtListener listener) {
-            onQueryVoltePreference(phoneId, listener);
+        public void queryVoltePreference(int phoneId, IQtiImsExtListener listener)
+                throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    QtiImsExtBase.this.onQueryVoltePreference(phoneId, listener),
+                    "queryVoltePreference", mExecutor,
+                    QtiImsExtUtils.READ_PHONE_STATE, mContext);
         }
 
         @Override
-        public void getHandoverConfig(int phoneId, IQtiImsExtListener listener) {
-            onGetHandoverConfig(phoneId, listener);
+        public void getHandoverConfig(int phoneId, IQtiImsExtListener listener)
+                throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    QtiImsExtBase.this.onGetHandoverConfig(phoneId, listener),
+                    "getHandoverConfig", mExecutor, QtiImsExtUtils.READ_PHONE_STATE, mContext);
         }
 
         @Override
         public void setHandoverConfig(int phoneId, int hoConfig,
-                IQtiImsExtListener listener) {
-            onSetHandoverConfig(phoneId, hoConfig, listener);
+                IQtiImsExtListener listener) throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    QtiImsExtBase.this.onSetHandoverConfig(phoneId, hoConfig, listener),
+                    "setHandoverConfig", mExecutor, QtiImsExtUtils.MODIFY_PHONE_STATE, mContext);
         }
 
         @Override
-        public void setUssdInfoListener(int phoneId, IQtiImsExtListener listener) {
-            onSetUssdInfoListener(phoneId, listener);
+        public void setUssdInfoListener(int phoneId, IQtiImsExtListener listener)
+                throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    QtiImsExtBase.this.onSetUssdInfoListener(phoneId, listener),
+                    "setUssdInfoListener", mExecutor, QtiImsExtUtils.MODIFY_PHONE_STATE, mContext);
         }
 
         @Override
-        public int setRcsAppConfig(int phoneId, int defaultSmsApp) {
-            return onSetRcsAppConfig(phoneId, defaultSmsApp);
+        public int setRcsAppConfig(int phoneId, int defaultSmsApp) throws RemoteException {
+            return QtiImsExtUtils.executeMethodAsyncForResult(() ->
+                    QtiImsExtBase.this.onSetRcsAppConfig(phoneId, defaultSmsApp),
+                    "setRcsAppConfig", getBinderExecutor(), QtiImsExtUtils.MODIFY_PHONE_STATE,
+                    mContext);
         }
 
         @Override
         public void setDataChannelCapabilityListener(int phoneId,
-                IQtiImsExtListener listener) {
-           onSetDataChannelCapabilityListener(phoneId, listener);
+                IQtiImsExtListener listener) throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    QtiImsExtBase.this.onSetDataChannelCapabilityListener(
+                    phoneId, listener), "setDataChannelCapabilityListener", mExecutor,
+                    QtiImsExtUtils.MODIFY_PHONE_STATE, mContext);
         }
 
         @Override
-        public int getRcsAppConfig(int phoneId) {
-            return onGetRcsAppConfig(phoneId);
-
+        public int getRcsAppConfig(int phoneId) throws RemoteException {
+            return QtiImsExtUtils.executeMethodAsyncForResult(() ->
+                    QtiImsExtBase.this.onGetRcsAppConfig(phoneId),
+                    "getRcsAppConfig", getBinderExecutor(),
+                    QtiImsExtUtils.READ_PHONE_STATE, mContext);
         }
 
         @Override
-        public int setVvmAppConfig(int phoneId, int defaultVvmApp) {
-            return onSetVvmAppConfig(phoneId, defaultVvmApp);
+        public int setVvmAppConfig(int phoneId, int defaultVvmApp) throws RemoteException {
+            return QtiImsExtUtils.executeMethodAsyncForResult(() ->
+                    QtiImsExtBase.this.onSetVvmAppConfig(phoneId, defaultVvmApp),
+                    "setVvmAppConfig", getBinderExecutor(),
+                    QtiImsExtUtils.MODIFY_PHONE_STATE, mContext);
         }
 
         @Override
-        public int getVvmAppConfig(int phoneId) {
-            return onGetVvmAppConfig(phoneId);
+        public int getVvmAppConfig(int phoneId) throws RemoteException {
+            return QtiImsExtUtils.executeMethodAsyncForResult(() ->
+                    QtiImsExtBase.this.onGetVvmAppConfig(phoneId),
+                    "getVvmAppConfig", getBinderExecutor(),
+                    QtiImsExtUtils.READ_PHONE_STATE, mContext);
         }
 
         @Override
-        public IImsMultiIdentityInterface getMultiIdentityInterface(int phoneId) {
-            return onGetMultiIdentityInterface(phoneId);
+        public IImsMultiIdentityInterface getMultiIdentityInterface(int phoneId)
+                throws RemoteException {
+            return QtiImsExtUtils.executeMethodAsyncForResult(() ->
+                    QtiImsExtBase.this.onGetMultiIdentityInterface(phoneId),
+                    "getMultiIdentityInterface", mExecutor,
+                    QtiImsExtUtils.MODIFY_PHONE_STATE, mContext);
         }
 
         @Override
-        public IImsScreenShareController getScreenShareController(int phoneId) {
-            return onGetScreenShareController(phoneId);
+        public IImsScreenShareController getScreenShareController(int phoneId)
+                throws RemoteException {
+            return QtiImsExtUtils.executeMethodAsyncForResult(() ->
+                    QtiImsExtBase.this.onGetScreenShareController(phoneId),
+                    "getScreenShareController", mExecutor,
+                    QtiImsExtUtils.MODIFY_PHONE_STATE, mContext);
         }
 
         @Override
-        public int getImsFeatureState(int phoneId) {
-            return onGetImsFeatureState(phoneId);
+        public int getImsFeatureState(int phoneId) throws RemoteException {
+            return QtiImsExtUtils.executeMethodAsyncForResult(() ->
+                    QtiImsExtBase.this.onGetImsFeatureState(phoneId),
+                    "getImsFeatureState", mExecutor, QtiImsExtUtils.READ_PHONE_STATE, mContext);
         }
 
         @Override
-        public void setAnswerExtras(int phoneId, Bundle extras) {
-            onSetAnswerExtras(phoneId, extras);
+        public void setAnswerExtras(int phoneId, Bundle extras) throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    QtiImsExtBase.this.onSetAnswerExtras(phoneId, extras),
+                    "setAnswerExtras", mExecutor, QtiImsExtUtils.READ_PHONE_STATE, mContext);
         }
 
         @Override
-        public boolean isCallComposerEnabled(int phoneId) {
-            return onIsCallComposerEnabled(phoneId);
+        public boolean isCallComposerEnabled(int phoneId) throws RemoteException {
+            return QtiImsExtUtils.executeMethodAsyncForResult(() ->
+                    QtiImsExtBase.this.onIsCallComposerEnabled(phoneId),
+                    "isCallComposerEnabled", mExecutor, QtiImsExtUtils.READ_PHONE_STATE, mContext);
         }
 
         @Override
-        public ICrsCrbtController getCrsCrbtController(int phoneId) {
-            return onGetCrsCrbtController(phoneId);
+        public ICrsCrbtController getCrsCrbtController(int phoneId) throws RemoteException {
+            return QtiImsExtUtils.executeMethodAsyncForResult(() ->
+                    QtiImsExtBase.this.onGetCrsCrbtController(phoneId),
+                    "getCrsCrbtController", mExecutor, QtiImsExtUtils.READ_PHONE_STATE, mContext);
         }
 
         @Override
         public void queryCallForwardStatus(int phoneId, int reason, int serviceClass,
-                boolean expectMore, IQtiImsExtListener listener) {
-            onQueryCallForwardStatus(phoneId, reason, serviceClass, expectMore, listener);
+                boolean expectMore, IQtiImsExtListener listener) throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    QtiImsExtBase.this.onQueryCallForwardStatus(phoneId, reason,
+                    serviceClass, expectMore, listener),
+                    "queryCallForwardStatus", mExecutor, QtiImsExtUtils.READ_PHONE_STATE, mContext);
         }
 
         @Override
         public void queryCallBarring(int phoneId, int cbType, String password, int serviceClass,
-                boolean expectMore, IQtiImsExtListener listener) {
-            onQueryCallBarringStatus(phoneId, cbType, password, serviceClass, expectMore,
-                    listener);
+                boolean expectMore, IQtiImsExtListener listener) throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    QtiImsExtBase.this.onQueryCallBarringStatus(phoneId, cbType,
+                    password, serviceClass, expectMore, listener),
+                    "queryCallBarring", mExecutor, QtiImsExtUtils.READ_PHONE_STATE, mContext);
         }
 
         @Override
-        public void exitScbm(int phoneId, IQtiImsExtListener listener) {
-            onExitScbm(phoneId, listener);
+        public void exitScbm(int phoneId, IQtiImsExtListener listener) throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    QtiImsExtBase.this.onExitScbm(phoneId, listener),
+                    "exitScbm", mExecutor, QtiImsExtUtils.READ_PHONE_STATE, mContext);
         }
 
         @Override
-        public boolean isExitScbmFeatureSupported(int phoneId) {
-            return onIsExitScbmFeatureSupported(phoneId);
+        public boolean isExitScbmFeatureSupported(int phoneId) throws RemoteException {
+            return QtiImsExtUtils.executeMethodAsyncForResult(() ->
+                    QtiImsExtBase.this.onIsExitScbmFeatureSupported(phoneId),
+                    "isExitScbmFeatureSupported", mExecutor,
+                    QtiImsExtUtils.READ_PHONE_STATE, mContext);
         }
 
         @Override
-        public boolean isDataChannelEnabled(int phoneId) {
-            return onIsDataChannelEnabled(phoneId);
+        public boolean isDataChannelEnabled(int phoneId) throws RemoteException {
+            return QtiImsExtUtils.executeMethodAsyncForResult(() ->
+                    QtiImsExtBase.this.onIsDataChannelEnabled(phoneId),
+                    "isDataChannelEnabled", mExecutor,
+                    QtiImsExtUtils.READ_PHONE_STATE, mContext);
         }
 
         @Override
         public void sendVosSupportStatus(int phoneId, boolean isVosSupported,
-                IQtiImsExtListener listener) {
-            onSendVosSupportStatus(phoneId, isVosSupported, listener);
+                IQtiImsExtListener listener) throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() ->
+                    QtiImsExtBase.this.onSendVosSupportStatus(phoneId,
+                    isVosSupported, listener),
+                    "sendVosSupportStatus", mExecutor,
+                    QtiImsExtUtils.READ_PHONE_STATE, mContext);
         }
 
         @Override
         public void sendVosActionInfo(int phoneId, VosActionInfo vosActionInfo,
-                IQtiImsExtListener listener) {
-            onSendVosActionInfo(phoneId, vosActionInfo, listener);
+                IQtiImsExtListener listener) throws RemoteException {
+            QtiImsExtUtils.executeMethodAsync(() -> QtiImsExtBase.this.onSendVosActionInfo(phoneId,
+                    vosActionInfo, listener),
+                    "sendVosActionInfo", mExecutor,
+                    QtiImsExtUtils.READ_PHONE_STATE, mContext);
         }
+
     };
 
     private QtiImsExtBinder mQtiImsExtBinder;
+    private Executor mExecutor;
+    private Executor mBinderExecutor = Runnable::run;
+    private Context mContext;
 
     public QtiImsExtBinder getBinder() {
         if (mQtiImsExtBinder == null) {
@@ -224,6 +323,15 @@
         return mQtiImsExtBinder;
     }
 
+    public QtiImsExtBase(Executor executor, Context context) {
+        mExecutor = executor;
+        mContext = context;
+    }
+
+    private Executor getBinderExecutor() {
+        return mBinderExecutor;
+    }
+
     protected void onSetCallForwardUncondTimer(int phoneId, int startHour, int startMinute,
             int endHour, int endMinute, int action, int condition, int serviceClass, String number,
             IQtiImsExtListener listener) {
diff --git a/ims/ims-ext-common/src/org/codeaurora/ims/utils/QtiCarrierConfigHelper.java b/ims/ims-ext-common/src/org/codeaurora/ims/utils/QtiCarrierConfigHelper.java
index 132cee2..97d1008 100644
--- a/ims/ims-ext-common/src/org/codeaurora/ims/utils/QtiCarrierConfigHelper.java
+++ b/ims/ims-ext-common/src/org/codeaurora/ims/utils/QtiCarrierConfigHelper.java
@@ -44,6 +44,8 @@
 import java.util.List;
 import java.util.Map;
 
+import org.codeaurora.ims.QtiCallConstants;
+
 public class QtiCarrierConfigHelper {
     static final String TAG  = QtiCarrierConfigHelper.class.getSimpleName();
     private static final boolean DEBUG =
@@ -64,8 +66,9 @@
     private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
         @Override
         public void onReceive(Context context, Intent intent) {
-            if (intent != null && intent.getAction()
-                    .equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED)) {
+            if (intent != null && (intent.getAction()
+                    .equals(CarrierConfigManager.ACTION_CARRIER_CONFIG_CHANGED) ||
+                    intent.getAction().equals(QtiCallConstants.ACTION_ESSENTIAL_RECORDS_LOADED))) {
                 int phoneId = intent.getIntExtra(CarrierConfigManager.EXTRA_SLOT_INDEX,
                         SubscriptionManager.INVALID_SIM_SLOT_INDEX);
                 if (mSubscriptionManager != null) {
@@ -150,6 +153,7 @@
         subCache = new int[PHONE_COUNT];
         IntentFilter filter = new IntentFilter(CarrierConfigManager
                 .ACTION_CARRIER_CONFIG_CHANGED);
+        filter.addAction(QtiCallConstants.ACTION_ESSENTIAL_RECORDS_LOADED);
         mContext.registerReceiver(mReceiver, filter);
         mSubscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
     }
diff --git a/ims/ims-ext-common/src/org/codeaurora/ims/utils/QtiImsExtUtils.java b/ims/ims-ext-common/src/org/codeaurora/ims/utils/QtiImsExtUtils.java
old mode 100755
new mode 100644
index cb7505a..ded9d1b
--- a/ims/ims-ext-common/src/org/codeaurora/ims/utils/QtiImsExtUtils.java
+++ b/ims/ims-ext-common/src/org/codeaurora/ims/utils/QtiImsExtUtils.java
@@ -63,6 +63,7 @@
 
 package org.codeaurora.ims.utils;
 
+import android.Manifest;
 import android.content.ContentResolver;
 import android.content.Context;
 import android.content.res.Resources;
@@ -72,6 +73,7 @@
 import android.net.Uri;
 import android.os.ParcelFileDescriptor;
 import android.os.PersistableBundle;
+import android.os.RemoteException;
 import android.os.SystemProperties;
 import android.provider.Settings;
 import android.telephony.CarrierConfigManager;
@@ -92,6 +94,13 @@
 import org.codeaurora.ims.QtiImsException;
 import org.codeaurora.ims.QtiImsExtManager;
 
+import java.util.concurrent.CancellationException;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.CompletionException;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.Executor;
+import java.util.function.Supplier;
+
 /**
  * This class contains QtiImsExt specific utiltity functions.
  */
@@ -188,6 +197,10 @@
     /*RTT upgrade not supported */
     public static final int QTI_IMS_RTT_NOT_SUPPORTED = 0;
 
+    // Phone permissions
+    public static final String READ_PHONE_STATE = Manifest.permission.READ_PHONE_STATE;
+    public static final String MODIFY_PHONE_STATE = Manifest.permission.MODIFY_PHONE_STATE;
+
     /**
      * Private constructor for QtiImsExtUtils as we don't want to instantiate this class
      */
@@ -675,8 +688,12 @@
             CarrierConfigManager.KEY_RTT_DOWNGRADE_SUPPORTED_BOOL);
     }
 
-    // Returns true if previous carrier supported RTT downgrade
-    // False otherwise
+    /* @Deprecated
+     * Returns true if Carrier supports RTT downgrade
+     * False otherwise
+     * This functionality will now be supported using {@link PhoneAccount.CAPABILITY_RTT}
+     * check
+     */
     public static boolean isSimlessRttDowgradeSupported(int phoneId, Context context) {
         int simLessRttDowngradeSupportedValue = android.provider.Settings.Secure.getInt(
                 context.getContentResolver(), QtiCallConstants.
@@ -685,8 +702,12 @@
         return simLessRttDowngradeSupportedValue != QTI_IMS_RTT_DOWNGRADE_NOT_SUPPORTED;
     }
 
-    // Returns true if previous carrier supported RTT upgrade
-    // False otherwise
+    /* @Deprecated
+     * Returns true if previous carrier supported RTT upgrade
+     * False otherwise
+     * This functionality will now be supported using
+     * {@link PhoneAccount.CAPABILITY_DOWNGRADE_RTT} check
+     */
     public static boolean isSimlessRttSupported(int phoneId, Context context) {
         int simLessRttSupportedValue = android.provider.Settings.Secure.getInt(
                 context.getContentResolver(), QtiCallConstants.
@@ -852,4 +873,29 @@
         return isCarrierConfigEnabled(phoneId, context,
                 QtiCarrierConfigs.KEY_CARRIER_VIDEO_ONLINE_SERVICE_SUPPORTED);
     }
+
+    public static void executeMethodAsync(Runnable r, String errorLogName, Executor executor,
+            String permission, Context context) throws RemoteException {
+        context.enforceCallingOrSelfPermission(permission, errorLogName);
+        try {
+            CompletableFuture.runAsync(r, executor).join();
+        } catch (CancellationException | CompletionException e) {
+            Log.w(LOG_TAG, "executeMethodAsync for " + errorLogName + " failed with: " +
+                    e.getMessage());
+            throw new RemoteException(e.getMessage());
+        }
+    }
+
+    public static <T> T executeMethodAsyncForResult(Supplier<T> r, String errorLogName,
+            Executor executor, String permission, Context context) throws RemoteException {
+        context.enforceCallingOrSelfPermission(permission, errorLogName);
+        try {
+            CompletableFuture<T> future = CompletableFuture.supplyAsync(r, executor);
+            return future.get();
+        } catch (ExecutionException | InterruptedException e) {
+            Log.w(LOG_TAG, "executeMethodAsyncForResult for " + errorLogName + " failed with: " +
+                    e.getMessage());
+            throw new RemoteException(e.getMessage());
+        }
+    }
 }