Merge "Move reselect domain code block to a method" into main
diff --git a/src/com/android/phone/ImsProvisioningController.java b/src/com/android/phone/ImsProvisioningController.java
index e4bda19..ea60633 100644
--- a/src/com/android/phone/ImsProvisioningController.java
+++ b/src/com/android/phone/ImsProvisioningController.java
@@ -49,9 +49,11 @@
 import android.os.PersistableBundle;
 import android.os.RemoteCallbackList;
 import android.os.RemoteException;
+import android.telephony.AnomalyReporter;
 import android.telephony.CarrierConfigManager;
 import android.telephony.CarrierConfigManager.Ims;
 import android.telephony.SubscriptionManager;
+import android.telephony.TelephonyManager;
 import android.telephony.TelephonyRegistryManager;
 import android.telephony.ims.ProvisioningManager;
 import android.telephony.ims.aidl.IFeatureProvisioningCallback;
@@ -76,6 +78,7 @@
 
 import java.util.Arrays;
 import java.util.Map;
+import java.util.UUID;
 import java.util.concurrent.Executor;
 
 /**
@@ -154,6 +157,10 @@
             CAPABILITY_TYPE_PRESENCE_UCE, Ims.KEY_CAPABILITY_TYPE_PRESENCE_UCE_INT_ARRAY
     );
 
+    private static final UUID VOLTE_PROVISIONING_ANOMALY =
+            UUID.fromString("f5f90e4d-3d73-4f63-a0f9-cbe1941ca57c");
+    private static final String VOLTE_PROVISIONING_ANOMALY_DESC = "VoLTE is Not Provisioned";
+
     /**
      * Create a FeatureConnector for this class to use to connect to an ImsManager.
      */
@@ -249,7 +256,7 @@
                                         (FeatureProvisioningData) msg.obj);
                     } catch (NullPointerException e) {
                         logw(LOG_PREFIX, msg.arg1,
-                                "can not find callback manager message" + msg.what);
+                                "can not find callback manager, message" + msg.what);
                     }
                     break;
                 case EVENT_MULTI_SIM_CONFIGURATION_CHANGE:
@@ -257,9 +264,11 @@
                     onMultiSimConfigChanged(activeModemCount);
                     break;
                 case EVENT_PROVISIONING_VALUE_CHANGED:
