Merge "Add the niddApn to ProvisionSubscriberId" into main
diff --git a/flags/misc.aconfig b/flags/misc.aconfig
index 9d5cbd6..538a114 100644
--- a/flags/misc.aconfig
+++ b/flags/misc.aconfig
@@ -217,3 +217,25 @@
         purpose: PURPOSE_BUGFIX
     }
 }
+
+# OWNER=rambowang TARGET=24Q4
+flag {
+    name: "support_phone_uid_check_for_multiuser"
+    namespace: "telephony"
+    description: "Check phone/system processes from UID with multiuser-aware way"
+    bug:"328511085"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
+
+# OWNER=joonhunshin TARGET=24Q4
+flag {
+    name: "use_carrier_config_for_cfnry_time_via_mmi"
+    namespace: "telephony"
+    description: "This flag allows the no reply timer to be referenced in the carrier config when setting up call forward via MMI code and there is no timer value."
+    bug:"342346827"
+    metadata {
+        purpose: PURPOSE_BUGFIX
+    }
+}
diff --git a/proto/Android.bp b/proto/Android.bp
index 15c0aea..adc9b5e 100644
--- a/proto/Android.bp
+++ b/proto/Android.bp
@@ -31,3 +31,12 @@
     // Pin java_version until jarjar is certified to support later versions. http://b/72703434
     java_version: "1.8",
 }
+
+java_library_static {
+    name: "telephony-config-update-proto-lite",
+    proto: {
+        type: "lite",
+    },
+    srcs: ["src/**/telephony_config_update.proto"],
+    host_supported: true,
+}
diff --git a/src/java/com/android/internal/telephony/RadioSimProxy.java b/src/java/com/android/internal/telephony/RadioSimProxy.java
index 5265692..9bf9a50 100644
--- a/src/java/com/android/internal/telephony/RadioSimProxy.java
+++ b/src/java/com/android/internal/telephony/RadioSimProxy.java
@@ -530,6 +530,7 @@
             carrierRestrictions.allowedCarriersPrioritized =
                     (carrierRestrictionRules.getDefaultCarrierRestriction()
                             == CarrierRestrictionRules.CARRIER_RESTRICTION_DEFAULT_NOT_ALLOWED);
+            carrierRestrictions.status = carrierRestrictionRules.getCarrierRestrictionStatus();
             mSimProxy.setAllowedCarriers(serial, carrierRestrictions,
                     RILUtils.convertToHalSimLockMultiSimPolicyAidl(
                             carrierRestrictionRules.getMultiSimPolicy()));
diff --git a/src/java/com/android/internal/telephony/data/DataConfigManager.java b/src/java/com/android/internal/telephony/data/DataConfigManager.java
index 20761e2..9f4fa11 100644
--- a/src/java/com/android/internal/telephony/data/DataConfigManager.java
+++ b/src/java/com/android/internal/telephony/data/DataConfigManager.java
@@ -1503,6 +1503,14 @@
     }
 
     /**
+     * {@code True} enables mms to be attempted on iwlan if possible, even if existing cellular
+     *  networks already supports iwlan.
+     */
+    public boolean isForceIwlanMmsFeatureEnabled() {
+        return mResources.getBoolean(com.android.internal.R.bool.force_iwlan_mms_feature_enabled);
+    }
+
+    /**
      * Log debug messages.
      * @param s debug messages
      */
diff --git a/src/java/com/android/internal/telephony/data/DataNetwork.java b/src/java/com/android/internal/telephony/data/DataNetwork.java
index eaa0962..f47abfc 100644
--- a/src/java/com/android/internal/telephony/data/DataNetwork.java
+++ b/src/java/com/android/internal/telephony/data/DataNetwork.java
@@ -1266,7 +1266,7 @@
                         getHandler(), EVENT_VOICE_CALL_ENDED, null);
             }
 
