Merge "AIDL IRadioModemIndication#onImeiMappingChanged() implementation for the change in the IMEI wrt sim slot" into main
diff --git a/src/java/com/android/internal/telephony/BaseCommands.java b/src/java/com/android/internal/telephony/BaseCommands.java
index 4ec1f71..3f3d297 100644
--- a/src/java/com/android/internal/telephony/BaseCommands.java
+++ b/src/java/com/android/internal/telephony/BaseCommands.java
@@ -118,6 +118,7 @@
     protected RegistrantList mConnectionSetupFailureRegistrants = new RegistrantList();
     protected RegistrantList mNotifyAnbrRegistrants = new RegistrantList();
     protected RegistrantList mTriggerImsDeregistrationRegistrants = new RegistrantList();
+    protected RegistrantList mImeiInfoRegistrants = new RegistrantList();
 
     @UnsupportedAppUsage
     protected Registrant mGsmSmsRegistrant;
@@ -1174,4 +1175,12 @@
     public void unregisterForTriggerImsDeregistration(Handler h) {
         mTriggerImsDeregistrationRegistrants.remove(h);
     }
+
+    /**
+     * Register to listen for the changes in the primary IMEI with respect to the sim slot.
+     */
+    @Override
+    public void registerForImeiMappingChanged(Handler h, int what, Object obj) {
+        mImeiInfoRegistrants.add(h, what, obj);
+    }
 }
diff --git a/src/java/com/android/internal/telephony/CommandsInterface.java b/src/java/com/android/internal/telephony/CommandsInterface.java
index 71c2001..1ed6be0 100644
--- a/src/java/com/android/internal/telephony/CommandsInterface.java
+++ b/src/java/com/android/internal/telephony/CommandsInterface.java
@@ -1735,6 +1735,12 @@
     public void getImei(Message response);
 
     /**
+     * Register to listen for the changes in the primary IMEI with respect to the sim slot.
+     */
+
+    public void registerForImeiMappingChanged(Handler h, int what, Object obj);
+
+    /**
      * Request the device MDN / H_SID / H_NID / MIN.
      * "response" is const char **
      *   [0] is MDN if CDMA subscription is available
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 52d5580..b5cc37b 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -514,6 +514,7 @@
         mCDM = new CarrierKeyDownloadManager(this, mFeatureFlags);
         mCIM = new CarrierInfoManager();
 
+        mCi.registerForImeiMappingChanged(this, EVENT_IMEI_MAPPING_CHANGED, null);
         initializeCarrierApps();
     }
 
@@ -3170,19 +3171,7 @@
             }
             break;
             case EVENT_GET_DEVICE_IMEI_DONE :
-                ar = (AsyncResult)msg.obj;
-                if (ar.exception != null || ar.result == null) {
-                    loge("Exception received : " + ar.exception);
-                    break;
-                }
-                ImeiInfo imeiInfo = (ImeiInfo) ar.result;
-                if (!TextUtils.isEmpty(imeiInfo.imei)) {
-                    mImeiType = imeiInfo.type;
-                    mImei = imeiInfo.imei;
-                    mImeiSv = imeiInfo.svn;
-                } else {
-                    // TODO Report telephony anomaly
-                }
+                parseImeiInfo(msg);
                 break;
             case EVENT_GET_DEVICE_IDENTITY_DONE:{
                 ar = (AsyncResult)msg.obj;
@@ -3668,11 +3657,33 @@
                     rsp.sendToTarget();
                 }
                 break;
+
+            case EVENT_IMEI_MAPPING_CHANGED:
+                logd("EVENT_GET_DEVICE_IMEI_CHANGE_DONE phoneId = " + getPhoneId());
+                parseImeiInfo(msg);
+                break;
+
             default:
                 super.handleMessage(msg);
         }
     }
 
+    private void parseImeiInfo(Message msg) {
+        AsyncResult ar = (AsyncResult)msg.obj;
+        if (ar.exception != null || ar.result == null) {
+            loge("parseImeiInfo :: Exception received : " + ar.exception);
+            return;
+        }
+        ImeiInfo imeiInfo = (ImeiInfo) ar.result;
+        if (!TextUtils.isEmpty(imeiInfo.imei)) {
+            mImeiType = imeiInfo.type;
+            mImei = imeiInfo.imei;
+            mImeiSv = imeiInfo.svn;
+        } else {
+            loge("parseImeiInfo :: IMEI value is empty");
+        }
+    }
+
     /**
      * Check if a different SIM is inserted at this slot from the last time. Storing last subId
      * in SharedPreference for now to detect SIM change.
diff --git a/src/java/com/android/internal/telephony/ModemIndication.java b/src/java/com/android/internal/telephony/ModemIndication.java
index 0ee40bb..3893c6a 100644
--- a/src/java/com/android/internal/telephony/ModemIndication.java
+++ b/src/java/com/android/internal/telephony/ModemIndication.java
@@ -19,12 +19,14 @@
 import static android.telephony.TelephonyManager.HAL_SERVICE_MODEM;
 
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_HARDWARE_CONFIG_CHANGED;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_IMEI_MAPPING_CHANGED;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_MODEM_RESTART;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RADIO_CAPABILITY;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RESPONSE_RADIO_STATE_CHANGED;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_RIL_CONNECTED;
 
 import android.hardware.radio.modem.IRadioModemIndication;
+import android.hardware.radio.modem.ImeiInfo;
 import android.os.AsyncResult;
 
 import java.util.ArrayList;
@@ -132,4 +134,18 @@
     public int getInterfaceVersion() {
         return IRadioModemIndication.VERSION;
     }
+
+    /**
+     * Indicates when there is a change in the IMEI with respect to the sim slot.
+     *
+     * @param imeiInfo IMEI information
+     */
+    public void onImeiMappingChanged(int indicationType, ImeiInfo imeiInfo) {
+        mRil.processIndication(HAL_SERVICE_MODEM, indicationType);
+
+        if (mRil.isLogOrTrace()) {
+            mRil.unsljLogMore(RIL_UNSOL_IMEI_MAPPING_CHANGED, "ImeiMappingChanged");
+        }
+        mRil.notifyRegistrantsImeiMappingChanged(imeiInfo);
+    }
 }
