[automerger skipped] Merge Android 24Q2 Release (ab/11526283) to aosp-main-future am: 43c5385e87 -s ours

am skip reason: Merged-In Iaa744f1834b45dff46ac79fb6ce8b6f8cfe883f0 with SHA-1 ed82a9496a is already in history

Original change: https://googleplex-android-review.googlesource.com/c/platform/packages/apps/ImsServiceEntitlement/+/27270747

Change-Id: I65e000d8fc5c4131056b5c097115028e573278d7
Signed-off-by: Automerger Merge Worker <[email protected]>
diff --git a/src/com/android/imsserviceentitlement/ImsEntitlementApi.java b/src/com/android/imsserviceentitlement/ImsEntitlementApi.java
index eeb4452..cc5e5f0 100644
--- a/src/com/android/imsserviceentitlement/ImsEntitlementApi.java
+++ b/src/com/android/imsserviceentitlement/ImsEntitlementApi.java
@@ -33,9 +33,9 @@
 import com.android.imsserviceentitlement.fcm.FcmTokenStore;
 import com.android.imsserviceentitlement.fcm.FcmUtils;
 import com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlAttributes;
-import com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlNode;
 import com.android.imsserviceentitlement.ts43.Ts43SmsOverIpStatus;
 import com.android.imsserviceentitlement.ts43.Ts43VolteStatus;
+import com.android.imsserviceentitlement.ts43.Ts43VonrStatus;
 import com.android.imsserviceentitlement.ts43.Ts43VowifiStatus;
 import com.android.imsserviceentitlement.utils.TelephonyUtils;
 import com.android.imsserviceentitlement.utils.XmlDoc;
@@ -113,6 +113,8 @@
                 token -> requestBuilder.setAuthenticationToken(token));
         FcmUtils.fetchFcmToken(mContext, mSubId);
         requestBuilder.setNotificationToken(FcmTokenStore.getToken(mContext, mSubId));
+        int entitlementVersion = TelephonyUtils.getEntitlementVersion(mContext, mSubId);
+        requestBuilder.setEntitlementVersion(entitlementVersion + ".0");
         requestBuilder.setAcceptContentType(ServiceEntitlementRequest.ACCEPT_CONTENT_TYPE_XML);
         if (mNeedsImsProvisioning) {
             requestBuilder.setConfigurationVersion(
@@ -132,7 +134,7 @@
                             : ImmutableList.of(ServiceEntitlement.APP_VOWIFI),
                     request);
             entitlementXmlDoc = new XmlDoc(rawXml);
-            mLastEntitlementConfiguration.update(rawXml);
+            mLastEntitlementConfiguration.update(entitlementVersion, rawXml);
             // Reset the retry count if no exception from queryEntitlementStatus()
             mRetryFullAuthenticationCount = AUTHENTICATION_RETRIES;
         } catch (ServiceEntitlementException e) {
@@ -152,8 +154,8 @@
                     // For handling the case of HTTP_UNAVAILABLE(503), client would perform the
                     // retry for the delay of Retry-After.
                     Log.d(TAG, "Server asking for retry. retryAfter = " + e.getRetryAfter());
-                    return EntitlementResult
-                            .builder()
+                    boolean isDefaultActive = TelephonyUtils.getDefaultStatus(mContext, mSubId);
+                    return EntitlementResult.builder(isDefaultActive)
                             .setRetryAfterSeconds(parseDelaySecondsByRetryAfter(e.getRetryAfter()))
                             .build();
                 }
@@ -184,30 +186,21 @@
     }
 
     private EntitlementResult toEntitlementResult(XmlDoc doc) {
-        EntitlementResult.Builder builder = EntitlementResult.builder();
+        boolean isDefaultActive = TelephonyUtils.getDefaultStatus(mContext, mSubId);
+        EntitlementResult.Builder builder = EntitlementResult.builder(isDefaultActive);
         ClientBehavior clientBehavior = mLastEntitlementConfiguration.entitlementValidation();
 
         if (mNeedsImsProvisioning && isResetToDefault(clientBehavior)) {
             // keep the entitlement result in default value and reset the configs.
-            if (clientBehavior == ClientBehavior.NEEDS_TO_RESET
-                    || clientBehavior == ClientBehavior.UNKNOWN_BEHAVIOR) {
-                mLastEntitlementConfiguration.reset();
-            } else {
-                mLastEntitlementConfiguration.resetConfigsExceptVers();
-            }
+            mLastEntitlementConfiguration.reset(clientBehavior);
         } else {
             builder.setVowifiStatus(Ts43VowifiStatus.builder(doc).build())
                     .setVolteStatus(Ts43VolteStatus.builder(doc).build())
+                    .setVonrStatus(Ts43VonrStatus.builder(doc).build())
                     .setSmsoveripStatus(Ts43SmsOverIpStatus.builder(doc).build());
-            doc.get(
-                    ResponseXmlNode.APPLICATION,
-                    ResponseXmlAttributes.SERVER_FLOW_URL,
-                    ServiceEntitlement.APP_VOWIFI)
+            doc.getFromVowifi(ResponseXmlAttributes.SERVER_FLOW_URL)
                     .ifPresent(url -> builder.setEmergencyAddressWebUrl(url));
-            doc.get(
-                    ResponseXmlNode.APPLICATION,
-                    ResponseXmlAttributes.SERVER_FLOW_USER_DATA,
-                    ServiceEntitlement.APP_VOWIFI)
+            doc.getFromVowifi(ResponseXmlAttributes.SERVER_FLOW_USER_DATA)
                     .ifPresent(userData -> builder.setEmergencyAddressWebData(userData));
         }
         return builder.build();
diff --git a/src/com/android/imsserviceentitlement/ImsEntitlementPollingService.java b/src/com/android/imsserviceentitlement/ImsEntitlementPollingService.java
index 04a5750..679bdcb 100644
--- a/src/com/android/imsserviceentitlement/ImsEntitlementPollingService.java
+++ b/src/com/android/imsserviceentitlement/ImsEntitlementPollingService.java
@@ -26,6 +26,7 @@
 import static com.android.imsserviceentitlement.ImsServiceEntitlementStatsLog.IMS_SERVICE_ENTITLEMENT_UPDATED__SERVICE_TYPE__SMSOIP;
 import static com.android.imsserviceentitlement.ImsServiceEntitlementStatsLog.IMS_SERVICE_ENTITLEMENT_UPDATED__SERVICE_TYPE__VOLTE;
 import static com.android.imsserviceentitlement.ImsServiceEntitlementStatsLog.IMS_SERVICE_ENTITLEMENT_UPDATED__SERVICE_TYPE__VOWIFI;
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementVersion.ENTITLEMENT_VERSION_EIGHT;
 
 import android.app.job.JobParameters;
 import android.app.job.JobService;
@@ -149,6 +150,7 @@
         private final TelephonyUtils mTelephonyUtils;
         private final MetricsLogger mMetricsLogger;
         private final int mSubid;
+        private final int mEntitlementVersion;
         private final boolean mNeedsImsProvisioning;
 
         // States for metrics
@@ -157,6 +159,7 @@
         private int mPurpose = IMS_SERVICE_ENTITLEMENT_UPDATED__PURPOSE__UNKNOWN_PURPOSE;
         private int mVowifiResult = IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__UNKNOWN_RESULT;
         private int mVolteResult = IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__UNKNOWN_RESULT;
+        private int mVonrResult = IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__UNKNOWN_RESULT;
         private int mSmsoipResult = IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__UNKNOWN_RESULT;
 
         EntitlementPollingTask(final JobParameters params, int subId) {
@@ -164,6 +167,8 @@
             this.mImsUtils = ImsUtils.getInstance(ImsEntitlementPollingService.this, subId);
             this.mTelephonyUtils = new TelephonyUtils(ImsEntitlementPollingService.this, subId);
             this.mSubid = subId;
+            this.mEntitlementVersion =
+                    TelephonyUtils.getEntitlementVersion(ImsEntitlementPollingService.this, mSubid);
             this.mNeedsImsProvisioning = TelephonyUtils.isImsProvisioningRequired(
                     ImsEntitlementPollingService.this, mSubid);
             this.mImsEntitlementApi = ImsEntitlementPollingService.this.mImsEntitlementApi != null
@@ -233,6 +238,16 @@
                     mVolteResult = IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__ENABLED;
                 }
 
+                if (mEntitlementVersion >= ENTITLEMENT_VERSION_EIGHT) {
+                    if (shouldTurnOffVonrHome(result)) {
+                        mImsUtils.setVonrProvisioned(false);
+                        mVonrResult = IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__DISABLED;
+                    } else {
+                        mImsUtils.setVonrProvisioned(true);
+                        mVonrResult = IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__ENABLED;
+                    }
+                }
+
                 if (shouldTurnOffSMSoIP(result)) {
                     mImsUtils.setSmsoipProvisioned(false);
                     mSmsoipResult = IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__DISABLED;
@@ -243,6 +258,7 @@
             } catch (RuntimeException e) {
                 mVowifiResult = IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__FAILED;
                 mVolteResult = IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__FAILED;
+                mVonrResult = IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__FAILED;
                 mSmsoipResult = IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__FAILED;
                 Log.d(TAG, "checkEntitlementStatus failed.", e);
             }
@@ -333,6 +349,16 @@
             return !result.getVolteStatus().isActive();
         }
 
+        private boolean shouldTurnOffVonrHome(@Nullable EntitlementResult result) {
+            if (result == null) {
+                Log.d(TAG, "Entitlement API failed to return a result; don't turn off VoNR.");
+                return false;
+            }
+
+            // Only turn off VoNR in Home for known patterns indicating VoNR not activated.
+            return !result.getVonrStatus().isHomeActive();
+        }
+
         private boolean shouldTurnOffSMSoIP(@Nullable EntitlementResult result) {
             if (result == null) {
                 Log.d(TAG, "Entitlement API failed to return a result; don't turn off SMSoIP.");
@@ -364,5 +390,16 @@
                         IMS_SERVICE_ENTITLEMENT_UPDATED__SERVICE_TYPE__SMSOIP, mSmsoipResult);
             }
         }
+
+        @VisibleForTesting
+        int getVonrResult() {
+            return mVonrResult;
+        }
+
+        @VisibleForTesting
+        int getVowifiResult() {
+            return mVowifiResult;
+        }
     }
 }
+
diff --git a/src/com/android/imsserviceentitlement/ImsEntitlementReceiver.java b/src/com/android/imsserviceentitlement/ImsEntitlementReceiver.java
index d1d3a97..e4259d9 100644
--- a/src/com/android/imsserviceentitlement/ImsEntitlementReceiver.java
+++ b/src/com/android/imsserviceentitlement/ImsEntitlementReceiver.java
@@ -21,6 +21,8 @@
 import static com.android.imsserviceentitlement.entitlement.EntitlementConfiguration.ClientBehavior.NEEDS_TO_RESET;
 import static com.android.imsserviceentitlement.entitlement.EntitlementConfiguration.ClientBehavior.VALID_DURING_VALIDITY;
 import static com.android.imsserviceentitlement.entitlement.EntitlementConfiguration.ClientBehavior.VALID_WITHOUT_DURATION;
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementVersion.ENTITLEMENT_VERSION_EIGHT;
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementVersion.ENTITLEMENT_VERSION_TWO;
 import static com.android.imsserviceentitlement.utils.Executors.getAsyncExecutor;
 
 import android.content.BroadcastReceiver;
@@ -72,7 +74,8 @@
         if (!dependencies.userManager.isSystemUser()
                 || !SubscriptionManager.isValidSubscriptionId(currentSubId)
                 || dependencies.telephonyUtils.getSimApplicationState() != SIM_STATE_LOADED
-                || !TelephonyUtils.isImsProvisioningRequired(context, currentSubId)) {
+                || !TelephonyUtils.isImsProvisioningRequired(context, currentSubId)
+                || !isEntitlementVersionSupported(context, currentSubId)) {
             return;
         }
 
@@ -95,18 +98,6 @@
             PendingResult result) {
         boolean shouldQuery = false;
 
-        // Handle device boot up.
-        if (isBootUp(context, slotId)) {
-            ClientBehavior clientBehavior =
-                    new EntitlementConfiguration(context, currentSubId).entitlementValidation();
-            Log.d(TAG, "Device boot up, clientBehavior=" + clientBehavior);
-            if (clientBehavior == VALID_DURING_VALIDITY
-                    || clientBehavior == VALID_WITHOUT_DURATION
-                    || clientBehavior == NEEDS_TO_RESET) {
-                shouldQuery = true;
-            }
-        }
-
         // Handle SIM changed.
         int lastSubId = getAndSetSubId(context, currentSubId, slotId);
         if (currentSubId != lastSubId) {
@@ -118,6 +109,26 @@
             shouldQuery = true;
         }
 
+        // Handle device boot up.
+        if (!shouldQuery && isBootUp(context, slotId)) {
+            EntitlementConfiguration entitlementConfiguration =
+                    new EntitlementConfiguration(context, currentSubId);
+            ClientBehavior clientBehavior = entitlementConfiguration.entitlementValidation();
+            Log.d(TAG, "Device boot up, clientBehavior = " + clientBehavior);
+            if (clientBehavior == VALID_DURING_VALIDITY
+                    || clientBehavior == VALID_WITHOUT_DURATION
+                    || clientBehavior == NEEDS_TO_RESET) {
+                shouldQuery = true;
+            } else { // NEEDS_TO_RESET_EXCEPT_VERS or NEEDS_TO_RESET_EXCEPT_VERS_UNTIL_SETTING_ON
+                int storedEntitlementVersion = entitlementConfiguration.getEntitlementVersion();
+                int entitlementVersion =
+                        TelephonyUtils.getEntitlementVersion(context, currentSubId);
+                if (storedEntitlementVersion != entitlementVersion && entitlementVersion >= 8) {
+                    shouldQuery = true;
+                }
+            }
+        }
+
         if (shouldQuery) {
             jobManager.queryEntitlementStatusOnceNetworkReady();
         }
@@ -153,6 +164,16 @@
         return lastSubId;
     }
 
