Loading proto/src/persist_atoms.proto +2 −0 Original line number Diff line number Diff line Loading @@ -312,6 +312,8 @@ message VoiceCallSession { optional bool is_iwlan_cross_sim_at_connected = 39; optional bool vonr_enabled = 40; optional bool is_ntn = 41; optional bool supports_business_call_composer = 42; optional int32 call_composer_status = 43; // Internal use only optional int64 setup_begin_millis = 10001; Loading src/java/com/android/internal/telephony/metrics/MetricsCollector.java +3 −1 Original line number Diff line number Diff line Loading @@ -1127,7 +1127,9 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { session.isIwlanCrossSimAtEnd, session.isIwlanCrossSimAtConnected, session.vonrEnabled, session.isNtn); session.isNtn, session.supportsBusinessCallComposer, session.callComposerStatus); } Loading src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java +37 −2 Original line number Diff line number Diff line Loading @@ -41,16 +41,19 @@ import android.annotation.Nullable; import android.content.Context; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.PersistableBundle; import android.os.SystemClock; import android.telecom.VideoProfile; import android.telecom.VideoProfile.VideoState; import android.telephony.Annotation.NetworkType; import android.telephony.AnomalyReporter; import android.telephony.CarrierConfigManager; import android.telephony.DisconnectCause; import android.telephony.NetworkRegistrationInfo; import android.telephony.PreciseDataConnectionState; import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.telephony.TelephonyManager.CallComposerStatus; import android.telephony.data.ApnSetting; import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.ImsStreamMediaProfile; Loading Loading @@ -168,10 +171,8 @@ public class VoiceCallSessionStats { private final UiccController mUiccController = UiccController.getInstance(); private final DeviceStateHelper mDeviceStateHelper = PhoneFactory.getMetricsCollector().getDeviceStateHelper(); private final VonrHelper mVonrHelper = PhoneFactory.getMetricsCollector().getVonrHelper(); private final SatelliteController mSatelliteController; public VoiceCallSessionStats(int phoneId, Phone phone, @NonNull FeatureFlags featureFlags) { Loading Loading @@ -574,6 +575,10 @@ public class VoiceCallSessionStats { proto.vonrEnabled = mVonrHelper.getVonrEnabled(mPhone.getSubId()); } proto.supportsBusinessCallComposer = isBusinessCallSupported(); // 0 is defined as UNKNOWN in Enum proto.callComposerStatus = getCallComposerStatusForPhone() + 1; proto.isNtn = mSatelliteController != null ? mSatelliteController.isInSatelliteModeForCarrierRoaming(mPhone) : false; Loading Loading @@ -947,6 +952,36 @@ public class VoiceCallSessionStats { return false; } private @CallComposerStatus int getCallComposerStatusForPhone() { TelephonyManager telephonyManager = mPhone.getContext() .getSystemService(TelephonyManager.class); if (telephonyManager == null) { return TelephonyManager.CALL_COMPOSER_STATUS_OFF; } telephonyManager = telephonyManager.createForSubscriptionId(mPhone.getSubId()); return telephonyManager.getCallComposerStatus(); } private boolean isBusinessCallSupported() { CarrierConfigManager carrierConfigManager = (CarrierConfigManager) mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE); if (carrierConfigManager == null) { return false; } int subId = mPhone.getSubId(); PersistableBundle b = null; try { b = carrierConfigManager.getConfigForSubId(subId, CarrierConfigManager.KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL); } catch (RuntimeException e) { loge("CarrierConfigLoader is not available."); } if (b == null || b.isEmpty()) { return false; } return b.getBoolean(CarrierConfigManager.KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL); } @VisibleForTesting protected long getTimeMillis() { return SystemClock.elapsedRealtime(); Loading tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java +72 −1 Original line number Diff line number Diff line Loading @@ -50,8 +50,10 @@ import static org.mockito.Mockito.when; import android.annotation.NonNull; import android.os.Looper; import android.os.PersistableBundle; import android.telephony.AccessNetworkConstants; import android.telephony.Annotation.NetworkType; import android.telephony.CarrierConfigManager; import android.telephony.DisconnectCause; import android.telephony.NetworkRegistrationInfo; import android.telephony.PreciseDataConnectionState; Loading Loading @@ -226,7 +228,8 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { mVoiceCallSessionStats0 = new TestableVoiceCallSessionStats(0, mPhone, mFeatureFlags); mVoiceCallSessionStats0.onServiceStateChanged(mServiceState); mVoiceCallSessionStats1 = new TestableVoiceCallSessionStats(1, mSecondPhone, mFeatureFlags); mVoiceCallSessionStats1 = new TestableVoiceCallSessionStats( 1, mSecondPhone, mFeatureFlags); mVoiceCallSessionStats1.onServiceStateChanged(mSecondServiceState); doReturn(true).when(mFeatureFlags).vonrEnabledMetric(); Loading Loading @@ -2787,6 +2790,72 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { assertFalse(session.isNtn); } @Test @SmallTest public void singleCall_supportBusinessCall() { PersistableBundle mCarrierConfig = new PersistableBundle(); mCarrierConfig.putBoolean( CarrierConfigManager.KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL, true); when(mCarrierConfigManager.getConfigForSubId(eq(mPhone.getSubId()), eq(CarrierConfigManager.KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL))) .thenReturn(mCarrierConfig); 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(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections(); doReturn(2).when(mTelephonyManager).getCallComposerStatus(); 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.supportsBusinessCallComposer = true; // 0 is defined as UNKNOWN, adding 1 to original value. expectedCall.callComposerStatus = 3; 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( Loading Loading @@ -2875,6 +2944,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { call.setupBeginMillis = 0L; call.signalStrengthAtEnd = 2; call.vonrEnabled = false; call.callComposerStatus = 1; return call; } Loading Loading @@ -2910,6 +2980,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { call.isRoaming = false; call.setupBeginMillis = 0L; call.signalStrengthAtEnd = 2; call.callComposerStatus = 1; return call; } Loading Loading
proto/src/persist_atoms.proto +2 −0 Original line number Diff line number Diff line Loading @@ -312,6 +312,8 @@ message VoiceCallSession { optional bool is_iwlan_cross_sim_at_connected = 39; optional bool vonr_enabled = 40; optional bool is_ntn = 41; optional bool supports_business_call_composer = 42; optional int32 call_composer_status = 43; // Internal use only optional int64 setup_begin_millis = 10001; Loading
src/java/com/android/internal/telephony/metrics/MetricsCollector.java +3 −1 Original line number Diff line number Diff line Loading @@ -1127,7 +1127,9 @@ public class MetricsCollector implements StatsManager.StatsPullAtomCallback { session.isIwlanCrossSimAtEnd, session.isIwlanCrossSimAtConnected, session.vonrEnabled, session.isNtn); session.isNtn, session.supportsBusinessCallComposer, session.callComposerStatus); } Loading
src/java/com/android/internal/telephony/metrics/VoiceCallSessionStats.java +37 −2 Original line number Diff line number Diff line Loading @@ -41,16 +41,19 @@ import android.annotation.Nullable; import android.content.Context; import android.net.wifi.WifiInfo; import android.net.wifi.WifiManager; import android.os.PersistableBundle; import android.os.SystemClock; import android.telecom.VideoProfile; import android.telecom.VideoProfile.VideoState; import android.telephony.Annotation.NetworkType; import android.telephony.AnomalyReporter; import android.telephony.CarrierConfigManager; import android.telephony.DisconnectCause; import android.telephony.NetworkRegistrationInfo; import android.telephony.PreciseDataConnectionState; import android.telephony.ServiceState; import android.telephony.TelephonyManager; import android.telephony.TelephonyManager.CallComposerStatus; import android.telephony.data.ApnSetting; import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.ImsStreamMediaProfile; Loading Loading @@ -168,10 +171,8 @@ public class VoiceCallSessionStats { private final UiccController mUiccController = UiccController.getInstance(); private final DeviceStateHelper mDeviceStateHelper = PhoneFactory.getMetricsCollector().getDeviceStateHelper(); private final VonrHelper mVonrHelper = PhoneFactory.getMetricsCollector().getVonrHelper(); private final SatelliteController mSatelliteController; public VoiceCallSessionStats(int phoneId, Phone phone, @NonNull FeatureFlags featureFlags) { Loading Loading @@ -574,6 +575,10 @@ public class VoiceCallSessionStats { proto.vonrEnabled = mVonrHelper.getVonrEnabled(mPhone.getSubId()); } proto.supportsBusinessCallComposer = isBusinessCallSupported(); // 0 is defined as UNKNOWN in Enum proto.callComposerStatus = getCallComposerStatusForPhone() + 1; proto.isNtn = mSatelliteController != null ? mSatelliteController.isInSatelliteModeForCarrierRoaming(mPhone) : false; Loading Loading @@ -947,6 +952,36 @@ public class VoiceCallSessionStats { return false; } private @CallComposerStatus int getCallComposerStatusForPhone() { TelephonyManager telephonyManager = mPhone.getContext() .getSystemService(TelephonyManager.class); if (telephonyManager == null) { return TelephonyManager.CALL_COMPOSER_STATUS_OFF; } telephonyManager = telephonyManager.createForSubscriptionId(mPhone.getSubId()); return telephonyManager.getCallComposerStatus(); } private boolean isBusinessCallSupported() { CarrierConfigManager carrierConfigManager = (CarrierConfigManager) mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE); if (carrierConfigManager == null) { return false; } int subId = mPhone.getSubId(); PersistableBundle b = null; try { b = carrierConfigManager.getConfigForSubId(subId, CarrierConfigManager.KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL); } catch (RuntimeException e) { loge("CarrierConfigLoader is not available."); } if (b == null || b.isEmpty()) { return false; } return b.getBoolean(CarrierConfigManager.KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL); } @VisibleForTesting protected long getTimeMillis() { return SystemClock.elapsedRealtime(); Loading
tests/telephonytests/src/com/android/internal/telephony/metrics/VoiceCallSessionStatsTest.java +72 −1 Original line number Diff line number Diff line Loading @@ -50,8 +50,10 @@ import static org.mockito.Mockito.when; import android.annotation.NonNull; import android.os.Looper; import android.os.PersistableBundle; import android.telephony.AccessNetworkConstants; import android.telephony.Annotation.NetworkType; import android.telephony.CarrierConfigManager; import android.telephony.DisconnectCause; import android.telephony.NetworkRegistrationInfo; import android.telephony.PreciseDataConnectionState; Loading Loading @@ -226,7 +228,8 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { mVoiceCallSessionStats0 = new TestableVoiceCallSessionStats(0, mPhone, mFeatureFlags); mVoiceCallSessionStats0.onServiceStateChanged(mServiceState); mVoiceCallSessionStats1 = new TestableVoiceCallSessionStats(1, mSecondPhone, mFeatureFlags); mVoiceCallSessionStats1 = new TestableVoiceCallSessionStats( 1, mSecondPhone, mFeatureFlags); mVoiceCallSessionStats1.onServiceStateChanged(mSecondServiceState); doReturn(true).when(mFeatureFlags).vonrEnabledMetric(); Loading Loading @@ -2787,6 +2790,72 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { assertFalse(session.isNtn); } @Test @SmallTest public void singleCall_supportBusinessCall() { PersistableBundle mCarrierConfig = new PersistableBundle(); mCarrierConfig.putBoolean( CarrierConfigManager.KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL, true); when(mCarrierConfigManager.getConfigForSubId(eq(mPhone.getSubId()), eq(CarrierConfigManager.KEY_SUPPORTS_BUSINESS_CALL_COMPOSER_BOOL))) .thenReturn(mCarrierConfig); 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(new ArrayList(List.of(mImsConnection0))).when(mImsCall0).getConnections(); doReturn(2).when(mTelephonyManager).getCallComposerStatus(); 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.supportsBusinessCallComposer = true; // 0 is defined as UNKNOWN, adding 1 to original value. expectedCall.callComposerStatus = 3; 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( Loading Loading @@ -2875,6 +2944,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { call.setupBeginMillis = 0L; call.signalStrengthAtEnd = 2; call.vonrEnabled = false; call.callComposerStatus = 1; return call; } Loading Loading @@ -2910,6 +2980,7 @@ public class VoiceCallSessionStatsTest extends TelephonyTest { call.isRoaming = false; call.setupBeginMillis = 0L; call.signalStrengthAtEnd = 2; call.callComposerStatus = 1; return call; } Loading