-                    log("subId " + msg.arg1 + " changed provisioning value item : " + msg.arg2
+                    logAttr("ImsConfig", "EVENT_PROVISIONING_VALUE_CHANGED", msg.arg1,
+                            "changed provisioning value, item : " + msg.arg2
                             + " value : " + (int) msg.obj);
-                    updateCapabilityTechFromKey(msg.arg1, msg.arg2, (int) msg.obj);
+                    updateCapabilityTechFromKey("ImsConfig[" + msg.arg1 + "]",
+                            msg.arg1, msg.arg2, (int) msg.obj);
                     break;
                 case EVENT_NOTIFY_INIT_PROVISIONED_VALUE:
                     int slotId = msg.arg1;
@@ -1136,11 +1145,12 @@
      * return the provisioning status for MmTel capability in specific radio tech
      */
     @VisibleForTesting
-    public boolean getImsProvisioningStatusForCapability(int subId, int capability, int tech) {
+    public boolean getImsProvisioningStatusForCapability(String attributionPackage, int subId,
+            int capability, int tech) {
         boolean mmTelProvisioned = isImsProvisioningRequiredForCapability(subId, capability, tech);
         if (!mmTelProvisioned) { // provisioning not required
-            log("getImsProvisioningStatusForCapability : not required "
-                    + " capability " + capability + " tech " + tech);
+            logAttr(attributionPackage, "getImsProvisioningStatusForCapability", subId,
+                    " not required, capability " + capability + " tech " + tech);
             return true;
         }
 
@@ -1153,14 +1163,15 @@
             result = getValueFromImsService(subId, capability, tech);
             mmTelProvisioned = getBoolValue(result);
             if (result != ProvisioningManager.PROVISIONING_RESULT_UNKNOWN) {
-                setAndNotifyMmTelProvisioningValue(subId, capability, tech, mmTelProvisioned);
+                setAndNotifyMmTelProvisioningValue(attributionPackage, subId, capability, tech,
+                        mmTelProvisioned);
             }
         } else {
             mmTelProvisioned = getBoolValue(result);
         }
 
-        log("getImsProvisioningStatusForCapability : "
-                + " capability " + capability
+        logAttr(attributionPackage, "getImsProvisioningStatusForCapability", subId,
+                " capability " + capability
                 + " tech " + tech
                 + " result " + mmTelProvisioned);
         return mmTelProvisioned;
@@ -1170,20 +1181,21 @@
      * set MmTel provisioning status in specific tech
      */
     @VisibleForTesting
-    public void setImsProvisioningStatusForCapability(int subId, int capability, int tech,
-            boolean isProvisioned) {
+    public void setImsProvisioningStatusForCapability(String attributionPackage, int subId,
+            int capability, int tech, boolean isProvisioned) {
         boolean mmTelProvisioned = isImsProvisioningRequiredForCapability(subId, capability, tech);
         if (!mmTelProvisioned) { // provisioning not required
-            log("setImsProvisioningStatusForCapability : not required "
-                    + " capability " + capability + " tech " + tech);
+            logAttr(attributionPackage, "setImsProvisioningStatusForCapability", subId,
+                    "not required, capability " + capability + " tech " + tech);
             return;
         }
 
         // write value to ImsProvisioningLoader
-        boolean isChanged = setAndNotifyMmTelProvisioningValue(subId, capability, tech,
-                isProvisioned);
+        boolean isChanged = setAndNotifyMmTelProvisioningValue(attributionPackage, subId,
+                capability, tech, isProvisioned);
         if (!isChanged) {
-            log("status not changed mmtel capability " + capability + " tech " + tech);
+            logAttr(attributionPackage, "setImsProvisioningStatusForCapability", subId,
+                    "status not changed, capability " + capability + " tech " + tech);
             return;
         }
 
@@ -1192,7 +1204,8 @@
         int value = getIntValue(isProvisioned);
         int key = getKeyFromCapability(capability, tech);
         if (key != INVALID_VALUE) {
-            log("setImsProvisioningStatusForCapability : matched key " + key);
+            logAttr(attributionPackage, "setImsProvisioningStatusForCapability", subId,
+                    "matched key " + key);
             try {
                 // set key and value to vendor ImsService for MmTel
                 mMmTelFeatureListenersSlotMap.get(slotId).setProvisioningValue(key, value);
@@ -1291,20 +1304,22 @@
      * {@link ImsConfigImplBase#CONFIG_RESULT_SUCCESS} or
      */
     @VisibleForTesting
-    public int setProvisioningValue(int subId, int key, int value) {
-        log("setProvisioningValue");
+    public int setProvisioningValue(String attributionPackage, int subId, int key, int value) {
+        logAttr(attributionPackage, "setProvisioningValue", subId, key + ": " + value);
 
         int retVal = ImsConfigImplBase.CONFIG_RESULT_FAILED;
         // check key value
         if (!Arrays.stream(LOCAL_IMS_CONFIG_KEYS).anyMatch(keyValue -> keyValue == key)) {
-            log("not matched key " + key);
+            logAttr(attributionPackage, "setProvisioningValue", subId,
+                    "not matched key " + key);
             return ImsConfigImplBase.CONFIG_RESULT_UNKNOWN;
         }
 
         // check subId
         int slotId = getSlotId(subId);
         if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX || slotId >= mNumSlot) {
-            loge("Fail to retrieve slotId from subId");
+            logAttrE(attributionPackage, "setProvisioningValue", subId,
+                    "Fail to retrieve slotId from subId");
             return ImsConfigImplBase.CONFIG_RESULT_FAILED;
         }
 
@@ -1326,12 +1341,13 @@
                 retVal = mRcsFeatureListenersSlotMap.get(slotId).setProvisioningValue(key, value);
             }
         } catch (NullPointerException e) {
-            loge("can not access FeatureListener to set provisioning value");
+            logAttrE(attributionPackage, "setProvisioningValue", subId,
+                    "can not access FeatureListener to set provisioning value");
             return ImsConfigImplBase.CONFIG_RESULT_FAILED;
         }
 
         // update and notify provisioning status changed capability and tech from key
-        updateCapabilityTechFromKey(subId, key, value);
+        updateCapabilityTechFromKey(attributionPackage, subId, key, value);
 
         return retVal;
     }
@@ -1349,17 +1365,19 @@
      * {@link ImsConfigImplBase#CONFIG_RESULT_UNKNOWN}
      */
     @VisibleForTesting
-    public int getProvisioningValue(int subId, int key) {
+    public int getProvisioningValue(String attributionPackage, int subId, int key) {
         // check key value
         if (!Arrays.stream(LOCAL_IMS_CONFIG_KEYS).anyMatch(keyValue -> keyValue == key)) {
-            log("not matched key " + key);
+            logAttr(attributionPackage, "getProvisioningValue", subId,
+                    "not matched key " + key);
             return ImsConfigImplBase.CONFIG_RESULT_UNKNOWN;
         }
 
         // check subId
         int slotId = getSlotId(subId);
         if (slotId <= SubscriptionManager.INVALID_SIM_SLOT_INDEX || slotId >= mNumSlot) {
-            loge("Fail to retrieve slotId from subId");
+            logAttrE(attributionPackage, "getProvisioningValue", subId,
+                    "Fail to retrieve slotId from subId");
             return ImsConfigImplBase.CONFIG_RESULT_UNKNOWN;
         }
 
@@ -1376,7 +1394,8 @@
                         capability, tech);
             }
             if (result != ImsProvisioningLoader.STATUS_NOT_SET) {
-                log("getProvisioningValue from loader : key " + key + " result " + result);
+                logAttr(attributionPackage, "getProvisioningValue", subId,
+                        "cache hit : key=" + key + ": value=" + result);
                 return result;
             }
         }
@@ -1385,24 +1404,27 @@
         if (key == KEY_EAB_PROVISIONING_STATUS) {
             result = getRcsValueFromImsService(subId, capability);
             if (result == ImsConfigImplBase.CONFIG_RESULT_UNKNOWN) {
-                logw("getProvisioningValue : fail to get data from ImsService capability"
-                        + capability);
+                logAttrW(attributionPackage, "getProvisioningValue", subId,
+                        "fail to get data from ImsService, capability=" + capability);
                 return result;
             }
-            log("getProvisioningValue from vendor : key " + key + " result " + result);
+            logAttr(attributionPackage, "getProvisioningValue", subId,
+                    "cache miss, get from RCS - key=" + key + ": value=" + result);
 
             setAndNotifyRcsProvisioningValueForAllTech(subId, capability, getBoolValue(result));
             return result;
         } else {
             result = getValueFromImsService(subId, capability, tech);
             if (result == ImsConfigImplBase.CONFIG_RESULT_UNKNOWN) {
-                logw("getProvisioningValue : fail to get data from ImsService capability"
-                        + capability);
+                logAttrW(attributionPackage, "getProvisioningValue", subId,
+                        "fail to get data from ImsService, capability=" + capability);
                 return result;
             }
-            log("getProvisioningValue from vendor : key " + key + " result " + result);
+            logAttr(attributionPackage, "getProvisioningValue", subId,
+                    "cache miss, get from MMTEL - key=" + key + ": value=" + result);
 
-            setAndNotifyMmTelProvisioningValue(subId, capability, tech, getBoolValue(result));
+            setAndNotifyMmTelProvisioningValue(attributionPackage, subId, capability, tech,
+                    getBoolValue(result));
             return result;
         }
     }
@@ -1531,20 +1553,23 @@
         }
     }
 
-    private void  updateCapabilityTechFromKey(int subId, int key, int value) {
+    private void  updateCapabilityTechFromKey(String attributionPackage, int subId, int key,
+            int value) {
         boolean isProvisioned = getBoolValue(value);
         int capability = getCapabilityFromKey(key);
         int tech = getTechFromKey(key);
 
         if (capability == INVALID_VALUE || tech == INVALID_VALUE) {
-            logw("updateCapabilityTechFromKey : unknown key " + key);
+            logAttrW(attributionPackage, "updateCapabilityTechFromKey", subId,
+                    "unknown key " + key);
             return;
         }
 
         if (key == KEY_VOLTE_PROVISIONING_STATUS
                 || key == KEY_VT_PROVISIONING_STATUS
                 || key == KEY_VOICE_OVER_WIFI_ENABLED_OVERRIDE) {
-            setAndNotifyMmTelProvisioningValue(subId, capability, tech, isProvisioned);
+            setAndNotifyMmTelProvisioningValue(attributionPackage, subId, capability, tech,
+                    isProvisioned);
         }
         if (key == KEY_EAB_PROVISIONING_STATUS) {
             setAndNotifyRcsProvisioningValueForAllTech(subId, capability, isProvisioned);
@@ -1631,12 +1656,33 @@
         return value == ProvisioningManager.PROVISIONING_VALUE_ENABLED ? true : false;
     }
 
-    private boolean setAndNotifyMmTelProvisioningValue(int subId, int capability, int tech,
+    // If VoLTE is not provisioned, generate an anomaly report as this is not expected.
+    private void checkProvisioningValueForAnomaly(String attributionPackage, int subId,
+            int capability, int tech, boolean isProvisioned) {
+        if (isProvisioned) return;
+        boolean isVolte = capability == CAPABILITY_TYPE_VOICE && tech == REGISTRATION_TECH_LTE;
+        if (!isVolte) return;
+        // We have hit the condition where VoLTE has been de-provisioned
+        int carrierId = TelephonyManager.UNKNOWN_CARRIER_ID;
+        TelephonyManager manager = mApp.getSystemService(TelephonyManager.class);
+        if (manager != null) {
+            carrierId = manager.createForSubscriptionId(subId).getSimCarrierId();
+        }
+        logAttrW(attributionPackage, "checkProvisioningValueForAnomaly", subId,
+                "VoLTE provisioning disabled");
+        AnomalyReporter.reportAnomaly(VOLTE_PROVISIONING_ANOMALY,
+                VOLTE_PROVISIONING_ANOMALY_DESC, carrierId);
+    }
+
+    private boolean setAndNotifyMmTelProvisioningValue(String attributionPackage, int subId,
+            int capability, int tech,
             boolean isProvisioned) {
         boolean changed = mImsProvisioningLoader.setProvisioningStatus(subId, FEATURE_MMTEL,
                 capability, tech, isProvisioned);
         // notify MmTel capability changed
         if (changed) {
+            checkProvisioningValueForAnomaly(attributionPackage, subId, capability, tech,
+                    isProvisioned);
             mHandler.sendMessage(mHandler.obtainMessage(EVENT_PROVISIONING_CAPABILITY_CHANGED,
                     getSlotId(subId), 0, (Object) new FeatureProvisioningData(
                             capability, tech, isProvisioned, /*isMmTel*/true)));
@@ -1766,6 +1812,18 @@
         }
     }
 
+    private void logAttr(String attr, String prefix, int subId, String log) {
+        Rlog.d(TAG, prefix + "[" + subId + "]: " + log + ", attr = [" + attr + "]");
+    }
+
+    private void logAttrW(String attr, String prefix, int subId, String log) {
+        Rlog.w(TAG, prefix + "[" + subId + "]: " + log + ", attr = [" + attr + "]");
+    }
+
+    private void logAttrE(String attr, String prefix, int subId, String log) {
+        Rlog.e(TAG, prefix + "[" + subId + "]: " + log + ", attr = [" + attr + "]");
+    }
+
     private void log(String s) {
         Rlog.d(TAG, s);
     }
diff --git a/src/com/android/phone/ImsProvisioningLoader.java b/src/com/android/phone/ImsProvisioningLoader.java
index 1238b9a..8d63463 100644
--- a/src/com/android/phone/ImsProvisioningLoader.java
+++ b/src/com/android/phone/ImsProvisioningLoader.java
@@ -113,7 +113,7 @@
                     logd("check UT provisioning status " + UtProvisioningStatus);
 
                     if (STATUS_PROVISIONED == UtProvisioningStatus) {
-                        setProvisioningStatusToSubIdBundle(ImsFeature.FEATURE_MMTEL, tech,
+                        setProvisioningStatusToSubIdBundle(subId, ImsFeature.FEATURE_MMTEL, tech,
                                 MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_UT, subIdBundle,
                                 UtProvisioningStatus);
                     }
@@ -130,7 +130,7 @@
             subIdBundle = mSubIdBundleArray.get(subId, null);
         }
 
-        return getProvisioningStatusFromSubIdBundle(imsFeature, tech,
+        return getProvisioningStatusFromSubIdBundle(subId, imsFeature, tech,
                 capability, subIdBundle);
     }
 
@@ -146,42 +146,44 @@
             }
 
             PersistableBundle subIdBundle = mSubIdBundleArray.get(subId, null);
-            setProvisioningStatusToSubIdBundle(imsFeature, tech, capability, subIdBundle,
+            setProvisioningStatusToSubIdBundle(subId, imsFeature, tech, capability, subIdBundle,
                     newValue);
             saveSubIdBundleToXml(subId, subIdBundle);
         }
         return true;
     }
 
-    private int getProvisioningStatusFromSubIdBundle(int imsFeature, int tech,
+    private int getProvisioningStatusFromSubIdBundle(int subId, int imsFeature, int tech,
             int capability, PersistableBundle subIdBundle) {
         // If it doesn't exist in xml, return STATUS_NOT_SET
         if (subIdBundle == null || subIdBundle.isEmpty()) {
-            logd("xml is empty");
+            logd("getProvisioningStatusFromSubIdBundle", subId, "xml is empty");
             return STATUS_NOT_SET;
         }
 
         PersistableBundle regTechBundle = subIdBundle.getPersistableBundle(
                 String.valueOf(imsFeature));
         if (regTechBundle == null) {
-            logd("ImsFeature " + imsFeature + " is not exist in xml");
+            logd("getProvisioningStatusFromSubIdBundle", subId,
+                    "ImsFeature " + imsFeature + " does not exist in xml");
             return STATUS_NOT_SET;
         }
 
         PersistableBundle capabilityBundle = regTechBundle.getPersistableBundle(
                 String.valueOf(tech));
         if (capabilityBundle == null) {
-            logd("RegistrationTech " + tech + " is not exist in xml");
+            logd("getProvisioningStatusFromSubIdBundle", subId,
+                    "RegistrationTech " + tech + " does not exist in xml");
             return STATUS_NOT_SET;
         }
 
-        return getIntValueFromBundle(String.valueOf(capability), capabilityBundle);
+        return getIntValueFromBundle(subId, tech, String.valueOf(capability), capabilityBundle);
     }
 
-    private void setProvisioningStatusToSubIdBundle(int imsFeature, int tech,
+    private void setProvisioningStatusToSubIdBundle(int subId, int imsFeature, int tech,
             int capability, PersistableBundle subIdBundle, int newStatus) {
-        logd("set provisioning status " + newStatus + " ImsFeature "
-                + imsFeature + " tech " + tech + " capa " + capability);
+        logd("setProvisioningStatusToSubIdBundle", subId, "set provisioning status " + newStatus
+                + " ImsFeature " + imsFeature + " tech " + tech + " capa " + capability);
 
         PersistableBundle regTechBundle = subIdBundle.getPersistableBundle(
                 String.valueOf(imsFeature));
@@ -201,9 +203,10 @@
     }
 
     // Default value is STATUS_NOT_SET
-    private int getIntValueFromBundle(String key, PersistableBundle bundle) {
+    private int getIntValueFromBundle(int subId, int tech, String key, PersistableBundle bundle) {
         int value = bundle.getInt(key, STATUS_NOT_SET);
-        logd("get value " + value);
+        logd("getIntValueFromBundle", subId,
+                "Cache hit, tech=" + tech + " capability=" + key + ": returning " + value);
         return value;
     }
 
@@ -293,7 +296,7 @@
             String[] infoArray) {
         for (String info : infoArray) {
             String[] paramArray = info.split(",");
-            setProvisioningStatusToSubIdBundle(Integer.valueOf(paramArray[0]),
+            setProvisioningStatusToSubIdBundle(subId, Integer.valueOf(paramArray[0]),
                     Integer.valueOf(paramArray[1]), Integer.valueOf(paramArray[2]),
                     subIdBundle, Integer.valueOf(paramArray[3]));
         }
@@ -304,6 +307,10 @@
         Log.e(LOG_TAG, contents);
     }
 
+    private void logd(String prefix, int subId, String contents) {
+        Log.d(LOG_TAG, prefix + "[" + subId + "]: " + contents);
+    }
+
     private void logd(String contents) {
         Log.d(LOG_TAG, contents);
     }
diff --git a/src/com/android/phone/PhoneInterfaceManager.java b/src/com/android/phone/PhoneInterfaceManager.java
index 1652375..6dc2add 100644
--- a/src/com/android/phone/PhoneInterfaceManager.java
+++ b/src/com/android/phone/PhoneInterfaceManager.java
@@ -5466,6 +5466,7 @@
         enforceTelephonyFeatureWithException(getCurrentPackageName(),
                 FEATURE_TELEPHONY_IMS, "setImsProvisioningStatusForCapability");
 
+        String displayPackageName = getCurrentPackageNameOrPhone();
         final long identity = Binder.clearCallingIdentity();
         try {
             ImsProvisioningController controller = ImsProvisioningController.getInstance();
@@ -5473,7 +5474,7 @@
                 loge("setImsProvisioningStatusForCapability: Device does not support IMS");
                 return;
             }
-            controller.setImsProvisioningStatusForCapability(
+            controller.setImsProvisioningStatusForCapability(displayPackageName,
                     subId, capability, tech, isProvisioned);
         } finally {
             Binder.restoreCallingIdentity(identity);
@@ -5488,6 +5489,7 @@
         enforceTelephonyFeatureWithException(getCurrentPackageName(),
                 FEATURE_TELEPHONY_IMS, "getImsProvisioningStatusForCapability");
 
+        String displayPackageName = getCurrentPackageNameOrPhone();
         final long identity = Binder.clearCallingIdentity();
         try {
             ImsProvisioningController controller = ImsProvisioningController.getInstance();
@@ -5497,7 +5499,8 @@
                 // device does not support IMS, this method will return true always.
                 return true;
             }
-            return controller.getImsProvisioningStatusForCapability(subId, capability, tech);
+            return controller.getImsProvisioningStatusForCapability(displayPackageName,
+                    subId, capability, tech);
         } finally {
             Binder.restoreCallingIdentity(identity);
         }
@@ -5560,6 +5563,7 @@
         enforceTelephonyFeatureWithException(getCurrentPackageName(),
                 FEATURE_TELEPHONY_IMS, "getImsProvisioningInt");
 
+        String displayPackageName = getCurrentPackageNameOrPhone();
         final long identity = Binder.clearCallingIdentity();
         try {
             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
@@ -5577,7 +5581,8 @@
                 // device does not support IMS, this method will return CONFIG_RESULT_UNKNOWN.
                 return ImsConfigImplBase.CONFIG_RESULT_UNKNOWN;
             }
-            int retVal = controller.getProvisioningValue(subId, key);
+            int retVal = controller.getProvisioningValue(displayPackageName, subId,
+                    key);
             if (retVal != ImsConfigImplBase.CONFIG_RESULT_UNKNOWN) {
                 return retVal;
             }
@@ -5633,6 +5638,7 @@
         enforceTelephonyFeatureWithException(getCurrentPackageName(),
                 FEATURE_TELEPHONY_IMS, "setImsProvisioningInt");
 
+        String displayPackageName = getCurrentPackageNameOrPhone();
         final long identity = Binder.clearCallingIdentity();
         try {
             // TODO: Refactor to remove ImsManager dependence and query through ImsPhone directly.
@@ -5650,7 +5656,8 @@
                 // device does not support IMS, this method will return CONFIG_RESULT_FAILED.
                 return ImsConfigImplBase.CONFIG_RESULT_FAILED;
             }
-            int retVal = controller.setProvisioningValue(subId, key, value);
+            int retVal = controller.setProvisioningValue(displayPackageName, subId, key,
+                    value);
             if (retVal != ImsConfigImplBase.CONFIG_RESULT_UNKNOWN) {
                 return retVal;
             }
@@ -10853,6 +10860,19 @@
     }
 
     /**
+     * @return The calling package name or "phone" if the caller is the phone process. This is done
+     * because multiple Phone has multiple packages in it and the first element in the array is not
+     * actually always the caller.
+     * Note: This is for logging purposes only and should not be used for security checks.
+     */
+    private String getCurrentPackageNameOrPhone() {
+        PackageManager pm = mApp.getPackageManager();
+        String uidName = pm == null ? null : pm.getNameForUid(Binder.getCallingUid());
+        if (uidName != null && !uidName.isEmpty()) return uidName;
+        return getCurrentPackageName();
+    }
+
+    /**
      * Return whether data is enabled for certain APN type. This will tell if framework will accept
      * corresponding network requests on a subId.
      *
diff --git a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
index be7179e..75e39f9 100644
--- a/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
+++ b/src/com/android/phone/satellite/accesscontrol/SatelliteAccessController.java
@@ -1541,6 +1541,25 @@
         }
 
         mSatelliteCommunicationAllowedStateChangedListeners.put(callback.asBinder(), callback);
+
+        if (!mFeatureFlags.geofenceEnhancementForBetterUx()) {
+            plogd("The feature flag geofenceEnhancementForBetterUx is not enabled");
+            return SATELLITE_RESULT_SUCCESS;
+        }
+
+        this.post(() -> {
+            try {
+                synchronized (mSatelliteCommunicationAllowStateLock) {
+                    callback.onSatelliteCommunicationAllowedStateChanged(
+                            mCurrentSatelliteAllowedState);
+                    logd("registerForCommunicationAllowedStateChanged: "
+                            + "mCurrentSatelliteAllowedState " + mCurrentSatelliteAllowedState);
+                }
+            } catch (RemoteException ex) {
+                ploge("registerForCommunicationAllowedStateChanged: RemoteException ex=" + ex);
+            }
+        });
+
         return SATELLITE_RESULT_SUCCESS;
     }
 
diff --git a/src/com/android/phone/vvm/VvmDumpHandler.java b/src/com/android/phone/vvm/VvmDumpHandler.java
index 82c5bb5..bf09f30 100644
--- a/src/com/android/phone/vvm/VvmDumpHandler.java
+++ b/src/com/android/phone/vvm/VvmDumpHandler.java
@@ -19,15 +19,20 @@
         indentedWriter.println("******* OmtpVvm *******");
         indentedWriter.println("======= Configs =======");
         indentedWriter.increaseIndent();
-        for (PhoneAccountHandle handle : context.getSystemService(TelecomManager.class)
-                .getCallCapablePhoneAccounts()) {
-            int subId = PhoneAccountHandleConverter.toSubId(handle);
-            indentedWriter.println(
-                    "VisualVoicemailPackageName:" + telephonyManager.createForSubscriptionId(subId)
-                            .getVisualVoicemailPackageName());
-            indentedWriter.println(
-                    "VisualVoicemailSmsFilterSettings(" + subId + "):" + telephonyManager
-                            .getActiveVisualVoicemailSmsFilterSettings(subId));
+        try {
+            for (PhoneAccountHandle handle : context.getSystemService(TelecomManager.class)
+                    .getCallCapablePhoneAccounts()) {
+                int subId = PhoneAccountHandleConverter.toSubId(handle);
+                indentedWriter.println(
+                        "VisualVoicemailPackageName:" + telephonyManager.createForSubscriptionId(
+                                        subId)
+                                .getVisualVoicemailPackageName());
+                indentedWriter.println(
+                        "VisualVoicemailSmsFilterSettings(" + subId + "):" + telephonyManager
+                                .getActiveVisualVoicemailSmsFilterSettings(subId));
+            }
+        } catch (SecurityException se) {
+            indentedWriter.println("Could not get vvm config " + se);
         }
         indentedWriter.decreaseIndent();
         indentedWriter.println("======== Logs =========");
diff --git a/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java b/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
index dd753f8..3946d1a 100644
--- a/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
+++ b/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelector.java
@@ -1835,13 +1835,14 @@
         logi("notifyCrossStackTimerExpired");
 
         mCrossStackTimerExpired = true;
-        if (mDomainSelected && !hangupOngoingDialing()) {
+        boolean isHangupOngoingDialing = hangupOngoingDialing();
+        if (mDomainSelected && !isHangupOngoingDialing) {
             // When reselecting domain, terminateSelection will be called.
             return;
         }
         mIsWaitingForDataDisconnection = false;
         removeMessages(MSG_WAIT_DISCONNECTION_TIMEOUT);
-        terminateSelectionForCrossSimRedialing(false);
+        terminateSelectionForCrossSimRedialing(isHangupOngoingDialing);
     }
 
     private boolean hangupOngoingDialing() {
diff --git a/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml b/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml
index 43bb1c5..a6259c8 100644
--- a/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml
+++ b/testapps/TestSatelliteApp/res/layout/activity_TestSatelliteWrapper.xml
@@ -25,7 +25,8 @@
         android:layout_height="wrap_content"
         android:orientation="vertical"
         android:gravity="center"
-        android:paddingStart="4dp">
+        android:paddingStart="4dp"
+        android:paddingTop="68dp">
 
         <TextView
             android:layout_width="wrap_content"
@@ -142,6 +143,18 @@
             android:layout_height="wrap_content"
             android:paddingRight="4dp"
             android:text="@string/unregisterForCarrierRoamingNtnModeChanged"/>
+        <Button
+            android:id="@+id/registerForCommunicationAllowedStateChanged"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingRight="4dp"
+            android:text="@string/registerForCommunicationAllowedStateChanged"/>
+        <Button
+            android:id="@+id/unregisterForCommunicationAllowedStateChanged"
+            android:layout_width="match_parent"
+            android:layout_height="wrap_content"
+            android:paddingRight="4dp"
+            android:text="@string/unregisterForCommunicationAllowedStateChanged"/>
         <LinearLayout
             android:layout_width="match_parent"
             android:layout_height="wrap_content"
diff --git a/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml b/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml
index 1f2a3ca..86f458e 100644
--- a/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml
+++ b/testapps/TestSatelliteApp/res/values/donottranslate_strings.xml
@@ -44,6 +44,8 @@
     <string name="stopSatelliteTransmissionUpdates">stopSatelliteTransmissionUpdates</string>
     <string name="showDatagramSendStateTransition">showDatagramSendStateTransition</string>
     <string name="showDatagramReceiveStateTransition">showDatagramReceiveStateTransition</string>
+    <string name="registerForCommunicationAllowedStateChanged">registerForCommunicationAllowedStateChanged</string>
+    <string name="unregisterForCommunicationAllowedStateChanged">unregisterForCommunicationAllowedStateChanged</string>
 
     <string name="provisionSatelliteService">provisionSatelliteService</string>
     <string name="deprovisionSatelliteService">deprovisionSatelliteService</string>
diff --git a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java
index 93a8131..ace1e41 100644
--- a/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java
+++ b/testapps/TestSatelliteApp/src/com/android/phone/testapps/satellitetestapp/TestSatelliteWrapper.java
@@ -27,6 +27,7 @@
 import android.telephony.satellite.wrapper.NtnSignalStrengthCallbackWrapper;
 import android.telephony.satellite.wrapper.NtnSignalStrengthWrapper;
 import android.telephony.satellite.wrapper.SatelliteCapabilitiesCallbackWrapper;
+import android.telephony.satellite.wrapper.SatelliteCommunicationAllowedStateCallbackWrapper;
 import android.telephony.satellite.wrapper.SatelliteManagerWrapper;
 import android.util.Log;
 import android.view.View;
@@ -55,6 +56,7 @@
     private SatelliteManagerWrapper mSatelliteManagerWrapper;
     private NtnSignalStrengthCallback mNtnSignalStrengthCallback = null;
     private CarrierRoamingNtnModeListener mCarrierRoamingNtnModeListener = null;
+    private SatelliteCommunicationAllowedStateCallback mSatelliteCommunicationAllowedStateCallback;
     private SatelliteCapabilitiesCallbackWrapper mSatelliteCapabilitiesCallback;
     private SubscriptionManager mSubscriptionManager;
     private int mSubId;
@@ -105,6 +107,11 @@
                 .setOnClickListener(this::registerForCarrierRoamingNtnModeChanged);
         findViewById(R.id.unregisterForCarrierRoamingNtnModeChanged)
                 .setOnClickListener(this::unregisterForCarrierRoamingNtnModeChanged);
+        findViewById(R.id.registerForCommunicationAllowedStateChanged)
+                .setOnClickListener(this::registerForCommunicationAllowedStateChanged);
+        findViewById(R.id.unregisterForCommunicationAllowedStateChanged)
+                .setOnClickListener(this::unregisterForCommunicationAllowedStateChanged);
+
         findViewById(R.id.Back).setOnClickListener(new OnClickListener() {
             @Override
             public void onClick(View view) {
@@ -218,6 +225,38 @@
         }
     }
 
+    private void registerForCommunicationAllowedStateChanged(View view) {
+        addLogMessage("registerForCommunicationAllowedStateChanged");
+        logd("registerForCommunicationAllowedStateChanged()");
+        if (mSatelliteCommunicationAllowedStateCallback == null) {
+            logd("Creating new CarrierRoamingNtnModeListener instance.");
+            mSatelliteCommunicationAllowedStateCallback =
+                    new SatelliteCommunicationAllowedStateCallback();
+        }
+
+        try {
+            mSatelliteManagerWrapper.registerForCommunicationAllowedStateChanged(mExecutor,
+                    mSatelliteCommunicationAllowedStateCallback);
+        } catch (Exception ex) {
+            String errorMessage = "registerForCommunicationAllowedStateChanged: " + ex.getMessage();
+            logd(errorMessage);
+            addLogMessage(errorMessage);
+            mSatelliteCommunicationAllowedStateCallback = null;
+        }
+    }
+
+    private void unregisterForCommunicationAllowedStateChanged(View view) {
+        addLogMessage("unregisterForCommunicationAllowedStateChanged");
+        logd("unregisterForCommunicationAllowedStateChanged()");
+        if (mSatelliteCommunicationAllowedStateCallback != null) {
+            mSatelliteManagerWrapper.unregisterForCommunicationAllowedStateChanged(
+                    mSatelliteCommunicationAllowedStateCallback);
+            mSatelliteCommunicationAllowedStateCallback = null;
+            addLogMessage("mSatelliteCommunicationAllowedStateCallback was unregistered");
+        } else {
+            addLogMessage("mSatelliteCommunicationAllowedStateCallback is null, ignored.");
+        }
+    }
 
     private void registerForNtnSignalStrengthChanged(View view) {
         addLogMessage("registerForNtnSignalStrengthChanged");
@@ -334,6 +373,18 @@
         }
     }
 
+    private class SatelliteCommunicationAllowedStateCallback implements
+            SatelliteCommunicationAllowedStateCallbackWrapper {
+
+        @Override
+        public void onSatelliteCommunicationAllowedStateChanged(boolean isAllowed) {
+            String message =
+                    "Received onSatelliteCommunicationAllowedStateChanged isAllowed: " + isAllowed;
+            logd(message);
+            addLogMessage(message);
+        }
+    }
+
     private void isNonTerrestrialNetwork(View view) {
         boolean isNonTerrestrialNetwork = mSatelliteManagerWrapper.isNonTerrestrialNetwork(mSubId);
         addLogMessage("isNonTerrestrialNetwork=" + isNonTerrestrialNetwork);
diff --git a/tests/src/com/android/phone/ImsProvisioningControllerTest.java b/tests/src/com/android/phone/ImsProvisioningControllerTest.java
index 6599f03..c696151 100644
--- a/tests/src/com/android/phone/ImsProvisioningControllerTest.java
+++ b/tests/src/com/android/phone/ImsProvisioningControllerTest.java
@@ -112,6 +112,7 @@
             REGISTRATION_TECH_NR
     };
     private static final int RADIO_TECH_INVALID = ImsRegistrationImplBase.REGISTRATION_TECH_NONE;
+    private static final String TEST_ATTR = "TEST";
 
     @Mock
     Context mContext;
@@ -636,7 +637,8 @@
         for (int i = 0; i < RADIO_TECHS.length; i++) {
             // get provisioning status
             provisioned = mTestImsProvisioningController
-                    .getImsProvisioningStatusForCapability(mSubId0, capability, RADIO_TECHS[i]);
+                    .getImsProvisioningStatusForCapability(TEST_ATTR, mSubId0, capability,
+                            RADIO_TECHS[i]);
 
             // verify return value
             assertEquals(expectedVoiceProvisioningStatus[i], provisioned);
@@ -651,7 +653,8 @@
         for (int i = 0; i < RADIO_TECHS.length; i++) {
             // get provisioning status
             provisioned = mTestImsProvisioningController
-                    .getImsProvisioningStatusForCapability(mSubId0, capability, RADIO_TECHS[i]);
+                    .getImsProvisioningStatusForCapability(TEST_ATTR, mSubId0, capability,
+                            RADIO_TECHS[i]);
 
             // verify return value
             assertEquals(expectedVideoProvisioningStatus[i], provisioned);
@@ -666,7 +669,8 @@
         for (int i = 0; i < RADIO_TECHS.length; i++) {
             // get provisioning status
             provisioned = mTestImsProvisioningController
-                    .getImsProvisioningStatusForCapability(mSubId0, capability, RADIO_TECHS[i]);
+                    .getImsProvisioningStatusForCapability(TEST_ATTR, mSubId0, capability,
+                            RADIO_TECHS[i]);
 
             // verify return value
             assertEquals(expectedUtProvisioningStatus[i], provisioned);
@@ -718,7 +722,7 @@
         int capability = CAPABILITY_TYPE_VOICE;
         int tech = REGISTRATION_TECH_LTE;
         provisioned = mTestImsProvisioningController
-                .getImsProvisioningStatusForCapability(mSubId0, capability, tech);
+                .getImsProvisioningStatusForCapability(TEST_ATTR, mSubId0, capability, tech);
 
         // verify return value default false - not provisioned
         assertEquals(true, provisioned);
@@ -741,7 +745,7 @@
         capability = CAPABILITY_TYPE_VIDEO;
         tech = REGISTRATION_TECH_LTE;
         provisioned = mTestImsProvisioningController
-                .getImsProvisioningStatusForCapability(mSubId0, capability, tech);
+                .getImsProvisioningStatusForCapability(TEST_ATTR, mSubId0, capability, tech);
 
         // verify return value default false - not provisioned
         assertEquals(false, provisioned);
@@ -891,17 +895,19 @@
         for (int i = 0; i < RADIO_TECHS.length; i++) {
             // get provisioning status
             provisionedFirst = mTestImsProvisioningController
-                    .getImsProvisioningStatusForCapability(mSubId0, capability, RADIO_TECHS[i]);
+                    .getImsProvisioningStatusForCapability(TEST_ATTR, mSubId0, capability,
+                            RADIO_TECHS[i]);
 
             // verify return value default false - not provisioned
             assertEquals(false, provisionedFirst);
 
             mTestImsProvisioningController.setImsProvisioningStatusForCapability(
-                    mSubId0, capability, RADIO_TECHS[i], !provisionedFirst);
+                    TEST_ATTR, mSubId0, capability, RADIO_TECHS[i], !provisionedFirst);
             processAllMessages();
 
             provisionedSecond = mTestImsProvisioningController
-                    .getImsProvisioningStatusForCapability(mSubId0, capability, RADIO_TECHS[i]);
+                    .getImsProvisioningStatusForCapability(TEST_ATTR, mSubId0, capability,
+                            RADIO_TECHS[i]);
 
             // verify return value default false - provisioned
             assertEquals(!provisionedFirst, provisionedSecond);
@@ -968,17 +974,19 @@
         for (int i = 0; i < RADIO_TECHS.length; i++) {
             // get provisioning status
             provisionedFirst = mTestImsProvisioningController
-                    .getImsProvisioningStatusForCapability(mSubId0, capability, RADIO_TECHS[i]);
+                    .getImsProvisioningStatusForCapability(TEST_ATTR, mSubId0, capability,
+                            RADIO_TECHS[i]);
 
             // verify return value default false - not provisioned
             assertEquals(false, provisionedFirst);
 
             mTestImsProvisioningController.setImsProvisioningStatusForCapability(
-                    mSubId0, capability, RADIO_TECHS[i], !provisionedFirst);
+                    TEST_ATTR, mSubId0, capability, RADIO_TECHS[i], !provisionedFirst);
             processAllMessages();
 
             provisionedSecond = mTestImsProvisioningController
-                    .getImsProvisioningStatusForCapability(mSubId0, capability, RADIO_TECHS[i]);
+                    .getImsProvisioningStatusForCapability(TEST_ATTR, mSubId0, capability,
+                            RADIO_TECHS[i]);
 
             // verify return value default false - provisioned
             assertEquals(!provisionedFirst, provisionedSecond);
@@ -1161,7 +1169,7 @@
         for (int i = 0; i < keys.length; i++) {
             clearInvocations(mIFeatureProvisioningCallback0);
             result = mTestImsProvisioningController.setProvisioningValue(
-                    mSubId0, keys[i], PROVISIONING_VALUE_ENABLED);
+                    TEST_ATTR, mSubId0, keys[i], PROVISIONING_VALUE_ENABLED);
             processAllMessages();
 
             // check return value
@@ -1220,7 +1228,7 @@
         int capa = CAPABILITY_TYPE_PRESENCE_UCE;
 
         int result = mTestImsProvisioningController.setProvisioningValue(
-                    mSubId0, key, PROVISIONING_VALUE_ENABLED);
+                TEST_ATTR, mSubId0, key, PROVISIONING_VALUE_ENABLED);
         processAllMessages();
 
         // check return value
@@ -1271,7 +1279,7 @@
         };
         for (int key : keys) {
             int result = mTestImsProvisioningController.setProvisioningValue(
-                    mSubId0, key, PROVISIONING_VALUE_ENABLED);
+                    TEST_ATTR, mSubId0, key, PROVISIONING_VALUE_ENABLED);
             processAllMessages();
 
             // check return value
@@ -1349,7 +1357,8 @@
                 REGISTRATION_TECH_IWLAN
         };
         for (int i = 0; i < keys.length; i++) {
-            int result = mTestImsProvisioningController.getProvisioningValue(mSubId0, keys[i]);
+            int result = mTestImsProvisioningController.getProvisioningValue(TEST_ATTR, mSubId0,
+                    keys[i]);
             processAllMessages();
 
             // check return value
@@ -1365,7 +1374,7 @@
         int key = KEY_EAB_PROVISIONING_STATUS;
         int capa = CAPABILITY_TYPE_PRESENCE_UCE;
 
-        int result = mTestImsProvisioningController.getProvisioningValue(mSubId0, key);
+        int result = mTestImsProvisioningController.getProvisioningValue(TEST_ATTR, mSubId0, key);
         processAllMessages();
 
         // check return value
@@ -1453,7 +1462,8 @@
                 REGISTRATION_TECH_IWLAN
         };
         for (int i = 0; i < keys.length; i++) {
-            int result = mTestImsProvisioningController.getProvisioningValue(mSubId0, keys[i]);
+            int result = mTestImsProvisioningController.getProvisioningValue(TEST_ATTR, mSubId0,
+                    keys[i]);
             processAllMessages();
 
             // check return value
@@ -1481,7 +1491,7 @@
         int key = KEY_EAB_PROVISIONING_STATUS;
         int capa = CAPABILITY_TYPE_PRESENCE_UCE;
 
-        int result = mTestImsProvisioningController.getProvisioningValue(mSubId0, key);
+        int result = mTestImsProvisioningController.getProvisioningValue(TEST_ATTR, mSubId0, key);
         processAllMessages();
 
         // check return value
@@ -1590,8 +1600,8 @@
         int tech = REGISTRATION_TECH_LTE;
         boolean provisioned;
         provisioned = mTestImsProvisioningController.getImsProvisioningStatusForCapability(
-                mSubId1, capability, tech);
-        mTestImsProvisioningController.setImsProvisioningStatusForCapability(mSubId1,
+                TEST_ATTR, mSubId1, capability, tech);
+        mTestImsProvisioningController.setImsProvisioningStatusForCapability(TEST_ATTR, mSubId1,
                 capability, tech, !provisioned);
         processAllMessages();
 
@@ -1643,7 +1653,7 @@
         int capa = CAPABILITY_TYPE_PRESENCE_UCE;
         int tech = REGISTRATION_TECH_LTE;
 
-        int result = mTestImsProvisioningController.getProvisioningValue(mSubId0, key);
+        int result = mTestImsProvisioningController.getProvisioningValue(TEST_ATTR, mSubId0, key);
         processAllMessages();
 
         // check return value
@@ -1668,7 +1678,7 @@
         clearInvocations(mImsConfig);
         clearInvocations(mImsProvisioningLoader);
 
-        mTestImsProvisioningController.setProvisioningValue(mSubId0, key,
+        mTestImsProvisioningController.setProvisioningValue(TEST_ATTR, mSubId0, key,
                 PROVISIONING_VALUE_DISABLED);
         processAllMessages();
 
diff --git a/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java b/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
index 93bd9e8..90446af 100644
--- a/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
+++ b/tests/src/com/android/services/telephony/domainselection/EmergencyCallDomainSelectorTest.java
@@ -2831,7 +2831,7 @@
         mDomainSelector.notifyCrossStackTimerExpired();
 
         verify(mTransportSelectorCallback)
-                .onSelectionTerminated(eq(DisconnectCause.EMERGENCY_TEMP_FAILURE));
+                .onSelectionTerminated(eq(DisconnectCause.EMERGENCY_PERM_FAILURE));
     }
 
     @Test