diff --git a/src/java/com/android/internal/telephony/Phone.java b/src/java/com/android/internal/telephony/Phone.java
index 50cf844..72d0622 100644
--- a/src/java/com/android/internal/telephony/Phone.java
+++ b/src/java/com/android/internal/telephony/Phone.java
@@ -253,8 +253,8 @@
     protected static final int EVENT_TRIGGER_NOTIFY_ANBR = 68;
     protected static final int EVENT_GET_N1_MODE_ENABLED_DONE = 69;
     protected static final int EVENT_SET_N1_MODE_ENABLED_DONE = 70;
-
-    protected static final int EVENT_LAST = EVENT_SET_N1_MODE_ENABLED_DONE;
+    protected static final int EVENT_IMEI_MAPPING_CHANGED = 71;
+    protected static final int EVENT_LAST = EVENT_IMEI_MAPPING_CHANGED;
 
     // For shared prefs.
     private static final String GSM_ROAMING_LIST_OVERRIDE_PREFIX = "gsm_roaming_list_";
diff --git a/src/java/com/android/internal/telephony/RIL.java b/src/java/com/android/internal/telephony/RIL.java
index 7e8bfe8..da15df6 100644
--- a/src/java/com/android/internal/telephony/RIL.java
+++ b/src/java/com/android/internal/telephony/RIL.java
@@ -36,6 +36,7 @@
 import android.hardware.radio.V1_0.RadioIndicationType;
 import android.hardware.radio.V1_0.RadioResponseInfo;
 import android.hardware.radio.V1_0.RadioResponseType;
+import android.hardware.radio.modem.ImeiInfo;
 import android.net.KeepalivePacketData;
 import android.net.LinkProperties;
 import android.os.AsyncResult;
@@ -5785,6 +5786,13 @@
         }
     }
 
