Add vonr_enabled to voice call metric

vonr_enabled help us to identify VoNR and EPSFB calls.

Bug: 288449751
Test: m, atest VoiceCallSessionStatsTest and  maunal test

Change-Id: I5375a64ba6e3f36d9e618dbef7198b5fcf40a395
diff --git a/flags/data.aconfig b/flags/data.aconfig
index 152660b..267048e 100644
--- a/flags/data.aconfig
+++ b/flags/data.aconfig
@@ -83,3 +83,10 @@
   description: "notify data activity changed for slot id"
   bug: "309896936"
 }
+
+flag {
+  name: "vonr_enabled_metric"
+  namespace: "telephony"
+  description: "Collect vonr status in voice call metric"
+  bug:"288449751"
+}
diff --git a/proto/src/persist_atoms.proto b/proto/src/persist_atoms.proto
index 6d1008b..d7a6062 100644
--- a/proto/src/persist_atoms.proto
+++ b/proto/src/persist_atoms.proto
@@ -280,6 +280,7 @@
     optional bool is_iwlan_cross_sim_at_start = 37;
     optional bool is_iwlan_cross_sim_at_end = 38;
     optional bool is_iwlan_cross_sim_at_connected = 39;
+    optional bool vonr_enabled = 40;
 
     // Internal use only
     optional int64 setup_begin_millis = 10001;
diff --git a/src/java/com/android/internal/telephony/GsmCdmaPhone.java b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
index 3ef7164..6fd13fb 100644
--- a/src/java/com/android/internal/telephony/GsmCdmaPhone.java
+++ b/src/java/com/android/internal/telephony/GsmCdmaPhone.java
@@ -341,7 +341,7 @@
 
         // phone type needs to be set before other initialization as other objects rely on it
         mPrecisePhoneType = precisePhoneType;
-        mVoiceCallSessionStats = new VoiceCallSessionStats(mPhoneId, this);
+        mVoiceCallSessionStats = new VoiceCallSessionStats(mPhoneId, this, featureFlags);
         mImsManagerFactory = imsManagerFactory;
         initOnce(ci);
         initRatSpecific(precisePhoneType);
diff --git a/src/java/com/android/internal/telephony/PhoneFactory.java b/src/java/com/android/internal/telephony/PhoneFactory.java
index 0cbc035..d29eed1 100644
--- a/src/java/com/android/internal/telephony/PhoneFactory.java
+++ b/src/java/com/android/internal/telephony/PhoneFactory.java
@@ -161,7 +161,7 @@
                 }
 
                 // register statsd pullers.
-                sMetricsCollector = new MetricsCollector(context);
+                sMetricsCollector = new MetricsCollector(context, sFeatureFlags);
 
                 sPhoneNotifier = new DefaultPhoneNotifier(context, featureFlags);
 
diff --git a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
index 9866c74..21b2cea 100644
--- a/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
+++ b/src/java/com/android/internal/telephony/metrics/MetricsCollector.java
@@ -54,6 +54,7 @@
 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION;
 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN;
 
+import android.annotation.NonNull;
 import android.app.StatsManager;
 import android.content.Context;
 import android.telephony.SubscriptionManager;
@@ -65,6 +66,7 @@
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.TelephonyStatsLog;
 import com.android.internal.telephony.emergency.EmergencyNumberTracker;
+import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.imsphone.ImsPhone;
 import com.android.internal.telephony.nano.PersistAtomsProto.CellularDataServiceSwitch;
 import com.android.internal.telephony.nano.PersistAtomsProto.CellularServiceState;
@@ -149,21 +151,25 @@
     private final PersistAtomsStorage mStorage;
     private final DeviceStateHelper mDeviceStateHelper;
     private final StatsManager mStatsManager;
+    private final VonrHelper mVonrHelper;
     private final AirplaneModeStats mAirplaneModeStats;
     private final Set<DataCallSessionStats> mOngoingDataCallStats = ConcurrentHashMap.newKeySet();
     private static final Random sRandom = new Random();
 