+    private boolean isEntitlementVersionSupported(Context context, int currentSubId) {
+        int entitlementVersion = TelephonyUtils.getEntitlementVersion(context, currentSubId);
+        if (entitlementVersion == ENTITLEMENT_VERSION_TWO
+                || entitlementVersion == ENTITLEMENT_VERSION_EIGHT) {
+            return true;
+        }
+        Log.d(TAG, "Unsupported entitltment version: " + entitlementVersion);
+        return false;
+    }
+
     /** Returns initialized dependencies */
     @VisibleForTesting
     Dependencies createDependency(Context context, int subId) {
diff --git a/src/com/android/imsserviceentitlement/entitlement/EntitlementConfiguration.java b/src/com/android/imsserviceentitlement/entitlement/EntitlementConfiguration.java
index 1aa92dd..bf04b3d 100644
--- a/src/com/android/imsserviceentitlement/entitlement/EntitlementConfiguration.java
+++ b/src/com/android/imsserviceentitlement/entitlement/EntitlementConfiguration.java
@@ -18,6 +18,8 @@
 
 import android.content.Context;
 
+import androidx.annotation.VisibleForTesting;
+
 import com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlAttributes;
 import com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlNode;
 import com.android.imsserviceentitlement.utils.XmlDoc;
@@ -34,59 +36,62 @@
     private static final long DEFAULT_VALIDITY = 0;
     /** Default value of VoLTE/VoWifi/SMSoverIP entitlemenet status. */
     private static final int INCOMPATIBLE_STATE = 2;
+    /** Default raw XML with both version and validity set to -1. */
+    @VisibleForTesting
+    public static final String RAW_XML_VERS_MINUS_ONE =
+                                "<wap-provisioningdoc version=\"1.1\">"
+                                + "  <characteristic type=\"VERS\">"
+                                + "    <parm name=\"version\" value=\"-1\"/>"
+                                + "    <parm name=\"validity\" value=\"-1\"/>"
+                                + "  </characteristic>"
+                                + "  <characteristic type=\"TOKEN\">"
+                                + "    <parm name=\"token\" value=\"\"/>"
+                                + "    <parm name=\"validity\" value=\"0\"/>"
+                                + "  </characteristic>"
+                                + "</wap-provisioningdoc>";
+    /** Default raw XML with both version and validity set to -2. */
+    @VisibleForTesting
+    public static final String RAW_XML_VERS_MINUS_TWO =
+                                "<wap-provisioningdoc version=\"1.1\">"
+                                + "  <characteristic type=\"VERS\">"
+                                + "    <parm name=\"version\" value=\"-2\"/>"
+                                + "    <parm name=\"validity\" value=\"-2\"/>"
+                                + "  </characteristic>"
+                                + "  <characteristic type=\"TOKEN\">"
+                                + "    <parm name=\"token\" value=\"\"/>"
+                                + "    <parm name=\"validity\" value=\"0\"/>"
+                                + "  </characteristic>"
+                                + "</wap-provisioningdoc>";
 
     private final EntitlementConfigurationsDataStore mConfigurationsDataStore;
-
-    private XmlDoc mXmlDoc = new XmlDoc(null);
+    private XmlDoc mXmlDoc;
 
     public EntitlementConfiguration(Context context, int subId) {
         mConfigurationsDataStore = EntitlementConfigurationsDataStore.getInstance(context, subId);
-        mConfigurationsDataStore.get().ifPresent(rawXml -> mXmlDoc = new XmlDoc(rawXml));
+        mXmlDoc = new XmlDoc(mConfigurationsDataStore.getRawXml().orElse(null));
     }
 
-    /** Update VERS characteristics with given version and validity. */
-    public void update(String rawXml) {
+    // Updates raw XML only.
+    private void update(String rawXml) {
         mConfigurationsDataStore.set(rawXml);
         mXmlDoc = new XmlDoc(rawXml);
     }
 
-    /**
-     * Returns VoLTE entitlement status from the {@link EntitlementConfigurationsDataStore}. If no
-     * data exist then return the default value {@link #INCOMPATIBLE_STATE}.
-     */
-    public int getVolteStatus() {
-        return mXmlDoc.get(
-                ResponseXmlNode.APPLICATION,
-                ResponseXmlAttributes.ENTITLEMENT_STATUS,
-                ServiceEntitlement.APP_VOLTE)
-                .map(Integer::parseInt)
-                .orElse(INCOMPATIBLE_STATE);
+    /** Updates entitlement version and raw XML. */
+    public void update(int version, String rawXml) {
+        mConfigurationsDataStore.set(version, rawXml);
+        mXmlDoc = new XmlDoc(rawXml);
     }
 
-    /**
-     * Returns VoWiFi entitlement status from the {@link EntitlementConfigurationsDataStore}. If no
-     * data exist then return the default value {@link #INCOMPATIBLE_STATE}.
-     */
-    public int getVoWifiStatus() {
-        return mXmlDoc.get(
-                ResponseXmlNode.APPLICATION,
-                ResponseXmlAttributes.ENTITLEMENT_STATUS,
-                ServiceEntitlement.APP_VOWIFI)
-                .map(Integer::parseInt)
-                .orElse(INCOMPATIBLE_STATE);
+    /** Returns the raw XML stored in the {@link EntitlementConfigurationsDataStore}. */
+    @VisibleForTesting
+    public String getRawXml() {
+        return mConfigurationsDataStore.getRawXml().orElse(null);
     }
 
-    /**
-     * Returns SMSoIP entitlement status from the {@link EntitlementConfigurationsDataStore}. If no
-     * data exist then return the default value {@link #INCOMPATIBLE_STATE}.
-     */
-    public int getSmsOverIpStatus() {
-        return mXmlDoc.get(
-                ResponseXmlNode.APPLICATION,
-                ResponseXmlAttributes.ENTITLEMENT_STATUS,
-                ServiceEntitlement.APP_SMSOIP)
-                .map(Integer::parseInt)
-                .orElse(INCOMPATIBLE_STATE);
+    /** Returns the entitlement version stored in the {@link EntitlementConfigurationsDataStore}. */
+    public int getEntitlementVersion() {
+        return  Integer.parseInt(mConfigurationsDataStore.getEntitlementVersion().orElse("0"));
     }
 
     /**
@@ -96,7 +101,7 @@
      */
     public Optional<String> getToken() {
         return isTokenInValidityPeriod()
-                ? mXmlDoc.get(ResponseXmlNode.TOKEN, ResponseXmlAttributes.TOKEN, null)
+                ? mXmlDoc.getFromToken(ResponseXmlAttributes.TOKEN)
                 : Optional.empty();
     }
 
@@ -123,10 +128,7 @@
      * received by the client. If no data exist then returns default value 0.
      */
     public long getTokenValidity() {
-        return mXmlDoc.get(
-                ResponseXmlNode.TOKEN,
-                ResponseXmlAttributes.VALIDITY,
-                null)
+        return mXmlDoc.getFromToken(ResponseXmlAttributes.VALIDITY)
                 .map(Long::parseLong)
                 .orElse(DEFAULT_VALIDITY);
     }
@@ -136,7 +138,7 @@
      * If no data exists then return the default value {@link #DEFAULT_VERSION}.
      */
     public String getVersion() {
-        return mXmlDoc.get(ResponseXmlNode.VERS, ResponseXmlAttributes.VERSION, null)
+        return mXmlDoc.getFromVersion(ResponseXmlAttributes.VERSION)
                 .orElse(String.valueOf(DEFAULT_VERSION));
     }
 
@@ -145,10 +147,7 @@
      * received by the client. If no data exist then returns default value 0.
      */
     public long getVersValidity() {
-        return mXmlDoc.get(
-                ResponseXmlNode.VERS,
-                ResponseXmlAttributes.VALIDITY,
-                null)
+        return mXmlDoc.getFromVersion(ResponseXmlAttributes.VALIDITY)
                 .map(Long::parseLong)
                 .orElse(DEFAULT_VALIDITY);
     }
@@ -178,18 +177,8 @@
 
     /** Returns {@link ClientBehavior} for the service to be configured. */
     public ClientBehavior entitlementValidation() {
-        int version = mXmlDoc.get(
-                ResponseXmlNode.VERS,
-                ResponseXmlAttributes.VERSION,
-                null)
-                .map(Integer::parseInt)
-                .orElse(DEFAULT_VERSION);
-        long validity = mXmlDoc.get(
-                ResponseXmlNode.VERS,
-                ResponseXmlAttributes.VALIDITY,
-                null)
-                .map(Long::parseLong)
-                .orElse(DEFAULT_VALIDITY);
+        int version = Integer.parseInt(getVersion());
+        long validity = getVersValidity();
 
         if (version > 0 && validity > 0) {
             return ClientBehavior.VALID_DURING_VALIDITY;
@@ -212,8 +201,8 @@
      * <ul>
      *   <li>on SIM card change
      *   <li>on menu Factory reset
-     *   <li>if a service is barred by the Service Provider (i.e. configuration version set to 0,
-     *       -1, -2). In that case, version and validity are not reset
+     *   <li>reset by the Service Provider (i.e. configuration version set to 0).
+     *       In that case, version and validity are not reset
      * </ul>
      */
     public void reset() {
@@ -222,37 +211,17 @@
         //   - VERS.validity = 0
         //   - TOKEN.token = null (i.e. no value assigned)
         //   - TOKEN.validity =0
-        //   - VoLTE.EntitlementStatus=2 (INCOMPATIBLE_STATE)
-        //   - VoWiFi.EntitlementStatus=2 (INCOMPATIBLE_STATE)
-        //   - SMSoIP.EntitlementStatus=2 (INCOMPATIBLE_STATE)
         update(null);
     }
 
     /** Reverts to the default configurations except the version and validity. */
-    public void resetConfigsExceptVers() {
-        String rawXml =
-                "<wap-provisioningdoc version=\"1.1\">"
-                + "  <characteristic type=\"VERS\">"
-                + "    <parm name=\"version\" value=\"" + getVersion() + "\"/>"
-                + "    <parm name=\"validity\" value=\"" + getVersValidity() + "\"/>"
-                + "  </characteristic>"
-                + "  <characteristic type=\"TOKEN\">"
-                + "    <parm name=\"token\" value=\"\"/>"
-                + "    <parm name=\"validity\" value=\"0\"/>"
-                + "  </characteristic>"
-                + "  <characteristic type=\"APPLICATION\">"
-                + "    <parm name=\"AppID\" value=\"ap2003\"/>"
-                + "    <parm name=\"EntitlementStatus\" value=\"2\"/>"
-                + "  </characteristic>"
-                + "  <characteristic type=\"APPLICATION\">"
-                + "    <parm name=\"AppID\" value=\"ap2004\"/>"
-                + "    <parm name=\"EntitlementStatus\" value=\"2\"/>"
-                + "  </characteristic>"
-                + "  <characteristic type=\"APPLICATION\">"
-                + "    <parm name=\"AppID\" value=\"ap2005\"/>"
-                + "    <parm name=\"EntitlementStatus\" value=\"2\"/>"
-                + "  </characteristic>"
-                + "</wap-provisioningdoc>";
+    public void reset(ClientBehavior clientBehavior) {
+        String rawXml = null;
+        if (clientBehavior == ClientBehavior.NEEDS_TO_RESET_EXCEPT_VERS) {
+            rawXml = RAW_XML_VERS_MINUS_ONE;
+        } else if (clientBehavior == ClientBehavior.NEEDS_TO_RESET_EXCEPT_VERS_UNTIL_SETTING_ON) {
+            rawXml = RAW_XML_VERS_MINUS_TWO;
+        }
         update(rawXml);
     }
 }
diff --git a/src/com/android/imsserviceentitlement/entitlement/EntitlementConfigurationsDataStore.java b/src/com/android/imsserviceentitlement/entitlement/EntitlementConfigurationsDataStore.java
index 6947e2b..37111e3 100644
--- a/src/com/android/imsserviceentitlement/entitlement/EntitlementConfigurationsDataStore.java
+++ b/src/com/android/imsserviceentitlement/entitlement/EntitlementConfigurationsDataStore.java
@@ -26,6 +26,7 @@
     private static final String PREFERENCE_ENTITLEMENT_CHARACTERISTICS =
             "ENTITLEMENT_CHARACTERISTICS";
     private static final String XML_DOCUMENT = "XML_DOCUMENT";
+    private static final String ENTITLEMENT_VERSION = "ENTITLEMENT_VERSION";
     private static final String QUERY_TIME_MILLIS = "QUERY_TIME_MILLIS";
 
     private final SharedPreferences mPreferences;
@@ -46,6 +47,15 @@
                 Context.MODE_PRIVATE);
     }
 
+    public void set(int entitlementVersion, String characteristics) {
+        mPreferences
+                .edit()
+                .putString(XML_DOCUMENT, characteristics)
+                .putString(ENTITLEMENT_VERSION, String.valueOf(entitlementVersion))
+                .putLong(QUERY_TIME_MILLIS, System.currentTimeMillis())
+                .apply();
+    }
+
     public void set(String characteristics) {
         mPreferences
                 .edit()
@@ -54,11 +64,15 @@
                 .apply();
     }
 
-    public Optional<String> get() {
+    public Optional<String> getRawXml() {
         return Optional.ofNullable(mPreferences.getString(XML_DOCUMENT, null));
     }
 
     public long getQueryTimeMillis() {
         return mPreferences.getLong(QUERY_TIME_MILLIS, 0);
     }
+
+    public Optional<String> getEntitlementVersion() {
+        return Optional.ofNullable(mPreferences.getString(ENTITLEMENT_VERSION, null));
+    }
 }
diff --git a/src/com/android/imsserviceentitlement/entitlement/EntitlementResult.java b/src/com/android/imsserviceentitlement/entitlement/EntitlementResult.java
index 480d78a..fe65eb1 100644
--- a/src/com/android/imsserviceentitlement/entitlement/EntitlementResult.java
+++ b/src/com/android/imsserviceentitlement/entitlement/EntitlementResult.java
@@ -16,8 +16,10 @@
 
 package com.android.imsserviceentitlement.entitlement;
 
+import com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementStatus;
 import com.android.imsserviceentitlement.ts43.Ts43SmsOverIpStatus;
 import com.android.imsserviceentitlement.ts43.Ts43VolteStatus;
+import com.android.imsserviceentitlement.ts43.Ts43VonrStatus;
 import com.android.imsserviceentitlement.ts43.Ts43VowifiStatus;
 
 import com.google.auto.value.AutoValue;
@@ -27,28 +29,60 @@
 public abstract class EntitlementResult {
     private static final Ts43VowifiStatus INACTIVE_VOWIFI_STATUS =
             Ts43VowifiStatus.builder()
-                    .setEntitlementStatus(Ts43VowifiStatus.EntitlementStatus.INCOMPATIBLE)
+                    .setEntitlementStatus(EntitlementStatus.INCOMPATIBLE)
                     .setTcStatus(Ts43VowifiStatus.TcStatus.NOT_AVAILABLE)
                     .setAddrStatus(Ts43VowifiStatus.AddrStatus.NOT_AVAILABLE)
                     .setProvStatus(Ts43VowifiStatus.ProvStatus.NOT_PROVISIONED)
                     .build();
 
+    private static final Ts43VowifiStatus ACTIVE_VOWIFI_STATUS =
+            Ts43VowifiStatus.builder()
+                    .setEntitlementStatus(EntitlementStatus.ENABLED)
+                    .setTcStatus(Ts43VowifiStatus.TcStatus.NOT_REQUIRED)
+                    .setAddrStatus(Ts43VowifiStatus.AddrStatus.NOT_REQUIRED)
+                    .setProvStatus(Ts43VowifiStatus.ProvStatus.NOT_REQUIRED)
+                    .build();
+
     private static final Ts43VolteStatus INACTIVE_VOLTE_STATUS =
             Ts43VolteStatus.builder()
-                    .setEntitlementStatus(Ts43VolteStatus.EntitlementStatus.INCOMPATIBLE)
+                    .setEntitlementStatus(EntitlementStatus.INCOMPATIBLE)
+                    .build();
+
+    private static final Ts43VolteStatus ACTIVE_VOLTE_STATUS =
+            Ts43VolteStatus.builder()
+                    .setEntitlementStatus(EntitlementStatus.ENABLED)
+                    .build();
+
+    private static final Ts43VonrStatus INACTIVE_VONR_STATUS =
+            Ts43VonrStatus.builder()
+                    .setHomeEntitlementStatus(EntitlementStatus.INCOMPATIBLE)
+                    .setRoamingEntitlementStatus(EntitlementStatus.INCOMPATIBLE)
+                    .build();
+
+    private static final Ts43VonrStatus ACTIVE_VONR_STATUS =
+            Ts43VonrStatus.builder()
+                    .setHomeEntitlementStatus(EntitlementStatus.ENABLED)
+                    .setRoamingEntitlementStatus(EntitlementStatus.ENABLED)
                     .build();
 
     private static final Ts43SmsOverIpStatus INACTIVE_SMSOVERIP_STATUS =
             Ts43SmsOverIpStatus.builder()
-                    .setEntitlementStatus(Ts43SmsOverIpStatus.EntitlementStatus.INCOMPATIBLE)
+                    .setEntitlementStatus(EntitlementStatus.INCOMPATIBLE)
+                    .build();
+
+    private static final Ts43SmsOverIpStatus ACTIVE_SMSOVERIP_STATUS =
+            Ts43SmsOverIpStatus.builder()
+                    .setEntitlementStatus(EntitlementStatus.ENABLED)
                     .build();
 
     /** Returns a new {@link Builder} object. */
-    public static Builder builder() {
+    public static Builder builder(boolean isDefaultEnabled) {
         return new AutoValue_EntitlementResult.Builder()
-                .setVowifiStatus(INACTIVE_VOWIFI_STATUS)
-                .setVolteStatus(INACTIVE_VOLTE_STATUS)
-                .setSmsoveripStatus(INACTIVE_SMSOVERIP_STATUS)
+                .setVowifiStatus(isDefaultEnabled ? ACTIVE_VOWIFI_STATUS : INACTIVE_VOWIFI_STATUS)
+                .setVolteStatus(isDefaultEnabled ? ACTIVE_VOLTE_STATUS : INACTIVE_VOLTE_STATUS)
+                .setSmsoveripStatus(
+                        isDefaultEnabled ? ACTIVE_SMSOVERIP_STATUS : INACTIVE_SMSOVERIP_STATUS)
+                .setVonrStatus(isDefaultEnabled ? ACTIVE_VONR_STATUS : INACTIVE_VONR_STATUS)
                 .setEmergencyAddressWebUrl("")
                 .setEmergencyAddressWebData("")
                 .setTermsAndConditionsWebUrl("")
@@ -59,6 +93,8 @@
     public abstract Ts43VowifiStatus getVowifiStatus();
     /** The entitlement and service status of VoLTE. */
     public abstract Ts43VolteStatus getVolteStatus();
+    /** The entitlement and service status of VoNR. */
+    public abstract Ts43VonrStatus getVonrStatus();
     /** The entitlement and service status of SMSoIP. */
     public abstract Ts43SmsOverIpStatus getSmsoveripStatus();
     /** The URL to the WFC emergency address web form. */
@@ -76,6 +112,7 @@
         public abstract EntitlementResult build();
         public abstract Builder setVowifiStatus(Ts43VowifiStatus vowifiStatus);
         public abstract Builder setVolteStatus(Ts43VolteStatus volteStatus);
+        public abstract Builder setVonrStatus(Ts43VonrStatus vonrStatus);
         public abstract Builder setSmsoveripStatus(Ts43SmsOverIpStatus smsoveripStatus);
         public abstract Builder setEmergencyAddressWebUrl(String emergencyAddressWebUrl);
         public abstract Builder setEmergencyAddressWebData(String emergencyAddressWebData);
@@ -88,6 +125,7 @@
         StringBuilder builder = new StringBuilder("EntitlementResult{");
         builder.append(",getVowifiStatus=").append(getVowifiStatus());
         builder.append(",getVolteStatus=").append(getVolteStatus());
+        builder.append(",getVonrStatus=").append(getVonrStatus());
         builder.append(",getSmsoveripStatus=").append(getSmsoveripStatus());
         builder.append(",getEmergencyAddressWebUrl=").append(opaque(getEmergencyAddressWebUrl()));
         builder.append(",getEmergencyAddressWebData=").append(opaque(getEmergencyAddressWebData()));
diff --git a/src/com/android/imsserviceentitlement/ts43/Ts43Constants.java b/src/com/android/imsserviceentitlement/ts43/Ts43Constants.java
index 22d6022..b58be89 100644
--- a/src/com/android/imsserviceentitlement/ts43/Ts43Constants.java
+++ b/src/com/android/imsserviceentitlement/ts43/Ts43Constants.java
@@ -56,5 +56,63 @@
         public static final String VERSION = "version";
         /** XML attribute name of validity. */
         public static final String VALIDITY = "validity";
+        /** XML attribute name of RATVoiceEntitleInfoDetails. */
+        public static final String RAT_VOICE_ENTITLE_INFO_DETAILS = "RATVoiceEntitleInfoDetails";
+        /** XML attribute name of AccessType in TS43 v8 section 4.1.1. */
+        public static final String ACCESS_TYPE = "AccessType";
+        /** XML attribute name of HomeRoamingNWType in TS43 v8 section 4.1.1. */
+        public static final String HOME_ROAMING_NW_TYPE = "HomeRoamingNWType";
+        /** XML attribute name of NetworkVoiceIRatCapability in TS43 v8 section 4.1.1. */
+        public static final String NETWORK_VOICE_IRAT_CAPABILITY = "NetworkVoiceIRatCapability";
+    }
+
+    /** Value of EntitlementStatus. */
+    public static final class EntitlementStatus {
+        private EntitlementStatus() {}
+
+        /** The service allowed, but not yet provisioned and activated on the network side. */
+        public static final int DISABLED = 0;
+        /** The service allowed, provisioned and activated on the network side. */
+        public static final int ENABLED = 1;
+        /** The service cannot be offered. */
+        public static final int INCOMPATIBLE = 2;
+        /** The service being provisioned on the network side. */
+        public static final int PROVISIONING = 3;
+    }
+
+    /** Value of AccessType. */
+    public static final class AccessTypeValue {
+        private AccessTypeValue() {}
+
+        /** RAT of type LTE (4G). */
+        public static final String LTE = "1";
+
+        /** RAT of type NG-RAN (5G). */
+        public static final String NGRAN = "2";
+    }
+
+    /** Value of HomeRoamingNWTypeValue. */
+    public static final class HomeRoamingNwTypeValue {
+        private HomeRoamingNwTypeValue() {}
+
+        /** Include both home and roaming networks. */
+        public static final String ALL = "1";
+
+        /** Home network type. */
+        public static final String HOME = "2";
+
+        /** Roaming network type. */
+        public static final String ROAMING = "3";
+    }
+
+    /** Value of entitlement_version parameters */
+    public static final class EntitlementVersion {
+        private EntitlementVersion() {}
+
+        /** Version 2.0. */
+        public static final int ENTITLEMENT_VERSION_TWO = 2;
+
+        /** Version 8.0. */
+        public static final int ENTITLEMENT_VERSION_EIGHT = 8;
     }
 }
diff --git a/src/com/android/imsserviceentitlement/ts43/Ts43SmsOverIpStatus.java b/src/com/android/imsserviceentitlement/ts43/Ts43SmsOverIpStatus.java
index cdbd435..f7c14b3 100644
--- a/src/com/android/imsserviceentitlement/ts43/Ts43SmsOverIpStatus.java
+++ b/src/com/android/imsserviceentitlement/ts43/Ts43SmsOverIpStatus.java
@@ -16,10 +16,9 @@
 
 package com.android.imsserviceentitlement.ts43;
 
+import com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementStatus;
 import com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlAttributes;
-import com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlNode;
 import com.android.imsserviceentitlement.utils.XmlDoc;
-import com.android.libraries.entitlement.ServiceEntitlement;
 
 import com.google.auto.value.AutoValue;
 
@@ -30,16 +29,6 @@
 @AutoValue
 public abstract class Ts43SmsOverIpStatus {
     /** The entitlement status of SMSoIP service. */
-    public static class EntitlementStatus {
-        public EntitlementStatus() {}
-
-        public static final int DISABLED = 0;
-        public static final int ENABLED = 1;
-        public static final int INCOMPATIBLE = 2;
-        public static final int PROVISIONING = 3;
-    }
-
-    /** The entitlement status of SMSoIP service. */
     public abstract int entitlementStatus();
 
     public static Ts43SmsOverIpStatus.Builder builder() {
@@ -50,9 +39,7 @@
     public static Ts43SmsOverIpStatus.Builder builder(XmlDoc doc) {
         return builder()
                 .setEntitlementStatus(
-                        doc.get(ResponseXmlNode.APPLICATION,
-                                ResponseXmlAttributes.ENTITLEMENT_STATUS,
-                                ServiceEntitlement.APP_SMSOIP)
+                        doc.getFromSmsoverip(ResponseXmlAttributes.ENTITLEMENT_STATUS)
                                 .map(status -> Integer.parseInt(status))
                                 .orElse(EntitlementStatus.INCOMPATIBLE));
     }
diff --git a/src/com/android/imsserviceentitlement/ts43/Ts43VolteStatus.java b/src/com/android/imsserviceentitlement/ts43/Ts43VolteStatus.java
index d324c22..8eaa794 100644
--- a/src/com/android/imsserviceentitlement/ts43/Ts43VolteStatus.java
+++ b/src/com/android/imsserviceentitlement/ts43/Ts43VolteStatus.java
@@ -16,10 +16,9 @@
 
 package com.android.imsserviceentitlement.ts43;
 
+import com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementStatus;
 import com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlAttributes;
-import com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlNode;
 import com.android.imsserviceentitlement.utils.XmlDoc;
-import com.android.libraries.entitlement.ServiceEntitlement;
 
 import com.google.auto.value.AutoValue;
 
@@ -30,16 +29,6 @@
 @AutoValue
 public abstract class Ts43VolteStatus {
     /** The entitlement status of Volte service. */
-    public static class EntitlementStatus {
-        public EntitlementStatus() {}
-
-        public static final int DISABLED = 0;
-        public static final int ENABLED = 1;
-        public static final int INCOMPATIBLE = 2;
-        public static final int PROVISIONING = 3;
-    }
-
-    /** The entitlement status of Volte service. */
     public abstract int entitlementStatus();
 
     public static Ts43VolteStatus.Builder builder() {
@@ -50,9 +39,7 @@
     public static Ts43VolteStatus.Builder builder(XmlDoc doc) {
         return builder()
                 .setEntitlementStatus(
-                        doc.get(ResponseXmlNode.APPLICATION,
-                                ResponseXmlAttributes.ENTITLEMENT_STATUS,
-                                ServiceEntitlement.APP_VOLTE)
+                        doc.getFromVolte(ResponseXmlAttributes.ENTITLEMENT_STATUS)
                                 .map(status -> Integer.parseInt(status))
                                 .orElse(EntitlementStatus.INCOMPATIBLE));
     }
diff --git a/src/com/android/imsserviceentitlement/ts43/Ts43VonrStatus.java b/src/com/android/imsserviceentitlement/ts43/Ts43VonrStatus.java
new file mode 100644
index 0000000..390d48b
--- /dev/null
+++ b/src/com/android/imsserviceentitlement/ts43/Ts43VonrStatus.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2023 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.android.imsserviceentitlement.ts43;
+
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlAttributes.ENTITLEMENT_STATUS;
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlAttributes.NETWORK_VOICE_IRAT_CAPABILITY;
+
+import com.android.imsserviceentitlement.utils.XmlDoc;
+import com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementStatus;
+
+import com.google.auto.value.AutoValue;
+
+/**
+ * Implementation of Vonr entitlement status and server data availability for TS.43 entitlement
+ * solution. This class is only used to report the entitlement status of Vonr.
+ */
+@AutoValue
+public abstract class Ts43VonrStatus {
+    /** The entitlement status of Vonr service in Home network. */
+    public abstract int homeEntitlementStatus();
+
+    /** The entitlement status of Vonr service in Roaming network.. */
+    public abstract int roamingEntitlementStatus();
+
+    /** The voice rat capability status of vonr service in home network. */
+    public abstract String homeNetworkVoiceIRatCapability();
+
+    /** The voice rat capability status of vonr service in roaming network. */
+    public abstract String roamingNetworkVoiceIRatCapability();
+
+    public static Ts43VonrStatus.Builder builder() {
+        return new AutoValue_Ts43VonrStatus.Builder()
+                .setHomeEntitlementStatus(EntitlementStatus.INCOMPATIBLE)
+                .setRoamingNetworkVoiceIRatCapability("")
+                .setRoamingEntitlementStatus(EntitlementStatus.INCOMPATIBLE)
+                .setHomeNetworkVoiceIRatCapability("");
+    }
+
+    public static Ts43VonrStatus.Builder builder(XmlDoc doc) {
+        return builder()
+                .setHomeEntitlementStatus(
+                        doc.getFromVonrHome(ENTITLEMENT_STATUS)
+                                .map(status -> Integer.parseInt(status))
+                                .orElse(EntitlementStatus.INCOMPATIBLE))
+                .setHomeNetworkVoiceIRatCapability(
+                        doc.getFromVonrHome(NETWORK_VOICE_IRAT_CAPABILITY).orElse(""))
+                .setRoamingEntitlementStatus(
+                        doc.getFromVonrRoaming(ENTITLEMENT_STATUS)
+                                .map(status -> Integer.parseInt(status))
+                                .orElse(EntitlementStatus.INCOMPATIBLE))
+                .setRoamingNetworkVoiceIRatCapability(
+                        doc.getFromVonrRoaming(NETWORK_VOICE_IRAT_CAPABILITY).orElse(""));
+    }
+
+    /** Builder of {@link Ts43VonrStatus}. */
+    @AutoValue.Builder
+    public abstract static class Builder {
+        public abstract Ts43VonrStatus build();
+
+        public abstract Builder setHomeEntitlementStatus(int entitlementStatus);
+
+        public abstract Builder setRoamingEntitlementStatus(int entitlementStatus);
+
+        public abstract Builder setHomeNetworkVoiceIRatCapability(
+                String networkVoiceIRatCapability);
+
+        public abstract Builder setRoamingNetworkVoiceIRatCapability(
+                String networkVoiceIRatCapability);
+    }
+
+    public boolean isHomeActive() {
+        return homeEntitlementStatus() == EntitlementStatus.ENABLED;
+    }
+
+    public boolean isRoamingActive() {
+        return roamingEntitlementStatus() == EntitlementStatus.ENABLED;
+    }
+
+    public final String toString() {
+        return "Ts43VonrStatus {"
+                + "HomeEntitlementStatus="
+                + homeEntitlementStatus()
+                + ", HomeNetworkVoiceIRatCapability="
+                + homeNetworkVoiceIRatCapability()
+                + ", RomaingEntitlementStatus="
+                + roamingEntitlementStatus()
+                + ", RoamingNetworkVoiceIRatCapability="
+                + roamingNetworkVoiceIRatCapability()
+                + "}";
+    }
+}
diff --git a/src/com/android/imsserviceentitlement/ts43/Ts43VowifiStatus.java b/src/com/android/imsserviceentitlement/ts43/Ts43VowifiStatus.java
index b202102..39b2da5 100644
--- a/src/com/android/imsserviceentitlement/ts43/Ts43VowifiStatus.java
+++ b/src/com/android/imsserviceentitlement/ts43/Ts43VowifiStatus.java
@@ -16,10 +16,9 @@
 
 package com.android.imsserviceentitlement.ts43;
 
+import com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementStatus;
 import com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlAttributes;
-import com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlNode;
 import com.android.imsserviceentitlement.utils.XmlDoc;
-import com.android.libraries.entitlement.ServiceEntitlement;
 
 import com.google.auto.value.AutoValue;
 
@@ -29,16 +28,6 @@
  */
 @AutoValue
 public abstract class Ts43VowifiStatus {
-    /** The entitlement status of Vowifi service. */
-    public static class EntitlementStatus {
-        public EntitlementStatus() {}
-
-        public static final int DISABLED = 0;
-        public static final int ENABLED = 1;
-        public static final int INCOMPATIBLE = 2;
-        public static final int PROVISIONING = 3;
-    }
-
     /** The emergency address status of vowifi service. */
     public static class AddrStatus {
         public AddrStatus() {}
@@ -89,29 +78,21 @@
     public static Ts43VowifiStatus.Builder builder(XmlDoc doc) {
         return builder()
                 .setEntitlementStatus(
-                        doc.get(ResponseXmlNode.APPLICATION,
-                                ResponseXmlAttributes.ENTITLEMENT_STATUS,
-                                ServiceEntitlement.APP_VOWIFI)
-                            .map(status -> Integer.parseInt(status))
-                            .orElse(EntitlementStatus.INCOMPATIBLE))
+                        doc.getFromVowifi(ResponseXmlAttributes.ENTITLEMENT_STATUS)
+                                .map(status -> Integer.parseInt(status))
+                                .orElse(EntitlementStatus.INCOMPATIBLE))
                 .setTcStatus(
-                        doc.get(ResponseXmlNode.APPLICATION,
-                                ResponseXmlAttributes.TC_STATUS,
-                                ServiceEntitlement.APP_VOWIFI)
-                            .map(status -> Integer.parseInt(status))
-                            .orElse(TcStatus.NOT_REQUIRED))
+                        doc.getFromVowifi(ResponseXmlAttributes.TC_STATUS)
+                                .map(status -> Integer.parseInt(status))
+                                .orElse(TcStatus.NOT_REQUIRED))
                 .setAddrStatus(
-                        doc.get(ResponseXmlNode.APPLICATION,
-                                ResponseXmlAttributes.ADDR_STATUS,
-                                ServiceEntitlement.APP_VOWIFI)
-                            .map(status -> Integer.parseInt(status))
-                            .orElse(AddrStatus.NOT_REQUIRED))
+                        doc.getFromVowifi(ResponseXmlAttributes.ADDR_STATUS)
+                                .map(status -> Integer.parseInt(status))
+                                .orElse(AddrStatus.NOT_REQUIRED))
                 .setProvStatus(
-                        doc.get(ResponseXmlNode.APPLICATION,
-                                ResponseXmlAttributes.PROVISION_STATUS,
-                                ServiceEntitlement.APP_VOWIFI)
-                            .map(status -> Integer.parseInt(status))
-                            .orElse(ProvStatus.NOT_REQUIRED));
+                        doc.getFromVowifi(ResponseXmlAttributes.PROVISION_STATUS)
+                                .map(status -> Integer.parseInt(status))
+                                .orElse(ProvStatus.NOT_REQUIRED));
     }
 
     /** Builder of {@link Ts43VowifiStatus}. */
@@ -172,4 +153,4 @@
                 + provStatus()
                 + "}";
     }
-}
\ No newline at end of file
+}
diff --git a/src/com/android/imsserviceentitlement/utils/ImsUtils.java b/src/com/android/imsserviceentitlement/utils/ImsUtils.java
index 5681afe..802941b 100644
--- a/src/com/android/imsserviceentitlement/utils/ImsUtils.java
+++ b/src/com/android/imsserviceentitlement/utils/ImsUtils.java
@@ -16,6 +16,9 @@
 
 package com.android.imsserviceentitlement.utils;
 
+import static android.telephony.ims.feature.MmTelFeature.MmTelCapabilities.CAPABILITY_TYPE_VOICE;
+import static android.telephony.ims.stub.ImsRegistrationImplBase.REGISTRATION_TECH_NR;
+
 import android.content.Context;
 import android.os.AsyncTask;
 import android.os.PersistableBundle;
@@ -128,6 +131,11 @@
         }
     }
 
+    /** Sets whether Vonr is provisioned. */
+    public void setVonrProvisioned(boolean value) {
+        setProvisioningIntValue(CAPABILITY_TYPE_VOICE, REGISTRATION_TECH_NR, value);
+    }
+
     /** Sets whether SMSoIP is provisioned. */
     public void setSmsoipProvisioned(boolean value) {
         try {
@@ -141,6 +149,15 @@
         }
     }
 
+    private void setProvisioningIntValue(int capability, int tech, boolean provisioned) {
+        try {
+            mProvisioningManager.setProvisioningStatusForCapability(capability, tech, provisioned);
+        } catch (RuntimeException e) {
+            // ignore this exception, possible exception should be NullPointerException or
+            // RemoteException.
+        }
+    }
+
     /** Disables WFC and reset WFC mode to carrier default value */
     @VisibleForTesting
     void disableAndResetVoWiFiImsSettings() {
diff --git a/src/com/android/imsserviceentitlement/utils/TelephonyUtils.java b/src/com/android/imsserviceentitlement/utils/TelephonyUtils.java
index 62bc8d7..5306b26 100644
--- a/src/com/android/imsserviceentitlement/utils/TelephonyUtils.java
+++ b/src/com/android/imsserviceentitlement/utils/TelephonyUtils.java
@@ -16,6 +16,8 @@
 
 package com.android.imsserviceentitlement.utils;
 
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementVersion.ENTITLEMENT_VERSION_TWO;
+
 import android.content.Context;
 import android.net.ConnectivityManager;
 import android.net.NetworkInfo;
@@ -33,6 +35,11 @@
 /** This class implements Telephony helper methods. */
 public class TelephonyUtils {
     public static final String TAG = "IMSSE-TelephonyUtils";
+    // TODO(b/326358344) : API review for hide carrier configurations
+    private static final String KEY_ENTITLEMENT_VERSION_INT =
+            "imsserviceentitlement.entitlement_version_int";
+    private static final String KEY_DEFAULT_SERVICE_ENTITLEMENT_STATUS_BOOL =
+            "imsserviceentitlement.default_service_entitlement_status_bool";
 
     private final ConnectivityManager mConnectivityManager;
     private final TelephonyManager mTelephonyManager;
@@ -144,7 +151,7 @@
     }
 
     /**
-     * Returns true if app needs to do IMS (VoLTE/VoWiFi/SMSoIP) provisioning in the background
+     * Returns true if app needs to do IMS (VoLTE/VoNR/VoWiFi/SMSoIP) provisioning in the background
      * or false if it doesn't need to do.
      */
     public static boolean isImsProvisioningRequired(Context context, int subId) {
@@ -154,6 +161,28 @@
         );
     }
 
+    /**
+     * Returns entitlement version for the {@code subId} or {@link
+     * Ts43Constants.ENTITLEMENT_VERSION_TWO} if it is not available.
+     */
+    public static int getEntitlementVersion(Context context, int subId) {
+        return getConfigForSubId(context, subId).getInt(
+                KEY_ENTITLEMENT_VERSION_INT,
+                ENTITLEMENT_VERSION_TWO
+        );
+    }
+
+    /**
+     * Returns default service entitlement status for the {@code subId} or false if it is not
+     * available.
+     */
+    public static boolean getDefaultStatus(Context context, int subId) {
+        return getConfigForSubId(context, subId).getBoolean(
+                KEY_DEFAULT_SERVICE_ENTITLEMENT_STATUS_BOOL,
+                false
+        );
+    }
+
     /** Returns SubIds which support FCM. */
     public static ImmutableSet<Integer> getSubIdsWithFcmSupported(Context context) {
         SubscriptionManager subscriptionManager =
diff --git a/src/com/android/imsserviceentitlement/utils/XmlDoc.java b/src/com/android/imsserviceentitlement/utils/XmlDoc.java
index 26299e9..e4f3b86 100644
--- a/src/com/android/imsserviceentitlement/utils/XmlDoc.java
+++ b/src/com/android/imsserviceentitlement/utils/XmlDoc.java
@@ -16,16 +16,25 @@
 
 package com.android.imsserviceentitlement.utils;
 
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.AccessTypeValue.LTE;
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.AccessTypeValue.NGRAN;
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.HomeRoamingNwTypeValue.ALL;
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.HomeRoamingNwTypeValue.HOME;
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.HomeRoamingNwTypeValue.ROAMING;
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlAttributes.ACCESS_TYPE;
 import static com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlAttributes.APP_ID;
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlAttributes.HOME_ROAMING_NW_TYPE;
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlAttributes.RAT_VOICE_ENTITLE_INFO_DETAILS;
 import static com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlNode.APPLICATION;
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlNode.TOKEN;
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.ResponseXmlNode.VERS;
 
 import android.text.TextUtils;
 import android.util.ArrayMap;
 import android.util.Log;
 
-import androidx.annotation.Nullable;
-
 import com.android.imsserviceentitlement.debug.DebugUtils;
+import com.android.libraries.entitlement.ServiceEntitlement;
 
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
@@ -59,14 +68,43 @@
         parseXmlResponse(responseBody);
     }
 
-    /** Returns param value for given node and key. */
-    public Optional<String> get(String node, String key, @Nullable String appId) {
-        Map<String, String> paramsMap = mNodesMap.get(combineKeyWithAppId(node, appId));
+    public Optional<String> getFromToken(String key) {
+        Map<String, String> paramsMap = mNodesMap.get(TOKEN);
         return Optional.ofNullable(paramsMap == null ? null : paramsMap.get(key));
     }
 
-    private String combineKeyWithAppId(String node, @Nullable String appId) {
-        return APPLICATION.equals(node) && !TextUtils.isEmpty(appId) ? node + "_" + appId : node;
+    public Optional<String> getFromVersion(String key) {
+        Map<String, String> paramsMap = mNodesMap.get(VERS);
+        return Optional.ofNullable(paramsMap == null ? null : paramsMap.get(key));
+    }
+
+    public Optional<String> getFromVowifi(String key) {
+        Map<String, String> paramsMap = mNodesMap.get(ServiceEntitlement.APP_VOWIFI);
+        return Optional.ofNullable(paramsMap == null ? null : paramsMap.get(key));
+    }
+
+    public Optional<String> getFromVolte(String key) {
+        Map<String, String> paramsMap = mNodesMap.get(ServiceEntitlement.APP_VOLTE);
+        paramsMap = paramsMap == null ? mNodesMap.get(LTE + ALL) : paramsMap;
+        paramsMap = paramsMap == null ? mNodesMap.get(LTE + HOME) : paramsMap;
+        return Optional.ofNullable(paramsMap == null ? null : paramsMap.get(key));
+    }
+
+    public Optional<String> getFromSmsoverip(String key) {
+        Map<String, String> paramsMap = mNodesMap.get(ServiceEntitlement.APP_SMSOIP);
+        return Optional.ofNullable(paramsMap == null ? null : paramsMap.get(key));
+    }
+
+    public Optional<String> getFromVonrHome(String key) {
+        Map<String, String> paramsMap = mNodesMap.get(NGRAN + ALL);
+        paramsMap = paramsMap == null ? mNodesMap.get(NGRAN + HOME) : paramsMap;
+        return Optional.ofNullable(paramsMap == null ? null : paramsMap.get(key));
+    }
+
+    public Optional<String> getFromVonrRoaming(String key) {
+        Map<String, String> paramsMap = mNodesMap.get(NGRAN + ALL);
+        paramsMap = paramsMap == null ? mNodesMap.get(NGRAN + ROAMING) : paramsMap;
+        return Optional.ofNullable(paramsMap == null ? null : paramsMap.get(key));
     }
 
     /**
@@ -78,6 +116,9 @@
             return;
         }
 
+        if (DebugUtils.isPiiLoggable()) {
+            Log.d(TAG, "Raw Response Body: " + responseBody);
+        }
         // Workaround: some server doesn't escape "&" in XML response and that will cause XML parser
         // failure later.
         // This is a quick impl of escaping w/o intorducing a ton of new dependencies.
@@ -108,12 +149,23 @@
                                     + " node value="
                                     + map.item(0).getNodeValue());
                 }
-                Map<String, String> paramsMap = new ArrayMap<>();
                 Element element = (Element) nodeList.item(i);
+                if (element.getElementsByTagName(NODE_CHARACTERISTIC).getLength() != 0) {
+                    continue;
+                }
+
+                Map<String, String> paramsMap = new ArrayMap<>();
+                String characteristicType = map.item(0).getNodeValue();
+                String key;
                 paramsMap.putAll(parseParams(element.getElementsByTagName(NODE_PARM)));
-                mNodesMap.put(
-                        combineKeyWithAppId(map.item(0).getNodeValue(), paramsMap.get(APP_ID)),
-                        paramsMap);
+                if (APPLICATION.equals(characteristicType)) {
+                    key = paramsMap.get(APP_ID);
+                } else if (RAT_VOICE_ENTITLE_INFO_DETAILS.equals(characteristicType)) {
+                    key = paramsMap.get(ACCESS_TYPE) + paramsMap.get(HOME_ROAMING_NW_TYPE);
+                } else { // VERS or TOKEN
+                    key = characteristicType;
+                }
+                mNodesMap.put(key, paramsMap);
             }
         } catch (ParserConfigurationException | IOException | SAXException e) {
             Log.e(TAG, "Failed to parse XML node. " + e);
diff --git a/tests/unittests/src/com/android/imsserviceentitlement/ImsEntitlementApiTest.java b/tests/unittests/src/com/android/imsserviceentitlement/ImsEntitlementApiTest.java
index 3f7a7be..6e6cbfd 100644
--- a/tests/unittests/src/com/android/imsserviceentitlement/ImsEntitlementApiTest.java
+++ b/tests/unittests/src/com/android/imsserviceentitlement/ImsEntitlementApiTest.java
@@ -18,6 +18,7 @@
 
 import static com.android.imsserviceentitlement.entitlement.EntitlementConfiguration.ClientBehavior.NEEDS_TO_RESET;
 import static com.android.imsserviceentitlement.entitlement.EntitlementConfiguration.ClientBehavior.VALID_DURING_VALIDITY;
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementVersion.ENTITLEMENT_VERSION_TWO;
 import static com.android.libraries.entitlement.ServiceEntitlementException.ERROR_HTTP_STATUS_NOT_SUCCESS;
 
 import static com.google.common.truth.Truth.assertThat;
@@ -45,6 +46,7 @@
 
 import com.google.common.collect.ImmutableList;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -72,8 +74,13 @@
     @Mock private EntitlementConfiguration mMockEntitlementConfiguration;
     @Mock private CarrierConfigManager mCarrierConfigManager;
 
+    private PersistableBundle mCarrierConfig;
+
     private static final int SUB_ID = 1;
+    private static final int ENTITLEMENT_VERSION = 2;
     private static final String FCM_TOKEN = "FCM_TOKEN";
+    private static final String KEY_DEFAULT_SERVICE_ENTITLEMENT_STATUS_BOOL =
+            "imsserviceentitlement.default_service_entitlement_status_bool";
     private static final String RAW_XML =
             "<wap-provisioningdoc version=\"1.1\">"
                     + "  <characteristic type=\"VERS\">"
@@ -104,7 +111,6 @@
                     + "    <parm name=\"EntitlementStatus\" value=\"1\"/>"
                     + "  </characteristic>"
                     + "</wap-provisioningdoc>";
-
     private static final String MULTIPLE_APPIDS_RAW_XML =
             "<wap-provisioningdoc version=\"1.1\">"
                     + "  <characteristic type=\"VERS\">"
@@ -128,6 +134,51 @@
                     + "    <parm name=\"EntitlementStatus\" value=\"1\"/>"
                     + "  </characteristic>"
                     + "</wap-provisioningdoc>";
+    private static final String RAW_XML_NEED_TO_RESET =
+            "<wap-provisioningdoc version=\"1.1\">"
+                    + "  <characteristic type=\"VERS\">"
+                    + "    <parm name=\"version\" value=\"0\"/>"
+                    + "    <parm name=\"validity\" value=\"0\"/>"
+                    + "  </characteristic>"
+                    + "  <characteristic type=\"TOKEN\">"
+                    + "    <parm name=\"token\" value=\"kZYfCEpSsMr88KZVmab5UsZVzl+nWSsX\"/>"
+                    + "    <parm name=\"validity\" value=\"3600\"/>"
+                    + "  </characteristic>"
+                    + "  <characteristic type=\"APPLICATION\">"
+                    + "    <parm name=\"AppID\" value=\"ap2004\"/>"
+                    + "    <parm name=\"EntitlementStatus\" value=\"1\"/>"
+                    + "  </characteristic>"
+                    + "</wap-provisioningdoc>";
+    private static final String RAW_XML_NEED_TO_RESET_EXCEPT_VERS =
+            "<wap-provisioningdoc version=\"1.1\">"
+                    + "  <characteristic type=\"VERS\">"
+                    + "    <parm name=\"version\" value=\"-1\"/>"
+                    + "    <parm name=\"validity\" value=\"-1\"/>"
+                    + "  </characteristic>"
+                    + "  <characteristic type=\"TOKEN\">"
+                    + "    <parm name=\"token\" value=\"kZYfCEpSsMr88KZVmab5UsZVzl+nWSsX\"/>"
+                    + "    <parm name=\"validity\" value=\"3600\"/>"
+                    + "  </characteristic>"
+                    + "  <characteristic type=\"APPLICATION\">"
+                    + "    <parm name=\"AppID\" value=\"ap2004\"/>"
+                    + "    <parm name=\"EntitlementStatus\" value=\"1\"/>"
+                    + "  </characteristic>"
+                    + "</wap-provisioningdoc>";
+    private static final String RAW_XML_NEED_TO_RESET_EXCEPT_VERS_UNTIL_SETTING_ON =
+            "<wap-provisioningdoc version=\"1.1\">"
+                    + "  <characteristic type=\"VERS\">"
+                    + "    <parm name=\"version\" value=\"-2\"/>"
+                    + "    <parm name=\"validity\" value=\"-2\"/>"
+                    + "  </characteristic>"
+                    + "  <characteristic type=\"TOKEN\">"
+                    + "    <parm name=\"token\" value=\"kZYfCEpSsMr88KZVmab5UsZVzl+nWSsX\"/>"
+                    + "    <parm name=\"validity\" value=\"3600\"/>"
+                    + "  </characteristic>"
+                    + "  <characteristic type=\"APPLICATION\">"
+                    + "    <parm name=\"AppID\" value=\"ap2004\"/>"
+                    + "    <parm name=\"EntitlementStatus\" value=\"1\"/>"
+                    + "  </characteristic>"
+                    + "</wap-provisioningdoc>";
 
     private final EntitlementConfiguration mEntitlementConfiguration =
             new EntitlementConfiguration(ApplicationProvider.getApplicationContext(), SUB_ID);
@@ -137,10 +188,16 @@
     @Before
     public void setUp() {
         setImsProvisioningBool(true);
+        setDefaultStatus(false);
         FcmTokenStore.setToken(mContext, SUB_ID, FCM_TOKEN);
         mEntitlementConfiguration.reset();
     }
 
+    @After
+    public void tearDown() {
+        mCarrierConfig = null;
+    }
+
     @Test
     public void checkEntitlementStatus_verifyVowifiStatus() throws Exception {
         setImsProvisioningBool(false);
@@ -171,6 +228,117 @@
     }
 
     @Test
+    public void checkEntitlementStatus_responseWithVersZero_resetConfiguration() throws Exception {
+        setupImsEntitlementApi(mEntitlementConfiguration);
+        when(mMockServiceEntitlement.queryEntitlementStatus(
+                eq(ImmutableList.of(
+                        ServiceEntitlement.APP_VOWIFI,
+                        ServiceEntitlement.APP_VOLTE,
+                        ServiceEntitlement.APP_SMSOIP)), any())
+        ).thenReturn(RAW_XML_NEED_TO_RESET);
+
+        EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
+
+        assertThat(mEntitlementConfiguration.getRawXml()).isEqualTo(null);
+        verifyDefaultEntitlementResult(result, false);
+    }
+
+    @Test
+    public void checkEntitlementStatus_responseWithVersMinusOne_resetConfiguration()
+            throws Exception {
+        setupImsEntitlementApi(mEntitlementConfiguration);
+        when(mMockServiceEntitlement.queryEntitlementStatus(
+                eq(ImmutableList.of(
+                        ServiceEntitlement.APP_VOWIFI,
+                        ServiceEntitlement.APP_VOLTE,
+                        ServiceEntitlement.APP_SMSOIP)), any())
+        ).thenReturn(RAW_XML_NEED_TO_RESET_EXCEPT_VERS);
+
+        EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
+
+        assertThat(mEntitlementConfiguration.getRawXml())
+                .isEqualTo(EntitlementConfiguration.RAW_XML_VERS_MINUS_ONE);
+        verifyDefaultEntitlementResult(result, false);
+    }
+
+    @Test
+    public void checkEntitlementStatus_responseWithVersMinusTwo_resetConfiguration()
+            throws Exception {
+        setupImsEntitlementApi(mEntitlementConfiguration);
+        when(mMockServiceEntitlement.queryEntitlementStatus(
+                eq(ImmutableList.of(
+                        ServiceEntitlement.APP_VOWIFI,
+                        ServiceEntitlement.APP_VOLTE,
+                        ServiceEntitlement.APP_SMSOIP)), any())
+        ).thenReturn(RAW_XML_NEED_TO_RESET_EXCEPT_VERS_UNTIL_SETTING_ON);
+
+        EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
+
+        assertThat(mEntitlementConfiguration.getRawXml())
+                .isEqualTo(EntitlementConfiguration.RAW_XML_VERS_MINUS_TWO);
+        verifyDefaultEntitlementResult(result, false);
+    }
+
+    @Test
+    public void
+            checkEntitlementStatus_defaultEnabledAndResponseWithVersZero_resetConfiguration()
+                    throws Exception {
+        setDefaultStatus(true);
+        setupImsEntitlementApi(mEntitlementConfiguration);
+        when(mMockServiceEntitlement.queryEntitlementStatus(
+                eq(ImmutableList.of(
+                        ServiceEntitlement.APP_VOWIFI,
+                        ServiceEntitlement.APP_VOLTE,
+                        ServiceEntitlement.APP_SMSOIP)), any())
+        ).thenReturn(RAW_XML_NEED_TO_RESET);
+
+        EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
+
+        assertThat(mEntitlementConfiguration.getRawXml()).isEqualTo(null);
+        verifyDefaultEntitlementResult(result, true);
+    }
+
+    @Test
+    public void
+            checkEntitlementStatus_defaultEnabledAndResponseWithVersMinusOne_resetConfiguration()
+                    throws Exception {
+        setupImsEntitlementApi(mEntitlementConfiguration);
+        setDefaultStatus(true);
+        when(mMockServiceEntitlement.queryEntitlementStatus(
+                eq(ImmutableList.of(
+                        ServiceEntitlement.APP_VOWIFI,
+                        ServiceEntitlement.APP_VOLTE,
+                        ServiceEntitlement.APP_SMSOIP)), any())
+        ).thenReturn(RAW_XML_NEED_TO_RESET_EXCEPT_VERS);
+
+        EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
+
+        assertThat(mEntitlementConfiguration.getRawXml())
+                .isEqualTo(EntitlementConfiguration.RAW_XML_VERS_MINUS_ONE);
+        verifyDefaultEntitlementResult(result, true);
+    }
+
+    @Test
+    public void
+            checkEntitlementStatus_defaultEnabledAndResponseWithVersMinusTwo_resetConfiguration()
+                    throws Exception {
+        setupImsEntitlementApi(mEntitlementConfiguration);
+        setDefaultStatus(true);
+        when(mMockServiceEntitlement.queryEntitlementStatus(
+                eq(ImmutableList.of(
+                        ServiceEntitlement.APP_VOWIFI,
+                        ServiceEntitlement.APP_VOLTE,
+                        ServiceEntitlement.APP_SMSOIP)), any())
+        ).thenReturn(RAW_XML_NEED_TO_RESET_EXCEPT_VERS_UNTIL_SETTING_ON);
+
+        EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
+
+        assertThat(mEntitlementConfiguration.getRawXml())
+                .isEqualTo(EntitlementConfiguration.RAW_XML_VERS_MINUS_TWO);
+        verifyDefaultEntitlementResult(result, true);
+    }
+
+    @Test
     public void checkEntitlementStatus_verifyConfigs() throws Exception {
         setImsProvisioningBool(false);
         setupImsEntitlementApi(mEntitlementConfiguration);
@@ -180,9 +348,7 @@
 
         EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
 
-        assertThat(mEntitlementConfiguration.getVoWifiStatus()).isEqualTo(1);
-        assertThat(mEntitlementConfiguration.getVolteStatus()).isEqualTo(2);
-        assertThat(mEntitlementConfiguration.getSmsOverIpStatus()).isEqualTo(2);
+        assertThat(mEntitlementConfiguration.getRawXml()).isEqualTo(RAW_XML);
         assertThat(mEntitlementConfiguration.getToken().get()).isEqualTo(
                 "kZYfCEpSsMr88KZVmab5UsZVzl+nWSsX");
         assertThat(mEntitlementConfiguration.getTokenValidity()).isEqualTo(3600);
@@ -200,9 +366,7 @@
         EntitlementResult result = mImsEntitlementApi.checkEntitlementStatus();
 
         assertThat(result.getVowifiStatus().vowifiEntitled()).isFalse();
-        assertThat(mEntitlementConfiguration.getVoWifiStatus()).isEqualTo(2);
-        assertThat(mEntitlementConfiguration.getVolteStatus()).isEqualTo(2);
-        assertThat(mEntitlementConfiguration.getSmsOverIpStatus()).isEqualTo(2);
+        assertThat(mEntitlementConfiguration.getRawXml()).isEqualTo(null);
         assertThat(mEntitlementConfiguration.getToken().isPresent()).isFalse();
         assertThat(mEntitlementConfiguration.getTokenValidity()).isEqualTo(0);
         assertThat(mEntitlementConfiguration.entitlementValidation()).isEqualTo(NEEDS_TO_RESET);
@@ -228,7 +392,7 @@
     public void checkEntitlementStatus_httpResponse511_fullAuthnDone() throws Exception {
         setImsProvisioningBool(false);
         setupImsEntitlementApi(mEntitlementConfiguration);
-        mEntitlementConfiguration.update(RAW_XML);
+        mEntitlementConfiguration.update(ENTITLEMENT_VERSION, RAW_XML);
         // While perform fast-authn, throws exception with code 511
         when(mMockServiceEntitlement.queryEntitlementStatus(
                 ImmutableList.of(ServiceEntitlement.APP_VOWIFI),
@@ -253,7 +417,7 @@
             throws Exception {
         setImsProvisioningBool(false);
         setupImsEntitlementApi(mEntitlementConfiguration);
-        mEntitlementConfiguration.update(RAW_XML);
+        mEntitlementConfiguration.update(ENTITLEMENT_VERSION, RAW_XML);
         Clock fixedClock = Clock.fixed(Instant.ofEpochSecond(0), ZoneOffset.UTC);
         ImsEntitlementApi.sClock = fixedClock;
 
@@ -279,7 +443,7 @@
             throws Exception {
         setImsProvisioningBool(false);
         setupImsEntitlementApi(mEntitlementConfiguration);
-        mEntitlementConfiguration.update(RAW_XML);
+        mEntitlementConfiguration.update(ENTITLEMENT_VERSION, RAW_XML);
         // While perform fast-authn, throws exception with code 503
         when(mMockServiceEntitlement.queryEntitlementStatus(
                 ImmutableList.of(ServiceEntitlement.APP_VOWIFI),
@@ -312,6 +476,7 @@
         if (token != null) {
             requestBuilder.setAuthenticationToken(token);
         }
+        requestBuilder.setEntitlementVersion(String.valueOf(ENTITLEMENT_VERSION_TWO) + ".0");
         requestBuilder.setNotificationToken(FcmTokenStore.getToken(mContext, SUB_ID));
         requestBuilder.setAcceptContentType(ServiceEntitlementRequest.ACCEPT_CONTENT_TYPE_XML);
         return requestBuilder.build();
@@ -327,14 +492,24 @@
     }
 
     private void setImsProvisioningBool(boolean provisioning) {
-        PersistableBundle carrierConfig = new PersistableBundle();
-        carrierConfig.putBoolean(
-                CarrierConfigManager.ImsServiceEntitlement.KEY_IMS_PROVISIONING_BOOL,
-                provisioning
-        );
-        when(mCarrierConfigManager.getConfigForSubId(SUB_ID)).thenReturn(carrierConfig);
-        when(mContext.getSystemService(CarrierConfigManager.class))
-                .thenReturn(mCarrierConfigManager);
+        initializeCarrierConfig();
+        mCarrierConfig.putBoolean(
+                CarrierConfigManager.ImsServiceEntitlement.KEY_IMS_PROVISIONING_BOOL, provisioning);
+    }
+
+    private void setDefaultStatus(Boolean defaultStatus) {
+        initializeCarrierConfig();
+        mCarrierConfig.putBoolean(
+                KEY_DEFAULT_SERVICE_ENTITLEMENT_STATUS_BOOL, defaultStatus);
+    }
+
+    private void initializeCarrierConfig() {
+        if (mCarrierConfig == null) {
+            mCarrierConfig = new PersistableBundle();
+            when(mCarrierConfigManager.getConfigForSubId(SUB_ID)).thenReturn(mCarrierConfig);
+            when(mContext.getSystemService(CarrierConfigManager.class))
+                    .thenReturn(mCarrierConfigManager);
+        }
     }
 
     private String getDateTimeAfter(long seconds, Clock fixedClock) {
@@ -343,4 +518,14 @@
         dateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
         return dateFormat.format(Date.from(fixedClock.instant().plusSeconds(seconds)));
     }
+
+    private void verifyDefaultEntitlementResult(EntitlementResult result, boolean isActive) {
+        assertThat(result.getVowifiStatus().vowifiEntitled()).isEqualTo(isActive);
+        assertThat(result.getVowifiStatus().serverDataMissing()).isEqualTo(false);
+        assertThat(result.getVowifiStatus().inProgress()).isEqualTo(false);
+        assertThat(result.getVolteStatus().isActive()).isEqualTo(isActive);
+        assertThat(result.getVonrStatus().isHomeActive()).isEqualTo(isActive);
+        assertThat(result.getVonrStatus().isRoamingActive()).isEqualTo(isActive);
+        assertThat(result.getSmsoveripStatus().isActive()).isEqualTo(isActive);
+    }
 }
diff --git a/tests/unittests/src/com/android/imsserviceentitlement/ImsEntitlementPollingServiceTest.java b/tests/unittests/src/com/android/imsserviceentitlement/ImsEntitlementPollingServiceTest.java
index ce71f2c..fbb4a0c 100644
--- a/tests/unittests/src/com/android/imsserviceentitlement/ImsEntitlementPollingServiceTest.java
+++ b/tests/unittests/src/com/android/imsserviceentitlement/ImsEntitlementPollingServiceTest.java
@@ -16,6 +16,13 @@
 
 package com.android.imsserviceentitlement;
 
+import static com.android.imsserviceentitlement.ImsServiceEntitlementStatsLog.IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__DISABLED;
+import static com.android.imsserviceentitlement.ImsServiceEntitlementStatsLog.IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__ENABLED;
+import static com.android.imsserviceentitlement.ImsServiceEntitlementStatsLog.IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__FAILED;
+import static com.android.imsserviceentitlement.ImsServiceEntitlementStatsLog.IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__UNKNOWN_RESULT;
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementVersion.ENTITLEMENT_VERSION_EIGHT;
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementVersion.ENTITLEMENT_VERSION_TWO;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.ArgumentMatchers.anyBoolean;
@@ -37,15 +44,17 @@
 
 import com.android.imsserviceentitlement.entitlement.EntitlementResult;
 import com.android.imsserviceentitlement.job.JobManager;
+import com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementStatus;
 import com.android.imsserviceentitlement.ts43.Ts43SmsOverIpStatus;
 import com.android.imsserviceentitlement.ts43.Ts43VolteStatus;
+import com.android.imsserviceentitlement.ts43.Ts43VonrStatus;
 import com.android.imsserviceentitlement.ts43.Ts43VowifiStatus;
 import com.android.imsserviceentitlement.ts43.Ts43VowifiStatus.AddrStatus;
-import com.android.imsserviceentitlement.ts43.Ts43VowifiStatus.EntitlementStatus;
 import com.android.imsserviceentitlement.ts43.Ts43VowifiStatus.ProvStatus;
 import com.android.imsserviceentitlement.ts43.Ts43VowifiStatus.TcStatus;
 import com.android.imsserviceentitlement.utils.ImsUtils;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -72,9 +81,12 @@
 
     private ImsEntitlementPollingService mService;
     private JobScheduler mScheduler;
+    private PersistableBundle mCarrierConfig;
 
     private static final int SUB_ID = 1;
     private static final int SLOT_ID = 0;
+    private static final String KEY_ENTITLEMENT_VERSION_INT =
+            "imsserviceentitlement.entitlement_version_int";
 
     @Before
     public void setUp() throws Exception {
@@ -89,6 +101,12 @@
         setJobParameters();
         setWfcEnabledByUser(true);
         setImsProvisioningBool(false);
+        setEntitlementVersion(ENTITLEMENT_VERSION_TWO);
+    }
+
+    @After
+    public void tearDown() {
+        mCarrierConfig = null;
     }
 
     @Test
@@ -140,6 +158,30 @@
         verify(mImsUtils).setVolteProvisioned(false);
         verify(mImsUtils).setVowifiProvisioned(false);
         verify(mImsUtils).setSmsoipProvisioned(false);
+        verify(mImsUtils, never()).setVonrProvisioned(anyBoolean());
+        assertThat(mService.mOngoingTask.getVonrResult())
+                .isEqualTo(IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__UNKNOWN_RESULT);
+    }
+
+    @Test
+    public void doV8EntitlementCheck_shouldTurnOffImsApps_setAllProvisionedFalse()
+            throws Exception {
+        setImsProvisioningBool(true);
+        setEntitlementVersion(ENTITLEMENT_VERSION_EIGHT);
+        EntitlementResult entitlementResult =
+                getImsEntitlementResult(
+                        sDisableVoWiFi, sDisableVoLte, sDisableVonr, sDisableSmsoverip);
+        when(mImsEntitlementApi.checkEntitlementStatus()).thenReturn(entitlementResult);
+
+        mService.onStartJob(mJobParameters);
+        mService.mOngoingTask.get(); // wait for job finish.
+
+        verify(mImsUtils).setVolteProvisioned(false);
+        verify(mImsUtils).setVowifiProvisioned(false);
+        verify(mImsUtils).setSmsoipProvisioned(false);
+        verify(mImsUtils).setVonrProvisioned(false);
+        assertThat(mService.mOngoingTask.getVonrResult())
+                .isEqualTo(IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__DISABLED);
     }
 
     @Test
@@ -158,13 +200,54 @@
         verify(mImsUtils).setVolteProvisioned(true);
         verify(mImsUtils).setVowifiProvisioned(true);
         verify(mImsUtils).setSmsoipProvisioned(true);
+        verify(mImsUtils, never()).setVonrProvisioned(anyBoolean());
+        assertThat(mService.mOngoingTask.getVonrResult())
+                .isEqualTo(IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__UNKNOWN_RESULT);
+    }
+
+    @Test
+    public void doV8EntitlementCheck_shouldTurnOnImsApps_setAllProvisionedTrue() throws Exception {
+        setImsProvisioningBool(true);
+        setEntitlementVersion(ENTITLEMENT_VERSION_EIGHT);
+        EntitlementResult entitlementResult =
+                getImsEntitlementResult(sEnableVoWiFi, sEnableVoLte, sEnableVonr, sEnableSmsoverip);
+        when(mImsEntitlementApi.checkEntitlementStatus()).thenReturn(entitlementResult);
+
+        mService.onStartJob(mJobParameters);
+        mService.mOngoingTask.get(); // wait for job finish.
+
+        verify(mImsUtils).setVolteProvisioned(true);
+        verify(mImsUtils).setVowifiProvisioned(true);
+        verify(mImsUtils).setSmsoipProvisioned(true);
+        verify(mImsUtils).setVonrProvisioned(true);
+        assertThat(mService.mOngoingTask.getVonrResult())
+                .isEqualTo(IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__ENABLED);
+    }
+
+    @Test
+    public void doV8EntitlementCheck_entitlementResultNull_setAllProvisionedTrue()
+            throws Exception {
+        setImsProvisioningBool(true);
+        setEntitlementVersion(ENTITLEMENT_VERSION_EIGHT);
+        EntitlementResult entitlementResult = null;
+        when(mImsEntitlementApi.checkEntitlementStatus()).thenReturn(entitlementResult);
+
+        mService.onStartJob(mJobParameters);
+        mService.mOngoingTask.get(); // wait for job finish.
+
+        verify(mImsUtils).setVolteProvisioned(true);
+        verify(mImsUtils).setVowifiProvisioned(true);
+        verify(mImsUtils).setSmsoipProvisioned(true);
+        verify(mImsUtils).setVonrProvisioned(true);
+        assertThat(mService.mOngoingTask.getVonrResult())
+                .isEqualTo(IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__ENABLED);
     }
 
     @Test
     public void doEntitlementCheck_ImsEntitlementShouldRetry_rescheduleJob() throws Exception {
         setImsProvisioningBool(true);
         EntitlementResult entitlementResult =
-                EntitlementResult.builder().setRetryAfterSeconds(120).build();
+                EntitlementResult.builder(false).setRetryAfterSeconds(120).build();
         when(mImsEntitlementApi.checkEntitlementStatus()).thenReturn(entitlementResult);
 
         mService.onStartJob(mJobParameters);
@@ -173,6 +256,9 @@
         verify(mImsUtils, never()).setVolteProvisioned(anyBoolean());
         verify(mImsUtils, never()).setVowifiProvisioned(anyBoolean());
         verify(mImsUtils, never()).setSmsoipProvisioned(anyBoolean());
+        verify(mImsUtils, never()).setVonrProvisioned(anyBoolean());
+        assertThat(mService.mOngoingTask.getVonrResult())
+                .isEqualTo(IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__UNKNOWN_RESULT);
         assertThat(
                 mScheduler.getPendingJob(
                         jobIdWithSubId(JobManager.QUERY_ENTITLEMENT_STATUS_JOB_ID, SUB_ID)))
@@ -182,7 +268,7 @@
     @Test
     public void doEntitlementCheck_WfcEntitlementShouldRetry_rescheduleJob() throws Exception {
         EntitlementResult entitlementResult =
-                EntitlementResult.builder().setRetryAfterSeconds(120).build();
+                EntitlementResult.builder(false).setRetryAfterSeconds(120).build();
         when(mImsEntitlementApi.checkEntitlementStatus()).thenReturn(entitlementResult);
 
         mService.onStartJob(mJobParameters);
@@ -191,6 +277,9 @@
         verify(mImsUtils, never()).setVolteProvisioned(anyBoolean());
         verify(mImsUtils, never()).setVowifiProvisioned(anyBoolean());
         verify(mImsUtils, never()).setSmsoipProvisioned(anyBoolean());
+        verify(mImsUtils, never()).setVonrProvisioned(anyBoolean());
+        assertThat(mService.mOngoingTask.getVonrResult())
+                .isEqualTo(IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__UNKNOWN_RESULT);
         assertThat(
                 mScheduler.getPendingJob(
                         jobIdWithSubId(JobManager.QUERY_ENTITLEMENT_STATUS_JOB_ID, SUB_ID)))
@@ -198,6 +287,29 @@
     }
 
     @Test
+    public void doEntitlementCheck_runtimeException_entitlementUpdateFail() throws Exception {
+        setImsProvisioningBool(true);
+        when(mImsEntitlementApi.checkEntitlementStatus()).thenThrow(new RuntimeException());
+
+        mService.onStartJob(mJobParameters);
+        mService.mOngoingTask.get(); // wait for job finish.
+
+        assertThat(mService.mOngoingTask.getVonrResult())
+                .isEqualTo(IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__FAILED);
+    }
+
+    @Test
+    public void doWfcEntitlementCheck_runtimeException_entitlementUpdateFail() throws Exception {
+        when(mImsEntitlementApi.checkEntitlementStatus()).thenThrow(new RuntimeException());
+
+        mService.onStartJob(mJobParameters);
+        mService.mOngoingTask.get(); // wait for job finish.
+
+        assertThat(mService.mOngoingTask.getVowifiResult())
+                .isEqualTo(IMS_SERVICE_ENTITLEMENT_UPDATED__APP_RESULT__FAILED);
+    }
+
+    @Test
     public void enqueueJob_hasJob() {
         ImsEntitlementPollingService.enqueueJob(mContext, SUB_ID, 0);
 
@@ -235,33 +347,55 @@
     }
 
     private void setImsProvisioningBool(boolean provisioning) {
-        PersistableBundle carrierConfig = new PersistableBundle();
-        carrierConfig.putBoolean(
+        initializeCarrierConfig();
+        mCarrierConfig.putBoolean(
                 CarrierConfigManager.ImsServiceEntitlement.KEY_IMS_PROVISIONING_BOOL,
                 provisioning
         );
-        when(mCarrierConfigManager.getConfigForSubId(SUB_ID)).thenReturn(carrierConfig);
-        when(mContext.getSystemService(CarrierConfigManager.class))
-                .thenReturn(mCarrierConfigManager);
+    }
+
+    private void setEntitlementVersion(int entitlementVersion) {
+        initializeCarrierConfig();
+        mCarrierConfig.putInt(KEY_ENTITLEMENT_VERSION_INT, entitlementVersion);
+    }
+
+    private void initializeCarrierConfig() {
+        if (mCarrierConfig == null) {
+            mCarrierConfig = new PersistableBundle();
+            when(mCarrierConfigManager.getConfigForSubId(SUB_ID)).thenReturn(mCarrierConfig);
+            when(mContext.getSystemService(CarrierConfigManager.class))
+                    .thenReturn(mCarrierConfigManager);
+        }
     }
 
     private static EntitlementResult getEntitlementResult(Ts43VowifiStatus vowifiStatus) {
-        return EntitlementResult.builder()
-                .setVowifiStatus(vowifiStatus)
-                .build();
+        return EntitlementResult.builder(false).setVowifiStatus(vowifiStatus).build();
     }
 
     private static EntitlementResult getImsEntitlementResult(
             Ts43VowifiStatus vowifiStatus,
             Ts43VolteStatus volteStatus,
             Ts43SmsOverIpStatus smsOverIpStatus) {
-        return EntitlementResult.builder()
+        return EntitlementResult.builder(false)
                 .setVowifiStatus(vowifiStatus)
                 .setVolteStatus(volteStatus)
                 .setSmsoveripStatus(smsOverIpStatus)
                 .build();
     }
 
+    private static EntitlementResult getImsEntitlementResult(
+            Ts43VowifiStatus vowifiStatus,
+            Ts43VolteStatus volteStatus,
+            Ts43VonrStatus vonrStatus,
+            Ts43SmsOverIpStatus smsOverIpStatus) {
+        return EntitlementResult.builder(false)
+                .setVowifiStatus(vowifiStatus)
+                .setVolteStatus(volteStatus)
+                .setVonrStatus(vonrStatus)
+                .setSmsoveripStatus(smsOverIpStatus)
+                .build();
+    }
+
     private int jobIdWithSubId(int jobId, int subId) {
         return 1000 * subId + jobId;
     }
@@ -292,6 +426,18 @@
                     .setEntitlementStatus(EntitlementStatus.ENABLED)
                     .build();
 
+    private static final Ts43VonrStatus sDisableVonr =
+            Ts43VonrStatus.builder()
+                    .setHomeEntitlementStatus(EntitlementStatus.DISABLED)
+                    .setRoamingEntitlementStatus(EntitlementStatus.DISABLED)
+                    .build();
+
+    private static final Ts43VonrStatus sEnableVonr =
+            Ts43VonrStatus.builder()
+                    .setHomeEntitlementStatus(EntitlementStatus.ENABLED)
+                    .setRoamingEntitlementStatus(EntitlementStatus.ENABLED)
+                    .build();
+
     private static final Ts43SmsOverIpStatus sDisableSmsoverip =
             Ts43SmsOverIpStatus.builder()
                     .setEntitlementStatus(EntitlementStatus.DISABLED)
diff --git a/tests/unittests/src/com/android/imsserviceentitlement/ImsEntitlementReceiverTest.java b/tests/unittests/src/com/android/imsserviceentitlement/ImsEntitlementReceiverTest.java
index 117745c..84ddf0a 100644
--- a/tests/unittests/src/com/android/imsserviceentitlement/ImsEntitlementReceiverTest.java
+++ b/tests/unittests/src/com/android/imsserviceentitlement/ImsEntitlementReceiverTest.java
@@ -19,6 +19,9 @@
 import static android.telephony.TelephonyManager.SIM_STATE_LOADED;
 import static android.telephony.TelephonyManager.SIM_STATE_PIN_REQUIRED;
 
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementVersion.ENTITLEMENT_VERSION_EIGHT;
+import static com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementVersion.ENTITLEMENT_VERSION_TWO;
+
 import static com.google.common.truth.Truth.assertThat;
 
 import static org.mockito.Mockito.never;
@@ -44,6 +47,7 @@
 import com.android.imsserviceentitlement.utils.Executors;
 import com.android.imsserviceentitlement.utils.TelephonyUtils;
 
+import org.junit.After;
 import org.junit.Before;
 import org.junit.Rule;
 import org.junit.Test;
@@ -59,6 +63,8 @@
 public class ImsEntitlementReceiverTest {
     private static final int SUB_ID = 1;
     private static final int LAST_SUB_ID = 2;
+    private static final String KEY_ENTITLEMENT_VERSION_INT =
+            "imsserviceentitlement.entitlement_version_int";
     private static final String RAW_XML =
             "<wap-provisioningdoc version=\"1.1\">\n"
                     + "    <characteristic type=\"APPLICATION\">\n"
@@ -96,6 +102,7 @@
     @Spy private final Context mContext = ApplicationProvider.getApplicationContext();
 
     private ImsEntitlementReceiver mReceiver;
+    private PersistableBundle mCarrierConfig;
     private boolean mIsBootUp;
 
     @Before
@@ -117,23 +124,28 @@
         };
         mIsBootUp = false;
 
-        new EntitlementConfiguration(mContext, LAST_SUB_ID).update(RAW_XML);
+        new EntitlementConfiguration(mContext, LAST_SUB_ID)
+                .update(ENTITLEMENT_VERSION_TWO, RAW_XML);
         new EntitlementConfiguration(mContext, SUB_ID).reset();
 
         when(mMockUserManager.isSystemUser()).thenReturn(true);
         when(mMockTelephonyUtils.getSimApplicationState()).thenReturn(SIM_STATE_LOADED);
 
         setLastSubId(LAST_SUB_ID, 0);
-        setupCarrierConfig();
+        setImsProvisioningBool(true);
         useDirectExecutor();
     }
 
+    @After
+    public void tearDown() {
+        mCarrierConfig = null;
+    }
+
     @Test
     public void onReceive_simChanged_dataReset() {
         mReceiver.onReceive(mContext, getCarrierConfigChangedIntent(SUB_ID, /* slotId= */ 0));
 
-        assertThat(
-                new EntitlementConfiguration(mContext, LAST_SUB_ID).getVoWifiStatus()).isEqualTo(2);
+        assertThat(new EntitlementConfiguration(mContext, LAST_SUB_ID).getRawXml()).isEqualTo(null);
         verify(mMockJobManager, times(1)).queryEntitlementStatusOnceNetworkReady();
     }
 
@@ -145,8 +157,8 @@
         mReceiver.onReceive(mContext, getCarrierConfigChangedIntent(SUB_ID, /* slotId= */ 0));
 
         // no-op
-        assertThat(
-                new EntitlementConfiguration(mContext, LAST_SUB_ID).getVoWifiStatus()).isEqualTo(1);
+        assertThat(new EntitlementConfiguration(mContext, LAST_SUB_ID).getRawXml())
+                .isEqualTo(RAW_XML);
         verify(mMockJobManager, never()).queryEntitlementStatusOnceNetworkReady();
 
         // SIM LOADED
@@ -155,8 +167,7 @@
         mReceiver.onReceive(mContext, getCarrierConfigChangedIntent(SUB_ID, /* slotId= */ 0));
 
         // configuration reset and entitlement query scheduled.
-        assertThat(
-                new EntitlementConfiguration(mContext, LAST_SUB_ID).getVoWifiStatus()).isEqualTo(2);
+        assertThat(new EntitlementConfiguration(mContext, LAST_SUB_ID).getRawXml()).isEqualTo(null);
         verify(mMockJobManager, times(1)).queryEntitlementStatusOnceNetworkReady();
     }
 
@@ -165,8 +176,8 @@
         mReceiver.onReceive(
                 mContext, getCarrierConfigChangedIntent(LAST_SUB_ID, /* slotId= */ 0));
 
-        assertThat(
-                new EntitlementConfiguration(mContext, LAST_SUB_ID).getVoWifiStatus()).isEqualTo(1);
+        assertThat(new EntitlementConfiguration(mContext, LAST_SUB_ID).getRawXml())
+                .isEqualTo(RAW_XML);
         verify(mMockJobManager, never()).queryEntitlementStatusOnceNetworkReady();
     }
 
@@ -177,8 +188,8 @@
         mReceiver.onReceive(
                 mContext, getCarrierConfigChangedIntent(LAST_SUB_ID, /* slotId= */ 1));
 
-        assertThat(
-                new EntitlementConfiguration(mContext, LAST_SUB_ID).getVoWifiStatus()).isEqualTo(1);
+        assertThat(new EntitlementConfiguration(mContext, LAST_SUB_ID).getRawXml())
+                .isEqualTo(RAW_XML);
         verify(mMockJobManager, never()).queryEntitlementStatusOnceNetworkReady();
     }
 