-            if (mFlags.forceIwlanMms()) {
+            if (mFlags.forceIwlanMms() && mDataConfigManager.isForceIwlanMmsFeatureEnabled()) {
                 if (mDataProfile.canSatisfy(NetworkCapabilities.NET_CAPABILITY_MMS)) {
                     mAccessNetworksManagerCallback = new AccessNetworksManagerCallback(
                             getHandler()::post) {
@@ -1292,7 +1292,8 @@
         @Override
         public void exit() {
             logv("Unregistering all events.");
-            if (mFlags.forceIwlanMms() && mAccessNetworksManagerCallback != null) {
+            if (mFlags.forceIwlanMms() && mAccessNetworksManagerCallback != null
+                    && mDataConfigManager.isForceIwlanMmsFeatureEnabled()) {
                 mAccessNetworksManager.unregisterCallback(mAccessNetworksManagerCallback);
             }
 
@@ -2491,7 +2492,8 @@
         // will be attempted on IWLAN if possible, even if existing cellular networks already
         // supports IWLAN.
         if (mFlags.forceIwlanMms() && builder.build()
-                .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)) {
+                .hasCapability(NetworkCapabilities.NET_CAPABILITY_MMS)
+                && mDataConfigManager.isForceIwlanMmsFeatureEnabled()) {
             // If QNS sets MMS preferred on IWLAN, and it is possible to setup an MMS network on
             // IWLAN, then we need to remove the MMS capability on the cellular network. This will
             // allow the new MMS network to be brought up on IWLAN when MMS network request arrives.
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
index 10cbe77..cb188ea 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhone.java
@@ -1016,8 +1016,8 @@
 
         // Only look at the Network portion for mmi
         String networkPortion = PhoneNumberUtils.extractNetworkPortionAlt(newDialString);
-        ImsPhoneMmiCode mmi =
-                ImsPhoneMmiCode.newFromDialString(networkPortion, this, wrappedCallback);
+        ImsPhoneMmiCode mmi =  ImsPhoneMmiCode.newFromDialString(networkPortion, this,
+                wrappedCallback, mFeatureFlags);
         if (DBG) logd("dialInternal: dialing w/ mmi '" + mmi + "'...");
 
         if (mmi == null) {
@@ -1440,12 +1440,13 @@
     }
 
     @Override
-    public void sendUssdResponse(String ussdMessge) {
+    public void sendUssdResponse(String ussdMessage) {
         logd("sendUssdResponse");
-        ImsPhoneMmiCode mmi = ImsPhoneMmiCode.newFromUssdUserInput(ussdMessge, this);
+        ImsPhoneMmiCode mmi = ImsPhoneMmiCode.newFromUssdUserInput(ussdMessage, this,
+                mFeatureFlags);
         mPendingMMIs.add(mmi);
         mMmiRegistrants.notifyRegistrants(new AsyncResult(null, mmi, null));
-        mmi.sendUssd(ussdMessge);
+        mmi.sendUssd(ussdMessage);
     }
 
     public void sendUSSD(String ussdString, Message response) {
@@ -1575,14 +1576,12 @@
                 // also, discard if there is no message to present
                 ImsPhoneMmiCode mmi;
                 mmi = ImsPhoneMmiCode.newNetworkInitiatedUssd(ussdMessage,
-                        isUssdRequest,
-                        this);
+                        isUssdRequest, this, mFeatureFlags);
                 onNetworkInitiatedUssd(mmi);
         } else if (isUssdError) {
             ImsPhoneMmiCode mmi;
             mmi = ImsPhoneMmiCode.newNetworkInitiatedUssd(ussdMessage,
-                    true,
-                    this);
+                    true, this, mFeatureFlags);
             mmi.onUssdFinishedError();
         }
     }
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
index 7fd970b..b2966b6 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneCallTracker.java
@@ -4959,7 +4959,7 @@
             }
             case EVENT_SUPP_SERVICE_INDICATION: {
                 ar = (AsyncResult) msg.obj;
-                ImsPhoneMmiCode mmiCode = new ImsPhoneMmiCode(mPhone);
+                ImsPhoneMmiCode mmiCode = new ImsPhoneMmiCode(mPhone, mFeatureFlags);
                 try {
                     mmiCode.setIsSsInfo(true);
                     mmiCode.processImsSsData(ar);
diff --git a/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java b/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
index 25fa8a2..d573f5d 100644
--- a/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
+++ b/src/java/com/android/internal/telephony/imsphone/ImsPhoneMmiCode.java
@@ -63,6 +63,7 @@
 import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.MmiCode;
 import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.gsm.GsmMmiCode;
 import com.android.internal.telephony.uicc.IccRecords;
 import com.android.telephony.Rlog;
@@ -165,6 +166,9 @@
     private static final int NUM_PRESENTATION_ALLOWED     = 0;
     private static final int NUM_PRESENTATION_RESTRICTED  = 1;
 
+    // Using same value with CallForwardEditPreference#DEFAULT_NO_REPLY_TIMER_FOR_CFNRY
+    private static final int DEFAULT_NO_REPLY_TIMER_FOR_CFNRY = 20;
+
     //***** Supplementary Service Query Bundle Keys
     // Used by IMS Service layer to put supp. serv. query
     // responses into the ssInfo Bundle.
@@ -245,6 +249,8 @@
     private static final int MATCH_GROUP_DIALING_NUMBER = 12;
     static private String[] sTwoDigitNumberPattern;
 
+    private final FeatureFlags mFeatureFlags;
+
     //***** Public Class methods
 
     /**
@@ -262,12 +268,13 @@
 
     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
     @VisibleForTesting
-    public static ImsPhoneMmiCode newFromDialString(String dialString, ImsPhone phone) {
-       return newFromDialString(dialString, phone, null);
+    public static ImsPhoneMmiCode newFromDialString(String dialString, ImsPhone phone,
+            FeatureFlags featureFlags) {
+        return newFromDialString(dialString, phone, null, featureFlags);
     }
 
-    static ImsPhoneMmiCode newFromDialString(String dialString,
-                                             ImsPhone phone, ResultReceiver wrappedCallback) {
+    static ImsPhoneMmiCode newFromDialString(String dialString, ImsPhone phone,
+            ResultReceiver wrappedCallback, FeatureFlags featureFlags) {
         Matcher m;
         ImsPhoneMmiCode ret = null;
 
@@ -287,7 +294,7 @@
 
         // Is this formatted like a standard supplementary service code?
         if (m.matches()) {
-            ret = new ImsPhoneMmiCode(phone);
+            ret = new ImsPhoneMmiCode(phone, featureFlags);
             ret.mPoundString = makeEmptyNull(m.group(MATCH_GROUP_POUND_STRING));
             ret.mAction = makeEmptyNull(m.group(MATCH_GROUP_ACTION));
             ret.mSc = makeEmptyNull(m.group(MATCH_GROUP_SERVICE_CODE));
@@ -305,7 +312,7 @@
             if (ret.mDialingNumber != null &&
                     ret.mDialingNumber.endsWith("#") &&
                     dialString.endsWith("#")){
-                ret = new ImsPhoneMmiCode(phone);
+                ret = new ImsPhoneMmiCode(phone, featureFlags);
                 ret.mPoundString = dialString;
             }
         } else if (dialString.endsWith("#")) {
@@ -313,7 +320,7 @@
             // "Entry of any characters defined in the 3GPP TS 23.038 [8] Default Alphabet
             // (up to the maximum defined in 3GPP TS 24.080 [10]), followed by #SEND".
 
-            ret = new ImsPhoneMmiCode(phone);
+            ret = new ImsPhoneMmiCode(phone, featureFlags);
             ret.mPoundString = dialString;
         } else if (GsmMmiCode.isTwoDigitShortCode(phone.getContext(), phone.getSubId(),
                 dialString)) {
@@ -321,7 +328,7 @@
             ret = null;
         } else if (isShortCode(dialString, phone)) {
             // this may be a short code, as defined in TS 22.030, 6.5.3.2
-            ret = new ImsPhoneMmiCode(phone);
+            ret = new ImsPhoneMmiCode(phone, featureFlags);
             ret.mDialingNumber = dialString;
         }
         return ret;
@@ -348,10 +355,10 @@
     }
 
     public static ImsPhoneMmiCode newNetworkInitiatedUssd(String ussdMessage,
-            boolean isUssdRequest, ImsPhone phone) {
+            boolean isUssdRequest, ImsPhone phone, FeatureFlags featureFlags) {
         ImsPhoneMmiCode ret;
 
-        ret = new ImsPhoneMmiCode(phone);
+        ret = new ImsPhoneMmiCode(phone, featureFlags);
 
         ret.mMessage = ussdMessage;
         ret.mIsUssdRequest = isUssdRequest;
@@ -368,10 +375,11 @@
         return ret;
     }
 
-    static ImsPhoneMmiCode newFromUssdUserInput(String ussdMessge, ImsPhone phone) {
-        ImsPhoneMmiCode ret = new ImsPhoneMmiCode(phone);
+    static ImsPhoneMmiCode newFromUssdUserInput(String ussdMessage, ImsPhone phone,
+            FeatureFlags featureFlags) {
+        ImsPhoneMmiCode ret = new ImsPhoneMmiCode(phone, featureFlags);
 
-        ret.mMessage = ussdMessge;
+        ret.mMessage = ussdMessage;
         ret.mState = State.PENDING;
         ret.mIsPendingUSSD = true;
 
@@ -584,13 +592,15 @@
 
     //***** Constructor
 
-    public ImsPhoneMmiCode(ImsPhone phone) {
+    public ImsPhoneMmiCode(ImsPhone phone, FeatureFlags featureFlags) {
         // The telephony unit-test cases may create ImsPhoneMmiCode's
         // in secondary threads
         super(phone.getHandler().getLooper());
         mPhone = phone;
         mContext = phone.getContext();
         mIccRecords = mPhone.mDefaultPhone.getIccRecords();
+
+        mFeatureFlags = featureFlags;
     }
 
     //***** MmiCode implementation
@@ -907,7 +917,19 @@
                 String dialingNumber = mSia;
                 int reason = scToCallForwardReason(mSc);
                 int serviceClass = siToServiceClass(mSib);
-                int time = siToTime(mSic);
+                int time;
+
+                if (mFeatureFlags.useCarrierConfigForCfnryTimeViaMmi()) {
+                    // If the code is CFNRy and time is null(empty)
+                    // use the default time value from CarrierConfig
+                    if (mSc.equals(SC_CFNRy) && isEmptyOrNull(mSic)) {
+                        time = getCfnryTime();
+                    } else {
+                        time = siToTime(mSic);
+                    }
+                } else {
+                    time = siToTime(mSic);
+                }
 
                 if (isInterrogate()) {
                     mPhone.getCallForwardingOption(reason, serviceClass,
@@ -1147,6 +1169,27 @@
         }
     }
 
+    private int getCfnryTime() {
+        CarrierConfigManager configManager = mContext.getSystemService(CarrierConfigManager.class);
+        if (configManager == null) {
+            return DEFAULT_NO_REPLY_TIMER_FOR_CFNRY;
+        }
+
+        PersistableBundle carrierConfig = configManager.getConfigForSubId(mPhone.getSubId());
+        if (carrierConfig == null
+                || !carrierConfig.getBoolean(
+                        CarrierConfigManager.KEY_SUPPORT_NO_REPLY_TIMER_FOR_CFNRY_BOOL, true)) {
+            return DEFAULT_NO_REPLY_TIMER_FOR_CFNRY;
+        }
+
+        int time = carrierConfig.getInt(
+                CarrierConfigManager.KEY_NO_REPLY_TIMER_FOR_CFNRY_SEC_INT,
+                DEFAULT_NO_REPLY_TIMER_FOR_CFNRY);
+
+        Rlog.d(LOG_TAG, "getCfnryTime: " + time);
+        return time;
+    }
+
     private boolean isUssdOverImsAllowed() {
         if (mContext.getResources().getBoolean(
                 com.android.internal.R.bool.config_allow_ussd_over_ims)) {
diff --git a/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java b/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
index d4717dd..3b4f869 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/TelephonyPermissionsTest.java
@@ -37,9 +37,11 @@
 import android.os.Build;
 import android.os.Bundle;
 import android.os.IBinder;
+import android.os.Process;
 import android.os.ServiceManager;
 import android.os.UserHandle;
 import android.permission.LegacyPermissionManager;
+import android.platform.test.flag.junit.SetFlagsRule;
 import android.provider.DeviceConfig;
 import android.provider.Settings;
 import android.telephony.SubscriptionManager;
@@ -50,11 +52,13 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.telephony.flags.FeatureFlags;
+import com.android.internal.telephony.flags.Flags;
 import com.android.internal.util.test.FakeSettingsProvider;
 import com.android.server.pm.permission.LegacyPermissionManagerService;
 
 import org.junit.After;
 import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
 
 import java.lang.reflect.Field;
@@ -71,6 +75,9 @@
     private static final String FEATURE = "com.example.feature";
     private static final String MSG = "message";
 
+    @Rule
+    public final SetFlagsRule mSetFlagsRule = new SetFlagsRule();
+
     // Mocked classes
     private Context mMockContext;
     private AppOpsManager mMockAppOps;
@@ -90,6 +97,7 @@
 
     @Before
     public void setUp() throws Exception {
+        mSetFlagsRule.enableFlags(Flags.FLAG_SUPPORT_PHONE_UID_CHECK_FOR_MULTIUSER);
         mMockContext = mock(Context.class);
         mMockAppOps = mock(AppOpsManager.class);
         mMockSubscriptionManager = mock(SubscriptionManager.class);
@@ -558,6 +566,38 @@
                 UserHandle.SYSTEM));
     }
 
+    @Test
+    public void testIsSystemOrPhone_systemUser() {
+        assertTrue(TelephonyPermissions.isSystemOrPhone(Process.SYSTEM_UID));
+        assertTrue(TelephonyPermissions.isSystemOrPhone(Process.PHONE_UID));
+
+        assertFalse(TelephonyPermissions.isSystemOrPhone(1002));
+    }
+
+    @Test
+    public void testIsSystemOrPhone_nonSystemUser() {
+        assertTrue(TelephonyPermissions.isSystemOrPhone(1001000));
+        assertTrue(TelephonyPermissions.isSystemOrPhone(1001001));
+
+        assertFalse(TelephonyPermissions.isSystemOrPhone(1001002));
+    }
+
+    @Test
+    public void testIsRootOrShell_systemUser() {
+        assertTrue(TelephonyPermissions.isRootOrShell(Process.ROOT_UID));
+        assertTrue(TelephonyPermissions.isRootOrShell(Process.SHELL_UID));
+
+        assertFalse(TelephonyPermissions.isRootOrShell(1002));
+    }
+
+    @Test
+    public void testIsRootOrShell_nonSystemUser() {
+        assertTrue(TelephonyPermissions.isRootOrShell(1000000));
+        assertTrue(TelephonyPermissions.isRootOrShell(1002000));
+
+        assertFalse(TelephonyPermissions.isRootOrShell(1001002));
+    }
+
     // Put mMockTelephony into service cache so that TELEPHONY_SUPPLIER will get it.
     private void setTelephonyMockAsService() throws Exception {
         when(mMockTelephonyBinder.queryLocalInterface(anyString())).thenReturn(mMockTelephony);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
index 8be0f8b..1a5c1af 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/data/DataNetworkTest.java
@@ -2419,6 +2419,7 @@
     @Test
     public void testMmsCapabilityRemovedWhenMmsPreferredOnIwlan() throws Exception {
         doReturn(true).when(mFeatureFlags).forceIwlanMms();
+        doReturn(true).when(mDataConfigManager).isForceIwlanMmsFeatureEnabled();
         setupDataNetwork();
 
         TelephonyNetworkAgent mockNetworkAgent = Mockito.mock(TelephonyNetworkAgent.class);
diff --git a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java
index 3c1b045..6f42350 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/imsphone/ImsPhoneMmiCodeTest.java
@@ -19,10 +19,13 @@
 import static junit.framework.Assert.fail;
 
 import static org.junit.Assert.assertTrue;
+import static org.mockito.ArgumentMatchers.any;
 import static org.mockito.ArgumentMatchers.anyInt;
 import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.doNothing;
 import static org.mockito.Mockito.doReturn;
 import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.times;
 import static org.mockito.Mockito.verify;
 
 import android.os.AsyncResult;
@@ -35,6 +38,7 @@
 import androidx.test.filters.SmallTest;
 
 import com.android.internal.telephony.CommandException;
+import com.android.internal.telephony.CommandsInterface;
 import com.android.internal.telephony.TelephonyTest;
 import com.android.internal.telephony.flags.FeatureFlags;
 
@@ -54,6 +58,9 @@
     private static final String TEST_DIAL_STRING_SERVICE_CODE = "*67911";
     private static final String TEST_DIAL_STRING_NO_SERVICE_CODE = "*767911";
     private static final String TEST_DIAL_STRING_NON_EMERGENCY_NUMBER = "11976";
+    private static final String TEST_DIAL_NUMBER = "123456789";
+    private static final String TEST_DIAL_STRING_CFNRY_ACTIVE_CODE = "**61*" + TEST_DIAL_NUMBER;
+    private static final String TEST_DIAL_STRING_CFNRY_DEACTIVE_CODE = "##61#";
     private ImsPhoneMmiCode mImsPhoneMmiCode;
     private ImsPhone mImsPhoneUT;
 
@@ -90,7 +97,7 @@
         // Test *67911 is treated as temporary mode CLIR
         doReturn(true).when(mTelephonyManager).isEmergencyNumber(TEST_DIAL_STRING_SERVICE_CODE);
         mImsPhoneMmiCode = ImsPhoneMmiCode.newFromDialString(TEST_DIAL_STRING_SERVICE_CODE,
-                mImsPhoneUT);
+                mImsPhoneUT, mFeatureFlags);
         assertTrue(mImsPhoneMmiCode.isTemporaryModeCLIR());
     }
 
@@ -99,7 +106,7 @@
         // Test if prefix isn't *67 or *82
         doReturn(true).when(mTelephonyManager).isEmergencyNumber(TEST_DIAL_STRING_NO_SERVICE_CODE);
         mImsPhoneMmiCode = ImsPhoneMmiCode.newFromDialString(TEST_DIAL_STRING_NO_SERVICE_CODE,
-                mImsPhoneUT);
+                mImsPhoneUT, mFeatureFlags);
         assertTrue(mImsPhoneMmiCode == null);
     }
 
@@ -107,13 +114,14 @@
     public void testIsTemporaryModeCLIRForNonEmergencyNumber() {
         // Test if dialing string isn't an emergency number
         mImsPhoneMmiCode = ImsPhoneMmiCode.newFromDialString(TEST_DIAL_STRING_NON_EMERGENCY_NUMBER,
-                mImsPhoneUT);
+                mImsPhoneUT, mFeatureFlags);
         assertTrue(mImsPhoneMmiCode == null);
     }
 
     @Test
     public void testNoCrashOnEmptyMessage() {
-        ImsPhoneMmiCode mmi = ImsPhoneMmiCode.newNetworkInitiatedUssd(null, true, mImsPhoneUT);
+        ImsPhoneMmiCode mmi = ImsPhoneMmiCode.newNetworkInitiatedUssd(null, true, mImsPhoneUT,
+                mFeatureFlags);
         try {
             mmi.onUssdFinishedError();
         } catch (Exception e) {
@@ -134,7 +142,8 @@
     @Test
     @SmallTest
     public void testOperationNotSupported() {
-        mImsPhoneMmiCode = ImsPhoneMmiCode.newNetworkInitiatedUssd(null, true, mImsPhoneUT);
+        mImsPhoneMmiCode = ImsPhoneMmiCode.newNetworkInitiatedUssd(null, true, mImsPhoneUT,
+                mFeatureFlags);
 
         // Emulate request not supported from the network.
         AsyncResult ar = new AsyncResult(null, null,
@@ -143,4 +152,80 @@
         verify(mContext.getResources()).getText(
                 eq(com.android.internal.R.string.mmiErrorNotSupported));
     }
+
+    @Test
+    @SmallTest
+    public void testActivationCfnrWithCfnry() throws Exception {
+        doNothing().when(mImsPhone).setCallForwardingOption(
+                anyInt(), anyInt(), any(), anyInt(), anyInt(), any());
+
+        doReturn(true).when(mFeatureFlags).useCarrierConfigForCfnryTimeViaMmi();
+
+        int carrierConfigTime = 40;
+        PersistableBundle bundle = new PersistableBundle();
+        bundle.putInt(CarrierConfigManager
+                .KEY_NO_REPLY_TIMER_FOR_CFNRY_SEC_INT, carrierConfigTime);
+        doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
+
+        int mmiTime = 30;
+        String withoutTimeCode = TEST_DIAL_STRING_CFNRY_ACTIVE_CODE + "#";
+        String withTimeCode = TEST_DIAL_STRING_CFNRY_ACTIVE_CODE + "**" + mmiTime + "#";
+
+        mImsPhoneMmiCode = ImsPhoneMmiCode.newFromDialString(withoutTimeCode, mImsPhoneUT,
+                mFeatureFlags);
+        // For verification, replace the internal object of target with mock
+        replaceInstance(ImsPhoneMmiCode.class, "mPhone", mImsPhoneMmiCode, mImsPhone);
+
+        mImsPhoneMmiCode.processCode();
+        verify(mImsPhone, times(1)).setCallForwardingOption(
+                eq(CommandsInterface.CF_ACTION_REGISTRATION),
+                anyInt(),
+                eq(TEST_DIAL_NUMBER),
+                anyInt(),
+                eq(carrierConfigTime),
+                any());
+
+        mImsPhoneMmiCode = ImsPhoneMmiCode.newFromDialString(withTimeCode, mImsPhoneUT,
+                mFeatureFlags);
+        // For verification, replace the internal object of target with mock
+        replaceInstance(ImsPhoneMmiCode.class, "mPhone", mImsPhoneMmiCode, mImsPhone);
+
+        mImsPhoneMmiCode.processCode();
+        verify(mImsPhone, times(1)).setCallForwardingOption(
+                eq(CommandsInterface.CF_ACTION_REGISTRATION),
+                anyInt(),
+                eq(TEST_DIAL_NUMBER),
+                anyInt(),
+                eq(mmiTime),
+                any());
+    }
+
+    @Test
+    @SmallTest
+    public void testDeactivationCfnrWithCfnry() throws Exception {
+        doNothing().when(mImsPhone).setCallForwardingOption(
+                anyInt(), anyInt(), any(), anyInt(), anyInt(), any());
+
+        doReturn(true).when(mFeatureFlags).useCarrierConfigForCfnryTimeViaMmi();
+
+        int carrierConfigTime = 40;
+        PersistableBundle bundle = new PersistableBundle();
+        bundle.putInt(CarrierConfigManager
+                .KEY_NO_REPLY_TIMER_FOR_CFNRY_SEC_INT, carrierConfigTime);
+        doReturn(bundle).when(mCarrierConfigManager).getConfigForSubId(anyInt());
+
+        mImsPhoneMmiCode = ImsPhoneMmiCode.newFromDialString(TEST_DIAL_STRING_CFNRY_DEACTIVE_CODE,
+                mImsPhoneUT, mFeatureFlags);
+        // For verification, replace the internal object of target with mock
+        replaceInstance(ImsPhoneMmiCode.class, "mPhone", mImsPhoneMmiCode, mImsPhone);
+
+        mImsPhoneMmiCode.processCode();
+        verify(mImsPhone, times(1)).setCallForwardingOption(
+                eq(CommandsInterface.CF_ACTION_ERASURE),
+                anyInt(),
+                eq(null),
+                anyInt(),
+                eq(carrierConfigTime),
+                any());
+    }
 }