-    public MetricsCollector(Context context) {
-        this(context, new PersistAtomsStorage(context), new DeviceStateHelper(context));
+    public MetricsCollector(Context context, @NonNull FeatureFlags featureFlags) {
+        this(context, new PersistAtomsStorage(context),
+                new DeviceStateHelper(context), new VonrHelper(featureFlags));
     }
 
     /** Allows dependency injection. Used during unit tests. */
     @VisibleForTesting
     public MetricsCollector(
-            Context context, PersistAtomsStorage storage, DeviceStateHelper deviceStateHelper) {
+            Context context, PersistAtomsStorage storage, DeviceStateHelper deviceStateHelper,
+                    VonrHelper vonrHelper) {
         mStorage = storage;
         mDeviceStateHelper = deviceStateHelper;
         mStatsManager = (StatsManager) context.getSystemService(Context.STATS_MANAGER);
+        mVonrHelper = vonrHelper;
         if (mStatsManager != null) {
             // Most (but not all) of these are subject to cooldown specified by MIN_COOLDOWN_MILLIS.
             registerAtom(CELLULAR_DATA_SERVICE_SWITCH);
@@ -308,6 +314,11 @@
         return mDeviceStateHelper;
     }
 
+    /** Returns the {@link VonrHelper}. */
+    public VonrHelper getVonrHelper() {
+        return mVonrHelper;
+    }
+
     /** Updates duration segments and calls {@link PersistAtomsStorage#flushAtoms()}. */
     public void flushAtomsStorage() {
         concludeAll();
@@ -993,7 +1004,9 @@
                 session.handoverInProgress,
                 session.isIwlanCrossSimAtStart,
                 session.isIwlanCrossSimAtEnd,
-                session.isIwlanCrossSimAtConnected);
+                session.isIwlanCrossSimAtConnected,
+                session.vonrEnabled);
+
     }
 
     private static StatsEvent buildStatsEvent(IncomingSms sms) {
diff --git a/src/java/com/android/internal/telephony/metrics/PerSimStatus.java b/src/java/com/android/internal/telephony/metrics/PerSimStatus.java
index a8c7421..70ff491 100644
--- a/src/java/com/android/internal/telephony/metrics/PerSimStatus.java
+++ b/src/java/com/android/internal/telephony/metrics/PerSimStatus.java
@@ -303,7 +303,7 @@
     }
 
     /** Returns true if VoNR is enabled */