@@ -188,8 +199,7 @@
 
         mReceiver.onReceive(mContext, getCarrierConfigChangedIntent(SUB_ID, /* slotId= */ 1));
 
-        assertThat(
-                new EntitlementConfiguration(mContext, LAST_SUB_ID).getVoWifiStatus()).isEqualTo(2);
+        assertThat(new EntitlementConfiguration(mContext, LAST_SUB_ID).getRawXml()).isEqualTo(null);
         verify(mMockJobManager).queryEntitlementStatusOnceNetworkReady();
     }
 
@@ -213,7 +223,8 @@
 
     @Test
     public void onReceive_deviceBootUp_jobScheduled() {
-        new EntitlementConfiguration(mContext, LAST_SUB_ID).update(RAW_XML_VERSION_0_VALIDITY_0);
+        new EntitlementConfiguration(mContext, LAST_SUB_ID)
+                .update(ENTITLEMENT_VERSION_TWO, RAW_XML_VERSION_0_VALIDITY_0);
         mIsBootUp = true;
 
         mReceiver.onReceive(mContext, getCarrierConfigChangedIntent(LAST_SUB_ID, /* slotId= */ 0));
@@ -223,7 +234,8 @@
 
     @Test
     public void onReceive_bootCompleteInvalidVers_noJobScheduled() {
-        new EntitlementConfiguration(mContext, LAST_SUB_ID).update(RAW_XML_INVALID_VERS);
+        new EntitlementConfiguration(mContext, LAST_SUB_ID)
+                .update(ENTITLEMENT_VERSION_TWO, RAW_XML_INVALID_VERS);
         mIsBootUp = true;
 
         mReceiver.onReceive(mContext, getCarrierConfigChangedIntent(LAST_SUB_ID, /* slotId= */ 0));
@@ -232,6 +244,39 @@
     }
 
     @Test
+    public void
+            onReceiveAndEntitlementUpdatedFromZeroToTwo_bootCompleteInvalidVers_noJobScheduled() {
+        new EntitlementConfiguration(mContext, LAST_SUB_ID).update(0, RAW_XML_INVALID_VERS);
+        setEntitlementVersion(ENTITLEMENT_VERSION_TWO);
+        mIsBootUp = true;
+
+        mReceiver.onReceive(mContext, getCarrierConfigChangedIntent(LAST_SUB_ID, /* slotId= */ 0));
+
+        verify(mMockJobManager, never()).queryEntitlementStatusOnceNetworkReady();
+    }
+
+    @Test
+    public void
+            onReceiveAndEntitlementUpdatedFromZeroToEight_bootCompleteInvalidVers_JobScheduled() {
+        new EntitlementConfiguration(mContext, LAST_SUB_ID).update(0, RAW_XML_INVALID_VERS);
+        setEntitlementVersion(ENTITLEMENT_VERSION_EIGHT);
+        mIsBootUp = true;
+
+        mReceiver.onReceive(mContext, getCarrierConfigChangedIntent(LAST_SUB_ID, /* slotId= */ 0));
+
+        verify(mMockJobManager).queryEntitlementStatusOnceNetworkReady();
+    }
+
+    @Test
+    public void onReceive_unsupportedEntitlementVersion_noJobScheduled() {
+        setEntitlementVersion(1);
+
+        mReceiver.onReceive(mContext, getCarrierConfigChangedIntent(LAST_SUB_ID, 0));
+
+        verify(mMockJobManager, never()).queryEntitlementStatusOnceNetworkReady();
+    }
+
+    @Test
     public void onReceive_invalidSubId_noJobScheduled() {
         mReceiver.onReceive(mContext,
                 getCarrierConfigChangedIntent(SubscriptionManager.INVALID_SUBSCRIPTION_ID, 0));
@@ -259,14 +304,25 @@
         return intent;
     }
 
-    private void setupCarrierConfig() {
-        PersistableBundle carrierConfig = new PersistableBundle();
-        carrierConfig.putBoolean(
-                CarrierConfigManager.ImsServiceEntitlement.KEY_IMS_PROVISIONING_BOOL, true);
-        when(mContext.getSystemService(CarrierConfigManager.class))
-                .thenReturn(mCarrierConfigManager);
-        when(mCarrierConfigManager.getConfigForSubId(SUB_ID)).thenReturn(carrierConfig);
-        when(mCarrierConfigManager.getConfigForSubId(LAST_SUB_ID)).thenReturn(carrierConfig);
+    private void setImsProvisioningBool(boolean provisioning) {
+        initializeCarrierConfig();
+        mCarrierConfig.putBoolean(
+                CarrierConfigManager.ImsServiceEntitlement.KEY_IMS_PROVISIONING_BOOL, provisioning);
+    }
+
+    private void setEntitlementVersion(int entitlementVersion) {
+        initializeCarrierConfig();
+        mCarrierConfig.putInt(KEY_ENTITLEMENT_VERSION_INT, entitlementVersion);
+    }
+
+    private void initializeCarrierConfig() {
+        if (mCarrierConfig == null) {
+            mCarrierConfig = new PersistableBundle();
+            when(mCarrierConfigManager.getConfigForSubId(SUB_ID)).thenReturn(mCarrierConfig);
+            when(mCarrierConfigManager.getConfigForSubId(LAST_SUB_ID)).thenReturn(mCarrierConfig);
+            when(mContext.getSystemService(CarrierConfigManager.class))
+                    .thenReturn(mCarrierConfigManager);
+        }
     }
 
     private void setLastSubId(int subId, int slotId) {
diff --git a/tests/unittests/src/com/android/imsserviceentitlement/WfcActivationControllerTest.java b/tests/unittests/src/com/android/imsserviceentitlement/WfcActivationControllerTest.java
index cf72f1f..b986f54 100644
--- a/tests/unittests/src/com/android/imsserviceentitlement/WfcActivationControllerTest.java
+++ b/tests/unittests/src/com/android/imsserviceentitlement/WfcActivationControllerTest.java
@@ -40,9 +40,9 @@
 import androidx.test.runner.AndroidJUnit4;
 
 import com.android.imsserviceentitlement.entitlement.EntitlementResult;
+import com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementStatus;
 import com.android.imsserviceentitlement.ts43.Ts43VowifiStatus;
 import com.android.imsserviceentitlement.ts43.Ts43VowifiStatus.AddrStatus;
-import com.android.imsserviceentitlement.ts43.Ts43VowifiStatus.EntitlementStatus;
 import com.android.imsserviceentitlement.ts43.Ts43VowifiStatus.ProvStatus;
 import com.android.imsserviceentitlement.ts43.Ts43VowifiStatus.TcStatus;
 import com.android.imsserviceentitlement.utils.Executors;
@@ -165,18 +165,17 @@
 
     @Test
     public void finishFlow_startForUpdate_showGeneralWaitingUi() {
-        when(mMockActivationApi.checkEntitlementStatus()).thenReturn(
-                EntitlementResult
-                        .builder()
-                        .setVowifiStatus(
-                                Ts43VowifiStatus
-                                        .builder()
-                                        .setEntitlementStatus(EntitlementStatus.ENABLED)
-                                        .setProvStatus(ProvStatus.PROVISIONED)
-                                        .setTcStatus(TcStatus.AVAILABLE)
-                                        .setAddrStatus(AddrStatus.AVAILABLE)
-                                        .build())
-                        .build());
+        when(mMockActivationApi.checkEntitlementStatus())
+                .thenReturn(
+                        EntitlementResult.builder(false)
+                                .setVowifiStatus(
+                                        Ts43VowifiStatus.builder()
+                                                .setEntitlementStatus(EntitlementStatus.ENABLED)
+                                                .setProvStatus(ProvStatus.PROVISIONED)
+                                                .setTcStatus(TcStatus.AVAILABLE)
+                                                .setAddrStatus(AddrStatus.AVAILABLE)
+                                                .build())
+                                .build());
         setNetworkConnected(false);
         Intent intent = new Intent(Intent.ACTION_MAIN);
         intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, SUB_ID);
@@ -230,18 +229,17 @@
         intent.putExtra(SubscriptionManager.EXTRA_SUBSCRIPTION_INDEX, SUB_ID);
         intent.putExtra(ActivityConstants.EXTRA_LAUNCH_CARRIER_APP,
                 ActivityConstants.LAUNCH_APP_ACTIVATE);
-        when(mMockActivationApi.checkEntitlementStatus()).thenReturn(
-                EntitlementResult
-                        .builder()
-                        .setVowifiStatus(
-                                Ts43VowifiStatus
-                                        .builder()
-                                        .setEntitlementStatus(EntitlementStatus.ENABLED)
-                                        .setProvStatus(ProvStatus.PROVISIONED)
-                                        .setTcStatus(TcStatus.AVAILABLE)
-                                        .setAddrStatus(AddrStatus.AVAILABLE)
-                                        .build())
-                        .build());
+        when(mMockActivationApi.checkEntitlementStatus())
+                .thenReturn(
+                        EntitlementResult.builder(false)
+                                .setVowifiStatus(
+                                        Ts43VowifiStatus.builder()
+                                                .setEntitlementStatus(EntitlementStatus.ENABLED)
+                                                .setProvStatus(ProvStatus.PROVISIONED)
+                                                .setTcStatus(TcStatus.AVAILABLE)
+                                                .setAddrStatus(AddrStatus.AVAILABLE)
+                                                .build())
+                                .build());
         mWfcActivationController =
                 new WfcActivationController(
                         mContext,
@@ -263,7 +261,7 @@
     @Test
     public void handleEntitlementStatusForActivation_isVowifiEntitledTrue_setActivityResultOk() {
         EntitlementResult entitlementResult =
-                EntitlementResult.builder()
+                EntitlementResult.builder(false)
                         .setVowifiStatus(
                                 Ts43VowifiStatus.builder()
                                         .setEntitlementStatus(EntitlementStatus.ENABLED)
@@ -283,7 +281,7 @@
     @Test
     public void handleEntitlementStatusForActivation_isServerDataMissingTrue_showWebview() {
         EntitlementResult entitlementResult =
-                EntitlementResult.builder()
+                EntitlementResult.builder(false)
                         .setVowifiStatus(
                                 Ts43VowifiStatus.builder()
                                         .setEntitlementStatus(EntitlementStatus.DISABLED)
@@ -305,7 +303,7 @@
     @Test
     public void handleEntitlementStatusForActivation_showTc_showWebview() {
         EntitlementResult entitlementResult =
-                EntitlementResult.builder()
+                EntitlementResult.builder(false)
                         .setVowifiStatus(
                                 Ts43VowifiStatus.builder()
                                         .setEntitlementStatus(EntitlementStatus.DISABLED)
@@ -325,7 +323,7 @@
     @Test
     public void handleEntitlementStatusForActivation_isIncompatibleTrue_showErrorUi() {
         EntitlementResult entitlementResult =
-                EntitlementResult.builder()
+                EntitlementResult.builder(false)
                         .setVowifiStatus(
                                 Ts43VowifiStatus.builder()
                                         .setEntitlementStatus(EntitlementStatus.INCOMPATIBLE)
@@ -342,7 +340,7 @@
     @Test
     public void handleEntitlementStatusForActivation_unexpectedStatus_showGeneralErrorUi() {
         EntitlementResult entitlementResult =
-                EntitlementResult.builder()
+                EntitlementResult.builder(false)
                         .setVowifiStatus(
                                 Ts43VowifiStatus.builder()
                                         .setEntitlementStatus(EntitlementStatus.DISABLED)
@@ -361,7 +359,7 @@
     @Test
     public void handleEntitlementStatusAfterActivation_isVowifiEntitledTrue_setActivityResultOk() {
         EntitlementResult entitlementResult =
-                EntitlementResult.builder()
+                EntitlementResult.builder(false)
                         .setVowifiStatus(
                                 Ts43VowifiStatus.builder()
                                         .setEntitlementStatus(EntitlementStatus.ENABLED)
@@ -381,7 +379,7 @@
     @Test
     public void handleEntitlementStatusAfterActivation_unexpectedStatus_showGeneralErrorUi() {
         EntitlementResult entitlementResult =
-                EntitlementResult.builder()
+                EntitlementResult.builder(false)
                         .setVowifiStatus(
                                 Ts43VowifiStatus.builder()
                                         .setEntitlementStatus(EntitlementStatus.DISABLED)
@@ -400,7 +398,7 @@
     @Test
     public void handleEntitlementStatusAfterUpdating_entitlementStatusEnabled_setResultOk() {
         EntitlementResult entitlementResult =
-                EntitlementResult.builder()
+                EntitlementResult.builder(false)
                         .setVowifiStatus(
                                 Ts43VowifiStatus.builder()
                                         .setEntitlementStatus(EntitlementStatus.ENABLED)
@@ -420,7 +418,7 @@
     @Test
     public void handleEntitlementStatusAfterUpdating_entitlementStatusNoServerData_turnOffWfc() {
         EntitlementResult entitlementResult =
-                EntitlementResult.builder()
+                EntitlementResult.builder(false)
                         .setVowifiStatus(
                                 Ts43VowifiStatus.builder()
                                         .setEntitlementStatus(EntitlementStatus.DISABLED)
@@ -450,7 +448,7 @@
     @Test
     public void handleEntitlementStatusAfterUpdating_unexpectedStatus_showGeneralErrorUi() {
         EntitlementResult entitlementResult =
-                EntitlementResult.builder()
+                EntitlementResult.builder(false)
                         .setVowifiStatus(
                                 Ts43VowifiStatus.builder()
                                         .setEntitlementStatus(EntitlementStatus.DISABLED)
@@ -468,20 +466,19 @@
 
     @Test
     public void handleEntitlementStatusForUpdate_serviceEntitled_showWebview() {
-        when(mMockActivationApi.checkEntitlementStatus()).thenReturn(
-                EntitlementResult
-                        .builder()
-                        .setVowifiStatus(
-                                Ts43VowifiStatus
-                                        .builder()
-                                        .setEntitlementStatus(EntitlementStatus.ENABLED)
-                                        .setProvStatus(ProvStatus.PROVISIONED)
-                                        .setTcStatus(TcStatus.AVAILABLE)
-                                        .setAddrStatus(AddrStatus.AVAILABLE)
-                                        .build())
-                        .setEmergencyAddressWebUrl(EMERGENCY_ADDRESS_WEB_URL)
-                        .setEmergencyAddressWebData(EMERGENCY_ADDRESS_WEB_DATA)
-                        .build());
+        when(mMockActivationApi.checkEntitlementStatus())
+                .thenReturn(
+                        EntitlementResult.builder(false)
+                                .setVowifiStatus(
+                                        Ts43VowifiStatus.builder()
+                                                .setEntitlementStatus(EntitlementStatus.ENABLED)
+                                                .setProvStatus(ProvStatus.PROVISIONED)
+                                                .setTcStatus(TcStatus.AVAILABLE)
+                                                .setAddrStatus(AddrStatus.AVAILABLE)
+                                                .build())
+                                .setEmergencyAddressWebUrl(EMERGENCY_ADDRESS_WEB_URL)
+                                .setEmergencyAddressWebData(EMERGENCY_ADDRESS_WEB_DATA)
+                                .build());
         buildActivity(ActivityConstants.LAUNCH_APP_UPDATE);
 
         mWfcActivationController.evaluateEntitlementStatus();
@@ -492,19 +489,18 @@
 
     @Test
     public void handleEntitlementStatusForUpdate_showTc_showWebview() {
-        when(mMockActivationApi.checkEntitlementStatus()).thenReturn(
-                EntitlementResult
-                        .builder()
-                        .setVowifiStatus(
-                                Ts43VowifiStatus
-                                        .builder()
-                                        .setEntitlementStatus(EntitlementStatus.ENABLED)
-                                        .setProvStatus(ProvStatus.PROVISIONED)
-                                        .setTcStatus(TcStatus.AVAILABLE)
-                                        .setAddrStatus(AddrStatus.AVAILABLE)
-                                        .build())
-                        .setTermsAndConditionsWebUrl(EMERGENCY_ADDRESS_WEB_URL)
-                        .build());
+        when(mMockActivationApi.checkEntitlementStatus())
+                .thenReturn(
+                        EntitlementResult.builder(false)
+                                .setVowifiStatus(
+                                        Ts43VowifiStatus.builder()
+                                                .setEntitlementStatus(EntitlementStatus.ENABLED)
+                                                .setProvStatus(ProvStatus.PROVISIONED)
+                                                .setTcStatus(TcStatus.AVAILABLE)
+                                                .setAddrStatus(AddrStatus.AVAILABLE)
+                                                .build())
+                                .setTermsAndConditionsWebUrl(EMERGENCY_ADDRESS_WEB_URL)
+                                .build());
         buildActivity(ActivityConstants.LAUNCH_APP_SHOW_TC);
 
         mWfcActivationController.evaluateEntitlementStatus();
@@ -515,7 +511,7 @@
     @Test
     public void handleEntitlementStatusForUpdate_entitlementStatusIncompatible_showErrorUi() {
         EntitlementResult entitlementResult =
-                EntitlementResult.builder()
+                EntitlementResult.builder(false)
                         .setVowifiStatus(
                                 Ts43VowifiStatus.builder()
                                         .setEntitlementStatus(EntitlementStatus.INCOMPATIBLE)
@@ -532,7 +528,7 @@
     @Test
     public void handleEntitlementStatusForUpdate_entitlementStatusDisabled_showGenericErrorUi() {
         EntitlementResult entitlementResult =
-                EntitlementResult.builder()
+                EntitlementResult.builder(false)
                         .setVowifiStatus(
                                 Ts43VowifiStatus.builder()
                                         .setEntitlementStatus(EntitlementStatus.DISABLED)
diff --git a/tests/unittests/src/com/android/imsserviceentitlement/entitlement/EntitlementConfigurationTest.java b/tests/unittests/src/com/android/imsserviceentitlement/entitlement/EntitlementConfigurationTest.java
index eb32c49..53df827 100644
--- a/tests/unittests/src/com/android/imsserviceentitlement/entitlement/EntitlementConfigurationTest.java
+++ b/tests/unittests/src/com/android/imsserviceentitlement/entitlement/EntitlementConfigurationTest.java
@@ -88,6 +88,7 @@
                     + "    </characteristic>\n"
                     + "</wap-provisioningdoc>\n";
     private static final int SUB_ID = 1;
+    private static final int ENTITLEMENT_VERSION = 2;
 
     private Context mContext;
     private EntitlementConfiguration mConfiguration;
@@ -101,11 +102,10 @@
 
     @Test
     public void updateConfigurations_verifyConfigs() {
-        mConfiguration.update(RAW_XML);
+        mConfiguration.update(ENTITLEMENT_VERSION, RAW_XML);
 
-        assertThat(mConfiguration.getVolteStatus()).isEqualTo(0);
-        assertThat(mConfiguration.getVoWifiStatus()).isEqualTo(1);
-        assertThat(mConfiguration.getSmsOverIpStatus()).isEqualTo(2);
+        assertThat(mConfiguration.getEntitlementVersion()).isEqualTo(ENTITLEMENT_VERSION);
+        assertThat(mConfiguration.getRawXml()).isEqualTo(RAW_XML);
         assertThat(mConfiguration.getToken().get()).isEqualTo("kZYfCEpSsMr88KZVmab5UsZVzl+nWSsX");
         assertThat(mConfiguration.getTokenValidity()).isEqualTo(3600);
         assertThat(mConfiguration.getVersion()).isEqualTo("1");
@@ -115,12 +115,11 @@
 
     @Test
     public void updateConfigurations_reset_verifyDefaultValues() {
-        mConfiguration.update(RAW_XML);
+        mConfiguration.update(ENTITLEMENT_VERSION, RAW_XML);
         mConfiguration.reset();
 
-        assertThat(mConfiguration.getVolteStatus()).isEqualTo(2);
-        assertThat(mConfiguration.getVoWifiStatus()).isEqualTo(2);
-        assertThat(mConfiguration.getSmsOverIpStatus()).isEqualTo(2);
+        assertThat(mConfiguration.getEntitlementVersion()).isEqualTo(ENTITLEMENT_VERSION);
+        assertThat(mConfiguration.getRawXml()).isEqualTo(null);
         assertThat(mConfiguration.getToken().isPresent()).isFalse();
         assertThat(mConfiguration.getTokenValidity()).isEqualTo(0);
         assertThat(mConfiguration.entitlementValidation()).isEqualTo(ClientBehavior.NEEDS_TO_RESET);
@@ -128,16 +127,18 @@
 
     @Test
     public void updateConfigurations_noTokenValidity_tokenValid() {
-        mConfiguration.update(RAW_XML_NO_TOKEN_VALIDITY);
+        mConfiguration.update(ENTITLEMENT_VERSION, RAW_XML_NO_TOKEN_VALIDITY);
 
+        assertThat(mConfiguration.getEntitlementVersion()).isEqualTo(ENTITLEMENT_VERSION);
         assertThat(mConfiguration.getToken().get()).isEqualTo("kZYfCEpSsMr88KZVmab5UsZVzl+nWSsX");
         assertThat(mConfiguration.getTokenValidity()).isEqualTo(0);
     }
 
     @Test
     public void updateConfigurations_noVersVersion_getDefaultValue() {
-        mConfiguration.update(RAW_XML_NO_VERS_VERSION);
+        mConfiguration.update(ENTITLEMENT_VERSION, RAW_XML_NO_VERS_VERSION);
 
+        assertThat(mConfiguration.getEntitlementVersion()).isEqualTo(ENTITLEMENT_VERSION);
         assertThat(mConfiguration.getVersion()).isEqualTo("0");
     }
 }
diff --git a/tests/unittests/src/com/android/imsserviceentitlement/ts43/Ts43VowifiStatusTest.java b/tests/unittests/src/com/android/imsserviceentitlement/ts43/Ts43VowifiStatusTest.java
index b39fcf4..0f9b3e8 100644
--- a/tests/unittests/src/com/android/imsserviceentitlement/ts43/Ts43VowifiStatusTest.java
+++ b/tests/unittests/src/com/android/imsserviceentitlement/ts43/Ts43VowifiStatusTest.java
@@ -20,8 +20,8 @@
 
 import androidx.test.runner.AndroidJUnit4;
 
+import com.android.imsserviceentitlement.ts43.Ts43Constants.EntitlementStatus;
 import com.android.imsserviceentitlement.ts43.Ts43VowifiStatus.AddrStatus;
-import com.android.imsserviceentitlement.ts43.Ts43VowifiStatus.EntitlementStatus;
 import com.android.imsserviceentitlement.ts43.Ts43VowifiStatus.ProvStatus;
 import com.android.imsserviceentitlement.ts43.Ts43VowifiStatus.TcStatus;
 
diff --git a/tests/unittests/src/com/android/imsserviceentitlement/utils/XmlDocTest.java b/tests/unittests/src/com/android/imsserviceentitlement/utils/XmlDocTest.java
index 949c642..28c19a2 100644
--- a/tests/unittests/src/com/android/imsserviceentitlement/utils/XmlDocTest.java
+++ b/tests/unittests/src/com/android/imsserviceentitlement/utils/XmlDocTest.java
@@ -121,15 +121,93 @@
                     + "</characteristic>"
                     + "</wap-provisioningdoc>";
 
+    // A TS43 v8 XML sample with separate 5G config for home and roaming networks
+    private static final String AUTH_RESPONSE_XML_7 =
+            "<wap-provisioningdoc version=\"1.1\">"
+                    + "<characteristic type=\"APPLICATION\">"
+                    + "<parm name=\"AppID\" value=\"ap2003\"/>"
+                    + "<parm name=\"Name\" value=\"Voice over Cellular Entitlement settings\"/>"
+                    + "<characteristic type=\"VoiceOverCellularEntitleInfo\">"
+                    + "<characteristic type=\"RATVoiceEntitleInfoDetails\">"
+                    + "<parm name=\"AccessType\" value=\"2\"/>" // 5G
+                    + "<parm name=\"HomeRoamingNWType\" value=\"2\"/>" // Home network
+                    + "<parm name=\"EntitlementStatus\" value=\"1\"/>" // Enabled
+                    + "<parm name=\"NetworkVoiceIRATCapablity\" value=\"EPS-Fallback\"/>"
+                    + "</characteristic>"
+                    + "<characteristic type=\"RATVoiceEntitleInfoDetails\">"
+                    + "<parm name=\"AccessType\" value=\"2\"/>" // 5G
+                    + "<parm name=\"HomeRoamingNWType\" value=\"3\"/>" // Roaming network
+                    + "<parm name=\"EntitlementStatus\" value=\"2\"/>" // Incompatible
+                    + "<parm name=\"MessageForIncompatible\" value=\"z\"/>"
+                    + "</characteristic>"
+                    + "</characteristic>"
+                    + "</characteristic>"
+                    + "</wap-provisioningdoc>";
+
+    // A TS43 v8 XML sample with single 4G and 5G config for both home and roaming networks
+    private static final String AUTH_RESPONSE_XML_8 =
+            "<wap-provisioningdoc version=\"1.1\">"
+                    + "<characteristic type=\"APPLICATION\">"
+                    + "<parm name=\"AppID\" value=\"ap2003\"/>"
+                    + "<parm name=\"Name\" value=\"Voice over Cellular Entitlement settings\"/>"
+                    + "<characteristic type=\"VoiceOverCellularEntitleInfo\">"
+                    + "<characteristic type=\"RATVoiceEntitleInfoDetails\">"
+                    + "<parm name=\"AccessType\" value=\"1\"/>" // 4G
+                    + "<parm name=\"HomeRoamingNWType\" value=\"1\"/>" // Home&Roaming
+                    + "<parm name=\"EntitlementStatus\" value=\"1\"/>" // Enabled
+                    + "</characteristic>"
+                    + "<characteristic type=\"RATVoiceEntitleInfoDetails\">"
+                    + "<parm name=\"AccessType\" value=\"2\"/>" // 5G
+                    + "<parm name=\"HomeRoamingNWType\" value=\"1\"/>" // Both Home and Roaming
+                    + "<parm name=\"EntitlementStatus\" value=\"1\"/>" // Enabled
+                    + "<parm name=\"NetworkVoiceIRATCapablity\" value=\"EPS-Fallback\"/>"
+                    + "</characteristic>"
+                    + "</characteristic>"
+                    + "</characteristic>"
+                    + "</wap-provisioningdoc>";
+
+    // A TS43 v8 XML sample with single 4G for home network only - unlikely to happen
+    private static final String AUTH_RESPONSE_XML_9 =
+            "<wap-provisioningdoc version=\"1.1\">"
+                    + "<characteristic type=\"APPLICATION\">"
+                    + "<parm name=\"AppID\" value=\"ap2003\"/>"
+                    + "<parm name=\"Name\" value=\"Voice over Cellular Entitlement settings\"/>"
+                    + "<characteristic type=\"VoiceOverCellularEntitleInfo\">"
+                    + "<characteristic type=\"RATVoiceEntitleInfoDetails\">"
+                    + "<parm name=\"AccessType\" value=\"1\"/>" // 4G
+                    + "<parm name=\"HomeRoamingNWType\" value=\"2\"/>" // Home
+                    + "<parm name=\"EntitlementStatus\" value=\"1\"/>" // Enabled
+                    + "</characteristic>"
+                    + "</characteristic>"
+                    + "</characteristic>"
+                    + "</wap-provisioningdoc>";
+
+    // A TS43 v8 XML sample with single 5G for home network only - unlikely to happen
+    private static final String AUTH_RESPONSE_XML_10 =
+            "<wap-provisioningdoc version=\"1.1\">"
+                    + "<characteristic type=\"APPLICATION\">"
+                    + "<parm name=\"AppID\" value=\"ap2003\"/>"
+                    + "<parm name=\"Name\" value=\"Voice over Cellular Entitlement settings\"/>"
+                    + "<characteristic type=\"VoiceOverCellularEntitleInfo\">"
+                    + "<characteristic type=\"RATVoiceEntitleInfoDetails\">"
+                    + "<parm name=\"AccessType\" value=\"2\"/>" // 5G
+                    + "<parm name=\"HomeRoamingNWType\" value=\"2\"/>" // Home
+                    + "<parm name=\"EntitlementStatus\" value=\"1\"/>" // Enabled
+                    + "</characteristic>"
+                    + "</characteristic>"
+                    + "</characteristic>"
+                    + "</wap-provisioningdoc>";
+
     private static final String TOKEN = "kZYfCEpSsMr88KZVmab5UsZVzl+nWSsX";
 
     @Test
     public void parseAuthenticateResponse() {
         XmlDoc xmlDoc = new XmlDoc(AUTH_RESPONSE_XML);
 
-        assertThat(xmlDoc.get("TOKEN", "token", "ap2004").get()).isEqualTo(TOKEN);
+        assertThat(xmlDoc.getFromToken("token").get()).isEqualTo(TOKEN);
+        assertThat(xmlDoc.getFromVersion("version").get()).isEqualTo("1");
         // Note "&amp;" in input XML are un-escaped to "&".
-        assertThat(xmlDoc.get("APPLICATION", "ServiceFlow_UserData", "ap2004").get())
+        assertThat(xmlDoc.getFromVowifi("ServiceFlow_UserData").get())
                 .isEqualTo("token=Y5vcmc%3D"
                         + "&entitlementStatus=0"
                         + "&protocol=TS43"
@@ -143,9 +221,9 @@
     public void parseAuthenticateResponse2() {
         XmlDoc xmlDoc = new XmlDoc(AUTH_RESPONSE_XML_2);
 
-        assertThat(xmlDoc.get("TOKEN", "token", "ap2004").get()).isEqualTo(TOKEN);
+        assertThat(xmlDoc.getFromToken("token").get()).isEqualTo(TOKEN);
         // Note the "&" in input XML is kept as is
-        assertThat(xmlDoc.get("APPLICATION", "ServiceFlow_UserData", "ap2004").get())
+        assertThat(xmlDoc.getFromVowifi("ServiceFlow_UserData").get())
                 .isEqualTo("PostData=U6%2FbQ%2BEP&req_locale=en_US");
     }
 
@@ -154,7 +232,7 @@
         XmlDoc xmlDoc = new XmlDoc(AUTH_RESPONSE_XML_3);
 
         // Note the "&amp;amp;" in input XML is un-escaped to "&amp;"
-        assertThat(xmlDoc.get("APPLICATION", "ServiceFlow_UserData", "ap2004").get())
+        assertThat(xmlDoc.getFromVowifi("ServiceFlow_UserData").get())
                 .isEqualTo("PostData=U6%2FbQ%2BEP&amp;l=en_US");
     }
 
@@ -162,25 +240,62 @@
     public void parseAuthenticateResponse4() {
         XmlDoc xmlDoc = new XmlDoc(AUTH_RESPONSE_XML_4);
 
-        assertThat(xmlDoc.get("APPLICATION", "ServiceFlow_URL", "ap2004").isPresent()).isFalse();
-        assertThat(
-                xmlDoc.get("APPLICATION", "ServiceFlow_UserData", "ap2004").isPresent()).isFalse();
+        assertThat(xmlDoc.getFromVowifi("ServiceFlow_URL").isPresent()).isFalse();
+        assertThat(xmlDoc.getFromVowifi("ServiceFlow_UserData").isPresent()).isFalse();
     }
 
     @Test
     public void parseAuthenticateResponse5() {
         XmlDoc xmlDoc = new XmlDoc(AUTH_RESPONSE_XML_5);
 
-        assertThat(xmlDoc.get("APPLICATION", "ServiceFlow_URL", "ap2004").isPresent()).isFalse();
-        assertThat(
-                xmlDoc.get("APPLICATION", "ServiceFlow_UserData", "ap2004").isPresent()).isTrue();
+        assertThat(xmlDoc.getFromVowifi("ServiceFlow_URL").isPresent()).isFalse();
+        assertThat(xmlDoc.getFromVowifi("ServiceFlow_UserData").isPresent()).isTrue();
     }
 
     @Test
     public void parseAuthenticateResponse6() {
         XmlDoc xmlDoc = new XmlDoc(AUTH_RESPONSE_XML_6);
 
-        assertThat(xmlDoc.get("APPLICATION", "EntitlementStatus", "ap2004").get()).isEqualTo("0");
-        assertThat(xmlDoc.get("APPLICATION", "EntitlementStatus", "ap2005").get()).isEqualTo("1");
+        assertThat(xmlDoc.getFromVowifi("EntitlementStatus").get()).isEqualTo("0");
+        assertThat(xmlDoc.getFromSmsoverip("EntitlementStatus").get()).isEqualTo("1");
+    }
+
+    @Test
+    public void parseAuthenticateResponse7() {
+        XmlDoc xmlDoc = new XmlDoc(AUTH_RESPONSE_XML_7);
+
+        assertThat(xmlDoc.getFromVonrHome("EntitlementStatus").get()).isEqualTo("1");
+        assertThat(xmlDoc.getFromVonrHome("NetworkVoiceIRATCapablity").get())
+                .isEqualTo("EPS-Fallback");
+        assertThat(xmlDoc.getFromVonrRoaming("EntitlementStatus").get()).isEqualTo("2");
+        assertThat(xmlDoc.getFromVonrRoaming("NetworkVoiceIRATCapablity").isPresent()).isFalse();
+    }
+
+    @Test
+    public void parseAuthenticateResponse8() {
+        XmlDoc xmlDoc = new XmlDoc(AUTH_RESPONSE_XML_8);
+
+        assertThat(xmlDoc.getFromVolte("EntitlementStatus").get()).isEqualTo("1");
+        assertThat(xmlDoc.getFromVonrHome("EntitlementStatus").get()).isEqualTo("1");
+        assertThat(xmlDoc.getFromVonrHome("NetworkVoiceIRATCapablity").get())
+                .isEqualTo("EPS-Fallback");
+        assertThat(xmlDoc.getFromVonrRoaming("EntitlementStatus").get()).isEqualTo("1");
+        assertThat(xmlDoc.getFromVonrRoaming("NetworkVoiceIRATCapablity").get())
+                .isEqualTo("EPS-Fallback");
+    }
+
+    @Test
+    public void parseAuthenticateResponse9() {
+        XmlDoc xmlDoc = new XmlDoc(AUTH_RESPONSE_XML_9);
+
+        assertThat(xmlDoc.getFromVolte("EntitlementStatus").get()).isEqualTo("1");
+    }
+
+    @Test
+    public void parseAuthenticateResponse10() {
+        XmlDoc xmlDoc = new XmlDoc(AUTH_RESPONSE_XML_10);
+
+        assertThat(xmlDoc.getFromVonrHome("EntitlementStatus").get()).isEqualTo("1");
+        assertThat(xmlDoc.getFromVonrRoaming("EntitlementStatus").isPresent()).isFalse();
     }
 }