+    void notifyRegistrantsImeiMappingChanged(ImeiInfo imeiInfo) {
+        if (mImeiInfoRegistrants != null) {
+            mImeiInfoRegistrants.notifyRegistrants(
+                    new AsyncResult(null, imeiInfo, null));
+        }
+    }
+
     @UnsupportedAppUsage
     void riljLog(String msg) {
         Rlog.d(RILJ_LOG_TAG, msg + (" [PHONE" + mPhoneId + "]"));
diff --git a/src/java/com/android/internal/telephony/RILUtils.java b/src/java/com/android/internal/telephony/RILUtils.java
index c2c29f8..cb5684f 100644
--- a/src/java/com/android/internal/telephony/RILUtils.java
+++ b/src/java/com/android/internal/telephony/RILUtils.java
@@ -241,6 +241,7 @@
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_EXIT_EMERGENCY_CALLBACK_MODE;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_HARDWARE_CONFIG_CHANGED;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_ICC_SLOT_STATUS;
+import static com.android.internal.telephony.RILConstants.RIL_UNSOL_IMEI_MAPPING_CHANGED;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_KEEPALIVE_STATUS;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_LCEDATA_RECV;
 import static com.android.internal.telephony.RILConstants.RIL_UNSOL_MODEM_RESTART;
@@ -5269,6 +5270,8 @@
                 return "UNSOL_NOTIFY_ANBR";
             case RIL_UNSOL_TRIGGER_IMS_DEREGISTRATION:
                 return "UNSOL_TRIGGER_IMS_DEREGISTRATION";
+            case RIL_UNSOL_IMEI_MAPPING_CHANGED:
+                return "UNSOL_IMEI_MAPPING_CHANGED";
             default:
                 return "<unknown response " + response + ">";
         }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
index 5aa474e..2563fdf 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/GsmCdmaPhoneTest.java
@@ -2734,4 +2734,31 @@
         verify(mSimulatedCommandsVerifier).getNetworkSelectionMode(any(Message.class));
         verify(mSimulatedCommandsVerifier).setNetworkSelectionModeAutomatic(any(Message.class));
     }
+
+    /**
+     * Verify the ImeiMappingChange and EVENT_GET_DEVICE_IMEI_CHANGE_DONE are handled properly.
+     */
+    @Test
+    public void testChangeInPrimaryImei() {
+        // Initially assign the primaryImei and test it.
+        Message message = mPhoneUT.obtainMessage(Phone.EVENT_GET_DEVICE_IMEI_DONE);
+        ImeiInfo imeiInfo = new ImeiInfo();
+        imeiInfo.imei = FAKE_IMEI;
+        imeiInfo.svn = FAKE_IMEISV;
+        imeiInfo.type = ImeiInfo.ImeiType.PRIMARY;
+        AsyncResult.forMessage(message, imeiInfo, null);
+        mPhoneUT.handleMessage(message);
+        assertEquals(Phone.IMEI_TYPE_PRIMARY, mPhoneUT.getImeiType());
+        assertEquals(FAKE_IMEI, mPhoneUT.getImei());
+
+        // Now update the same one to secondary and check whether it is reflecting or not.
+        message = mPhoneUT.obtainMessage(Phone.EVENT_IMEI_MAPPING_CHANGED);
+        imeiInfo.imei = FAKE_IMEI;
+        imeiInfo.svn = FAKE_IMEISV;
+        imeiInfo.type = ImeiInfo.ImeiType.SECONDARY;
+        AsyncResult.forMessage(message, imeiInfo, null);
+        mPhoneUT.handleMessage(message);
+        assertEquals(Phone.IMEI_TYPE_SECONDARY, mPhoneUT.getImeiType());
+        assertEquals(FAKE_IMEI, mPhoneUT.getImei());
+    }
 }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommandsVerifier.java b/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommandsVerifier.java
index 4858e91..6fc5616 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommandsVerifier.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/SimulatedCommandsVerifier.java
@@ -1475,4 +1475,12 @@
     @Override
     public void cancelHandover(Message result, int callId) {
     }
+
+    /**
+     * Register to listen for the changes in the primary IMEI with respect to the sim slot.
+     */
+    @Override
+    public void registerForImeiMappingChanged(Handler h, int what, Object obj) {
+
+    }
 }