-    private static boolean isVonrEnabled(Phone phone) {
+    static boolean isVonrEnabled(Phone phone) {
         TelephonyManager telephonyManager =
                 phone.getContext()
                         .getSystemService(TelephonyManager.class);
diff --git a/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java b/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java
index 5dbf645..9cf53c9 100644
--- a/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java
+++ b/src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java
@@ -36,6 +36,7 @@
 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__SIGNAL_STRENGTH_AT_END__SIGNAL_STRENGTH_GREAT;
 import static com.android.internal.telephony.TelephonyStatsLog.VOICE_CALL_SESSION__SIGNAL_STRENGTH_AT_END__SIGNAL_STRENGTH_NONE_OR_UNKNOWN;
 
+import android.annotation.NonNull;
 import android.annotation.Nullable;
 import android.content.Context;
 import android.net.wifi.WifiInfo;
@@ -69,6 +70,7 @@
 import com.android.internal.telephony.ServiceStateTracker;
 import com.android.internal.telephony.analytics.TelephonyAnalytics;
 import com.android.internal.telephony.analytics.TelephonyAnalytics.CallAnalytics;
+import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.imsphone.ImsPhone;
 import com.android.internal.telephony.imsphone.ImsPhoneConnection;
 import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallSession;
@@ -156,6 +158,7 @@
      */
     private final VoiceCallRatTracker mRatUsage = new VoiceCallRatTracker();
 
+    private final @NonNull FeatureFlags mFlags;
     private final int mPhoneId;
     private final Phone mPhone;
 
@@ -165,10 +168,13 @@
     private final DeviceStateHelper mDeviceStateHelper =
             PhoneFactory.getMetricsCollector().getDeviceStateHelper();
 
-    public VoiceCallSessionStats(int phoneId, Phone phone) {
+    private final VonrHelper mVonrHelper =
+            PhoneFactory.getMetricsCollector().getVonrHelper();
+
+    public VoiceCallSessionStats(int phoneId, Phone phone, @NonNull FeatureFlags featureFlags) {
         mPhoneId = phoneId;
         mPhone = phone;
-
+        mFlags = featureFlags;
         DataConnectionStateTracker.getInstance(phoneId).start(phone);
     }
 
@@ -457,6 +463,10 @@
         @VideoState int videoState = conn.getVideoState();
         VoiceCallSession proto = new VoiceCallSession();
 
+        if (mFlags.vonrEnabledMetric()) {
+            mVonrHelper.updateVonrEnabledState();
+        }
+
         proto.bearerAtStart = bearer;
         proto.bearerAtEnd = bearer;
         proto.direction = getDirection(conn);
@@ -556,6 +566,10 @@
         // Set device fold state
         proto.foldState = mDeviceStateHelper.getFoldState();
 
+        if (mFlags.vonrEnabledMetric()) {
+            proto.vonrEnabled = mVonrHelper.getVonrEnabled(mPhone.getSubId());
+        }
+
         mAtomsStorage.addVoiceCallSession(proto);
 
         // merge RAT usages to PersistPullers when the call session ends (i.e. no more active calls)
diff --git a/src/java/com/android/internal/telephony/metrics/VonrHelper.java b/src/java/com/android/internal/telephony/metrics/VonrHelper.java
new file mode 100644
index 0000000..8f14a86
--- /dev/null
+++ b/src/java/com/android/internal/telephony/metrics/VonrHelper.java
@@ -0,0 +1,80 @@
+/*
+ * 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.internal.telephony.metrics;
+
+import static com.android.internal.telephony.metrics.MetricsCollector.getPhonesIfAny;
+import static com.android.internal.telephony.metrics.PerSimStatus.isVonrEnabled;
+
+import android.annotation.NonNull;
+import android.os.Handler;
+import android.os.HandlerThread;
+
+import com.android.internal.annotations.VisibleForTesting;
+import com.android.internal.telephony.Phone;
+import com.android.internal.telephony.flags.FeatureFlags;
+
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+
+/**
+ * Vonr state handler.
+ *
+ * <p>This class is instantiated in {@link MetricsCollector}.
+*/
+public class VonrHelper {
+    private final @NonNull FeatureFlags mFlags;
+
+    private Handler mHandler;
+    private Map<Integer, Boolean> mPhoneVonrState = new ConcurrentHashMap<>();
+
+    public VonrHelper(@NonNull FeatureFlags featureFlags) {
+        this.mFlags = featureFlags;
+        if (mFlags.vonrEnabledMetric()) {
+            HandlerThread mHandlerThread = new HandlerThread("VonrHelperThread");
+            mHandlerThread.start();
+            mHandler = new Handler(mHandlerThread.getLooper());
+        }
+    }
+
+    /** Update vonr_enabled state */
+    public void updateVonrEnabledState() {
+        if (mFlags.vonrEnabledMetric()) {
+            mHandler.post(mVonrRunnable);
+        }
+    }
+
+    @VisibleForTesting
+    protected Runnable mVonrRunnable =
+            new Runnable() {
+                @Override
+                public void run() {
+                    mPhoneVonrState.clear();
+                    for (Phone phone : getPhonesIfAny()) {
+                        mPhoneVonrState.put(phone.getSubId(), isVonrEnabled(phone));
+                    }
+                }
+            };
+
+    /** Get vonr_enabled per subId */
+    public boolean getVonrEnabled(int subId) {
+        if (mFlags.vonrEnabledMetric()) {
+            return mPhoneVonrState.getOrDefault(subId, false);
+        } else {
+            return false;
+        }
+    }
+}
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java
index 66bf482..2a8c597 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/MetricsCollectorTest.java
@@ -92,6 +92,7 @@
     private UiccCard mActiveCard;
     private UiccPort mActivePort;
     private ServiceStateStats mServiceStateStats;
+    private VonrHelper mVonrHelper;
 
     private MetricsCollector mMetricsCollector;
 
@@ -104,8 +105,10 @@
         mActiveCard = mock(UiccCard.class);
         mActivePort = mock(UiccPort.class);
         mServiceStateStats = mock(ServiceStateStats.class);
+        mVonrHelper = mock(VonrHelper.class);
         mMetricsCollector =
-                new MetricsCollector(mContext, mPersistAtomsStorage, mDeviceStateHelper);
+                new MetricsCollector(mContext, mPersistAtomsStorage,
+                        mDeviceStateHelper, mVonrHelper);
         doReturn(mSST).when(mSecondPhone).getServiceStateTracker();
         doReturn(mServiceStateStats).when(mSST).getServiceStateStats();
     }
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java
index 00ba0f8..1498eb4 100644
--- a/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java
@@ -44,6 +44,7 @@
 import static org.mockito.Mockito.verify;
 import static org.mockito.Mockito.verifyNoMoreInteractions;
 
+import android.annotation.NonNull;
 import android.os.Looper;
 import android.telephony.AccessNetworkConstants;
 import android.telephony.Annotation.NetworkType;
@@ -68,6 +69,7 @@
 import com.android.internal.telephony.PhoneFactory;
 import com.android.internal.telephony.ServiceStateTracker;
 import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.flags.FeatureFlags;
 import com.android.internal.telephony.imsphone.ImsPhoneCall;
 import com.android.internal.telephony.imsphone.ImsPhoneConnection;
 import com.android.internal.telephony.nano.PersistAtomsProto.VoiceCallRatUsage;
@@ -114,12 +116,14 @@
     private GsmCdmaCall mCsCall1;
     private ImsPhoneCall mImsCall0;
     private ImsPhoneCall mImsCall1;
+    private VonrHelper mVonrHelper;
 
     private static class TestableVoiceCallSessionStats extends VoiceCallSessionStats {
         private long mTimeMillis = 0L;
 
-        TestableVoiceCallSessionStats(int phoneId, Phone phone) {
-            super(phoneId, phone);
+        TestableVoiceCallSessionStats(int phoneId, Phone phone,
+                @NonNull FeatureFlags featureFlags) {
+            super(phoneId, phone, featureFlags);
         }
 
         @Override
@@ -160,6 +164,7 @@
         mCsCall1 = mock(GsmCdmaCall.class);
         mImsCall0 = mock(ImsPhoneCall.class);
         mImsCall1 = mock(ImsPhoneCall.class);
+        mVonrHelper = mock(VonrHelper.class);
         replaceInstance(PhoneFactory.class, "sPhones", null, new Phone[] {mPhone, mSecondPhone});
         doReturn(CARRIER_ID_SLOT_0).when(mPhone).getCarrierId();
         // mPhone's mContext/mSST/mServiceState has been set up by TelephonyTest
@@ -212,10 +217,14 @@
             Looper.prepare();
         }
 
-        mVoiceCallSessionStats0 = new TestableVoiceCallSessionStats(0, mPhone);
+        doReturn(mVonrHelper).when(mMetricsCollector).getVonrHelper();
+
+        mVoiceCallSessionStats0 = new TestableVoiceCallSessionStats(0, mPhone, mFeatureFlags);
         mVoiceCallSessionStats0.onServiceStateChanged(mServiceState);
-        mVoiceCallSessionStats1 = new TestableVoiceCallSessionStats(1, mSecondPhone);
+        mVoiceCallSessionStats1 = new TestableVoiceCallSessionStats(1, mSecondPhone, mFeatureFlags);
         mVoiceCallSessionStats1.onServiceStateChanged(mSecondServiceState);
+
+        doReturn(true).when(mFeatureFlags).vonrEnabledMetric();
     }
 
     @After
@@ -2686,6 +2695,63 @@
         assertProtoEquals(expectedRatUsage, ratUsage.get()[0]);
     }
 
+    @Test
+    @SmallTest
+    public void singleCall_vonrEnabled() {
+        setServiceState(mServiceState, TelephonyManager.NETWORK_TYPE_LTE);
+        doReturn(TelephonyManager.NETWORK_TYPE_LTE).when(mImsStats).getImsVoiceRadioTech();
+        doReturn(mImsPhone).when(mPhone).getImsPhone();
+        doReturn(false).when(mImsConnection0).isIncoming();
+        doReturn(2000L).when(mImsConnection0).getCreateTime();
+        doReturn(0L).when(mImsConnection0).getDurationMillis();
+        doReturn(mImsCall0).when(mImsConnection0).getCall();
+        doReturn(true).when(mVonrHelper).getVonrEnabled(anyInt());
+        doReturn(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections();
+        VoiceCallSession expectedCall =
+                makeSlot0CallProto(
+                        VOICE_CALL_SESSION__BEARER_AT_END__CALL_BEARER_IMS,
+                        VOICE_CALL_SESSION__DIRECTION__CALL_DIRECTION_MO,
+                        TelephonyManager.NETWORK_TYPE_LTE,
+                        ImsReasonInfo.CODE_REMOTE_CALL_DECLINE);
+        expectedCall.setupDurationMillis = 200;
+        expectedCall.setupFailed = true;
+        expectedCall.ratAtConnected = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+        expectedCall.codecBitmask = 1L << AudioCodec.AUDIO_CODEC_EVS_SWB;
+        expectedCall.mainCodecQuality =
+                VOICE_CALL_SESSION__MAIN_CODEC_QUALITY__CODEC_QUALITY_SUPER_WIDEBAND;
+        expectedCall.ratAtConnected = TelephonyManager.NETWORK_TYPE_UNKNOWN;
+        expectedCall.callDuration = VOICE_CALL_SESSION__CALL_DURATION__CALL_DURATION_UNKNOWN;
+        expectedCall.vonrEnabled = true;
+        VoiceCallRatUsage expectedRatUsage =
+                makeRatUsageProto(
+                        CARRIER_ID_SLOT_0, TelephonyManager.NETWORK_TYPE_LTE, 2000L, 12000L, 1L);
+        final AtomicReference<VoiceCallRatUsage[]> ratUsage = setupRatUsageCapture();
+
+        mVoiceCallSessionStats0.setTimeMillis(2000L);
+        doReturn(Call.State.DIALING).when(mImsCall0).getState();
+        doReturn(Call.State.DIALING).when(mImsConnection0).getState();
+        mVoiceCallSessionStats0.onImsDial(mImsConnection0);
+        mVoiceCallSessionStats0.setTimeMillis(2100L);
+        mVoiceCallSessionStats0.onAudioCodecChanged(
+                mImsConnection0, ImsStreamMediaProfile.AUDIO_QUALITY_EVS_SWB);
+        mVoiceCallSessionStats0.setTimeMillis(2200L);
+        doReturn(Call.State.ALERTING).when(mImsCall0).getState();
+        doReturn(Call.State.ALERTING).when(mImsConnection0).getState();
+        mVoiceCallSessionStats0.onCallStateChanged(mImsCall0);
+        mVoiceCallSessionStats0.setTimeMillis(12000L);
+        mVoiceCallSessionStats0.onImsCallTerminated(
+                mImsConnection0, new ImsReasonInfo(ImsReasonInfo.CODE_REMOTE_CALL_DECLINE, 0));
+
+        ArgumentCaptor<VoiceCallSession> callCaptor =
+                ArgumentCaptor.forClass(VoiceCallSession.class);
+        verify(mPersistAtomsStorage, times(1)).addVoiceCallSession(callCaptor.capture());
+        verify(mPersistAtomsStorage, times(1)).addVoiceCallRatUsage(any());
+        verifyNoMoreInteractions(mPersistAtomsStorage);
+        assertProtoEquals(expectedCall, callCaptor.getValue());
+        assertThat(ratUsage.get()).hasLength(1);
+        assertProtoEquals(expectedRatUsage, ratUsage.get()[0]);
+    }
+
     private AtomicReference<VoiceCallRatUsage[]> setupRatUsageCapture() {
         final AtomicReference<VoiceCallRatUsage[]> ratUsage = new AtomicReference<>(null);
         doAnswer(
@@ -2773,6 +2839,7 @@
         call.isRoaming = false;
         call.setupBeginMillis = 0L;
         call.signalStrengthAtEnd = 2;
+        call.vonrEnabled = false;
         return call;
     }
 
diff --git a/tests/telephonytests/src/com/android/internal/telephony/metrics/VonrHelperTest.java b/tests/telephonytests/src/com/android/internal/telephony/metrics/VonrHelperTest.java
new file mode 100644
index 0000000..04cd925
--- /dev/null
+++ b/tests/telephonytests/src/com/android/internal/telephony/metrics/VonrHelperTest.java
@@ -0,0 +1,80 @@
+/*
+ * Copyright (C) 2020 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.internal.telephony.metrics;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import static org.mockito.Mockito.doReturn;
+
+import android.annotation.NonNull;
+import android.test.suitebuilder.annotation.SmallTest;
+
+import com.android.internal.telephony.TelephonyTest;
+import com.android.internal.telephony.flags.FeatureFlags;
+
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+
+public class VonrHelperTest extends TelephonyTest {
+    private static final int SUBID = 1;
+
+    private static class TestableVonrHelper extends VonrHelper {
+        TestableVonrHelper(@NonNull FeatureFlags featureFlags) {
+            super(featureFlags);
+        }
+
+        @Override
+        public void updateVonrEnabledState() {
+            mVonrRunnable.run();
+        }
+    }
+
+    private TestableVonrHelper mVonrHelper;
+
+    @Before
+    public void setUp() throws Exception {
+        super.setUp(getClass().getSimpleName());
+        doReturn(SUBID).when(mPhone).getSubId();
+        doReturn(false).when(mTelephonyManager).isVoNrEnabled();
+        mVonrHelper = new TestableVonrHelper(mFeatureFlags);
+        doReturn(true).when(mFeatureFlags).vonrEnabledMetric();
+    }
+
+    @After
+    public void tearDown() throws Exception {
+        super.tearDown();
+    }
+
+    @Test
+    @SmallTest
+    public void vonr_enabled() {
+        doReturn(true).when(mTelephonyManager).isVoNrEnabled();
+
+        mVonrHelper.updateVonrEnabledState();
+
+        assertThat(mVonrHelper.getVonrEnabled(SUBID)).isTrue();
+    }
+
+    @Test
+    @SmallTest
+    public void vonr_disabled() {
+        mVonrHelper.updateVonrEnabledState();
+
+        assertThat(mVonrHelper.getVonrEnabled(SUBID)).isFalse();
+    }
+}