diff options
author | sangyun <sangyun@google.com> | 2023-02-22 06:29:06 +0900 |
---|---|---|
committer | sangyun <sangyun@google.com> | 2023-03-13 18:18:37 +0900 |
commit | 3fb7100cb4ddc6d787cc3a54c9f2ad7ca094d83c (patch) | |
tree | d7b998709318001f9cc058280dee6014b32bd8d4 | |
parent | 91bd6a427da8d68f5faf80a2dae6610a7ddeb016 (diff) | |
download | Telephony-3fb7100cb4ddc6d787cc3a54c9f2ad7ca094d83c.tar.gz |
[QNS] Introduction of the qns metric (QNS metric v1.3)
Atom for QualifiedRatListChanged
- Pushed atom when a QNS update qualified RAT list.
Atom for FallbackRestrictionChanged
- Pushed atom when QNS fallback restriction changed.
Atom for ImsCallDrop
- Pushed atom when IMS call drop occurred in when both transport
type available.
Atom for RatPreferenceMismatchInfo
- Pulls the history for mismatch between RAT preference and
actual one.
Atom for HandoverTimeMillis
- Pulls for time taken from update of RAT preference until
successful handover completion.
Atom for HandoverPingpong
- Pulls for count of handover pingpong in short time
Bug: 235436630
Test: atest QualifiedNetworksServiceTests
Change-Id: I5b3bd2db6c1ca00412e0cbb2a7435fde7bc28015
27 files changed, 5268 insertions, 4 deletions
diff --git a/services/QualifiedNetworksService/Android.bp b/services/QualifiedNetworksService/Android.bp index 1a5426f..80e6d14 100644 --- a/services/QualifiedNetworksService/Android.bp +++ b/services/QualifiedNetworksService/Android.bp @@ -17,6 +17,13 @@ package { default_applicable_licenses: ["Android-Apache-2.0"], } +genrule { + name: "statslog-qns-java-gen", + tools: ["stats-log-api-gen"], + cmd: "$(location stats-log-api-gen) --java $(out) --module qns --javaPackage com.android.telephony.qns.stats --javaClass QnsStatsLog --worksource", + out: ["com/android/telephony/qns/stats/QnsStatsLog.java"], +} + android_app { name: "QualifiedNetworksService", system_ext_specific: true, @@ -25,11 +32,13 @@ android_app { srcs: [ "src/**/*.java", "src/**/I*.aidl", + ":statslog-qns-java-gen", ], static_libs: [ "androidx.appcompat_appcompat", "androidx.browser_browser", + "TelephonyStatsLib", ], libs: [ @@ -72,6 +81,7 @@ android_test { "src/**/*.java", "src/**/I*.aidl", "tests/**/*.java", + ":statslog-qns-java-gen", ], libs: [ "android.test.runner", @@ -90,8 +100,9 @@ android_test { "frameworks-base-testutils", "mockito-target-extended-minus-junit4", "platform-test-annotations", - "truth-prebuilt", - "testables", + "truth-prebuilt", + "testables", + "TelephonyStatsLib", ], jni_libs: [ "libdexmakerjvmtiagent", diff --git a/services/QualifiedNetworksService/AndroidManifest.xml b/services/QualifiedNetworksService/AndroidManifest.xml index 5170124..9b2444b 100644 --- a/services/QualifiedNetworksService/AndroidManifest.xml +++ b/services/QualifiedNetworksService/AndroidManifest.xml @@ -26,6 +26,7 @@ <uses-permission android:name="android.permission.READ_PHONE_STATE" /> <uses-permission android:name="android.permission.READ_PRECISE_PHONE_STATE" /> <uses-permission android:name="android.permission.READ_PRIVILEGED_PHONE_STATE" /> + <uses-permission android:name="android.permission.REGISTER_STATS_PULL_ATOM" /> <application android:directBootAware="true" android:defaultToDeviceProtectedStorage="true"> diff --git a/services/QualifiedNetworksService/privapp-permissions_com.android.telephony.qns.xml b/services/QualifiedNetworksService/privapp-permissions_com.android.telephony.qns.xml index 223aa19..3f31bcf 100644 --- a/services/QualifiedNetworksService/privapp-permissions_com.android.telephony.qns.xml +++ b/services/QualifiedNetworksService/privapp-permissions_com.android.telephony.qns.xml @@ -20,5 +20,6 @@ <permission name="android.permission.NETWORK_SIGNAL_STRENGTH_WAKEUP"/> <permission name="android.permission.READ_PRECISE_PHONE_STATE"/> <permission name="android.permission.READ_PRIVILEGED_PHONE_STATE"/> + <permission name="android.permission.REGISTER_STATS_PULL_ATOM" /> </privapp-permissions> </permissions> diff --git a/services/QualifiedNetworksService/src/com/android/telephony/qns/AccessNetworkEvaluator.java b/services/QualifiedNetworksService/src/com/android/telephony/qns/AccessNetworkEvaluator.java index 46405b7..e8a742d 100644 --- a/services/QualifiedNetworksService/src/com/android/telephony/qns/AccessNetworkEvaluator.java +++ b/services/QualifiedNetworksService/src/com/android/telephony/qns/AccessNetworkEvaluator.java @@ -26,6 +26,7 @@ import android.telephony.AccessNetworkConstants; import android.telephony.AccessNetworkConstants.AccessNetworkType; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; +import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.ProvisioningManager; import android.util.Log; @@ -61,6 +62,7 @@ class AccessNetworkEvaluator { private static final int EVENT_IMS_REGISTRATION_STATE_CHANGED = EVENT_BASE + 10; private static final int EVENT_WIFI_RTT_STATUS_CHANGED = EVENT_BASE + 11; private static final int EVENT_SIP_DIALOG_SESSION_STATE_CHANGED = EVENT_BASE + 12; + private static final int EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED = EVENT_BASE + 13; private static final int EVALUATE_SPECIFIC_REASON_NONE = 0; private static final int EVALUATE_SPECIFIC_REASON_IWLAN_DISABLE = 1; private static final int EVALUATE_SPECIFIC_REASON_DATA_DISCONNECTED = 2; @@ -88,6 +90,9 @@ class AccessNetworkEvaluator { protected QnsProvisioningListener mQnsProvisioningListener; protected QnsImsManager mQnsImsManager; protected WifiBackhaulMonitor mWifiBackhaulMonitor; + protected QnsTelephonyListener mQnsTelephonyListener; + // for metric + protected QnsMetrics mQnsMetrics; protected int mCellularAccessNetworkType = AccessNetworkType.UNKNOWN; protected boolean mCellularAvailable = false; @@ -117,6 +122,7 @@ class AccessNetworkEvaluator { private boolean mSipDialogSessionState = false; private int mCachedTransportTypeForEmergencyInitialConnect = AccessNetworkConstants.TRANSPORT_TYPE_INVALID; + private int mLastEvaluateSpecificReason = EVALUATE_SPECIFIC_REASON_NONE; AccessNetworkEvaluator(QnsComponents qnsComponents, int netCapability, int slotIndex) { mNetCapability = netCapability; @@ -155,6 +161,8 @@ class AccessNetworkEvaluator { mNetCapability); mQnsImsManager = mQnsComponents.getQnsImsManager(mSlotIndex); mWifiBackhaulMonitor = mQnsComponents.getWifiBackhaulMonitor(mSlotIndex); + mQnsTelephonyListener = mQnsComponents.getQnsTelephonyListener(mSlotIndex); + mQnsMetrics = mQnsComponents.getQnsMetrics(); // Pre-Conditions mCellularNetworkStatusTracker = mQnsComponents.getCellularNetworkStatusTracker(mSlotIndex); @@ -213,6 +221,8 @@ class AccessNetworkEvaluator { mQnsProvisioningListener = mQnsComponents.getQnsProvisioningListener(mSlotIndex); mQnsImsManager = mQnsComponents.getQnsImsManager(mSlotIndex); mWifiBackhaulMonitor = mQnsComponents.getWifiBackhaulMonitor(mSlotIndex); + mQnsTelephonyListener = mQnsComponents.getQnsTelephonyListener(mSlotIndex); + mQnsMetrics = mQnsComponents.getQnsMetrics(); mHandlerThread = new HandlerThread(AccessNetworkEvaluator.class.getSimpleName() + mNetCapability); mHandlerThread.start(); @@ -248,6 +258,7 @@ class AccessNetworkEvaluator { isAllowed(AccessNetworkConstants.TRANSPORT_TYPE_WWAN))) { mHandler.post(this::evaluate); } + mLastEvaluateSpecificReason = EVALUATE_SPECIFIC_REASON_NONE; } void close() { @@ -327,6 +338,9 @@ class AccessNetworkEvaluator { QualifiedNetworksInfo info = new QualifiedNetworksInfo(mNetCapability, accessNetworkTypes); QnsAsyncResult ar = new QnsAsyncResult(null, info, null); mQualifiedNetworksChangedRegistrants.notifyRegistrants(ar); + + // metrics + sendMetricsForQualifiedNetworks(info); } private void initSettings() { @@ -383,6 +397,10 @@ class AccessNetworkEvaluator { } mQnsProvisioningListener.registerProvisioningItemInfoChanged( mHandler, EVENT_PROVISIONING_INFO_CHANGED, null, true); + if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) { + mQnsTelephonyListener.registerImsCallDropDisconnectCauseListener( + mHandler, EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED, null); + } List<Integer> events = new ArrayList<>(); events.add(QnsEventDispatcher.QNS_EVENT_WFC_ENABLED); events.add(QnsEventDispatcher.QNS_EVENT_WFC_DISABLED); @@ -419,6 +437,9 @@ class AccessNetworkEvaluator { mWifiBackhaulMonitor.unRegisterForRttStatusChange(mHandler); } } + if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) { + mQnsTelephonyListener.unregisterImsCallDropDisconnectCauseListener(mHandler); + } mQnsProvisioningListener.unregisterProvisioningItemInfoChanged(mHandler); mQnsEventDispatcher.unregisterEvent(mHandler); mRestrictManager.unRegisterRestrictInfoChanged(mHandler); @@ -522,7 +543,9 @@ class AccessNetworkEvaluator { protected void onIwlanNetworkStatusChanged(IwlanAvailabilityInfo info) { if (info != null) { - mIwlanAvailable = info.getIwlanAvailable(); + if (mIwlanAvailable != info.getIwlanAvailable()) { + mIwlanAvailable = info.getIwlanAvailable(); + } mIsCrossWfc = info.isCrossWfc(); log("onIwlanNetworkStatusChanged IwlanAvailable:" + mIwlanAvailable); if (info.getNotifyIwlanDisabled()) { @@ -660,6 +683,10 @@ class AccessNetworkEvaluator { && callType == QnsConstants.CALL_TYPE_EMERGENCY) { if (!mDataConnectionStatusTracker.isActiveState()) return; } + + // metrics + sendMetricsForCallTypeChanged(mCallType, callType); + mCallType = callType; mRestrictManager.setQnsCallType(mCallType); log("onSetCallType CallType:" + mCallType); @@ -754,6 +781,10 @@ class AccessNetworkEvaluator { } break; } + + // metrics + sendMetricsForDataConnectionChanged(info); + if (needEvaluate) { evaluate(evaluateSpecificReason); } @@ -917,6 +948,26 @@ class AccessNetworkEvaluator { } } + protected void onImsCallDisconnectCauseChanged(ImsReasonInfo imsReasonInfo) { + if (imsReasonInfo == null) { + return; + } + if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS + && imsReasonInfo.getCode() == ImsReasonInfo.CODE_MEDIA_NO_DATA) { + log( + "onImsCallDisconnectCauseChanged: iwlanAvailable=" + + mIwlanAvailable + + " cellularAvailable=" + + mCellularAvailable + + " imsReasonInfo=" + + imsReasonInfo); + if (mIwlanAvailable && mCellularAvailable) { + // metrics + sendMetricsForImsCallDropStats(); + } + } + } + protected void onCellularQualityChanged(Threshold[] ths) { if (ths == null || ths.length == 0) { log("onCellularQualityChanged: E threshold is null"); @@ -1194,6 +1245,7 @@ class AccessNetworkEvaluator { if (DBG) log("ANE is not initialized yet."); return; } + mLastEvaluateSpecificReason = specificReason; log("evaluate reason:" + evaluateSpecificReasonToString(specificReason)); if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_EIMS) { if (!mDataConnectionStatusTracker.isActiveState()) { @@ -1954,6 +2006,9 @@ class AccessNetworkEvaluator { case EVENT_SIP_DIALOG_SESSION_STATE_CHANGED: onSipDialogSessionStateChanged((boolean) ar.mResult); break; + case EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED: + onImsCallDisconnectCauseChanged((ImsReasonInfo) ar.mResult); + break; case QnsEventDispatcher.QNS_EVENT_WFC_ENABLED: onWfcEnabledChanged(true, false); break; @@ -2099,4 +2154,50 @@ class AccessNetworkEvaluator { boolean getSipDialogSessionState() { return mSipDialogSessionState; } + + private void sendMetricsForQualifiedNetworks(QualifiedNetworksInfo info) { + if (!mCellularAvailable + || !mIwlanAvailable + || mCellularAccessNetworkType == AccessNetworkType.UNKNOWN + || mLastEvaluateSpecificReason == EVALUATE_SPECIFIC_REASON_DATA_DISCONNECTED) { + // b/268557926, decided to cut off if WWAN and WLAN are not in contention. + return; + } + mQnsMetrics.reportAtomForQualifiedNetworks( + info, + mSlotIndex, + mDataConnectionStatusTracker.getLastTransportType(), + mCoverage, + mSettingWfcEnabled, + mSettingWfcRoamingEnabled, + mSettingWfcMode, + mSettingWfcRoamingMode, + mCellularAccessNetworkType, + mIwlanAvailable, + mIsCrossWfc, + mRestrictManager, + mCellularQualityMonitor, + mWifiQualityMonitor, + mCallType); + } + + private void sendMetricsForCallTypeChanged(int oldCallType, int newCallType) { + int transportTypeOfCall = mDataConnectionStatusTracker.getLastTransportType(); + mQnsMetrics.reportAtomForCallTypeChanged(mNetCapability, mSlotIndex, + oldCallType, newCallType, mRestrictManager, transportTypeOfCall); + } + + private void sendMetricsForDataConnectionChanged( + DataConnectionStatusTracker.DataConnectionChangedInfo info) { + mQnsMetrics.reportAtomForDataConnectionChanged( + mNetCapability, mSlotIndex, info, mConfigManager.getCarrierId()); + } + + private void sendMetricsForImsCallDropStats() { + int transportTypeOfCall = mDataConnectionStatusTracker.getLastTransportType(); + mQnsMetrics.reportAtomForImsCallDropStats(mNetCapability, mSlotIndex, mRestrictManager, + mCellularQualityMonitor, mWifiQualityMonitor, transportTypeOfCall, + mCellularAccessNetworkType); + } + } diff --git a/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsComponents.java b/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsComponents.java index 1c9b898..1c14bae 100644 --- a/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsComponents.java +++ b/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsComponents.java @@ -46,6 +46,7 @@ class QnsComponents { private final List<Integer> mSlotIds; private IwlanNetworkStatusTracker mIwlanNetworkStatusTracker; private WifiQualityMonitor mWifiQualityMonitor; + private QnsMetrics mQnsMetrics; /** Constructor to instantiate QnsComponents class. */ QnsComponents(Context context) { @@ -113,6 +114,9 @@ class QnsComponents { mQnsImsManagers.get(slotId), mQnsTelephonyListeners.get(slotId), slotId); + if (mQnsMetrics == null) { + mQnsMetrics = new QnsMetrics(mContext); + } Log.d(mLogTag, "QnsComponents created for slot " + slotId); } @@ -132,6 +136,7 @@ class QnsComponents { QnsCallStatusTracker qnsCallStatusTracker, WifiBackhaulMonitor wifiBackhaulMonitor, WifiQualityMonitor wifiQualityMonitor, + QnsMetrics qnsMetrics, int slotId) { this(context); mSlotIds.add(slotId); @@ -155,6 +160,7 @@ class QnsComponents { qnsImsManager, qnsTelephonyListener, slotId); + mQnsMetrics = qnsMetrics; } /** Returns instance of AlternativeEventListener for given slotId. */ @@ -217,6 +223,11 @@ class QnsComponents { return mWifiQualityMonitor; } + /** Returns instance of WifiQualityMonitor. */ + QnsMetrics getQnsMetrics() { + return mQnsMetrics; + } + /** Returns context. */ Context getContext() { return mContext; @@ -229,8 +240,10 @@ class QnsComponents { if (mSlotIds.size() == 1) { mIwlanNetworkStatusTracker.close(); mWifiQualityMonitor.close(); + mQnsMetrics.close(); mIwlanNetworkStatusTracker = null; mWifiQualityMonitor = null; + mQnsMetrics = null; } WifiBackhaulMonitor wifiBackhaulMonitor = mWifiBackhaulMonitors.get(slotId); diff --git a/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsMetrics.java b/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsMetrics.java new file mode 100644 index 0000000..d936d0b --- /dev/null +++ b/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsMetrics.java @@ -0,0 +1,1026 @@ +/* + * Copyright (C) 2022 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.telephony.qns; + +import android.content.Context; +import android.net.NetworkCapabilities; +import android.os.Handler; +import android.os.HandlerThread; +import android.os.Message; +import android.telephony.AccessNetworkConstants; +import android.telephony.AccessNetworkConstants.AccessNetworkType; +import android.telephony.SignalThresholdInfo; +import android.telephony.qns.QnsProtoEnums; +import android.util.Log; + +import com.android.internal.annotations.VisibleForTesting; +import com.android.internal.util.State; +import com.android.internal.util.StateMachine; +import com.android.telephony.qns.DataConnectionStatusTracker.DataConnectionChangedInfo; +import com.android.telephony.qns.QualifiedNetworksServiceImpl.QualifiedNetworksInfo; +import com.android.telephony.qns.atoms.AtomsQnsFallbackRestrictionChangedInfo; +import com.android.telephony.qns.atoms.AtomsQnsHandoverPingPongInfo; +import com.android.telephony.qns.atoms.AtomsQnsHandoverTimeMillisInfo; +import com.android.telephony.qns.atoms.AtomsQnsImsCallDropStats; +import com.android.telephony.qns.atoms.AtomsQnsRatPreferenceMismatchInfo; +import com.android.telephony.qns.atoms.AtomsQualifiedRatListChangedInfo; +import com.android.telephony.statslib.StatsLib; + +import java.util.HashMap; +import java.util.List; +import java.util.concurrent.ConcurrentHashMap; + +/** QnsStats class */ +class QnsMetrics { + + private StatsLib mStats; + private final String mLogTag; + private final Handler mHandler; + private final HandlerThread mHandlerThread; + + // For HandoverTIme. + private final ConcurrentHashMap<Integer, HandoverTimeStateMachine> mHandoverTimeMap; + private final ConcurrentHashMap<Integer, PingPongTime> mPingPongTime; + private final ConcurrentHashMap<Integer, RatMismatchTime> mRatMismatchTime; + private final ConcurrentHashMap<Integer, RtpCallDrop> mRtpCallDrop; + + /** Constructor */ + QnsMetrics(Context context) { + mStats = new StatsLib(context); + mLogTag = QnsMetrics.class.getSimpleName(); + + mHandoverTimeMap = new ConcurrentHashMap<>(); + mPingPongTime = new ConcurrentHashMap<>(); + mRatMismatchTime = new ConcurrentHashMap<>(); + mRtpCallDrop = new ConcurrentHashMap<>(); + + mHandlerThread = new HandlerThread(QnsMetrics.class.getSimpleName()); + mHandlerThread.start(); + mHandler = new Handler(mHandlerThread.getLooper()); + } + + @VisibleForTesting + QnsMetrics(StatsLib statsLib) { + mStats = statsLib; + mLogTag = QnsMetrics.class.getSimpleName(); + + mHandoverTimeMap = new ConcurrentHashMap<>(); + mPingPongTime = new ConcurrentHashMap<>(); + mRatMismatchTime = new ConcurrentHashMap<>(); + mRtpCallDrop = new ConcurrentHashMap<>(); + + mHandlerThread = new HandlerThread(QnsMetrics.class.getSimpleName()); + mHandlerThread.start(); + mHandler = new Handler(mHandlerThread.getLooper()); + } + + @VisibleForTesting + Handler getHandler() { + return mHandler; + } + + /** close */ + public void close() { + mStats = null; + mHandlerThread.quitSafely(); + } + + /** + * Report atoms when the qualified access network is reported. + * + * @param info QualifiedNetworksInfo + * @param slotId slot index + * @param dataConnectionCurrentTransportType transportType currently stayed in. + * @param coverage coverage home or roam. + * @param settingWfcEnabled setting for wfc + * @param settingWfcRoamingEnabled roaming setting for wfc + * @param settingWfcMode setting for wfc mode + * @param settingWfcRoamingMode roaming setting for wfc mode + * @param cellularAccessNetworkType cellular rat + * @param iwlanAvailable iwlan available + * @param isCrossWfc cross sim wfc enabled + * @param restrictManager restriction manager + * @param cellularQualityMonitor cellular quality monitor + * @param wifiQualityMonitor wifi quality monitor + * @param callType call type + */ + public void reportAtomForQualifiedNetworks( + QualifiedNetworksInfo info, + int slotId, + int dataConnectionCurrentTransportType, + int coverage, + boolean settingWfcEnabled, + boolean settingWfcRoamingEnabled, + int settingWfcMode, + int settingWfcRoamingMode, + int cellularAccessNetworkType, + boolean iwlanAvailable, + boolean isCrossWfc, + RestrictManager restrictManager, + QualityMonitor cellularQualityMonitor, + QualityMonitor wifiQualityMonitor, + int callType) { + mHandler.post(() -> procQualifiedNetworksForHandoverTime(info, slotId)); + mHandler.post(() -> + procQualifiedRatListChanged( + info, + slotId, + dataConnectionCurrentTransportType, + coverage, + settingWfcEnabled, + settingWfcRoamingEnabled, + settingWfcMode, + settingWfcRoamingMode, + cellularAccessNetworkType, + iwlanAvailable, + isCrossWfc, + restrictManager, + cellularQualityMonitor, + wifiQualityMonitor, + callType)); + } + + /** + * Report atom when data connection is changed + * + * @param netCapability Network Capability + * @param slotId slot Index + * @param info DataConnectionChangedInfo + * @param carrierId carrier id. + */ + public void reportAtomForDataConnectionChanged( + int netCapability, int slotId, DataConnectionChangedInfo info, int carrierId) { + mHandler.post(() -> procDataConnectionChangedForHandoverTime(netCapability, slotId, info)); + mHandler.post(() -> procDataConnectionChangedForHandoverPingPong( + netCapability, slotId, info, carrierId)); + mHandler.post(() -> procDataConnectionChangedForRatMismatch( + netCapability, slotId, info, carrierId)); + } + + /** + * Report atom when a restriction is set. + * + * @param netCapability Network Capability + * @param slotId slot Index + * @param wlanRestrictions list of restrictions on wlan + * @param wwanRestrictions list of restrictions on wwan + * @param carrierId carrier id. + */ + public void reportAtomForRestrictions( + int netCapability, + int slotId, + List<Integer> wlanRestrictions, + List<Integer> wwanRestrictions, + int carrierId) { + mHandler.post(() -> procRestrictionsForFallback( + netCapability, slotId, wlanRestrictions, wwanRestrictions, carrierId)); + } + + /** + * Report atom when call type change + * + * @param netCapability Network Capability + * @param slotId slot Index + * @param oldCallType previous call type + * @param newCallType new call type + * @param restrictManager restriction manager + * @param transportTypeOfCall transport type in call + */ + public void reportAtomForCallTypeChanged( + int netCapability, + int slotId, + int oldCallType, + int newCallType, + RestrictManager restrictManager, + int transportTypeOfCall) { + mHandler.post(() -> procCallTypeChangedForImsCallDrop(netCapability, slotId, + oldCallType, newCallType, restrictManager, transportTypeOfCall)); + } + + /** + * Report atom when ims call is dropped + * + * @param netCapability Network Capability + * @param slotId slot Index + * @param restrictManager restriction manager + * @param cellularQualityMonitor cellular quality monitor + * @param wifiQualityMonitor wifi quality monitor + * @param transportTypeOfCall transport type in call + * @param cellularAccessNetworkType cellular access network + */ + public void reportAtomForImsCallDropStats( + int netCapability, + int slotId, + RestrictManager restrictManager, + QualityMonitor cellularQualityMonitor, + QualityMonitor wifiQualityMonitor, + int transportTypeOfCall, + int cellularAccessNetworkType) { + mHandler.post(() -> procCallDroppedForImsCallDrop(netCapability, slotId, restrictManager, + cellularQualityMonitor, wifiQualityMonitor, transportTypeOfCall, + cellularAccessNetworkType)); + } + + private void procQualifiedRatListChanged( + QualifiedNetworksInfo info, + int slotId, + int dataConnectedTransportType, + int coverage, + boolean settingWfcEnabled, + boolean settingWfcRoamingEnabled, + int settingWfcMode, + int settingWfcRoamingMode, + int cellularAccessNetworkType, + boolean iwlanAvailable, + boolean isCrossWfc, + RestrictManager restrictManager, + QualityMonitor cellularQualityMonitor, + QualityMonitor wifiQualityMonitor, + int callType) { + int netCapability = info.getNetCapability(); + int firstQualifiedRat = getQualifiedAccessNetwork(info, 0); + int secondQualifiedRat = getQualifiedAccessNetwork(info, 1); + boolean wfcEnabled = getWfcEnabled(coverage, settingWfcEnabled, settingWfcRoamingEnabled); + int wfcMode = getWfcMode(coverage, settingWfcMode, settingWfcRoamingMode); + int iwlanNetworkType = getIwlanNetworkType(iwlanAvailable, isCrossWfc); + int restrictionsOnWwan = getRestrictionsBitmask( + AccessNetworkConstants.TRANSPORT_TYPE_WWAN, restrictManager); + int restrictionsOnWlan = getRestrictionsBitmask( + AccessNetworkConstants.TRANSPORT_TYPE_WLAN, restrictManager); + int signalStrength = getSignalStrength(cellularQualityMonitor, cellularAccessNetworkType); + int signalQuality = getSignalQuality(cellularQualityMonitor, cellularAccessNetworkType); + int signalNoise = getSignalNoise(cellularQualityMonitor, cellularAccessNetworkType); + int iwlanSignalStrength = getSignalStrength(wifiQualityMonitor, AccessNetworkType.IWLAN); + int updateReason = 0; + int imsCallQuality = 0; + + writeQualifiedRatListChangedInfo( + netCapability, + slotId, + firstQualifiedRat, + secondQualifiedRat, + dataConnectedTransportType, + wfcEnabled, + wfcMode, + cellularAccessNetworkType, + iwlanNetworkType, + restrictionsOnWwan, + restrictionsOnWlan, + signalStrength, + signalQuality, + signalNoise, + iwlanSignalStrength, + updateReason, + callType, + imsCallQuality); + } + + + private void procQualifiedNetworksForHandoverTime(QualifiedNetworksInfo info, int slotId) { + if (info.getNetCapability() != NetworkCapabilities.NET_CAPABILITY_IMS) { + return; + } + + HandoverTimeStateMachine handoverTimeStateMachine = mHandoverTimeMap.get(slotId); + if (handoverTimeStateMachine == null) { + handoverTimeStateMachine = + new HandoverTimeStateMachine(info.getNetCapability(), slotId, mHandler); + mHandoverTimeMap.put(slotId, handoverTimeStateMachine); + } + + handoverTimeStateMachine.sendQualifiedRatChanged(info); + } + + private void procDataConnectionChangedForHandoverTime( + int netCapability, int slotId, DataConnectionChangedInfo info) { + if (netCapability != NetworkCapabilities.NET_CAPABILITY_IMS) { + return; + } + + HandoverTimeStateMachine handoverTimeStateMachine = mHandoverTimeMap.get(slotId); + if (handoverTimeStateMachine == null) { + handoverTimeStateMachine = + new HandoverTimeStateMachine(netCapability, slotId, mHandler); + mHandoverTimeMap.put(slotId, handoverTimeStateMachine); + } + + handoverTimeStateMachine.sendDataStateChanged(info); + } + + private void procDataConnectionChangedForHandoverPingPong(int netCapability, int slotId, + DataConnectionChangedInfo info, int carrierId) { + if (netCapability != NetworkCapabilities.NET_CAPABILITY_IMS) { + return; + } + + PingPongTime pingPongTime = mPingPongTime.get(slotId); + if (pingPongTime == null) { + pingPongTime = new PingPongTime(); + mPingPongTime.put(slotId, pingPongTime); + } + + boolean bActiveState; + switch (info.getState()) { + case DataConnectionStatusTracker.STATE_INACTIVE: + case DataConnectionStatusTracker.STATE_CONNECTING: + bActiveState = false; + break; + case DataConnectionStatusTracker.STATE_CONNECTED: + case DataConnectionStatusTracker.STATE_HANDOVER: + default: + bActiveState = true; + break; + } + switch (info.getEvent()) { + case DataConnectionStatusTracker.EVENT_DATA_CONNECTION_CONNECTED: + pingPongTime.mSuccessTime = QnsUtils.getSystemElapsedRealTime(); + pingPongTime.mHandoverCount = 0; + break; + case DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED: + pingPongTime.mStartTime = QnsUtils.getSystemElapsedRealTime(); + break; + case DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_SUCCESS: + pingPongTime.mHandoverCount++; + pingPongTime.mSuccessTime = QnsUtils.getSystemElapsedRealTime(); + break; + } + + if (pingPongTime.mStartTime != 0L && pingPongTime.mSuccessTime != 0L) { + long pingPongTimeLimit = AtomsQnsHandoverPingPongInfo.PING_PONG_TIME_IN_MILLIS; + long elapsed = + (pingPongTime.mSuccessTime > pingPongTime.mStartTime) + ? (pingPongTime.mSuccessTime - pingPongTime.mStartTime) + : (pingPongTime.mStartTime - pingPongTime.mSuccessTime); + if (pingPongTime.mHandoverCount > 0) { + log("HandoverPingPong elapsed:" + elapsed + + " ping-pong count:" + (pingPongTime.mHandoverCount / 2)); + } + if (elapsed > pingPongTimeLimit || !bActiveState) { + if (pingPongTime.mHandoverCount > 1) { + int pingpongCount = pingPongTime.mHandoverCount / 2; + writeQnsHandoverPingPong(slotId, pingpongCount, carrierId); + } + pingPongTime.mHandoverCount = 0; + pingPongTime.mStartTime = 0L; + pingPongTime.mSuccessTime = 0L; + procDataConnectionChangedForHandoverPingPong( + netCapability, slotId, info, carrierId); + } + } + if (!bActiveState) { + pingPongTime.mHandoverCount = 0; + pingPongTime.mStartTime = 0L; + pingPongTime.mSuccessTime = 0L; + } + } + + private void procRestrictionsForFallback(int netCapability, int slotId, + List<Integer> wlanRestrictions, List<Integer> wwanRestrictions, int carrierId) { + if (netCapability != NetworkCapabilities.NET_CAPABILITY_IMS + || wlanRestrictions == null + || wwanRestrictions == null) { + return; + } + + boolean bRestrictionOnWlanByRtpThresholdBreached = + wlanRestrictions.contains(RestrictManager.RESTRICT_TYPE_RTP_LOW_QUALITY); + boolean bRestrictionOnWwanByRtpThresholdBreached = + wwanRestrictions.contains(RestrictManager.RESTRICT_TYPE_RTP_LOW_QUALITY); + boolean bRestrictionOnWlanByImsRegistrationFailed = + wlanRestrictions.contains( + RestrictManager.RESTRICT_TYPE_FALLBACK_TO_WWAN_IMS_REGI_FAIL); + boolean bRestrictionOnWlanByWifiBackhaulProblem = + wlanRestrictions.contains( + RestrictManager.RESTRICT_TYPE_FALLBACK_TO_WWAN_RTT_BACKHAUL_FAIL); + + // all false will not write atom because this atom is used for count metric. + if (bRestrictionOnWlanByRtpThresholdBreached + || bRestrictionOnWwanByRtpThresholdBreached + || bRestrictionOnWlanByImsRegistrationFailed + || bRestrictionOnWlanByWifiBackhaulProblem) { + writeQnsFallbackRestrictionChangedInfo( + bRestrictionOnWlanByRtpThresholdBreached, + bRestrictionOnWwanByRtpThresholdBreached, + bRestrictionOnWlanByImsRegistrationFailed, + bRestrictionOnWlanByWifiBackhaulProblem, + carrierId, + slotId); + } + } + + private void procDataConnectionChangedForRatMismatch( + int netCapability, int slotId, DataConnectionChangedInfo info, int carrierId) { + + RatMismatchTime mismatchTime = mRatMismatchTime.get(slotId); + if (mismatchTime == null) { + mismatchTime = new RatMismatchTime(); + mRatMismatchTime.put(slotId, mismatchTime); + } + + switch (info.getEvent()) { + case DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED: + if (mismatchTime.mCount == 0) { + mismatchTime.mStartTime = QnsUtils.getSystemElapsedRealTime(); + } + break; + case DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_FAILED: + mismatchTime.mCount++; + break; + default: + if (mismatchTime.mCount > 0) { + long duration = QnsUtils.getSystemElapsedRealTime() - mismatchTime.mStartTime; + int count = mismatchTime.mCount; + + writeQnsRatPreferenceMismatchInfo( + netCapability, count, (int) duration, carrierId, slotId); + mismatchTime.mCount = 0; + mismatchTime.mStartTime = 0L; + } + break; + } + } + + private void writeQualifiedRatListChangedInfo( + int netCapability, + int slotId, + int firstQualifiedRat, + int secondQualifiedRat, + int currentTransportType, + boolean wfcEnabled, + int wfcMode, + int cellularNetworkType, + int iwlanNetworkType, + int restrictionsOnWwan, + int restrictionsOnWlan, + int signalStrength, + int signalQuality, + int signalNoise, + int iwlanSignalStrength, + int updateReason, + int imsCallType, + int imsCallQuality) { + AtomsQualifiedRatListChangedInfo atoms = + new AtomsQualifiedRatListChangedInfo( + netCapability, + firstQualifiedRat, + secondQualifiedRat, + currentTransportType, + wfcEnabled, + wfcMode, + cellularNetworkType, + iwlanNetworkType, + restrictionsOnWwan, + restrictionsOnWlan, + signalStrength, + signalQuality, + signalNoise, + iwlanSignalStrength, + updateReason, + imsCallType, + imsCallQuality, + slotId); + mStats.write(atoms); + } + + + private void writeQnsHandoverTimeMillisInfo(long handoverTime, int slotIndex) { + AtomsQnsHandoverTimeMillisInfo atoms = + new AtomsQnsHandoverTimeMillisInfo((int) handoverTime, slotIndex); + mStats.append(atoms); + } + + private void writeQnsHandoverPingPong(int slotId, int pingPongCount, int carrierId) { + AtomsQnsHandoverPingPongInfo atoms = + new AtomsQnsHandoverPingPongInfo(pingPongCount, carrierId, slotId); + mStats.append(atoms); + } + + private void writeQnsFallbackRestrictionChangedInfo( + boolean bRestrictionOnWlanByRtpThresholdBreached, + boolean bRestrictionOnWwanByRtpThresholdBreached, + boolean bRestrictionOnWlanByImsRegistrationFailed, + boolean bRestrictionOnWlanByWifiBackhaulProblem, + int carrierId, + int slotId) { + AtomsQnsFallbackRestrictionChangedInfo atom = + new AtomsQnsFallbackRestrictionChangedInfo( + bRestrictionOnWlanByRtpThresholdBreached, + bRestrictionOnWwanByRtpThresholdBreached, + bRestrictionOnWlanByImsRegistrationFailed, + bRestrictionOnWlanByWifiBackhaulProblem, + carrierId, + slotId); + mStats.write(atom); + } + + private void writeQnsRatPreferenceMismatchInfo(int netCapability, int handoverFailCount, + int durationMismatch, int carrierId, int slotId) { + AtomsQnsRatPreferenceMismatchInfo atoms = new AtomsQnsRatPreferenceMismatchInfo( + netCapability, handoverFailCount, durationMismatch, carrierId, slotId); + mStats.append(atoms); + } + + class HandoverTimeStateMachine extends StateMachine { + + private static final int EVENT_DATA_STATE_CHANGED = 0; + private static final int EVENT_QUALIFIED_RAT_CHANGED = 1; + + private final IdleState mIdleState; + private final ConnectedState mConnectedState; + private final HandoverRequestedState mHandoverRequestedState; + private final HandoverInProgressState mHandoverInProgressState; + + private final int mNetCapability; + private final int mSlotId; + int mDataTransportType; + long mHandoverRequestedTime; + + HandoverTimeStateMachine(int netCapability, int slotId, Handler handler) { + super(mLogTag + "_" + HandoverTimeStateMachine.class.getSimpleName() + "_" + slotId + + "_" + QnsUtils.getNameOfNetCapability(netCapability), handler); + + mIdleState = new IdleState(); + mConnectedState = new ConnectedState(); + mHandoverRequestedState = new HandoverRequestedState(); + mHandoverInProgressState = new HandoverInProgressState(); + + mNetCapability = netCapability; + mSlotId = slotId; + mDataTransportType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID; + mHandoverRequestedTime = 0L; + + addState(mIdleState); + addState(mConnectedState); + addState(mHandoverRequestedState); + addState(mHandoverInProgressState); + setInitialState(mIdleState); + start(); + } + + public void sendDataStateChanged(DataConnectionChangedInfo info) { + sendMessage(EVENT_DATA_STATE_CHANGED, info); + } + + public void sendQualifiedRatChanged(QualifiedNetworksInfo info) { + sendMessage(EVENT_QUALIFIED_RAT_CHANGED, info); + } + + private final class IdleState extends State { + @Override + public void enter() { + log("IdleState"); + mDataTransportType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID; + mHandoverRequestedTime = 0L; + } + + @Override + public boolean processMessage(Message msg) { + log("IdleState processMessage=" + msg.what); + switch (msg.what) { + case EVENT_DATA_STATE_CHANGED: + DataConnectionChangedInfo dataInfo = (DataConnectionChangedInfo) msg.obj; + switch (dataInfo.getState()) { + case DataConnectionStatusTracker.STATE_CONNECTED: + mDataTransportType = dataInfo.getTransportType(); + transitionTo(mConnectedState); + return HANDLED; + case DataConnectionStatusTracker.STATE_HANDOVER: + mDataTransportType = dataInfo.getTransportType(); + transitionTo(mConnectedState); + break; + } + break; + case EVENT_QUALIFIED_RAT_CHANGED: + break; + } + return super.processMessage(msg); + } + + @Override + public void exit() { + super.exit(); + } + } + + private final class ConnectedState extends State { + @Override + public void enter() { + log("ConnectedState"); + mHandoverRequestedTime = 0L; + } + + @Override + public boolean processMessage(Message msg) { + log("ConnectedState processMessage=" + msg.what); + switch (msg.what) { + case EVENT_DATA_STATE_CHANGED: + DataConnectionChangedInfo dataInfo = (DataConnectionChangedInfo) msg.obj; + switch (dataInfo.getState()) { + case DataConnectionStatusTracker.STATE_INACTIVE: + case DataConnectionStatusTracker.STATE_CONNECTING: + transitionTo(mIdleState); + break; + case DataConnectionStatusTracker.STATE_CONNECTED: + case DataConnectionStatusTracker.STATE_HANDOVER: + mDataTransportType = dataInfo.getTransportType(); + return HANDLED; + } + break; + case EVENT_QUALIFIED_RAT_CHANGED: + QualifiedNetworksInfo qualifiedInfo = (QualifiedNetworksInfo) msg.obj; + // handover trigger + if (mNetCapability == qualifiedInfo.getNetCapability() + && qualifiedInfo.getAccessNetworkTypes().stream().anyMatch( + accessNetwork -> QnsUtils.getTransportTypeFromAccessNetwork( + accessNetwork) != mDataTransportType)) { + mHandoverRequestedTime = QnsUtils.getSystemElapsedRealTime(); + transitionTo(mHandoverRequestedState); + return HANDLED; + } + break; + } + + return super.processMessage(msg); + } + + @Override + public void exit() { + super.exit(); + } + } + + private final class HandoverRequestedState extends State { + @Override + public void enter() { + log("HandoverRequestedState"); + } + + @Override + public boolean processMessage(Message msg) { + log("HandoverRequestedState processMessage=" + msg.what); + switch (msg.what) { + case EVENT_DATA_STATE_CHANGED: + DataConnectionChangedInfo dataInfo = (DataConnectionChangedInfo) msg.obj; + switch (dataInfo.getState()) { + case DataConnectionStatusTracker.STATE_INACTIVE: + case DataConnectionStatusTracker.STATE_CONNECTING: + transitionTo(mIdleState); + break; + case DataConnectionStatusTracker.STATE_CONNECTED: + if (dataInfo.getTransportType() != mDataTransportType) { + // back to connected state, already reached to target transport. + mDataTransportType = dataInfo.getTransportType(); + transitionTo(mConnectedState); + } + break; + case DataConnectionStatusTracker.STATE_HANDOVER: + if (dataInfo.getTransportType() != mDataTransportType) { + // back to connected state, already reached to target transport. + mDataTransportType = dataInfo.getTransportType(); + transitionTo(mConnectedState); + } + transitionTo(mHandoverInProgressState); + break; + } + break; + case EVENT_QUALIFIED_RAT_CHANGED: + QualifiedNetworksInfo qualifiedInfo = (QualifiedNetworksInfo) msg.obj; + if (mNetCapability != qualifiedInfo.getNetCapability()) { + break; + } + if (qualifiedInfo.getAccessNetworkTypes().stream().noneMatch( + accessNetwork -> QnsUtils.getTransportTypeFromAccessNetwork( + accessNetwork) != mDataTransportType)) { + // back to connected state. no handover target transport. + transitionTo(mConnectedState); + return HANDLED; + } + break; + } + return super.processMessage(msg); + } + + @Override + public void exit() { + super.exit(); + } + } + + private final class HandoverInProgressState extends State { + @Override + public void enter() { + log("HandoverInProgressState"); + } + + @Override + public boolean processMessage(Message msg) { + log("HandoverInProgressState processMessage=" + msg.what); + switch (msg.what) { + case EVENT_DATA_STATE_CHANGED: + DataConnectionChangedInfo dataInfo = (DataConnectionChangedInfo) msg.obj; + switch (dataInfo.getState()) { + case DataConnectionStatusTracker.STATE_INACTIVE: + case DataConnectionStatusTracker.STATE_CONNECTING: + transitionTo(mIdleState); + break; + case DataConnectionStatusTracker.STATE_CONNECTED: + if (dataInfo.getTransportType() != mDataTransportType) { + if (mHandoverRequestedTime == 0L) { + break; + } + // handover done. + long handoverTime = QnsUtils.getSystemElapsedRealTime() + - mHandoverRequestedTime; + writeQnsHandoverTimeMillisInfo(handoverTime, mSlotId); + mDataTransportType = dataInfo.getTransportType(); + mHandoverRequestedTime = 0L; + transitionTo(mConnectedState); + } else { + // handover didn't have done yet. + transitionTo(mHandoverRequestedState); + } + break; + case DataConnectionStatusTracker.STATE_HANDOVER: + if (dataInfo.getTransportType() != mDataTransportType) { + // back to connected state, already reached to target transport. + mDataTransportType = dataInfo.getTransportType(); + transitionTo(mConnectedState); + } + break; + } + break; + case EVENT_QUALIFIED_RAT_CHANGED: + QualifiedNetworksInfo qualifiedInfo = (QualifiedNetworksInfo) msg.obj; + if (mNetCapability == qualifiedInfo.getNetCapability() + && qualifiedInfo.getAccessNetworkTypes().stream().noneMatch( + accessNetwork -> QnsUtils.getTransportTypeFromAccessNetwork( + accessNetwork) != mDataTransportType)) { + // back to connected state. no handover request + transitionTo(mConnectedState); + return HANDLED; + } + break; + } + return super.processMessage(msg); + } + + @Override + public void exit() { + super.exit(); + } + } + } + + private static class PingPongTime { + int mHandoverCount = 0; + long mStartTime = 0L; + long mSuccessTime = 0L; + } + + private static class RatMismatchTime { + int mCount = 0; + long mStartTime = 0L; + } + + private static class RtpCallDrop { + boolean mRtpThresholdBreached; + int mRestrictionsOnOtherTransportType; + } + + + private void procCallTypeChangedForImsCallDrop( + int netCapability, + int slotId, + int oldCallType, + int newCallType, + RestrictManager restrictManager, + int transportTypeOfCall) { + if (netCapability != NetworkCapabilities.NET_CAPABILITY_IMS) { + return; + } + + RtpCallDrop rtpCallDrop = mRtpCallDrop.get(slotId); + if (rtpCallDrop == null) { + rtpCallDrop = new RtpCallDrop(); + mRtpCallDrop.put(slotId, rtpCallDrop); + } + + // call ended + if (newCallType == QnsConstants.CALL_TYPE_IDLE + && oldCallType != QnsConstants.CALL_TYPE_IDLE) { + rtpCallDrop.mRtpThresholdBreached = + restrictManager.hasRestrictionType( + transportTypeOfCall, RestrictManager.RESTRICT_TYPE_RTP_LOW_QUALITY); + int otherTransportType = + transportTypeOfCall == AccessNetworkConstants.TRANSPORT_TYPE_WLAN + ? AccessNetworkConstants.TRANSPORT_TYPE_WWAN + : AccessNetworkConstants.TRANSPORT_TYPE_WLAN; + rtpCallDrop.mRestrictionsOnOtherTransportType = + getRestrictionsBitmask(otherTransportType, restrictManager); + } else { + rtpCallDrop.mRtpThresholdBreached = false; + rtpCallDrop.mRestrictionsOnOtherTransportType = 0; + } + } + + private void procCallDroppedForImsCallDrop( + int netCapability, + int slotId, + RestrictManager restrictManager, + QualityMonitor cellularQualityMonitor, + QualityMonitor wifiQualityMonitor, + int transportTypeOfCall, + int cellularAccessNetworkType) { + if (netCapability != NetworkCapabilities.NET_CAPABILITY_IMS) { + return; + } + + RtpCallDrop rtpCallDrop = mRtpCallDrop.get(slotId); + if (rtpCallDrop == null) { + rtpCallDrop = new RtpCallDrop(); + mRtpCallDrop.put(slotId, rtpCallDrop); + } + + if (!rtpCallDrop.mRtpThresholdBreached + || rtpCallDrop.mRestrictionsOnOtherTransportType == 0) { + rtpCallDrop.mRtpThresholdBreached = restrictManager.hasRestrictionType( + transportTypeOfCall, RestrictManager.RESTRICT_TYPE_RTP_LOW_QUALITY); + int otherTransportType = + transportTypeOfCall == AccessNetworkConstants.TRANSPORT_TYPE_WLAN + ? AccessNetworkConstants.TRANSPORT_TYPE_WWAN + : AccessNetworkConstants.TRANSPORT_TYPE_WLAN; + rtpCallDrop.mRestrictionsOnOtherTransportType = + getRestrictionsBitmask(otherTransportType, restrictManager); + } + + int signalStrength = getSignalStrength(cellularQualityMonitor, cellularAccessNetworkType); + int signalQuality = getSignalQuality(cellularQualityMonitor, cellularAccessNetworkType); + int signalNoise = getSignalNoise(cellularQualityMonitor, cellularAccessNetworkType); + int iwlanSignalStrength = getSignalStrength(wifiQualityMonitor, AccessNetworkType.IWLAN); + + writeQnsImsCallDropStats( + transportTypeOfCall, + rtpCallDrop.mRtpThresholdBreached, + rtpCallDrop.mRestrictionsOnOtherTransportType, + signalStrength, + signalQuality, + signalNoise, + iwlanSignalStrength, + cellularAccessNetworkType, + slotId); + } + + private void writeQnsImsCallDropStats( + int transportTypeCallDropped, + boolean rtpThresholdBreached, + int restrictionsOnOtherTransportType, + int signalStrength, + int signalQuality, + int signalNoise, + int iwlanSignalStrength, + int cellularNetworkType, + int slotId) { + AtomsQnsImsCallDropStats atoms = + new AtomsQnsImsCallDropStats( + transportTypeCallDropped, + rtpThresholdBreached, + restrictionsOnOtherTransportType, + signalStrength, + signalQuality, + signalNoise, + iwlanSignalStrength, + slotId, + cellularNetworkType); + mStats.write(atoms); + } + + private int getQualifiedAccessNetwork(QualifiedNetworksInfo info, int index) { + List<Integer> types = info.getAccessNetworkTypes(); + if (types == null || index >= types.size()) { + return QnsProtoEnums.EMPTY; + } + return types.get(index); + } + + private boolean getWfcEnabled(int coverage, boolean wfcEnabled, boolean wfcRoamingEnabled) { + return coverage == QnsConstants.COVERAGE_HOME ? wfcEnabled : wfcRoamingEnabled; + } + + private int getWfcMode(int coverage, int wfcMode, int wfcRoamingMode) { + return coverage == QnsConstants.COVERAGE_HOME ? wfcMode : wfcRoamingMode; + } + + private int getIwlanNetworkType(boolean iwlanAvailable, boolean isCrossWfc) { + if (!iwlanAvailable) { + return QnsProtoEnums.IWLAN_NETWORK_TYPE_NONE; + } else if (isCrossWfc) { + return QnsProtoEnums.IWLAN_NETWORK_TYPE_CST; + } + return QnsProtoEnums.IWLAN_NETWORK_TYPE_WIFI; + } + + static final HashMap<Integer, Integer> sAtomRestrictionsMap; + + static { + sAtomRestrictionsMap = new HashMap<>(); + sAtomRestrictionsMap.put( + RestrictManager.RESTRICT_TYPE_GUARDING, QnsProtoEnums.RESTRICT_TYPE_GUARDING); + sAtomRestrictionsMap.put( + RestrictManager.RESTRICT_TYPE_THROTTLING, QnsProtoEnums.RESTRICT_TYPE_THROTTLING); + sAtomRestrictionsMap.put( + RestrictManager.RESTRICT_TYPE_HO_NOT_ALLOWED, + QnsProtoEnums.RESTRICT_TYPE_HO_NOT_ALLOWED); + sAtomRestrictionsMap.put( + RestrictManager.RESTRICT_TYPE_NON_PREFERRED_TRANSPORT, + QnsProtoEnums.RESTRICT_TYPE_NON_PREFERRED_TRANSPORT); + sAtomRestrictionsMap.put( + RestrictManager.RESTRICT_TYPE_RTP_LOW_QUALITY, + QnsProtoEnums.RESTRICT_TYPE_RTP_LOW_QUALITY); + sAtomRestrictionsMap.put( + RestrictManager.RESTRICT_TYPE_RESTRICT_IWLAN_IN_CALL, + QnsProtoEnums.RESTRICT_TYPE_RESTRICT_IWLAN_IN_CALL); + sAtomRestrictionsMap.put( + RestrictManager.RESTRICT_TYPE_RESTRICT_IWLAN_CS_CALL, + QnsProtoEnums.RESTRICT_TYPE_RESTRICT_IWLAN_CS_CALL); + sAtomRestrictionsMap.put( + RestrictManager.RESTRICT_TYPE_FALLBACK_TO_WWAN_IMS_REGI_FAIL, + QnsProtoEnums.RESTRICT_TYPE_FALLBACK_TO_WWAN_IMS_REGI_FAIL); + sAtomRestrictionsMap.put( + RestrictManager.RESTRICT_TYPE_FALLBACK_ON_DATA_CONNECTION_FAIL, + QnsProtoEnums.RESTRICT_TYPE_FALLBACK_ON_DATA_CONNECTION_FAIL); + sAtomRestrictionsMap.put( + RestrictManager.RESTRICT_TYPE_FALLBACK_TO_WWAN_RTT_BACKHAUL_FAIL, + QnsProtoEnums.RESTRICT_TYPE_FALLBACK_TO_WWAN_RTT_BACKHAUL_FAIL); + } + + private int getRestrictionsBitmask(int transportType, RestrictManager restrictManager) { + int restrictions = QnsProtoEnums.RESTRICT_TYPE_NONE; + for (int restrictionType : sAtomRestrictionsMap.keySet()) { + if (restrictManager.hasRestrictionType(transportType, restrictionType)) { + restrictions |= sAtomRestrictionsMap.get(restrictionType); + } + } + return restrictions; + } + + private int getSignalStrength(QualityMonitor qm, int accessNetworkType) { + switch (accessNetworkType) { + case AccessNetworkType.GERAN: + case AccessNetworkType.IWLAN: + return qm.getCurrentQuality( + accessNetworkType, SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSI); + case AccessNetworkType.UTRAN: + return qm.getCurrentQuality( + accessNetworkType, SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSCP); + case AccessNetworkType.EUTRAN: + return qm.getCurrentQuality( + accessNetworkType, SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSRP); + case AccessNetworkType.NGRAN: + return qm.getCurrentQuality( + accessNetworkType, SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSRSRP); + } + return 0; + } + + private int getSignalQuality(QualityMonitor qm, int accessNetworkType) { + switch (accessNetworkType) { + case AccessNetworkType.EUTRAN: + return qm.getCurrentQuality( + accessNetworkType, SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSRQ); + case AccessNetworkType.NGRAN: + return qm.getCurrentQuality( + accessNetworkType, SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSRSRQ); + } + return 0; + } + + private int getSignalNoise(QualityMonitor qm, int accessNetworkType) { + switch (accessNetworkType) { + case AccessNetworkType.EUTRAN: + return qm.getCurrentQuality( + accessNetworkType, SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_RSSNR); + case AccessNetworkType.NGRAN: + return qm.getCurrentQuality( + accessNetworkType, SignalThresholdInfo.SIGNAL_MEASUREMENT_TYPE_SSSINR); + } + return 0; + } + + protected void log(String s) { + Log.d(mLogTag, s); + } +} diff --git a/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsTelephonyListener.java b/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsTelephonyListener.java index 32883d4..9e59736 100644 --- a/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsTelephonyListener.java +++ b/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsTelephonyListener.java @@ -37,6 +37,7 @@ import android.telephony.SubscriptionManager; import android.telephony.TelephonyCallback; import android.telephony.TelephonyManager; import android.telephony.VopsSupportInfo; +import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.MediaQualityStatus; import android.util.Log; @@ -69,6 +70,7 @@ class QnsTelephonyListener { QnsRegistrantList mSrvccStateListener = new QnsRegistrantList(); QnsRegistrantList mSubscriptionIdListener = new QnsRegistrantList(); QnsRegistrantList mIwlanServiceStateListener = new QnsRegistrantList(); + QnsRegistrantList mImsCallDropDisconnectCauseListener = new QnsRegistrantList(); List<Consumer<List<CallState>>> mCallStatesConsumerList = new ArrayList<>(); List<Consumer<Integer>> mSrvccStateConsumerList = new ArrayList<>(); List<Consumer<MediaQualityStatus>> mMediaQualityConsumerList = new ArrayList<>(); @@ -327,6 +329,21 @@ class QnsTelephonyListener { } /** + * Register an event for ImsCallDropDisconnectCause changed. + * + * @param h the Handler to get event. + * @param what the event. + * @param userObj user object. + */ + void registerImsCallDropDisconnectCauseListener(Handler h, int what, Object userObj) { + log("registerImsCallDropDisconnectCauseListener"); + if (h != null) { + QnsRegistrant r = new QnsRegistrant(h, what, userObj); + mImsCallDropDisconnectCauseListener.add(r); + } + } + + /** * Unregister an event for QnsTelephonyInfo changed. * * @param netCapability Network Capability to be notified. @@ -406,6 +423,18 @@ class QnsTelephonyListener { } } + /** + * Unregister an event for ImsCallDropDisconnectCause state changed. + * + * @param h the handler to get event. + */ + void unregisterImsCallDropDisconnectCauseListener(Handler h) { + log("unregisterImsCallDropDisconnectCauseListener"); + if (h != null) { + mImsCallDropDisconnectCauseListener.remove(h); + } + } + private void createTelephonyListener() { if (mTelephonyListener == null) { mTelephonyListener = new TelephonyListener(mContext.getMainExecutor()); @@ -429,6 +458,10 @@ class QnsTelephonyListener { (int srvccState) -> { onSrvccStateChanged(srvccState); }); + mTelephonyListener.setImsCallDisconnectCauseListener( + (ImsReasonInfo imsReasonInfo) -> { + onImsCallDisconnectCauseChanged(imsReasonInfo); + }); } } @@ -721,6 +754,10 @@ class QnsTelephonyListener { mSubscriptionIdListener.notifyResult(subId); } + protected void onImsCallDisconnectCauseChanged(ImsReasonInfo imsReasonInfo) { + mImsCallDropDisconnectCauseListener.notifyResult(imsReasonInfo); + } + protected void log(String s) { Log.d(mLogTag, s); } @@ -769,6 +806,11 @@ class QnsTelephonyListener { void onCallStatesChanged(List<CallState> callStateList); } + protected interface OnImsCallDisconnectCauseListener { + /** Notify the call disconnected cause changed. */ + void onImsCallDisconnectCauseChanged(@NonNull ImsReasonInfo imsReasonInfo); + } + protected static class Archiving<V> { protected HashMap<String, V> mArchiving = new HashMap<>(); @@ -1037,7 +1079,8 @@ class QnsTelephonyListener { TelephonyCallback.CallStateListener, TelephonyCallback.SrvccStateListener, TelephonyCallback.CallAttributesListener, - TelephonyCallback.MediaQualityStatusChangedListener { + TelephonyCallback.MediaQualityStatusChangedListener, + TelephonyCallback.ImsCallDisconnectCauseListener { private final Executor mExecutor; private OnServiceStateListener mServiceStateListener; private OnPreciseDataConnectionStateListener mPreciseDataConnectionStateListener; @@ -1046,6 +1089,7 @@ class QnsTelephonyListener { private OnSrvccStateChangedCallback mSrvccStateCallback; private OnSrvccStateChangedCallback mSrvccStateListener; private OnCallStatesChangedCallback mCallStatesCallback; + private OnImsCallDisconnectCauseListener mImsCallDisconnectCauseListener; private TelephonyManager mTelephonyManager; TelephonyListener(Executor executor) { @@ -1080,6 +1124,11 @@ class QnsTelephonyListener { void setCallStatesCallback(OnCallStatesChangedCallback listener) { mCallStatesCallback = listener; } + + void setImsCallDisconnectCauseListener(OnImsCallDisconnectCauseListener listener) { + mImsCallDisconnectCauseListener = listener; + } + /** * Register a TelephonyCallback for this listener. * @@ -1168,6 +1217,13 @@ class QnsTelephonyListener { consumer.accept(status); } } + + @Override + public void onImsCallDisconnectCauseChanged(@NonNull ImsReasonInfo imsReasonInfo) { + if (mImsCallDisconnectCauseListener != null) { + mImsCallDisconnectCauseListener.onImsCallDisconnectCauseChanged(imsReasonInfo); + } + } } void addCallStatesChangedCallback(Consumer<List<CallState>> consumer) { diff --git a/services/QualifiedNetworksService/src/com/android/telephony/qns/RestrictManager.java b/services/QualifiedNetworksService/src/com/android/telephony/qns/RestrictManager.java index 9ae8a1d..1c15346 100644 --- a/services/QualifiedNetworksService/src/com/android/telephony/qns/RestrictManager.java +++ b/services/QualifiedNetworksService/src/com/android/telephony/qns/RestrictManager.java @@ -162,6 +162,7 @@ class RestrictManager { private QnsCallStatusTracker.ActiveCallTracker mActiveCallTracker; private QnsImsManager mQnsImsManager; private WifiBackhaulMonitor mWifiBackhaulMonitor; + private QnsMetrics mQnsMetrics; private int mNetCapability; private int mSlotId; private int mTransportType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID; @@ -456,6 +457,7 @@ class RestrictManager { mDataConnectionStatusTracker = dcst; mQnsCallStatusTracker = qnsComponents.getQnsCallStatusTracker(mSlotId); mActiveCallTracker = qnsComponents.getQnsCallStatusTracker(mSlotId).getActiveCallTracker(); + mQnsMetrics = qnsComponents.getQnsMetrics(); mDataConnectionStatusTracker.registerDataConnectionStatusChanged( mHandler, EVENT_DATA_CONNECTION_CHANGED); if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) { @@ -1440,6 +1442,9 @@ class RestrictManager { Log.d(mLogTag, "notifyRestrictInfoChanged"); if (mRestrictInfoRegistrant != null) { mRestrictInfoRegistrant.notifyResult(mRestrictInfos); + + // metrics + sendRestrictionsForMetrics(); } else { Log.d(mLogTag, "notifyRestrictInfoChanged. no Registrant."); } @@ -1684,4 +1689,24 @@ class RestrictManager { + QnsConstants.callStateToString(mCallState)); pw.println(prefix + "mRestrictInfos=" + mRestrictInfos); } + + private void sendRestrictionsForMetrics() { + if (mNetCapability != NetworkCapabilities.NET_CAPABILITY_IMS) { + return; + } + ArrayList<Integer> wlanRestrictions = + new ArrayList<>( + mRestrictInfos + .get(AccessNetworkConstants.TRANSPORT_TYPE_WLAN) + .getRestrictionMap() + .keySet()); + ArrayList<Integer> wwanRestrictions = + new ArrayList<>( + mRestrictInfos + .get(AccessNetworkConstants.TRANSPORT_TYPE_WLAN) + .getRestrictionMap() + .keySet()); + mQnsMetrics.reportAtomForRestrictions(mNetCapability, mSlotId, + wlanRestrictions, wwanRestrictions, mQnsCarrierConfigManager.getCarrierId()); + } } diff --git a/services/QualifiedNetworksService/src/com/android/telephony/qns/atoms/AtomsQnsFallbackRestrictionChangedInfo.java b/services/QualifiedNetworksService/src/com/android/telephony/qns/atoms/AtomsQnsFallbackRestrictionChangedInfo.java new file mode 100644 index 0000000..05a2fdf --- /dev/null +++ b/services/QualifiedNetworksService/src/com/android/telephony/qns/atoms/AtomsQnsFallbackRestrictionChangedInfo.java @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2022 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.telephony.qns.atoms; + +import android.util.StatsEvent; + +import com.android.telephony.qns.stats.QnsStatsLog; +import com.android.telephony.statslib.AtomsPushed; + +import java.util.Objects; + +/** AtomsQnsFallbackRestrictionChangedInfo class */ +public class AtomsQnsFallbackRestrictionChangedInfo extends AtomsPushed { + + /** atom #1 : Restriction on WLAN caused by RTP threshold breached */ + private boolean mRestrictionOnWlanByRtpThresholdBreached; + + /** atom #2 : Restriction on WWAN caused by RTP threshold breached */ + private boolean mRestrictionOnWwanByRtpThresholdBreached; + + /** atom #3 : Restriction on WLAN caused by IMS registration fail */ + private boolean mRestrictionOnWlanByImsRegistrationFailed; + + /** atom #4 : Restriction on WLAN caused by Wi-Fi backhaul problem. */ + private boolean mRestrictionOnWlanByWifiBackhaulProblem; + + /** atom #5 : Carrier Id */ + private int mCarrierId; + + /** atom #6 : Slot Index */ + private int mSlotIndex; + + /** Constructor of AtomsQnsFallbackRestrictionChangedInfo */ + public AtomsQnsFallbackRestrictionChangedInfo() {} + + /** + * Constructor of AtomsQnsFallbackRestrictionChangedInfo + * + * @param restrictionOnWlanByRtpThresholdBreached Restriction on wlan caused by RTP threshold + * breached + * @param restrictionOnWwanByRtpThresholdBreached Restriction on wwan caused by RTP threshold + * breached + * @param restrictionOnWlanByImsRegistrationFailed Restriction on wlan caused by IMS + * registration fail + * @param restrictionOnWlanByWifiBackhaulProblem Restriction on wlan caused by Wifi backhaul + * problem. + * @param carrierId Carrier Id + * @param slotIndex Index of sim slot + */ + public AtomsQnsFallbackRestrictionChangedInfo( + boolean restrictionOnWlanByRtpThresholdBreached, + boolean restrictionOnWwanByRtpThresholdBreached, + boolean restrictionOnWlanByImsRegistrationFailed, + boolean restrictionOnWlanByWifiBackhaulProblem, + int carrierId, + int slotIndex) { + mRestrictionOnWlanByRtpThresholdBreached = restrictionOnWlanByRtpThresholdBreached; + mRestrictionOnWwanByRtpThresholdBreached = restrictionOnWwanByRtpThresholdBreached; + mRestrictionOnWlanByImsRegistrationFailed = restrictionOnWlanByImsRegistrationFailed; + mRestrictionOnWlanByWifiBackhaulProblem = restrictionOnWlanByWifiBackhaulProblem; + mCarrierId = carrierId; + mSlotIndex = slotIndex; + } + + /** + * Copy Constructor of AtomsQnsFallbackRestrictionChangedInfo + * + * @param info The info param to copy from. + */ + public AtomsQnsFallbackRestrictionChangedInfo(AtomsQnsFallbackRestrictionChangedInfo info) { + mRestrictionOnWlanByRtpThresholdBreached = info.mRestrictionOnWlanByRtpThresholdBreached; + mRestrictionOnWwanByRtpThresholdBreached = info.mRestrictionOnWwanByRtpThresholdBreached; + mRestrictionOnWlanByImsRegistrationFailed = info.mRestrictionOnWlanByImsRegistrationFailed; + mRestrictionOnWlanByWifiBackhaulProblem = info.mRestrictionOnWlanByWifiBackhaulProblem; + mCarrierId = info.mCarrierId; + mSlotIndex = info.mSlotIndex; + } + + /** + * Write the atom information to be recorded to the builder according to the type in order. + * + * @param builder Builder class for StatsEvent Builder object. + */ + @Override + public void build(StatsEvent.Builder builder) { + builder.writeBoolean(mRestrictionOnWlanByRtpThresholdBreached); // atom #1 + builder.writeBoolean(mRestrictionOnWwanByRtpThresholdBreached); // atom #2 + builder.writeBoolean(mRestrictionOnWlanByImsRegistrationFailed); // atom #3 + builder.writeBoolean(mRestrictionOnWlanByWifiBackhaulProblem); // atom #4 + builder.writeInt(mCarrierId); // atom #5 + builder.writeInt(mSlotIndex); // atom #6 + } + + /** Return atom id defined in proto. */ + @Override + public int getStatsId() { + return QnsStatsLog.QNS_FALLBACK_RESTRICTION_CHANGED; + } + + /** Return copy of the AtomsQnsFallbackRestrictionChangedInfo */ + @Override + public AtomsPushed copy() { + return new AtomsQnsFallbackRestrictionChangedInfo(this); + } + + public boolean getRestrictionOnWlanByRtpThresholdBreached() { + return mRestrictionOnWlanByRtpThresholdBreached; + } + + public void setRestrictionOnWlanByRtpThresholdBreached( + boolean restrictionOnWlanByRtpThresholdBreached) { + mRestrictionOnWlanByRtpThresholdBreached = restrictionOnWlanByRtpThresholdBreached; + } + + public boolean getRestrictionOnWwanByRtpThresholdBreached() { + return mRestrictionOnWwanByRtpThresholdBreached; + } + + public void setRestrictionOnWwanByRtpThresholdBreached( + boolean restrictionOnWwanByRtpThresholdBreached) { + mRestrictionOnWwanByRtpThresholdBreached = restrictionOnWwanByRtpThresholdBreached; + } + + public boolean getRestrictionOnWlanByImsRegistrationFailed() { + return mRestrictionOnWlanByImsRegistrationFailed; + } + + public void setRestrictionOnWlanByImsRegistrationFailed( + boolean restrictionOnWlanByImsRegistrationFailed) { + mRestrictionOnWlanByImsRegistrationFailed = restrictionOnWlanByImsRegistrationFailed; + } + + public boolean getRestrictionOnWlanByWifiBackhaulProblem() { + return mRestrictionOnWlanByWifiBackhaulProblem; + } + + public void setRestrictionOnWlanByWifiBackhaulProblem( + boolean restrictionOnWlanByWifiBackhaulProblem) { + mRestrictionOnWlanByWifiBackhaulProblem = restrictionOnWlanByWifiBackhaulProblem; + } + + public int getCarrierId() { + return mCarrierId; + } + + public void setCarrierId(int carrierId) { + mCarrierId = carrierId; + } + + public int getSlotIndex() { + return mSlotIndex; + } + + public void setSlotIndex(int slotIndex) { + mSlotIndex = slotIndex; + } + + @Override + public String toString() { + return "AtomsQnsFallbackRestrictionChangedInfo{" + + "mRestrictionWlanRtpThresholdBreached=" + + mRestrictionOnWlanByRtpThresholdBreached + + ", mRestrictionWwanRtpThresholdBreached=" + + mRestrictionOnWwanByRtpThresholdBreached + + ", mRestrictionWwanImsRegiFail=" + + mRestrictionOnWlanByImsRegistrationFailed + + ", mRestrictionWwanWifiBackhaulProblem=" + + mRestrictionOnWlanByWifiBackhaulProblem + + ", mCarrierId=" + + mCarrierId + + ", mSlotIndex=" + + mSlotIndex + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof AtomsQnsFallbackRestrictionChangedInfo)) return false; + AtomsQnsFallbackRestrictionChangedInfo that = (AtomsQnsFallbackRestrictionChangedInfo) o; + return mRestrictionOnWlanByRtpThresholdBreached + == that.mRestrictionOnWlanByRtpThresholdBreached + && mRestrictionOnWwanByRtpThresholdBreached + == that.mRestrictionOnWwanByRtpThresholdBreached + && mRestrictionOnWlanByImsRegistrationFailed + == that.mRestrictionOnWlanByImsRegistrationFailed + && mRestrictionOnWlanByWifiBackhaulProblem + == that.mRestrictionOnWlanByWifiBackhaulProblem + && mCarrierId == that.mCarrierId + && mSlotIndex == that.mSlotIndex; + } + + @Override + public int hashCode() { + return Objects.hash( + mRestrictionOnWlanByRtpThresholdBreached, + mRestrictionOnWwanByRtpThresholdBreached, + mRestrictionOnWlanByImsRegistrationFailed, + mRestrictionOnWlanByWifiBackhaulProblem, + mCarrierId, + mSlotIndex); + } +} diff --git a/services/QualifiedNetworksService/src/com/android/telephony/qns/atoms/AtomsQnsHandoverPingPongInfo.java b/services/QualifiedNetworksService/src/com/android/telephony/qns/atoms/AtomsQnsHandoverPingPongInfo.java new file mode 100644 index 0000000..a714e58 --- /dev/null +++ b/services/QualifiedNetworksService/src/com/android/telephony/qns/atoms/AtomsQnsHandoverPingPongInfo.java @@ -0,0 +1,159 @@ +/* + * Copyright (C) 2022 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.telephony.qns.atoms; + +import android.util.StatsEvent; + +import com.android.telephony.qns.stats.QnsStatsLog; +import com.android.telephony.statslib.AtomsPulled; + +import java.io.Serializable; +import java.util.Objects; + +/** AtomsQnsHandoverPingPongInfo class */ +public class AtomsQnsHandoverPingPongInfo extends AtomsPulled implements Serializable { + + private static final long serialVersionUID = 815898959L; // 0x30A1A14F + + /** atom #1 : Count of handover ping-pong */ + private int mCountHandoverPingPong; + + /** atom #2 : Carrier Id */ + private int mCarrierId; + + /** atom #3 : Slot Index */ + private int mSlotIndex; + + /** Constructor of AtomsQnsHandoverPingPongInfo */ + public AtomsQnsHandoverPingPongInfo() {} + + /** + * Constructor of AtomsQnsHandoverPingPongInfo + * + * @param countHandoverPingPong count of Handover Ping-Pong + * @param carrierId Carrier Id + * @param slotIndex Index of sim slot + */ + public AtomsQnsHandoverPingPongInfo(int countHandoverPingPong, int carrierId, int slotIndex) { + mCountHandoverPingPong = countHandoverPingPong; + mCarrierId = carrierId; + mSlotIndex = slotIndex; + } + + /** + * Copy Constructor of AtomsQnsHandoverPingPongInfo + * + * @param info The info param to copy from. + */ + public AtomsQnsHandoverPingPongInfo(AtomsQnsHandoverPingPongInfo info) { + mCountHandoverPingPong = info.mCountHandoverPingPong; + mCarrierId = info.mCarrierId; + mSlotIndex = info.mSlotIndex; + } + + /** + * Write the atom information to be recorded to the builder according to the type in order. + * + * @param builder Builder class for StatsEvent Builder object. + */ + @Override + public void build(StatsEvent.Builder builder) { + builder.writeInt(mCountHandoverPingPong); // atom #1 + builder.writeInt(mCarrierId); // atom #2 + builder.writeInt(mSlotIndex); // atom #3 + } + + /** Return atom id defined in proto. */ + @Override + public int getStatsId() { + return QnsStatsLog.QNS_HANDOVER_PINGPONG; + } + + /** Return copy of the AtomsQnsHandoverPingPongInfo */ + @Override + public AtomsPulled copy() { + return new AtomsQnsHandoverPingPongInfo(this); + } + + @Override + public String getDimension() { + return mCarrierId + "_" + mSlotIndex; + } + + @Override + public void accumulate(AtomsPulled info) { + if (!(info instanceof AtomsQnsHandoverPingPongInfo)) { + return; + } + AtomsQnsHandoverPingPongInfo atomsQnsHandoverPingPongInfo = + (AtomsQnsHandoverPingPongInfo) info; + this.mCountHandoverPingPong += atomsQnsHandoverPingPongInfo.getCountHandoverPingPong(); + } + + public int getCountHandoverPingPong() { + return mCountHandoverPingPong; + } + + public void setCountHandoverPingPong(int countHandoverPingPong) { + mCountHandoverPingPong = countHandoverPingPong; + } + + public int getCarrierId() { + return mCarrierId; + } + + public void setCarrierId(int carrierId) { + mCarrierId = carrierId; + } + + public int getSlotIndex() { + return mSlotIndex; + } + + public void setSlotIndex(int slotIndex) { + mSlotIndex = slotIndex; + } + + @Override + public String toString() { + return "AtomsQnsHandoverPingPongInfo{" + + "mCountHandoverPingPong=" + + mCountHandoverPingPong + + ", mCarrierId=" + + mCarrierId + + ", mSlotIndex=" + + mSlotIndex + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof AtomsQnsHandoverPingPongInfo)) return false; + AtomsQnsHandoverPingPongInfo that = (AtomsQnsHandoverPingPongInfo) o; + return mCountHandoverPingPong == that.mCountHandoverPingPong + && mCarrierId == that.mCarrierId + && mSlotIndex == that.mSlotIndex; + } + + @Override + public int hashCode() { + return Objects.hash(mCountHandoverPingPong, mCarrierId, mSlotIndex); + } + + public static long PING_PONG_TIME_IN_MILLIS = 5000L; +} diff --git a/services/QualifiedNetworksService/src/com/android/telephony/qns/atoms/AtomsQnsHandoverTimeMillisInfo.java b/services/QualifiedNetworksService/src/com/android/telephony/qns/atoms/AtomsQnsHandoverTimeMillisInfo.java new file mode 100644 index 0000000..e6924ac --- /dev/null +++ b/services/QualifiedNetworksService/src/com/android/telephony/qns/atoms/AtomsQnsHandoverTimeMillisInfo.java @@ -0,0 +1,133 @@ +/* + * Copyright (C) 2022 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.telephony.qns.atoms; + +import android.util.StatsEvent; + +import com.android.telephony.qns.stats.QnsStatsLog; +import com.android.telephony.statslib.AtomsPulled; + +import java.io.Serializable; +import java.util.Objects; + +/** AtomsQnsHandoverTimeMillisInfo class */ +public class AtomsQnsHandoverTimeMillisInfo extends AtomsPulled implements Serializable { + + private static final long serialVersionUID = 1379441656L; // 0x52389BF8 + + /** atom #1 : Time in milliseconds from QNS RAT update to successful HO completion */ + private int mTimeForHoSuccess; + + /** atom #2 : Slot Index */ + private int mSlotIndex; + + /** Constructor of AtomsQnsHandoverTimeMillisInfo */ + public AtomsQnsHandoverTimeMillisInfo() {} + + /** + * Constructor of AtomsQnsHandoverTimeMillisInfo + * + * @param timeForHoSuccess Time in milliseconds from QNS RAT update to successful HO completion + * @param slotIndex Index of sim slot + */ + public AtomsQnsHandoverTimeMillisInfo(int timeForHoSuccess, int slotIndex) { + mTimeForHoSuccess = timeForHoSuccess; + mSlotIndex = slotIndex; + } + + /** + * Copy Constructor of AtomsQnsHandoverTimeMillisInfo + * + * @param info The info param to copy from. + */ + public AtomsQnsHandoverTimeMillisInfo(AtomsQnsHandoverTimeMillisInfo info) { + mTimeForHoSuccess = info.mTimeForHoSuccess; + mSlotIndex = info.mSlotIndex; + } + + /** + * Write the atom information to be recorded to the builder according to the type in order. + * + * @param builder Builder class for StatsEvent Builder object. + */ + @Override + public void build(StatsEvent.Builder builder) { + builder.writeInt(mTimeForHoSuccess); // atom #1 + builder.writeInt(mSlotIndex); // atom #2 + } + + /** Return atom id defined in proto. */ + @Override + public int getStatsId() { + return QnsStatsLog.QNS_HANDOVER_TIME_MILLIS; + } + + /** Return copy of the AtomsQnsHandoverTimeMillisInfo */ + @Override + public AtomsPulled copy() { + return new AtomsQnsHandoverTimeMillisInfo(this); + } + + @Override + public String getDimension() { + return Integer.toString(mSlotIndex); + } + + @Override + public void accumulate(AtomsPulled info) { + if (!(info instanceof AtomsQnsRatPreferenceMismatchInfo)) { + return; + } + AtomsQnsHandoverTimeMillisInfo atomsQnsHandoverTimeMillisInfo = + (AtomsQnsHandoverTimeMillisInfo) info; + this.mTimeForHoSuccess += atomsQnsHandoverTimeMillisInfo.getTimeForHoSuccess(); + } + + public int getTimeForHoSuccess() { + return mTimeForHoSuccess; + } + + public void setTimeForHoSuccess(int timeForHoSuccess) { + mTimeForHoSuccess = timeForHoSuccess; + } + + public int getSlotIndex() { + return mSlotIndex; + } + + public void setSlotIndex(int slotIndex) { + mSlotIndex = slotIndex; + } + + @Override + public String toString() { + return "AtomsQnsHandoverTimeMillisInfo{" + "mTimeForHoSuccess=" + mTimeForHoSuccess + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof AtomsQnsHandoverTimeMillisInfo)) return false; + AtomsQnsHandoverTimeMillisInfo that = (AtomsQnsHandoverTimeMillisInfo) o; + return mTimeForHoSuccess == that.mTimeForHoSuccess && mSlotIndex == that.mSlotIndex; + } + + @Override + public int hashCode() { + return Objects.hash(mTimeForHoSuccess, mSlotIndex); + } +} diff --git a/services/QualifiedNetworksService/src/com/android/telephony/qns/atoms/AtomsQnsImsCallDropStats.java b/services/QualifiedNetworksService/src/com/android/telephony/qns/atoms/AtomsQnsImsCallDropStats.java new file mode 100644 index 0000000..991bce4 --- /dev/null +++ b/services/QualifiedNetworksService/src/com/android/telephony/qns/atoms/AtomsQnsImsCallDropStats.java @@ -0,0 +1,265 @@ +/* + * Copyright (C) 2022 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.telephony.qns.atoms; + +import android.util.StatsEvent; + +import com.android.telephony.qns.stats.QnsStatsLog; +import com.android.telephony.statslib.AtomsPushed; + +import java.util.Objects; + +/** AtomsQnsImsCallDropStats class */ +public class AtomsQnsImsCallDropStats extends AtomsPushed { + + /** atom #1 : Transport type in where IMS call drop occurred. */ + private int mTransportTypeCallDropped; + + /** atom #2 : RTP threshold breached event occurred. */ + private boolean mRtpThresholdBreached; + + /** atom #3 : Bit mask of restrictions on another transport type */ + private int mRestrictionsOnOtherTransportType; + + /** atom #4 : Cellular network signal strength {e.g. SSRSRP in NR, RSRP in LTE} */ + private int mSignalStrength; + + /** atom #5 : Cellular network signal quality {e.g. SSRSRQ in NR, RSRQ in LTE} */ + private int mSignalQuality; + + /** atom #6 : Cellular network signal noise ratio {e.g. SSSINR in NR, RSSNR in LTE} */ + private int mSignalNoise; + + /** atom #7 : Iwlan network signal strength (Wi-Fi RSSI) */ + private int mIwlanSignalStrength; + + /** atom #8 : Slot Index */ + private int mSlotIndex; + + /** atom #9 : cellular access network type. */ + private int mCellularNetworkType; + + /** Constructor of AtomsQnsImsCallDropStats */ + public AtomsQnsImsCallDropStats() {} + + /** + * Write the atom information to be recorded to the builder according to the type in order. + * + * @param builder Builder class for StatsEvent Builder object. + */ + @Override + public void build(StatsEvent.Builder builder) { + builder.writeInt(mTransportTypeCallDropped); // atom #1 + builder.writeBoolean(mRtpThresholdBreached); // atom #2 + builder.writeInt(mRestrictionsOnOtherTransportType); // atom #3 + builder.writeInt(mSignalStrength); // atom #4 + builder.writeInt(mSignalQuality); // atom #5 + builder.writeInt(mSignalNoise); // atom #6 + builder.writeInt(mIwlanSignalStrength); // atom #7 + builder.writeInt(mSlotIndex); // atom #8 + builder.writeInt(mCellularNetworkType); // atom #9 + } + + /** Return atom id defined in proto. */ + @Override + public int getStatsId() { + return QnsStatsLog.QNS_IMS_CALL_DROP_STATS; + } + + /** Return copy of the AtomsQnsImsCallDropStats */ + @Override + public AtomsPushed copy() { + return new AtomsQnsImsCallDropStats(this); + } + + /** + * Constructor of AtomsQnsImsCallDropStats + * + * @param transportTypeCallDropped Transport type in where IMS call drop occurred. + * @param rtpThresholdBreached RTP threshold breached event occurred. + * @param restrictionsOnOtherTransportType Bit mask of restrictions on another transport type. + * @param signalStrength Cellular network signal strength. + * @param signalQuality Cellular network signal quality. + * @param signalNoise Cellular network signal noise ratio. + * @param iwlanSignalStrength Wi-Fi network signal strength. + * @param slotIndex Index of sim slot. + * @param cellularNetworkType cellular access network type. + */ + public AtomsQnsImsCallDropStats( + int transportTypeCallDropped, + boolean rtpThresholdBreached, + int restrictionsOnOtherTransportType, + int signalStrength, + int signalQuality, + int signalNoise, + int iwlanSignalStrength, + int slotIndex, + int cellularNetworkType) { + mTransportTypeCallDropped = transportTypeCallDropped; + mRtpThresholdBreached = rtpThresholdBreached; + mRestrictionsOnOtherTransportType = restrictionsOnOtherTransportType; + mSignalStrength = signalStrength; + mSignalQuality = signalQuality; + mSignalNoise = signalNoise; + mIwlanSignalStrength = iwlanSignalStrength; + mSlotIndex = slotIndex; + mCellularNetworkType = cellularNetworkType; + } + + /** + * Copy Constructor of AtomsQnsImsCallDropStats + * + * @param info The info param to copy from. + */ + public AtomsQnsImsCallDropStats(AtomsQnsImsCallDropStats info) { + mTransportTypeCallDropped = info.mTransportTypeCallDropped; + mRtpThresholdBreached = info.mRtpThresholdBreached; + mRestrictionsOnOtherTransportType = info.mRestrictionsOnOtherTransportType; + mSignalStrength = info.mSignalStrength; + mSignalQuality = info.mSignalQuality; + mSignalNoise = info.mSignalNoise; + mIwlanSignalStrength = info.mIwlanSignalStrength; + mSlotIndex = info.mSlotIndex; + mCellularNetworkType = info.mCellularNetworkType; + } + + public int getTransportTypeCallDropped() { + return mTransportTypeCallDropped; + } + + public void setTransportTypeCallDropped(int transportTypeCallDropped) { + mTransportTypeCallDropped = transportTypeCallDropped; + } + + public boolean getRtpThresholdBreached() { + return mRtpThresholdBreached; + } + + public void setRtpThresholdBreached(boolean rtpThresholdBreached) { + mRtpThresholdBreached = rtpThresholdBreached; + } + + public int getRestrictionsOnOtherTransportType() { + return mRestrictionsOnOtherTransportType; + } + + public void setRestrictionsOnOtherTransportType(int restrictionsOnOtherTransportType) { + mRestrictionsOnOtherTransportType = restrictionsOnOtherTransportType; + } + + public int getSignalStrength() { + return mSignalStrength; + } + + public void setSignalStrength(int signalStrength) { + mSignalStrength = signalStrength; + } + + public int getSignalQuality() { + return mSignalQuality; + } + + public void setSignalQuality(int signalQuality) { + mSignalQuality = signalQuality; + } + + public int getSignalNoise() { + return mSignalNoise; + } + + public void setSignalNoise(int signalNoise) { + mSignalNoise = signalNoise; + } + + public int getIwlanSignalStrength() { + return mIwlanSignalStrength; + } + + public void setIwlanSignalStrength(int iwlanSignalStrength) { + mIwlanSignalStrength = iwlanSignalStrength; + } + + public int getSlotIndex() { + return mSlotIndex; + } + + public void setSlotIndex(int slotIndex) { + mSlotIndex = slotIndex; + } + + public int getCellularNetworkType() { + return mCellularNetworkType; + } + + public void setCellularNetworkType(int cellularNetworkType) { + mCellularNetworkType = cellularNetworkType; + } + + @Override + public String toString() { + return "AtomsQnsImsCallDropStats{" + + "mTransportTypeCallDropped=" + + mTransportTypeCallDropped + + ", mRtpThresholdBreached=" + + mRtpThresholdBreached + + ", mRestrictionsOnOtherTransportType=" + + mRestrictionsOnOtherTransportType + + ", mSignalStrength=" + + mSignalStrength + + ", mSignalQuality=" + + mSignalQuality + + ", mSignalNoise=" + + mSignalNoise + + ", mIwlanSignalStrength=" + + mIwlanSignalStrength + + ", mSlotIndex=" + + mSlotIndex + + ", mCellularNetworkType=" + + mCellularNetworkType + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof AtomsQnsImsCallDropStats)) return false; + AtomsQnsImsCallDropStats that = (AtomsQnsImsCallDropStats) o; + return mTransportTypeCallDropped == that.mTransportTypeCallDropped + && mRtpThresholdBreached == that.mRtpThresholdBreached + && mRestrictionsOnOtherTransportType == that.mRestrictionsOnOtherTransportType + && mSignalStrength == that.mSignalStrength + && mSignalQuality == that.mSignalQuality + && mSignalNoise == that.mSignalNoise + && mIwlanSignalStrength == that.mIwlanSignalStrength + && mSlotIndex == that.mSlotIndex + && mCellularNetworkType == that.mCellularNetworkType; + } + + @Override + public int hashCode() { + return Objects.hash( + mTransportTypeCallDropped, + mRtpThresholdBreached, + mRestrictionsOnOtherTransportType, + mSignalStrength, + mSignalQuality, + mSignalNoise, + mIwlanSignalStrength, + mSlotIndex, + mCellularNetworkType); + } +} diff --git a/services/QualifiedNetworksService/src/com/android/telephony/qns/atoms/AtomsQnsRatPreferenceMismatchInfo.java b/services/QualifiedNetworksService/src/com/android/telephony/qns/atoms/AtomsQnsRatPreferenceMismatchInfo.java new file mode 100644 index 0000000..150f6a1 --- /dev/null +++ b/services/QualifiedNetworksService/src/com/android/telephony/qns/atoms/AtomsQnsRatPreferenceMismatchInfo.java @@ -0,0 +1,200 @@ +/* + * Copyright (C) 2022 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.telephony.qns.atoms; + +import android.util.StatsEvent; + +import com.android.telephony.qns.stats.QnsStatsLog; +import com.android.telephony.statslib.AtomsPulled; + +import java.io.Serializable; +import java.util.Objects; + +/** AtomsQnsRatPreferenceMismatchInfo class */ +public class AtomsQnsRatPreferenceMismatchInfo extends AtomsPulled implements Serializable { + + private static final long serialVersionUID = 1913485192L; // 0x720D7788 + + /** atom #1 : Net capability of this information. */ + private int mNetCapability; + + /** atom #2 : Count of handover failed. */ + private int mHandoverFailCount; + + /** atom #3 : Duration of this mismatch. */ + private int mDurationOfMismatch; + + /** atom #4 : Carrier Id */ + private int mCarrierId; + + /** atom #5 : Slot Index */ + private int mSlotIndex; + + /** Constructor of AtomsQnsRatPreferenceMismatchInfo */ + public AtomsQnsRatPreferenceMismatchInfo() {} + + /** + * Constructor of AtomsQnsRatPreferenceMismatchInfo + * + * @param netCapability Net capability of this information. + * @param handoverFailCount Count of handover failed. + * @param durationOfMismatch Duration of this mismatch. + * @param carrierId Carrier Id + * @param slotIndex Index of sim slot + */ + public AtomsQnsRatPreferenceMismatchInfo( + int netCapability, + int handoverFailCount, + int durationOfMismatch, + int carrierId, + int slotIndex) { + mNetCapability = netCapability; + mHandoverFailCount = handoverFailCount; + mDurationOfMismatch = durationOfMismatch; + mCarrierId = carrierId; + mSlotIndex = slotIndex; + } + + /** + * Copy Constructor of AtomsQnsRatPreferenceMismatchInfo + * + * @param info The info param to copy from. + */ + public AtomsQnsRatPreferenceMismatchInfo(AtomsQnsRatPreferenceMismatchInfo info) { + mNetCapability = info.mNetCapability; + mHandoverFailCount = info.mHandoverFailCount; + mDurationOfMismatch = info.mDurationOfMismatch; + mCarrierId = info.mCarrierId; + mSlotIndex = info.mSlotIndex; + } + + /** + * Write the atom information to be recorded to the builder according to the type in order. + * + * @param builder Builder class for StatsEvent Builder object. + */ + @Override + public void build(StatsEvent.Builder builder) { + builder.writeInt(mNetCapability); // atom #1 + builder.writeInt(mHandoverFailCount); // atom #2 + builder.writeInt(mDurationOfMismatch); // atom #3 + builder.writeInt(mCarrierId); // atom #4 + builder.writeInt(mSlotIndex); // atom #5 + } + + /** Return atom id defined in proto. */ + @Override + public int getStatsId() { + return QnsStatsLog.QNS_RAT_PREFERENCE_MISMATCH_INFO; + } + + /** Return copy of the AtomsQnsRatPreferenceMismatchInfo */ + @Override + public AtomsPulled copy() { + return new AtomsQnsRatPreferenceMismatchInfo(this); + } + + @Override + public String getDimension() { + return mNetCapability + "_" + mCarrierId + "_" + mSlotIndex; + } + + @Override + public void accumulate(AtomsPulled info) { + if (!(info instanceof AtomsQnsRatPreferenceMismatchInfo)) { + return; + } + AtomsQnsRatPreferenceMismatchInfo atomsQnsRatPreferenceMismatchInfo = + (AtomsQnsRatPreferenceMismatchInfo) info; + this.mDurationOfMismatch += atomsQnsRatPreferenceMismatchInfo.getDurationOfMismatch(); + this.mHandoverFailCount += atomsQnsRatPreferenceMismatchInfo.getHandoverFailCount(); + } + + public int getNetCapability() { + return mNetCapability; + } + + public void setNetCapability(int netCapability) { + mNetCapability = netCapability; + } + + public int getHandoverFailCount() { + return mHandoverFailCount; + } + + public void setHandoverFailCount(int handoverFailCount) { + mHandoverFailCount = handoverFailCount; + } + + public int getDurationOfMismatch() { + return mDurationOfMismatch; + } + + public void setDurationOfMismatch(int durationOfMismatch) { + mDurationOfMismatch = durationOfMismatch; + } + + public int getCarrierId() { + return mCarrierId; + } + + public void setCarrierId(int carrierId) { + mCarrierId = carrierId; + } + + public int getSlotIndex() { + return mSlotIndex; + } + + public void setSlotIndex(int slotIndex) { + mSlotIndex = slotIndex; + } + + @Override + public String toString() { + return "AtomsQnsRatPreferenceMismatchInfo{" + + "mNetCapability=" + + mNetCapability + + ", mHandoverFailCount=" + + mHandoverFailCount + + ", mDurationOfMismatch=" + + mDurationOfMismatch + + ", mCarrierId=" + + mCarrierId + + ", mSlotIndex=" + + mSlotIndex + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof AtomsQnsRatPreferenceMismatchInfo)) return false; + AtomsQnsRatPreferenceMismatchInfo that = (AtomsQnsRatPreferenceMismatchInfo) o; + return mNetCapability == that.mNetCapability + && mHandoverFailCount == that.mHandoverFailCount + && mDurationOfMismatch == that.mDurationOfMismatch + && mCarrierId == that.mCarrierId + && mSlotIndex == that.mSlotIndex; + } + + @Override + public int hashCode() { + return Objects.hash( + mNetCapability, mHandoverFailCount, mDurationOfMismatch, mCarrierId, mSlotIndex); + } +} diff --git a/services/QualifiedNetworksService/src/com/android/telephony/qns/atoms/AtomsQualifiedRatListChangedInfo.java b/services/QualifiedNetworksService/src/com/android/telephony/qns/atoms/AtomsQualifiedRatListChangedInfo.java new file mode 100644 index 0000000..ea3ec6b --- /dev/null +++ b/services/QualifiedNetworksService/src/com/android/telephony/qns/atoms/AtomsQualifiedRatListChangedInfo.java @@ -0,0 +1,430 @@ +/* + * Copyright (C) 2022 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.telephony.qns.atoms; + +import android.util.StatsEvent; + +import com.android.telephony.qns.stats.QnsStatsLog; +import com.android.telephony.statslib.AtomsPushed; + +import java.util.Objects; + +/** AtomsQualifiedRatListChangedInfo class */ +public class AtomsQualifiedRatListChangedInfo extends AtomsPushed { + + /** atom #1 : NetCapability of this Qualified RAT update */ + private int mNetCapability; + /** atom #2 : The most preferred qualified RAT */ + private int mFirstQualifiedRat; + /** atom #3 : Second preferred qualified RAT */ + private int mSecondQualifiedRat; + /** atom #4 : Current actual transport type of Data session for this NetCapability */ + private int mCurrentTransportType; + /** atom #5 : Indicates whether WFC is enabled */ + private boolean mWfcEnabled; + /** atom #6 : Indicates the user's WFC mode */ + private int mWfcMode; + /** atom #7 : Current Cellular AccessNetwork Type */ + private int mCellularNetworkType; + /** atom #8 : Available IWLAN AccessNetwork */ + private int mIwlanNetworkType; + /** atom #9 : Bit mask of restrictions on WWAN */ + private int mRestrictionsOnWwan; + /** atom #10 : Bit mask of restrictions on WLAN */ + private int mRestrictionsOnWlan; + /** atom #11 : Cellular network signal strength {e.g. SSRSRP in NR, RSRP in LTE} */ + private int mSignalStrength; + /** atom #12 : Cellular network signal quality {e.g. SSRSRQ in NR, RSRQ in LTE} */ + private int mSignalQuality; + /** atom #13 : Cellular network signal noise ratio {e.g. SSSINR in NR, RSSNR in LTE} */ + private int mSignalNoise; + /** atom #14 : Iwlan network signal strength (Wi-Fi RSSI) */ + private int mIwlanSignalStrength; + /** atom #15 : Reason for preferred RAT update */ + private int mUpdateReason; + /** atom #16: IMS Call Type */ + private int mImsCallType; + /** atom #17 : IMS Call Quality */ + private int mImsCallQuality; + /** atom #18 : Slot Index */ + private int mSlotIndex; + + /** Constructor of AtomsQualifiedRatListChangedInfo */ + public AtomsQualifiedRatListChangedInfo() {} + + /** + * Constructor of AtomsQualifiedRatListChangedInfo + * + * @param netCapability NetCapability of this Qualified RAT update + * @param firstQualifiedRat The most preferred qualified RAT + * @param secondQualifiedRat Second preferred qualified RAT + * @param currentTransportType Current actual transport type of Data session for this + * NetCapability + * @param wfcEnabled Indicates whether WFC is enabled + * @param wfcMode Indicates the user's WFC mode + * @param cellularNetworkType Current Cellular AccessNetwork Type + * @param iwlanNetworkType Available IWLAN AccessNetwork + * @param restrictionsOnWwan Bit mask of restrictions on WWAN + * @param restrictionsOnWlan Bit mask of restrictions on WLAN + * @param signalStrength Cellular network signal strength {e.g. SSRSRP in NR, RSRP in LTE, RSCP + * in UMTS} + * @param signalQuality Cellular network signal quality {e.g. SSRSRQ in NR, RSRQ in LTE} + * @param signalNoise Cellular network signal noise ratio {e.g. SSSINR in NR, RSSNR in LTE} + * @param iwlanSignalStrength Iwlan network signal strength (Wi-Fi RSSI) + * @param updateReason Reason for preferred RAT update + * @param imsCallType Ims Call Type {e.g. IDLE, VOICE, VIDEO, E-CALL} + * @param imsCallQuality Ims Call Quality + * @param slotIndex Index of sim slot + */ + public AtomsQualifiedRatListChangedInfo( + int netCapability, + int firstQualifiedRat, + int secondQualifiedRat, + int currentTransportType, + boolean wfcEnabled, + int wfcMode, + int cellularNetworkType, + int iwlanNetworkType, + int restrictionsOnWwan, + int restrictionsOnWlan, + int signalStrength, + int signalQuality, + int signalNoise, + int iwlanSignalStrength, + int updateReason, + int imsCallType, + int imsCallQuality, + int slotIndex) { + mNetCapability = netCapability; + mFirstQualifiedRat = firstQualifiedRat; + mSecondQualifiedRat = secondQualifiedRat; + mCurrentTransportType = currentTransportType; + mWfcEnabled = wfcEnabled; + mWfcMode = wfcMode; + mCellularNetworkType = cellularNetworkType; + mIwlanNetworkType = iwlanNetworkType; + mRestrictionsOnWwan = restrictionsOnWwan; + mRestrictionsOnWlan = restrictionsOnWlan; + mSignalStrength = signalStrength; + mSignalQuality = signalQuality; + mSignalNoise = signalNoise; + mIwlanSignalStrength = iwlanSignalStrength; + mUpdateReason = updateReason; + mImsCallType = imsCallType; + mImsCallQuality = imsCallQuality; + mSlotIndex = slotIndex; + } + + /** + * Copy Constructor of AtomsQualifiedRatListChangedInfo + * + * @param info The info param to copy from. + */ + public AtomsQualifiedRatListChangedInfo(AtomsQualifiedRatListChangedInfo info) { + mNetCapability = info.mNetCapability; + mFirstQualifiedRat = info.mFirstQualifiedRat; + mSecondQualifiedRat = info.mSecondQualifiedRat; + mCurrentTransportType = info.mCurrentTransportType; + mWfcEnabled = info.mWfcEnabled; + mWfcMode = info.mWfcMode; + mCellularNetworkType = info.mCellularNetworkType; + mIwlanNetworkType = info.mIwlanNetworkType; + mRestrictionsOnWwan = info.mRestrictionsOnWwan; + mRestrictionsOnWlan = info.mRestrictionsOnWlan; + mSignalStrength = info.mSignalStrength; + mSignalQuality = info.mSignalQuality; + mSignalNoise = info.mSignalNoise; + mIwlanSignalStrength = info.mIwlanSignalStrength; + mUpdateReason = info.mUpdateReason; + mImsCallType = info.mImsCallType; + mImsCallQuality = info.mImsCallQuality; + mSlotIndex = info.mSlotIndex; + } + + /** + * Write the atom information to be recorded to the builder according to the type in order. + * + * @param builder Builder class for StatsEvent Builder object. + */ + @Override + public void build(StatsEvent.Builder builder) { + builder.writeInt(mNetCapability); // atom #1 + builder.writeInt(mFirstQualifiedRat); // atom #2 + builder.writeInt(mSecondQualifiedRat); // atom #3 + builder.writeInt(mCurrentTransportType); // atom #4 + builder.writeBoolean(mWfcEnabled); // atom #5 + builder.writeInt(mWfcMode); // atom #6 + builder.writeInt(mCellularNetworkType); // atom #7 + builder.writeInt(mIwlanNetworkType); // atom #8 + builder.writeInt(mRestrictionsOnWwan); // atom #9 + builder.writeInt(mRestrictionsOnWlan); // atom #10 + builder.writeInt(mSignalStrength); // atom #11 + builder.writeInt(mSignalQuality); // atom #12 + builder.writeInt(mSignalNoise); // atom #13 + builder.writeInt(mIwlanSignalStrength); // atom #14 + builder.writeInt(mUpdateReason); // atom #15 + builder.writeInt(mImsCallType); // atom #16 + builder.writeInt(mImsCallQuality); // atom #17 + builder.writeInt(mSlotIndex); // atom #18 + } + + /** Return atom id defined in proto. */ + @Override + public int getStatsId() { + return QnsStatsLog.QUALIFIED_RAT_LIST_CHANGED; + } + + /** Return copy of the AtomsQualifiedRatListChangedInfo */ + @Override + public AtomsPushed copy() { + return new AtomsQualifiedRatListChangedInfo(this); + } + + public int getNetCapability() { + return mNetCapability; + } + + public void setNetCapability(int netCapability) { + mNetCapability = netCapability; + } + + public int getFirstQualifiedRat() { + return mFirstQualifiedRat; + } + + public void setFirstQualifiedRat(int firstQualifiedRat) { + mFirstQualifiedRat = firstQualifiedRat; + } + + public int getSecondQualifiedRat() { + return mSecondQualifiedRat; + } + + public void setSecondQualifiedRat(int secondQualifiedRat) { + mSecondQualifiedRat = secondQualifiedRat; + } + + public int getCurrentTransportType() { + return mCurrentTransportType; + } + + public void setCurrentTransportType(int currentTransportType) { + mCurrentTransportType = currentTransportType; + } + + public boolean getWfcEnabled() { + return mWfcEnabled; + } + + public void setWfcEnabled(boolean wfcEnabled) { + mWfcEnabled = wfcEnabled; + } + + public int getWfcMode() { + return mWfcMode; + } + + public void setWfcMode(int wfcMode) { + mWfcMode = wfcMode; + } + + public int getCellularNetworkType() { + return mCellularNetworkType; + } + + public void setCellularNetworkType(int cellularNetworkType) { + mCellularNetworkType = cellularNetworkType; + } + + public int getIwlanNetworkType() { + return mIwlanNetworkType; + } + + public void setIwlanNetworkType(int iwlanNetworkType) { + mIwlanNetworkType = iwlanNetworkType; + } + + public int getRestrictionsOnWwan() { + return mRestrictionsOnWwan; + } + + public void setRestrictionsOnWwan(int restrictionsOnWwan) { + mRestrictionsOnWwan = restrictionsOnWwan; + } + + public int getRestrictionsOnWlan() { + return mRestrictionsOnWlan; + } + + public void setRestrictionsOnWlan(int restrictionsOnWlan) { + mRestrictionsOnWlan = restrictionsOnWlan; + } + + public int getSignalStrength() { + return mSignalStrength; + } + + public void setSignalStrength(int signalStrength) { + mSignalStrength = signalStrength; + } + + public int getSignalQuality() { + return mSignalQuality; + } + + public void setSignalQuality(int signalQuality) { + mSignalQuality = signalQuality; + } + + public int getSignalNoise() { + return mSignalNoise; + } + + public void setSignalNoise(int signalNoise) { + mSignalNoise = signalNoise; + } + + public int getIwlanSignalStrength() { + return mIwlanSignalStrength; + } + + public void setIwlanSignalStrength(int iwlanSignalStrength) { + mIwlanSignalStrength = iwlanSignalStrength; + } + + public int getUpdateReason() { + return mUpdateReason; + } + + public void setUpdateReason(int updateReason) { + mUpdateReason = updateReason; + } + + public int getImsCallType() { + return mImsCallType; + } + + public void setImsCallType(int imsCallType) { + mImsCallType = imsCallType; + } + + public int getImsCallQuality() { + return mImsCallQuality; + } + + public void setImsCallQuality(int imsCallQuality) { + mImsCallQuality = imsCallQuality; + } + + public int getSlotIndex() { + return mSlotIndex; + } + + public void setSlotIndex(int slotIndex) { + mSlotIndex = slotIndex; + } + + @Override + public String toString() { + return "AtomsQualifiedRatListChangedInfo{" + + "mNetCapability=" + + mNetCapability + + ", mFirstQualifiedRat=" + + mFirstQualifiedRat + + ", mSecondQualifiedRat=" + + mSecondQualifiedRat + + ", mCurrentTransportType=" + + mCurrentTransportType + + ", mWfcEnabled=" + + mWfcEnabled + + ", mWfcMode=" + + mWfcMode + + ", mCellularNetworkType=" + + mCellularNetworkType + + ", mIwlanNetworkType=" + + mIwlanNetworkType + + ", mRestrictionsOnWwan=" + + mRestrictionsOnWwan + + ", mRestrictionsOnWlan=" + + mRestrictionsOnWlan + + ", mSignalStrength=" + + mSignalStrength + + ", mSignalQuality=" + + mSignalQuality + + ", mSignalNoise=" + + mSignalNoise + + ", mIwlanSignalStrength=" + + mIwlanSignalStrength + + ", mUpdateReason=" + + mUpdateReason + + ", mImsCallType=" + + mImsCallType + + ", mImsCallQuality=" + + mImsCallQuality + + ", mSlotIndex=" + + mSlotIndex + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof AtomsQualifiedRatListChangedInfo)) return false; + AtomsQualifiedRatListChangedInfo that = (AtomsQualifiedRatListChangedInfo) o; + return mNetCapability == that.mNetCapability + && mFirstQualifiedRat == that.mFirstQualifiedRat + && mSecondQualifiedRat == that.mSecondQualifiedRat + && mCurrentTransportType == that.mCurrentTransportType + && mWfcEnabled == that.mWfcEnabled + && mWfcMode == that.mWfcMode + && mCellularNetworkType == that.mCellularNetworkType + && mIwlanNetworkType == that.mIwlanNetworkType + && mRestrictionsOnWwan == that.mRestrictionsOnWwan + && mRestrictionsOnWlan == that.mRestrictionsOnWlan + && mSignalStrength == that.mSignalStrength + && mSignalQuality == that.mSignalQuality + && mSignalNoise == that.mSignalNoise + && mIwlanSignalStrength == that.mIwlanSignalStrength + && mUpdateReason == that.mUpdateReason + && mImsCallType == that.mImsCallType + && mImsCallQuality == that.mImsCallQuality + && mSlotIndex == that.mSlotIndex; + } + + @Override + public int hashCode() { + return Objects.hash( + mNetCapability, + mFirstQualifiedRat, + mSecondQualifiedRat, + mCurrentTransportType, + mWfcEnabled, + mWfcMode, + mCellularNetworkType, + mIwlanNetworkType, + mRestrictionsOnWwan, + mRestrictionsOnWlan, + mSignalStrength, + mSignalQuality, + mSignalNoise, + mIwlanSignalStrength, + mUpdateReason, + mImsCallType, + mImsCallQuality, + mSlotIndex); + } +} diff --git a/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/AccessNetworkEvaluatorTest.java b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/AccessNetworkEvaluatorTest.java index 9ab4d2e..7530767 100644 --- a/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/AccessNetworkEvaluatorTest.java +++ b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/AccessNetworkEvaluatorTest.java @@ -29,6 +29,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyBoolean; import static org.mockito.ArgumentMatchers.anyInt; import static org.mockito.ArgumentMatchers.isNotNull; +import static org.mockito.Mockito.atLeast; import static org.mockito.Mockito.doNothing; import static org.mockito.Mockito.doReturn; import static org.mockito.Mockito.never; @@ -47,6 +48,7 @@ import android.telephony.ServiceState; import android.telephony.SignalThresholdInfo; import android.telephony.TelephonyManager; import android.telephony.data.ApnSetting; +import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.ProvisioningManager; import com.android.telephony.qns.AccessNetworkSelectionPolicy.PreCondition; @@ -88,6 +90,7 @@ public class AccessNetworkEvaluatorTest extends QnsTest { private static final int EVENT_WFC_ACTIVATION_WITH_IWLAN_CONNECTION_REQUIRED = EVENT_BASE + 9; private static final int EVENT_IMS_REGISTRATION_STATE_CHANGED = EVENT_BASE + 10; private static final int EVENT_SIP_DIALOG_SESSION_STATE_CHANGED = EVENT_BASE + 12; + private static final int EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED = EVENT_BASE + 13; @Mock private RestrictManager mRestrictManager; @Mock private DataConnectionStatusTracker mDataConnectionStatusTracker; @@ -166,6 +169,8 @@ public class AccessNetworkEvaluatorTest extends QnsTest { when(mMockQnsTelephonyListener.getLastQnsTelephonyInfo()) .thenReturn(mMockQnsTelephonyListener.new QnsTelephonyInfo()); + when(mMockQnsTelephonyListener.getLastQnsTelephonyInfo()) + .thenReturn(mMockQnsTelephonyListener.new QnsTelephonyInfo()); } @After @@ -1768,6 +1773,41 @@ public class AccessNetworkEvaluatorTest extends QnsTest { } @Test + public void testOnImsCallDisconnectCauseChanged() { + // ANE takes time to build ANSP. + waitForLastHandlerAction(mAne.mHandler); + when(mRestrictManager.isRestricted(anyInt())).thenReturn(false); + when(mRestrictManager.isAllowedOnSingleTransport(anyInt())).thenReturn(true); + when(mDataConnectionStatusTracker.getLastTransportType()) + .thenReturn(AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + + // make iwlan and cellular available + IwlanNetworkStatusTracker.IwlanAvailabilityInfo iwlanInfo = + mMockIwlanNetworkStatusTracker.new IwlanAvailabilityInfo(true, false); + mAne.onIwlanNetworkStatusChanged(iwlanInfo); + QnsTelephonyListener.QnsTelephonyInfo cellInfo = + mMockQnsTelephonyListener.new QnsTelephonyInfo(); + cellInfo.setCellularAvailable(true); + cellInfo.setCoverage(true); + cellInfo.setDataNetworkType(TelephonyManager.NETWORK_TYPE_LTE); + cellInfo.setVoiceNetworkType(TelephonyManager.NETWORK_TYPE_LTE); + cellInfo.setDataRegState(ServiceState.STATE_IN_SERVICE); + mAne.onQnsTelephonyInfoChanged(cellInfo); + assertTrue(mAne.mIwlanAvailable); + assertTrue(mAne.mCellularAvailable); + + // send ims call drop event. + ImsReasonInfo imsReasonInfo = new ImsReasonInfo(ImsReasonInfo.CODE_MEDIA_NO_DATA, 0); + Message.obtain(mAne.mHandler, EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED, + new QnsAsyncResult(null, imsReasonInfo, null)).sendToTarget(); + waitForLastHandlerAction(mAne.mHandler); + + verify(mMockQnsMetrics, atLeast(1)) + .reportAtomForImsCallDropStats( + anyInt(), anyInt(), any(), any(), any(), anyInt(), anyInt()); + } + + @Test public void testEvaluateSpecificReasonToString() throws Exception { Method method = AccessNetworkEvaluator.class.getDeclaredMethod( "evaluateSpecificReasonToString", int.class); diff --git a/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/QnsComponentsTest.java b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/QnsComponentsTest.java index 9924331..8b7bff3 100644 --- a/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/QnsComponentsTest.java +++ b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/QnsComponentsTest.java @@ -87,6 +87,7 @@ public class QnsComponentsTest extends QnsTest { mMockQnsCallStatusTracker, mMockWifiBm, mMockWifiQm, + mMockQnsMetrics, slotId); assertNotNull(qnsComponents.getQnsTelephonyListener(slotId)); @@ -101,6 +102,7 @@ public class QnsComponentsTest extends QnsTest { assertNotNull(qnsComponents.getWifiBackhaulMonitor(slotId)); assertNotNull(qnsComponents.getWifiQualityMonitor()); assertNotNull(qnsComponents.getIwlanNetworkStatusTracker()); + assertNotNull(qnsComponents.getQnsMetrics()); qnsComponents.closeComponents(slotId); @@ -116,6 +118,7 @@ public class QnsComponentsTest extends QnsTest { assertNull(qnsComponents.getWifiBackhaulMonitor(slotId)); assertNull(qnsComponents.getWifiQualityMonitor()); assertNull(qnsComponents.getIwlanNetworkStatusTracker()); + assertNull(qnsComponents.getQnsMetrics()); verify(mMockQnsTelephonyListener).close(); verify(mMockQnsImsManager).close(); @@ -129,5 +132,6 @@ public class QnsComponentsTest extends QnsTest { verify(mMockWifiBm).close(); verify(mMockWifiQm).close(); verify(mMockIwlanNetworkStatusTracker).close(); + verify(mMockQnsMetrics).close(); } } diff --git a/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/QnsMetricsTest.java b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/QnsMetricsTest.java new file mode 100644 index 0000000..e7d1d6f --- /dev/null +++ b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/QnsMetricsTest.java @@ -0,0 +1,773 @@ +/* + * Copyright (C) 2022 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.telephony.qns; + +import static com.android.dx.mockito.inline.extended.ExtendedMockito.doReturn; +import static com.android.dx.mockito.inline.extended.ExtendedMockito.mockitoSession; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.Mockito.lenient; +import static org.mockito.Mockito.timeout; +import static org.mockito.Mockito.verify; + +import android.net.NetworkCapabilities; +import android.telephony.AccessNetworkConstants; +import android.telephony.qns.QnsProtoEnums; + +import com.android.telephony.qns.DataConnectionStatusTracker.DataConnectionChangedInfo; +import com.android.telephony.qns.QualifiedNetworksServiceImpl.QualifiedNetworksInfo; +import com.android.telephony.qns.atoms.AtomsQnsFallbackRestrictionChangedInfo; +import com.android.telephony.qns.atoms.AtomsQnsHandoverPingPongInfo; +import com.android.telephony.qns.atoms.AtomsQnsHandoverTimeMillisInfo; +import com.android.telephony.qns.atoms.AtomsQnsImsCallDropStats; +import com.android.telephony.qns.atoms.AtomsQnsRatPreferenceMismatchInfo; +import com.android.telephony.qns.atoms.AtomsQualifiedRatListChangedInfo; +import com.android.telephony.statslib.AtomsPulled; +import com.android.telephony.statslib.AtomsPushed; +import com.android.telephony.statslib.StatsLib; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.mockito.MockitoSession; +import org.mockito.stubbing.Answer; + +import java.util.ArrayList; +import java.util.List; + +public class QnsMetricsTest extends QnsTest { + private static final int DEFAULT_CARRIER_ID = 1; + + private final int mSlotId = 0; + private final int mNetCapability = NetworkCapabilities.NET_CAPABILITY_IMS; + + @Mock private StatsLib mMockStatsLib; + @Mock private RestrictManager mMockRestrictManager; + @Mock private QualityMonitor mMockCellularQualityMonitor; + @Mock private QualityMonitor mMockWifiQualityMonitor; + + private MockitoSession mStaticMockSession; + private QnsMetrics mQnsMetrics; + private long mSystemElapsedRealTime; + + @Before + public void setUp() throws Exception { + MockitoAnnotations.initMocks(this); + + mStaticMockSession = mockitoSession().mockStatic(QnsUtils.class).startMocking(); + + mSystemElapsedRealTime = 0L; + lenient() + .when(QnsUtils.getSystemElapsedRealTime()) + .thenAnswer((Answer<Long>) invocation -> mSystemElapsedRealTime); + + mQnsMetrics = new QnsMetrics(mMockStatsLib); + } + + @After + public void cleanUp() { + mStaticMockSession.finishMocking(); + } + + private void spendSystemTime(long appendElapsedTime) { + mSystemElapsedRealTime += appendElapsedTime; + } + + private void sendDataConnectionMessage(int event, int state, int transportType) { + DataConnectionChangedInfo info = new DataConnectionChangedInfo(event, state, transportType); + mQnsMetrics.log("QnsMetricsTest currentTime:" + mSystemElapsedRealTime + "ms " + info); + mQnsMetrics.reportAtomForDataConnectionChanged( + mNetCapability, mSlotId, info, DEFAULT_CARRIER_ID); + waitForLastHandlerAction(mQnsMetrics.getHandler()); + } + + private void sendQualifiedNetworksMessage(int accessNetworkType) { + + List<Integer> list = new ArrayList<>(); + list.add(accessNetworkType); + + sendQualifiedNetworksMessage( + list, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN, + QnsConstants.COVERAGE_HOME, + true, + false, + QnsConstants.CELL_PREF, + QnsConstants.WIFI_PREF, + AccessNetworkConstants.AccessNetworkType.EUTRAN, + true, + false, + mMockRestrictManager, + mMockCellularQualityMonitor, + mMockWifiQualityMonitor, + QnsConstants.CALL_TYPE_IDLE); + } + + private void sendQualifiedNetworksMessage( + List<Integer> accessNetworkTypes, + int dataConnectionCurrentTransportType, + int coverage, + boolean settingWfcEnabled, + boolean settingWfcRoamingEnabled, + int settingWfcMode, + int settingWfcRoamingMode, + int cellularAccessNetworkType, + boolean iwlanAvailable, + boolean isCrossWfc, + RestrictManager restrictManager, + QualityMonitor cellularQualityMonitor, + QualityMonitor wifiQualityMonitor, + int callType) { + QualifiedNetworksInfo info = new QualifiedNetworksInfo( + NetworkCapabilities.NET_CAPABILITY_IMS, accessNetworkTypes); + + mQnsMetrics.log("QnsMetricsTest currentTime:" + mSystemElapsedRealTime + "ms " + info); + mQnsMetrics.reportAtomForQualifiedNetworks( + info, + mSlotId, + dataConnectionCurrentTransportType, + coverage, + settingWfcEnabled, + settingWfcRoamingEnabled, + settingWfcMode, + settingWfcRoamingMode, + cellularAccessNetworkType, + iwlanAvailable, + isCrossWfc, + restrictManager, + cellularQualityMonitor, + wifiQualityMonitor, + callType); + waitForLastHandlerAction(mQnsMetrics.getHandler()); + } + + @Test + public void testAtomsQnsHandoverTimeMillisInfo() { + + ArgumentCaptor<AtomsPulled> capturePulled = ArgumentCaptor.forClass(AtomsPulled.class); + ArgumentCaptor<AtomsPushed> capturePushed = ArgumentCaptor.forClass(AtomsPushed.class); + + spendSystemTime(10000L); + sendQualifiedNetworksMessage(AccessNetworkConstants.AccessNetworkType.EUTRAN); + + spendSystemTime(4010L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_STARTED, + DataConnectionStatusTracker.STATE_CONNECTING, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4020L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_CONNECTED, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(501L); + sendQualifiedNetworksMessage(AccessNetworkConstants.AccessNetworkType.IWLAN); + + spendSystemTime(4030L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED, + DataConnectionStatusTracker.STATE_HANDOVER, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4040L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_SUCCESS, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + + spendSystemTime(5002L); + sendQualifiedNetworksMessage(AccessNetworkConstants.AccessNetworkType.EUTRAN); + + spendSystemTime(4050L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED, + DataConnectionStatusTracker.STATE_HANDOVER, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + + spendSystemTime(4060L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_SUCCESS, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(50002L); + sendQualifiedNetworksMessage(AccessNetworkConstants.AccessNetworkType.IWLAN); + + spendSystemTime(4070L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED, + DataConnectionStatusTracker.STATE_HANDOVER, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4080L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_FAILED, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4090L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED, + DataConnectionStatusTracker.STATE_HANDOVER, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4100L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_FAILED, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4110L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED, + DataConnectionStatusTracker.STATE_HANDOVER, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4120L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_SUCCESS, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + + spendSystemTime(4130L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_DISCONNECTED, + DataConnectionStatusTracker.STATE_INACTIVE, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + + verify(mMockStatsLib, timeout(1000).times(4)).append(capturePulled.capture()); + verify(mMockStatsLib, timeout(1000).times(4)).write(capturePushed.capture()); + List<AtomsQnsHandoverTimeMillisInfo> listHandoverTime = new ArrayList<>(); + List<AtomsQualifiedRatListChangedInfo> listQualifiedRat = new ArrayList<>(); + for (AtomsPulled pulled : capturePulled.getAllValues()) { + if (pulled instanceof AtomsQnsHandoverTimeMillisInfo) { + listHandoverTime.add((AtomsQnsHandoverTimeMillisInfo) pulled); + mQnsMetrics.log("QnsMetricsTest HandoverTime atom:" + pulled); + } + } + for (AtomsPushed pushed : capturePushed.getAllValues()) { + if (pushed instanceof AtomsQualifiedRatListChangedInfo) { + listQualifiedRat.add((AtomsQualifiedRatListChangedInfo) pushed); + mQnsMetrics.log("QnsMetricsTest QualifiedRat atom:" + pushed); + } + } + assertEquals(3, listHandoverTime.size()); + assertEquals(8070, listHandoverTime.get(0).getTimeForHoSuccess()); + assertEquals(8110, listHandoverTime.get(1).getTimeForHoSuccess()); + assertEquals(24570, listHandoverTime.get(2).getTimeForHoSuccess()); + + assertEquals( + AccessNetworkConstants.AccessNetworkType.EUTRAN, + listQualifiedRat.get(0).getFirstQualifiedRat()); + assertEquals( + AccessNetworkConstants.AccessNetworkType.IWLAN, + listQualifiedRat.get(1).getFirstQualifiedRat()); + assertEquals( + AccessNetworkConstants.AccessNetworkType.EUTRAN, + listQualifiedRat.get(2).getFirstQualifiedRat()); + assertEquals( + AccessNetworkConstants.AccessNetworkType.IWLAN, + listQualifiedRat.get(3).getFirstQualifiedRat()); + } + + @Test + public void testAtomsQualifiedRatListChangedInfo() { + + ArgumentCaptor<AtomsQualifiedRatListChangedInfo> capture = + ArgumentCaptor.forClass(AtomsQualifiedRatListChangedInfo.class); + + doReturn(true) + .when(mMockRestrictManager) + .hasRestrictionType(anyInt(), eq(RestrictManager.RESTRICT_TYPE_RTP_LOW_QUALITY)); + doReturn(true) + .when(mMockRestrictManager) + .hasRestrictionType( + anyInt(), eq(RestrictManager.RESTRICT_TYPE_FALLBACK_TO_WWAN_IMS_REGI_FAIL)); + doReturn(true) + .when(mMockRestrictManager) + .hasRestrictionType( + anyInt(), + eq(RestrictManager.RESTRICT_TYPE_FALLBACK_TO_WWAN_RTT_BACKHAUL_FAIL)); + + List<Integer> cellularAccessNetwork = new ArrayList<>(); + cellularAccessNetwork.add(AccessNetworkConstants.AccessNetworkType.EUTRAN); + sendQualifiedNetworksMessage( + cellularAccessNetwork, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN, + QnsConstants.COVERAGE_HOME, + true, + false, + QnsConstants.CELL_PREF, + QnsConstants.WIFI_PREF, + AccessNetworkConstants.AccessNetworkType.EUTRAN, + false, + true, + mMockRestrictManager, + mMockCellularQualityMonitor, + mMockWifiQualityMonitor, + QnsConstants.CALL_TYPE_IDLE); + + List<Integer> wifiAccessNetwork = new ArrayList<>(); + wifiAccessNetwork.add(AccessNetworkConstants.AccessNetworkType.IWLAN); + sendQualifiedNetworksMessage( + wifiAccessNetwork, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN, + QnsConstants.COVERAGE_ROAM, + false, + true, + QnsConstants.WIFI_PREF, + QnsConstants.CELL_PREF, + AccessNetworkConstants.AccessNetworkType.NGRAN, + true, + false, + mMockRestrictManager, + mMockCellularQualityMonitor, + mMockWifiQualityMonitor, + QnsConstants.CALL_TYPE_VOICE); + + verify(mMockStatsLib, timeout(1000).times(2)).write(capture.capture()); + List<AtomsQualifiedRatListChangedInfo> list = capture.getAllValues(); + mQnsMetrics.log("QnsMetricsTest QualifiedRat atom[0]:" + list.get(0)); + mQnsMetrics.log("QnsMetricsTest QualifiedRat atom[1]:" + list.get(1)); + assertEquals( + AccessNetworkConstants.AccessNetworkType.EUTRAN, + list.get(0).getFirstQualifiedRat()); + assertEquals( + AccessNetworkConstants.AccessNetworkType.IWLAN, list.get(1).getFirstQualifiedRat()); + int expectedRestriction = + QnsProtoEnums.RESTRICT_TYPE_RTP_LOW_QUALITY + | QnsProtoEnums.RESTRICT_TYPE_FALLBACK_TO_WWAN_IMS_REGI_FAIL + | QnsProtoEnums.RESTRICT_TYPE_FALLBACK_TO_WWAN_RTT_BACKHAUL_FAIL; + assertEquals(expectedRestriction, list.get(0).getRestrictionsOnWlan()); + assertEquals(expectedRestriction, list.get(1).getRestrictionsOnWwan()); + } + + @Test + public void testAtomsQnsHandoverPingPongInfo() { + + ArgumentCaptor<AtomsQnsHandoverPingPongInfo> capture = + ArgumentCaptor.forClass(AtomsQnsHandoverPingPongInfo.class); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_STARTED, + DataConnectionStatusTracker.STATE_CONNECTING, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_CONNECTED, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED, + DataConnectionStatusTracker.STATE_HANDOVER, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_SUCCESS, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED, + DataConnectionStatusTracker.STATE_HANDOVER, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_SUCCESS, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED, + DataConnectionStatusTracker.STATE_HANDOVER, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_SUCCESS, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED, + DataConnectionStatusTracker.STATE_HANDOVER, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_SUCCESS, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED, + DataConnectionStatusTracker.STATE_HANDOVER, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(50000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_SUCCESS, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED, + DataConnectionStatusTracker.STATE_HANDOVER, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_SUCCESS, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_DISCONNECTED, + DataConnectionStatusTracker.STATE_INACTIVE, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + verify(mMockStatsLib, timeout(1000).times(2)).append(capture.capture()); + List<AtomsQnsHandoverPingPongInfo> list = capture.getAllValues(); + mQnsMetrics.log("QnsMetricsTest PingPong atom[0]:" + list.get(0)); + mQnsMetrics.log("QnsMetricsTest PingPong atom[1]:" + list.get(1)); + assertEquals(2, list.get(0).getCountHandoverPingPong()); + assertEquals(1, list.get(1).getCountHandoverPingPong()); + } + + @Test + public void testAtomsQnsRatPreferenceMismatchInfo() { + + ArgumentCaptor<AtomsQnsRatPreferenceMismatchInfo> capture = + ArgumentCaptor.forClass(AtomsQnsRatPreferenceMismatchInfo.class); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_STARTED, + DataConnectionStatusTracker.STATE_CONNECTING, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_CONNECTED, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED, + DataConnectionStatusTracker.STATE_HANDOVER, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4100L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_FAILED, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED, + DataConnectionStatusTracker.STATE_HANDOVER, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4200L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_FAILED, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED, + DataConnectionStatusTracker.STATE_HANDOVER, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_DISCONNECTED, + DataConnectionStatusTracker.STATE_INACTIVE, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(50000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_STARTED, + DataConnectionStatusTracker.STATE_CONNECTING, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_CONNECTED, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED, + DataConnectionStatusTracker.STATE_HANDOVER, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_SUCCESS, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED, + DataConnectionStatusTracker.STATE_HANDOVER, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + + spendSystemTime(4100L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_FAILED, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED, + DataConnectionStatusTracker.STATE_HANDOVER, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + + spendSystemTime(4200L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_FAILED, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_STARTED, + DataConnectionStatusTracker.STATE_HANDOVER, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + + spendSystemTime(4300L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_HANDOVER_FAILED, + DataConnectionStatusTracker.STATE_CONNECTED, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + + spendSystemTime(4000L); + sendDataConnectionMessage( + DataConnectionStatusTracker.EVENT_DATA_CONNECTION_DISCONNECTED, + DataConnectionStatusTracker.STATE_INACTIVE, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + verify(mMockStatsLib, timeout(1000).times(2)).append(capture.capture()); + List<AtomsQnsRatPreferenceMismatchInfo> list = capture.getAllValues(); + mQnsMetrics.log("QnsMetricsTest RatMismatch atom[0]:" + list.get(0)); + mQnsMetrics.log("QnsMetricsTest RatMismatch atom[1]:" + list.get(1)); + assertEquals(2, list.get(0).getHandoverFailCount()); + assertEquals(3, list.get(1).getHandoverFailCount()); + assertEquals(20300, list.get(0).getDurationOfMismatch()); + assertEquals(24600, list.get(1).getDurationOfMismatch()); + } + + private void sendCallTypeChanged( + int oldCallType, + int newCallType, + RestrictManager restrictManager, + int transportTypeOfCall) { + mQnsMetrics.log( + "QnsMetricsTest callTypeChanged " + + QnsConstants.callTypeToString(oldCallType) + + "->" + + QnsConstants.callTypeToString(newCallType) + + " transportType:" + + AccessNetworkConstants.transportTypeToString(transportTypeOfCall)); + mQnsMetrics.reportAtomForCallTypeChanged(mNetCapability, mSlotId, + oldCallType, newCallType, restrictManager, transportTypeOfCall); + waitForLastHandlerAction(mQnsMetrics.getHandler()); + } + + private void sendImsCallDropStats(int transportTypeOfCall, int cellularAccessNetworkType) { + mQnsMetrics.log( + "QnsMetricsTest ImsCallDropStats transportTypeOfCall:" + + AccessNetworkConstants.transportTypeToString(transportTypeOfCall) + + " cellularAccessNetworkType:" + + AccessNetworkConstants.AccessNetworkType.toString( + cellularAccessNetworkType)); + mQnsMetrics.reportAtomForImsCallDropStats(mNetCapability, mSlotId, mMockRestrictManager, + mMockCellularQualityMonitor, mMockWifiQualityMonitor, transportTypeOfCall, + cellularAccessNetworkType); + waitForLastHandlerAction(mQnsMetrics.getHandler()); + } + private void sendFallbackRestrictionChanged( + List<Integer> wlanRestrictions, List<Integer> wwanRestrictions) { + mQnsMetrics.log( + "QnsMetricsTest FallbackRestrictionChanged wlanRestrictions:" + + wlanRestrictions + + ", wwanRestrictions:" + + wwanRestrictions); + mQnsMetrics.reportAtomForRestrictions( + mNetCapability, mSlotId, wlanRestrictions, wwanRestrictions, DEFAULT_CARRIER_ID); + waitForLastHandlerAction(mQnsMetrics.getHandler()); + } + + @Test + public void testAtomsQnsImsCallDropStats() { + + ArgumentCaptor<AtomsQnsImsCallDropStats> capture = + ArgumentCaptor.forClass(AtomsQnsImsCallDropStats.class); + + // call start + sendCallTypeChanged( + QnsConstants.CALL_TYPE_IDLE, + QnsConstants.CALL_TYPE_VOICE, + mMockRestrictManager, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + // got rtp low from wwan side + spendSystemTime(10000L); + doReturn(true) + .when(mMockRestrictManager) + .hasRestrictionType( + eq(AccessNetworkConstants.TRANSPORT_TYPE_WWAN), + eq(RestrictManager.RESTRICT_TYPE_RTP_LOW_QUALITY)); + + // call end + spendSystemTime(3000L); + sendCallTypeChanged( + QnsConstants.CALL_TYPE_VOICE, + QnsConstants.CALL_TYPE_IDLE, + mMockRestrictManager, + AccessNetworkConstants.TRANSPORT_TYPE_WWAN); + + // media no data cause. + spendSystemTime(3000L); + sendImsCallDropStats( + AccessNetworkConstants.TRANSPORT_TYPE_WWAN, + AccessNetworkConstants.AccessNetworkType.EUTRAN); + + // call start over iwlan + spendSystemTime(10000L); + sendCallTypeChanged( + QnsConstants.CALL_TYPE_IDLE, + QnsConstants.CALL_TYPE_VOICE, + mMockRestrictManager, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + + // got rtp low from wlan side + spendSystemTime(10000L); + doReturn(true) + .when(mMockRestrictManager) + .hasRestrictionType( + eq(AccessNetworkConstants.TRANSPORT_TYPE_WLAN), + eq(RestrictManager.RESTRICT_TYPE_RTP_LOW_QUALITY)); + + // call end + spendSystemTime(3000L); + sendCallTypeChanged( + QnsConstants.CALL_TYPE_VOICE, + QnsConstants.CALL_TYPE_IDLE, + mMockRestrictManager, + AccessNetworkConstants.TRANSPORT_TYPE_WLAN); + + // media no data cause + spendSystemTime(3000L); + sendImsCallDropStats( + AccessNetworkConstants.TRANSPORT_TYPE_WLAN, + AccessNetworkConstants.AccessNetworkType.IWLAN); + + // verify + verify(mMockStatsLib, timeout(1000).times(2)).write(capture.capture()); + List<AtomsQnsImsCallDropStats> list = capture.getAllValues(); + mQnsMetrics.log("QnsMetricsTest ImsCallDrop atom[0]:" + list.get(0)); + mQnsMetrics.log("QnsMetricsTest ImsCallDrop atom[1]:" + list.get(1)); + assertTrue(list.get(0).getRtpThresholdBreached()); + assertTrue(list.get(1).getRtpThresholdBreached()); + } + + + @Test + public void testAtomsQnsFallbackRestrictionChangedInfo() { + + ArgumentCaptor<AtomsQnsFallbackRestrictionChangedInfo> capture = + ArgumentCaptor.forClass(AtomsQnsFallbackRestrictionChangedInfo.class); + + List<Integer> wlanRestrictions = new ArrayList<>(); + List<Integer> wwanRestrictions = new ArrayList<>(); + sendFallbackRestrictionChanged(wlanRestrictions, wwanRestrictions); + + wlanRestrictions.add(RestrictManager.RESTRICT_TYPE_GUARDING); + wwanRestrictions.add(RestrictManager.RESTRICT_TYPE_GUARDING); + sendFallbackRestrictionChanged(wlanRestrictions, wwanRestrictions); + + wlanRestrictions.clear(); + wwanRestrictions.clear(); + wlanRestrictions.add(RestrictManager.RESTRICT_TYPE_RTP_LOW_QUALITY); + sendFallbackRestrictionChanged(wlanRestrictions, wwanRestrictions); + + wlanRestrictions.clear(); + wwanRestrictions.clear(); + wwanRestrictions.add(RestrictManager.RESTRICT_TYPE_RTP_LOW_QUALITY); + sendFallbackRestrictionChanged(wlanRestrictions, wwanRestrictions); + + wlanRestrictions.clear(); + wwanRestrictions.clear(); + wlanRestrictions.add(RestrictManager.RESTRICT_TYPE_FALLBACK_TO_WWAN_IMS_REGI_FAIL); + sendFallbackRestrictionChanged(wlanRestrictions, wwanRestrictions); + + wlanRestrictions.clear(); + wwanRestrictions.clear(); + wwanRestrictions.add(RestrictManager.RESTRICT_TYPE_FALLBACK_TO_WWAN_IMS_REGI_FAIL); + sendFallbackRestrictionChanged(wlanRestrictions, wwanRestrictions); + + wlanRestrictions.clear(); + wwanRestrictions.clear(); + wlanRestrictions.add(RestrictManager.RESTRICT_TYPE_FALLBACK_TO_WWAN_RTT_BACKHAUL_FAIL); + sendFallbackRestrictionChanged(wlanRestrictions, wwanRestrictions); + + wlanRestrictions.clear(); + wwanRestrictions.clear(); + wwanRestrictions.add(RestrictManager.RESTRICT_TYPE_FALLBACK_TO_WWAN_RTT_BACKHAUL_FAIL); + sendFallbackRestrictionChanged(wlanRestrictions, wwanRestrictions); + + // verify + verify(mMockStatsLib, timeout(1000).times(4)).write(capture.capture()); + List<AtomsQnsFallbackRestrictionChangedInfo> list = capture.getAllValues(); + mQnsMetrics.log("QnsMetricsTest ImsCallDrop atom[0]:" + list.get(0)); + mQnsMetrics.log("QnsMetricsTest ImsCallDrop atom[1]:" + list.get(1)); + mQnsMetrics.log("QnsMetricsTest ImsCallDrop atom[2]:" + list.get(2)); + mQnsMetrics.log("QnsMetricsTest ImsCallDrop atom[3]:" + list.get(3)); + assertTrue(list.get(0).getRestrictionOnWlanByRtpThresholdBreached()); + assertTrue(list.get(1).getRestrictionOnWwanByRtpThresholdBreached()); + assertTrue(list.get(2).getRestrictionOnWlanByImsRegistrationFailed()); + assertTrue(list.get(3).getRestrictionOnWlanByWifiBackhaulProblem()); + } +} diff --git a/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/QnsTelephonyListenerTest.java b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/QnsTelephonyListenerTest.java index f1d63fa..2f50ff8 100644 --- a/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/QnsTelephonyListenerTest.java +++ b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/QnsTelephonyListenerTest.java @@ -47,6 +47,7 @@ import android.telephony.TelephonyManager; import android.telephony.VopsSupportInfo; import android.telephony.data.ApnSetting; import android.telephony.ims.ImsCallProfile; +import android.telephony.ims.ImsReasonInfo; import android.telephony.ims.MediaQualityStatus; import android.util.SparseArray; @@ -1035,6 +1036,20 @@ public final class QnsTelephonyListenerTest extends QnsTest { } @Test + public void testOnImsCallDisconnectCauseChanged() { + mQtListener.registerImsCallDropDisconnectCauseListener(mMockHandler, 0, null); + assertTrue(mQtListener.mImsCallDropDisconnectCauseListener.size() > 0); + verify(mMockHandler, never()).sendMessage(any()); + + ImsReasonInfo imsReasonInfo = new ImsReasonInfo(); + mQtListener.onImsCallDisconnectCauseChanged(imsReasonInfo); + verify(mMockHandler, times(1)).sendMessage(any()); + + mQtListener.unregisterImsCallDropDisconnectCauseListener(mMockHandler); + assertEquals(0, mQtListener.mImsCallDropDisconnectCauseListener.size()); + } + + @Test public void testNullTelephonyListener() { mQtListener.close(); setReady(false); diff --git a/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/QnsTest.java b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/QnsTest.java index 2144516..d535d97 100644 --- a/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/QnsTest.java +++ b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/QnsTest.java @@ -81,6 +81,7 @@ public abstract class QnsTest { @Mock protected QnsTelephonyListener mMockQnsTelephonyListener; @Mock protected QnsCallStatusTracker mMockQnsCallStatusTracker; @Mock protected WifiBackhaulMonitor mMockWifiBm; + @Mock protected QnsMetrics mMockQnsMetrics; protected QnsComponents[] mQnsComponents = new QnsComponents[2]; @@ -112,6 +113,7 @@ public abstract class QnsTest { mMockQnsCallStatusTracker, mMockWifiBm, mMockWifiQm, + mMockQnsMetrics, 0); mQnsComponents[1] = @@ -129,6 +131,7 @@ public abstract class QnsTest { mMockQnsCallStatusTracker, mMockWifiBm, mMockWifiQm, + mMockQnsMetrics, 1); } diff --git a/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/QualifiedNetworksServiceImplTest.java b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/QualifiedNetworksServiceImplTest.java index 3a82244..9e08cfa 100644 --- a/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/QualifiedNetworksServiceImplTest.java +++ b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/QualifiedNetworksServiceImplTest.java @@ -93,6 +93,7 @@ public class QualifiedNetworksServiceImplTest extends QnsTest { mMockQnsCallStatusTracker, mMockWifiBm, mMockWifiQm, + mMockQnsMetrics, slotId); } diff --git a/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/RestrictManagerTest.java b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/RestrictManagerTest.java index 466e687..67d1382 100644 --- a/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/RestrictManagerTest.java +++ b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/RestrictManagerTest.java @@ -75,6 +75,9 @@ import org.mockito.Mockito; import org.mockito.MockitoAnnotations; import org.mockito.MockitoSession; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.TimeUnit; + @RunWith(JUnit4.class) public class RestrictManagerTest extends QnsTest { @@ -144,6 +147,7 @@ public class RestrictManagerTest extends QnsTest { mMockQnsCallStatusTracker, mMockWifiBm, mMockWifiQm, + mMockQnsMetrics, 0); mRestrictManager = @@ -2790,4 +2794,29 @@ public class RestrictManagerTest extends QnsTest { mRestrictManager.releaseRestriction( AccessNetworkConstants.TRANSPORT_TYPE_WLAN, RESTRICT_TYPE_GUARDING, true); } + + @Test + public void testSendRestrictionsForMetrics() throws Exception { + CountDownLatch latch = new CountDownLatch(1); + Handler handler = new Handler(mHandlerThread.getLooper()) { + public void handleMessage(Message msg) { + latch.countDown(); + } + }; + + mRestrictManager.registerRestrictInfoChanged(handler, 0); + assertNotNull(mRestrictManager.mRestrictInfoRegistrant); + + mRestrictManager.addRestriction( + AccessNetworkConstants.TRANSPORT_TYPE_WLAN, + RESTRICT_TYPE_RTP_LOW_QUALITY, + sReleaseEventMap.get(RESTRICT_TYPE_NON_PREFERRED_TRANSPORT), + DEFAULT_RESTRICT_NON_PREFERRED_TRANSPORT_TIME); + + assertTrue(latch.await(3, TimeUnit.SECONDS)); + + mRestrictManager.unRegisterRestrictInfoChanged(handler); + assertNull(mRestrictManager.mRestrictInfoRegistrant); + } + } diff --git a/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/atoms/AtomsQnsFallbackRestrictionChangedInfoTest.java b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/atoms/AtomsQnsFallbackRestrictionChangedInfoTest.java new file mode 100644 index 0000000..159ab07 --- /dev/null +++ b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/atoms/AtomsQnsFallbackRestrictionChangedInfoTest.java @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2022 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.telephony.qns.atoms; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import android.util.StatsEvent; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@RunWith(JUnit4.class) +public class AtomsQnsFallbackRestrictionChangedInfoTest { + + @Mock + private StatsEvent.Builder mStatsEventBuilder; + + private static final boolean DEFAULT_RESTRICTION_WLAN_RTP_THRESHOLD_BREACHED = true; + private static final boolean DEFAULT_RESTRICTION_WWAN_RTP_THRESHOLD_BREACHED = true; + private static final boolean DEFAULT_RESTRICTION_WWAN_IMS_REGI_FAIL = true; + private static final boolean DEFAULT_RESTRICTION_WWAN_WIFI_BACKHAUL_PROBLEM = true; + private static final int DEFAULT_CARRIER_ID = 1; // TMO + + private AtomsQnsFallbackRestrictionChangedInfo mInfoEmpty; + private AtomsQnsFallbackRestrictionChangedInfo mInfoDefault; + private AtomsQnsFallbackRestrictionChangedInfo mInfoCopy; + + /** atom #1 : Restriction on WLAN caused by RTP threshold breached */ + private boolean mRestrictionWlanRtpThresholdBreached; + + /** atom #2 : Restriction on WWAN caused by RTP threshold breached */ + private boolean mRestrictionWwanRtpThresholdBreached; + + /** atom #3 : Restriction on WLAN caused by IMS registration fail */ + private boolean mRestrictionWwanImsRegiFail; + + /** atom #4 : Restriction on WLAN caused by Wifi backhaul problem. */ + private boolean mRestrictionWwanWifiBackhaulProblem; + + /** atom #5 : Carrier Id */ + private int mCarrierId; + + /** atom #6 : Slot Index */ + private int mSlotIndex; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mRestrictionWlanRtpThresholdBreached = DEFAULT_RESTRICTION_WLAN_RTP_THRESHOLD_BREACHED; + mRestrictionWwanRtpThresholdBreached = DEFAULT_RESTRICTION_WWAN_RTP_THRESHOLD_BREACHED; + mRestrictionWwanImsRegiFail = DEFAULT_RESTRICTION_WWAN_IMS_REGI_FAIL; + mRestrictionWwanWifiBackhaulProblem = DEFAULT_RESTRICTION_WWAN_WIFI_BACKHAUL_PROBLEM; + mCarrierId = DEFAULT_CARRIER_ID; + mSlotIndex = 0; + mInfoEmpty = new AtomsQnsFallbackRestrictionChangedInfo(); + mInfoDefault = + new AtomsQnsFallbackRestrictionChangedInfo( + mRestrictionWlanRtpThresholdBreached, + mRestrictionWwanRtpThresholdBreached, + mRestrictionWwanImsRegiFail, + mRestrictionWwanWifiBackhaulProblem, + mCarrierId, + mSlotIndex); + mInfoCopy = new AtomsQnsFallbackRestrictionChangedInfo(mInfoDefault); + } + + @After + public void tearDown() { + mInfoEmpty = null; + mInfoDefault = null; + mInfoCopy = null; + } + + @Test + public void testGetSetRestrictionWlanRtpThresholdBreached() { + assertFalse(mInfoEmpty.getRestrictionOnWlanByRtpThresholdBreached()); + assertTrue(mInfoDefault.getRestrictionOnWlanByRtpThresholdBreached()); + assertTrue(mInfoCopy.getRestrictionOnWlanByRtpThresholdBreached()); + + mInfoEmpty.setRestrictionOnWlanByRtpThresholdBreached(true); + mInfoDefault.setRestrictionOnWlanByRtpThresholdBreached(true); + mInfoCopy.setRestrictionOnWlanByRtpThresholdBreached(true); + + assertTrue(mInfoEmpty.getRestrictionOnWlanByRtpThresholdBreached()); + assertTrue(mInfoDefault.getRestrictionOnWlanByRtpThresholdBreached()); + assertTrue(mInfoCopy.getRestrictionOnWlanByRtpThresholdBreached()); + } + + @Test + public void testGetSetRestrictionWwanRtpThresholdBreached() { + assertFalse(mInfoEmpty.getRestrictionOnWwanByRtpThresholdBreached()); + assertTrue(mInfoDefault.getRestrictionOnWwanByRtpThresholdBreached()); + assertTrue(mInfoCopy.getRestrictionOnWwanByRtpThresholdBreached()); + + mInfoEmpty.setRestrictionOnWwanByRtpThresholdBreached(true); + mInfoDefault.setRestrictionOnWwanByRtpThresholdBreached(true); + mInfoCopy.setRestrictionOnWwanByRtpThresholdBreached(true); + + assertTrue(mInfoEmpty.getRestrictionOnWwanByRtpThresholdBreached()); + assertTrue(mInfoDefault.getRestrictionOnWwanByRtpThresholdBreached()); + assertTrue(mInfoCopy.getRestrictionOnWwanByRtpThresholdBreached()); + } + + @Test + public void testGetSetRestrictionWwanImsRegiFail() { + assertFalse(mInfoEmpty.getRestrictionOnWlanByImsRegistrationFailed()); + assertTrue(mInfoDefault.getRestrictionOnWlanByImsRegistrationFailed()); + assertTrue(mInfoCopy.getRestrictionOnWlanByImsRegistrationFailed()); + + mInfoEmpty.setRestrictionOnWlanByImsRegistrationFailed(true); + mInfoDefault.setRestrictionOnWlanByImsRegistrationFailed(true); + mInfoCopy.setRestrictionOnWlanByImsRegistrationFailed(true); + + assertTrue(mInfoEmpty.getRestrictionOnWlanByImsRegistrationFailed()); + assertTrue(mInfoDefault.getRestrictionOnWlanByImsRegistrationFailed()); + assertTrue(mInfoCopy.getRestrictionOnWlanByImsRegistrationFailed()); + } + + @Test + public void testGetSetRestrictionWwanWifiBackhaulProblem() { + assertFalse(mInfoEmpty.getRestrictionOnWlanByWifiBackhaulProblem()); + assertTrue(mInfoDefault.getRestrictionOnWlanByWifiBackhaulProblem()); + assertTrue(mInfoCopy.getRestrictionOnWlanByWifiBackhaulProblem()); + + mInfoEmpty.setRestrictionOnWlanByWifiBackhaulProblem(true); + mInfoDefault.setRestrictionOnWlanByWifiBackhaulProblem(true); + mInfoCopy.setRestrictionOnWlanByWifiBackhaulProblem(true); + + assertTrue(mInfoEmpty.getRestrictionOnWlanByWifiBackhaulProblem()); + assertTrue(mInfoDefault.getRestrictionOnWlanByWifiBackhaulProblem()); + assertTrue(mInfoCopy.getRestrictionOnWlanByWifiBackhaulProblem()); + } + + @Test + public void testGetSetCarrierId() { + assertEquals(0, mInfoEmpty.getCarrierId()); + assertEquals(DEFAULT_CARRIER_ID, mInfoDefault.getCarrierId()); + assertEquals(DEFAULT_CARRIER_ID, mInfoCopy.getCarrierId()); + + mInfoEmpty.setCarrierId(1); + mInfoDefault.setCarrierId(2); + mInfoCopy.setCarrierId(3); + + assertEquals(1, mInfoEmpty.getCarrierId()); + assertEquals(2, mInfoDefault.getCarrierId()); + assertEquals(3, mInfoCopy.getCarrierId()); + } + + @Test + public void testGetSetSlotIndex() { + assertEquals(0, mInfoEmpty.getSlotIndex()); + assertEquals(0, mInfoDefault.getSlotIndex()); + assertEquals(0, mInfoCopy.getSlotIndex()); + + mInfoEmpty.setSlotIndex(1); + mInfoDefault.setSlotIndex(2); + mInfoCopy.setSlotIndex(3); + + assertEquals(1, mInfoEmpty.getSlotIndex()); + assertEquals(2, mInfoDefault.getSlotIndex()); + assertEquals(3, mInfoCopy.getSlotIndex()); + } + + @Test + public void testToString() { + String strInfoEmpty = mInfoEmpty.toString(); + String strInfoDefault = mInfoDefault.toString(); + String strInfoCopy = mInfoCopy.toString(); + + assertNotNull(strInfoEmpty); + assertNotNull(strInfoDefault); + assertNotNull(strInfoCopy); + + assertTrue(strInfoDefault.startsWith("AtomsQnsFallbackRestrictionChangedInfo")); + + assertEquals(strInfoDefault, strInfoCopy); + assertNotEquals(strInfoEmpty, strInfoDefault); + } + + @Test + public void testEquals() { + assertEquals(mInfoDefault, mInfoDefault); + assertNotEquals(mInfoDefault, new Object()); + assertEquals(mInfoDefault, mInfoCopy); + mInfoDefault.setRestrictionOnWlanByRtpThresholdBreached(false); + mInfoCopy.setRestrictionOnWlanByRtpThresholdBreached(true); + assertNotEquals(mInfoDefault, mInfoCopy); + } + + @Test + public void testHashCode() { + AtomsQnsFallbackRestrictionChangedInfo a1, a2; + + a1 = + new AtomsQnsFallbackRestrictionChangedInfo( + true, true, false, false, mCarrierId, mSlotIndex); + a2 = + new AtomsQnsFallbackRestrictionChangedInfo( + false, false, false, false, mCarrierId, mSlotIndex); + assertNotEquals(a1.hashCode(), a2.hashCode()); + + a1 = + new AtomsQnsFallbackRestrictionChangedInfo( + mRestrictionWlanRtpThresholdBreached, + mRestrictionWwanRtpThresholdBreached, + mRestrictionWwanImsRegiFail, + mRestrictionWwanWifiBackhaulProblem, + mCarrierId, + mSlotIndex); + a2 = + new AtomsQnsFallbackRestrictionChangedInfo( + mRestrictionWlanRtpThresholdBreached, + mRestrictionWwanRtpThresholdBreached, + mRestrictionWwanImsRegiFail, + mRestrictionWwanWifiBackhaulProblem, + mCarrierId, + mSlotIndex); + assertEquals(a1.hashCode(), a2.hashCode()); + } + + @Test + public void testStatsId() { + final int statsId = 636; // QnsFallbackRestrictionChanged + assertEquals(statsId, mInfoDefault.copy().getStatsId()); + } + + @Test + public void testStatsEventBuilder() { + mInfoDefault.build(mStatsEventBuilder); + + verify(mStatsEventBuilder, times(4)).writeBoolean(anyBoolean()); + verify(mStatsEventBuilder, times(2)).writeInt(anyInt()); + } +} diff --git a/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/atoms/AtomsQnsHandoverPingPongInfoTest.java b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/atoms/AtomsQnsHandoverPingPongInfoTest.java new file mode 100644 index 0000000..e914579 --- /dev/null +++ b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/atoms/AtomsQnsHandoverPingPongInfoTest.java @@ -0,0 +1,191 @@ +/* + * Copyright (C) 2022 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.telephony.qns.atoms; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import android.util.StatsEvent; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@RunWith(JUnit4.class) +public class AtomsQnsHandoverPingPongInfoTest { + + @Mock + private StatsEvent.Builder mStatsEventBuilder; + + private static final int DEFAULT_COUNT_HANDOVER_PING_PONG = 2; + private static final int DEFAULT_CARRIER_ID = 1; // TMO + + private AtomsQnsHandoverPingPongInfo mInfoEmpty; + private AtomsQnsHandoverPingPongInfo mInfoDefault; + private AtomsQnsHandoverPingPongInfo mInfoCopy; + + /** atom #1 : Count of handover ping-pong */ + private int mCountHandoverPingPong; + + /** atom #2 : Carrier Id */ + private int mCarrierId; + + /** atom #3 : Slot Index */ + private int mSlotIndex; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mCountHandoverPingPong = DEFAULT_COUNT_HANDOVER_PING_PONG; + mCarrierId = DEFAULT_CARRIER_ID; + mSlotIndex = 0; + mInfoEmpty = new AtomsQnsHandoverPingPongInfo(); + mInfoDefault = + new AtomsQnsHandoverPingPongInfo(mCountHandoverPingPong, mCarrierId, mSlotIndex); + mInfoCopy = new AtomsQnsHandoverPingPongInfo(mInfoDefault); + } + + @After + public void tearDown() { + mInfoEmpty = null; + mInfoDefault = null; + mInfoCopy = null; + } + + @Test + public void testGetSetCountHandoverPingPong() { + assertEquals(0, mInfoEmpty.getCountHandoverPingPong()); + assertEquals(DEFAULT_COUNT_HANDOVER_PING_PONG, mInfoDefault.getCountHandoverPingPong()); + assertEquals(DEFAULT_COUNT_HANDOVER_PING_PONG, mInfoCopy.getCountHandoverPingPong()); + + mInfoEmpty.setCountHandoverPingPong(3); + mInfoDefault.setCountHandoverPingPong(4); + mInfoCopy.setCountHandoverPingPong(5); + + assertEquals(3, mInfoEmpty.getCountHandoverPingPong()); + assertEquals(4, mInfoDefault.getCountHandoverPingPong()); + assertEquals(5, mInfoCopy.getCountHandoverPingPong()); + } + + @Test + public void testGetSetCarrierId() { + assertEquals(0, mInfoEmpty.getCarrierId()); + assertEquals(DEFAULT_CARRIER_ID, mInfoDefault.getCarrierId()); + assertEquals(DEFAULT_CARRIER_ID, mInfoCopy.getCarrierId()); + + mInfoEmpty.setCarrierId(1); + mInfoDefault.setCarrierId(2); + mInfoCopy.setCarrierId(3); + + assertEquals(1, mInfoEmpty.getCarrierId()); + assertEquals(2, mInfoDefault.getCarrierId()); + assertEquals(3, mInfoCopy.getCarrierId()); + } + + @Test + public void testGetSetSlotIndex() { + assertEquals(0, mInfoEmpty.getSlotIndex()); + assertEquals(0, mInfoDefault.getSlotIndex()); + assertEquals(0, mInfoCopy.getSlotIndex()); + + mInfoEmpty.setSlotIndex(1); + mInfoDefault.setSlotIndex(2); + mInfoCopy.setSlotIndex(3); + + assertEquals(1, mInfoEmpty.getSlotIndex()); + assertEquals(2, mInfoDefault.getSlotIndex()); + assertEquals(3, mInfoCopy.getSlotIndex()); + } + + @Test + public void testToString() { + String strInfoEmpty = mInfoEmpty.toString(); + String strInfoDefault = mInfoDefault.toString(); + String strInfoCopy = mInfoCopy.toString(); + + assertNotNull(strInfoEmpty); + assertNotNull(strInfoDefault); + assertNotNull(strInfoCopy); + + assertTrue(strInfoDefault.startsWith("AtomsQnsHandoverPingPongInfo")); + + assertEquals(strInfoDefault, strInfoCopy); + assertNotEquals(strInfoEmpty, strInfoDefault); + } + + @Test + public void testEquals() { + assertEquals(mInfoDefault, mInfoDefault); + assertNotEquals(mInfoDefault, new Object()); + assertEquals(mInfoDefault, mInfoCopy); + mInfoDefault.setCountHandoverPingPong(2); + mInfoCopy.setCountHandoverPingPong(3); + assertNotEquals(mInfoDefault, mInfoCopy); + } + + @Test + public void testHashCode() { + AtomsQnsHandoverPingPongInfo a1, a2; + + a1 = new AtomsQnsHandoverPingPongInfo(2, 1, 0); + a2 = new AtomsQnsHandoverPingPongInfo(3, 1, 0); + assertNotEquals(a1.hashCode(), a2.hashCode()); + + a1 = new AtomsQnsHandoverPingPongInfo(mCountHandoverPingPong, mCarrierId, mSlotIndex); + a2 = new AtomsQnsHandoverPingPongInfo(mCountHandoverPingPong, mCarrierId, mSlotIndex); + assertEquals(a1.hashCode(), a2.hashCode()); + } + + @Test + public void testDimension() { + AtomsQnsHandoverPingPongInfo a1, a2; + + a1 = new AtomsQnsHandoverPingPongInfo(mCountHandoverPingPong, 3, mSlotIndex); + a2 = new AtomsQnsHandoverPingPongInfo(mCountHandoverPingPong, 1, mSlotIndex); + assertNotEquals(a1.getDimension(), a2.getDimension()); + + a1 = new AtomsQnsHandoverPingPongInfo(mCountHandoverPingPong, mCarrierId, 0); + a2 = new AtomsQnsHandoverPingPongInfo(mCountHandoverPingPong, mCarrierId, 1); + assertNotEquals(a1.getDimension(), a2.getDimension()); + + a1 = new AtomsQnsHandoverPingPongInfo(1, mCarrierId, mSlotIndex); + a2 = new AtomsQnsHandoverPingPongInfo(2, mCarrierId, mSlotIndex); + assertEquals(a1.getDimension(), a2.getDimension()); + } + + @Test + public void testStatsId() { + final int statsId = 10179; // QnsHandoverPingpong + assertEquals(statsId, mInfoDefault.copy().getStatsId()); + } + + @Test + public void testStatsEventBuilder() { + mInfoDefault.build(mStatsEventBuilder); + + verify(mStatsEventBuilder, times(3)).writeInt(anyInt()); + } +} diff --git a/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/atoms/AtomsQnsHandoverTimeMillisInfoTest.java b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/atoms/AtomsQnsHandoverTimeMillisInfoTest.java new file mode 100644 index 0000000..701874b --- /dev/null +++ b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/atoms/AtomsQnsHandoverTimeMillisInfoTest.java @@ -0,0 +1,162 @@ +/* + * Copyright (C) 2022 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.telephony.qns.atoms; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import android.util.StatsEvent; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@RunWith(JUnit4.class) +public class AtomsQnsHandoverTimeMillisInfoTest { + + @Mock + private StatsEvent.Builder mStatsEventBuilder; + + private static final int DEFAULT_TIMER_FOR_HANDOVER_SUCCESS = 5000; + + private AtomsQnsHandoverTimeMillisInfo mInfoEmpty; + private AtomsQnsHandoverTimeMillisInfo mInfoDefault; + private AtomsQnsHandoverTimeMillisInfo mInfoCopy; + + /** atom #1 : Time in milliseconds from QNS RAT update to successful HO completion */ + private int mTimeForHoSuccess; + + /** atom #2 : Slot Index */ + private int mSlotIndex; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mTimeForHoSuccess = DEFAULT_TIMER_FOR_HANDOVER_SUCCESS; + mSlotIndex = 0; + mInfoEmpty = new AtomsQnsHandoverTimeMillisInfo(); + mInfoDefault = new AtomsQnsHandoverTimeMillisInfo(mTimeForHoSuccess, mSlotIndex); + mInfoCopy = new AtomsQnsHandoverTimeMillisInfo(mInfoDefault); + } + + @After + public void tearDown() { + mInfoEmpty = null; + mInfoDefault = null; + mInfoCopy = null; + } + + @Test + public void testGetSetTimeForHoSuccess() { + assertEquals(0, mInfoEmpty.getTimeForHoSuccess()); + assertEquals(DEFAULT_TIMER_FOR_HANDOVER_SUCCESS, mInfoDefault.getTimeForHoSuccess()); + assertEquals(DEFAULT_TIMER_FOR_HANDOVER_SUCCESS, mInfoCopy.getTimeForHoSuccess()); + + mInfoEmpty.setTimeForHoSuccess(3000); + mInfoDefault.setTimeForHoSuccess(4000); + mInfoCopy.setTimeForHoSuccess(7000); + + assertEquals(3000, mInfoEmpty.getTimeForHoSuccess()); + assertEquals(4000, mInfoDefault.getTimeForHoSuccess()); + assertEquals(7000, mInfoCopy.getTimeForHoSuccess()); + } + + @Test + public void testGetSetSlotIndex() { + assertEquals(0, mInfoEmpty.getSlotIndex()); + assertEquals(0, mInfoDefault.getSlotIndex()); + assertEquals(0, mInfoCopy.getSlotIndex()); + + mInfoEmpty.setSlotIndex(1); + mInfoDefault.setSlotIndex(2); + mInfoCopy.setSlotIndex(3); + + assertEquals(1, mInfoEmpty.getSlotIndex()); + assertEquals(2, mInfoDefault.getSlotIndex()); + assertEquals(3, mInfoCopy.getSlotIndex()); + } + + @Test + public void testToString() { + String strInfoEmpty = mInfoEmpty.toString(); + String strInfoDefault = mInfoDefault.toString(); + String strInfoCopy = mInfoCopy.toString(); + + assertNotNull(strInfoEmpty); + assertNotNull(strInfoDefault); + assertNotNull(strInfoCopy); + + assertTrue(strInfoDefault.startsWith("AtomsQnsHandoverTimeMillisInfo")); + + assertEquals(strInfoDefault, strInfoCopy); + assertNotEquals(strInfoEmpty, strInfoDefault); + } + + @Test + public void testEquals() { + assertEquals(mInfoDefault, mInfoDefault); + assertNotEquals(mInfoDefault, new Object()); + assertEquals(mInfoDefault, mInfoCopy); + mInfoDefault.setTimeForHoSuccess(2000); + mInfoCopy.setTimeForHoSuccess(3000); + assertNotEquals(mInfoDefault, mInfoCopy); + } + + @Test + public void testHashCode() { + AtomsQnsHandoverTimeMillisInfo a1, a2; + + a1 = new AtomsQnsHandoverTimeMillisInfo(2000, 0); + a2 = new AtomsQnsHandoverTimeMillisInfo(3000, 0); + assertNotEquals(a1.hashCode(), a2.hashCode()); + + a1 = new AtomsQnsHandoverTimeMillisInfo(mTimeForHoSuccess, mSlotIndex); + a2 = new AtomsQnsHandoverTimeMillisInfo(mTimeForHoSuccess, mSlotIndex); + assertEquals(a1.hashCode(), a2.hashCode()); + } + + @Test + public void testDimension() { + AtomsQnsHandoverTimeMillisInfo a1, a2; + a1 = new AtomsQnsHandoverTimeMillisInfo(1000, 0); + a2 = new AtomsQnsHandoverTimeMillisInfo(2000, 1); + assertNotEquals(a1.getDimension(), a2.getDimension()); + assertEquals(a1.getDimension(), mInfoDefault.getDimension()); + } + + @Test + public void testStatsId() { + final int statsId = 10178; // QnsHandoverTimeMillis + assertEquals(statsId, mInfoDefault.copy().getStatsId()); + } + + @Test + public void testStatsEventBuilder() { + mInfoDefault.build(mStatsEventBuilder); + + verify(mStatsEventBuilder, times(2)).writeInt(anyInt()); + } +} diff --git a/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/atoms/AtomsQnsImsCallDropStatsTest.java b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/atoms/AtomsQnsImsCallDropStatsTest.java new file mode 100644 index 0000000..a2b68ad --- /dev/null +++ b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/atoms/AtomsQnsImsCallDropStatsTest.java @@ -0,0 +1,352 @@ +/* + * Copyright (C) 2022 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.telephony.qns.atoms; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import android.telephony.qns.QnsProtoEnums; +import android.util.StatsEvent; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@RunWith(JUnit4.class) +public class AtomsQnsImsCallDropStatsTest { + + @Mock + private StatsEvent.Builder mStatsEventBuilder; + + private static final int DEFAULT_CURRENT_TRANSPORT_TYPE = QnsProtoEnums.TRANSPORT_TYPE_WWAN; + private static final int DEFAULT_RESTRICTIONS = QnsProtoEnums.RESTRICT_TYPE_NONE; + private static final int DEFAULT_SIGNAL_STRENGTH = -100; + private static final int DEFAULT_SIGNAL_QUALITY = -10; + private static final int DEFAULT_SIGNAL_NOISE = -1; + private static final int DEFAULT_IWLAN_SIGNAL_STRENGTH = -70; + private static final int DEFAULT_CELLULAR_NETWORK_TYPE = QnsProtoEnums.EUTRAN; + + private AtomsQnsImsCallDropStats mInfoEmpty; + private AtomsQnsImsCallDropStats mInfoDefault; + private AtomsQnsImsCallDropStats mInfoCopy; + + /** atom #1 : Transport type in where IMS call drop occurred. */ + private int mTransportTypeCallDropped; + + /** atom #2 : RTP threshold breached event occurred. */ + private boolean mRtpThresholdBreached; + + /** atom #3 : Bit mask of restrictions on another transport type */ + private int mRestrictionsOnOtherTransportType; + + /** atom #4 : Cellular network signal strength {e.g. SSRSRP in NR, RSRP in LTE} */ + private int mSignalStrength; + + /** atom #5 : Cellular network signal quality {e.g. SSRSRQ in NR, RSRQ in LTE} */ + private int mSignalQuality; + + /** atom #6 : Cellular network signal noise ratio {e.g. SSSINR in NR, RSSNR in LTE} */ + private int mSignalNoise; + + /** atom #7 : Iwlan network signal strength (Wi-Fi RSSI) */ + private int mIwlanSignalStrength; + + /** atom #8 : Slot Index */ + private int mSlotIndex; + + /** atom #9 : cellular access network type. */ + private int mCellularNetworkType; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mTransportTypeCallDropped = DEFAULT_CURRENT_TRANSPORT_TYPE; + mRtpThresholdBreached = true; + mRestrictionsOnOtherTransportType = DEFAULT_RESTRICTIONS; + mSignalStrength = DEFAULT_SIGNAL_STRENGTH; + mSignalQuality = DEFAULT_SIGNAL_QUALITY; + mSignalNoise = DEFAULT_SIGNAL_NOISE; + mIwlanSignalStrength = DEFAULT_IWLAN_SIGNAL_STRENGTH; + mSlotIndex = 0; + mCellularNetworkType = DEFAULT_CELLULAR_NETWORK_TYPE; + + mInfoEmpty = new AtomsQnsImsCallDropStats(); + mInfoDefault = + new AtomsQnsImsCallDropStats( + mTransportTypeCallDropped, + mRtpThresholdBreached, + mRestrictionsOnOtherTransportType, + mSignalStrength, + mSignalQuality, + mSignalNoise, + mIwlanSignalStrength, + mSlotIndex, + mCellularNetworkType); + mInfoCopy = new AtomsQnsImsCallDropStats(mInfoDefault); + } + + @After + public void tearDown() { + mInfoEmpty = null; + mInfoDefault = null; + mInfoCopy = null; + } + + @Test + public void testGetSetTransportTypeCallDropped() { + assertEquals(0, mInfoEmpty.getTransportTypeCallDropped()); + assertEquals(DEFAULT_CURRENT_TRANSPORT_TYPE, mInfoDefault.getTransportTypeCallDropped()); + assertEquals(DEFAULT_CURRENT_TRANSPORT_TYPE, mInfoCopy.getTransportTypeCallDropped()); + + mInfoEmpty.setTransportTypeCallDropped(QnsProtoEnums.TRANSPORT_TYPE_WWAN); + mInfoDefault.setTransportTypeCallDropped(QnsProtoEnums.TRANSPORT_TYPE_WLAN); + mInfoCopy.setTransportTypeCallDropped(QnsProtoEnums.TRANSPORT_TYPE_INVALID); + + assertEquals(QnsProtoEnums.TRANSPORT_TYPE_WWAN, mInfoEmpty.getTransportTypeCallDropped()); + assertEquals(QnsProtoEnums.TRANSPORT_TYPE_WLAN, mInfoDefault.getTransportTypeCallDropped()); + assertEquals(QnsProtoEnums.TRANSPORT_TYPE_INVALID, mInfoCopy.getTransportTypeCallDropped()); + } + + @Test + public void testGetSetRtpThresholdBreached() { + assertFalse(mInfoEmpty.getRtpThresholdBreached()); + assertTrue(mInfoDefault.getRtpThresholdBreached()); + assertTrue(mInfoCopy.getRtpThresholdBreached()); + + mInfoEmpty.setRtpThresholdBreached(true); + mInfoDefault.setRtpThresholdBreached(true); + mInfoCopy.setRtpThresholdBreached(false); + + assertTrue(mInfoEmpty.getRtpThresholdBreached()); + assertTrue(mInfoDefault.getRtpThresholdBreached()); + assertFalse(mInfoCopy.getRtpThresholdBreached()); + } + + @Test + public void testGetSetRestrictionsOnOtherTransportType() { + assertEquals(0, mInfoEmpty.getRestrictionsOnOtherTransportType()); + assertEquals(DEFAULT_RESTRICTIONS, mInfoDefault.getRestrictionsOnOtherTransportType()); + assertEquals(DEFAULT_RESTRICTIONS, mInfoCopy.getRestrictionsOnOtherTransportType()); + + mInfoEmpty.setRestrictionsOnOtherTransportType(QnsProtoEnums.RESTRICT_TYPE_GUARDING); + mInfoDefault.setRestrictionsOnOtherTransportType(QnsProtoEnums.RESTRICT_TYPE_THROTTLING); + mInfoCopy.setRestrictionsOnOtherTransportType(QnsProtoEnums.RESTRICT_TYPE_NONE); + + assertEquals( + QnsProtoEnums.RESTRICT_TYPE_GUARDING, + mInfoEmpty.getRestrictionsOnOtherTransportType()); + assertEquals( + QnsProtoEnums.RESTRICT_TYPE_THROTTLING, + mInfoDefault.getRestrictionsOnOtherTransportType()); + assertEquals( + QnsProtoEnums.RESTRICT_TYPE_NONE, mInfoCopy.getRestrictionsOnOtherTransportType()); + } + + @Test + public void testGetSetSignalStrength() { + assertEquals(0, mInfoEmpty.getSignalStrength()); + assertEquals(DEFAULT_SIGNAL_STRENGTH, mInfoDefault.getSignalStrength()); + assertEquals(DEFAULT_SIGNAL_STRENGTH, mInfoCopy.getSignalStrength()); + + mInfoEmpty.setSignalStrength(DEFAULT_SIGNAL_STRENGTH); + mInfoDefault.setSignalStrength(-120); + mInfoCopy.setSignalStrength(-110); + + assertEquals(DEFAULT_SIGNAL_STRENGTH, mInfoEmpty.getSignalStrength()); + assertEquals(-120, mInfoDefault.getSignalStrength()); + assertEquals(-110, mInfoCopy.getSignalStrength()); + } + + @Test + public void testGetSetSignalQuality() { + assertEquals(0, mInfoEmpty.getSignalQuality()); + assertEquals(DEFAULT_SIGNAL_QUALITY, mInfoDefault.getSignalQuality()); + assertEquals(DEFAULT_SIGNAL_QUALITY, mInfoCopy.getSignalQuality()); + + mInfoEmpty.setSignalQuality(DEFAULT_SIGNAL_QUALITY); + mInfoDefault.setSignalQuality(-10); + mInfoCopy.setSignalQuality(-5); + + assertEquals(DEFAULT_SIGNAL_QUALITY, mInfoEmpty.getSignalQuality()); + assertEquals(-10, mInfoDefault.getSignalQuality()); + assertEquals(-5, mInfoCopy.getSignalQuality()); + } + + @Test + public void testGetSetSignalNoise() { + assertEquals(0, mInfoEmpty.getSignalNoise()); + assertEquals(DEFAULT_SIGNAL_NOISE, mInfoDefault.getSignalNoise()); + assertEquals(DEFAULT_SIGNAL_NOISE, mInfoCopy.getSignalNoise()); + + mInfoEmpty.setSignalNoise(DEFAULT_SIGNAL_NOISE); + mInfoDefault.setSignalNoise(1); + mInfoCopy.setSignalNoise(-1); + + assertEquals(DEFAULT_SIGNAL_NOISE, mInfoEmpty.getSignalNoise()); + assertEquals(1, mInfoDefault.getSignalNoise()); + assertEquals(-1, mInfoCopy.getSignalNoise()); + } + + @Test + public void testGetSetIwlanSignalStrength() { + assertEquals(0, mInfoEmpty.getIwlanSignalStrength()); + assertEquals(DEFAULT_IWLAN_SIGNAL_STRENGTH, mInfoDefault.getIwlanSignalStrength()); + assertEquals(DEFAULT_IWLAN_SIGNAL_STRENGTH, mInfoCopy.getIwlanSignalStrength()); + + mInfoEmpty.setIwlanSignalStrength(DEFAULT_IWLAN_SIGNAL_STRENGTH); + mInfoDefault.setIwlanSignalStrength(-80); + mInfoCopy.setIwlanSignalStrength(-50); + + assertEquals(DEFAULT_IWLAN_SIGNAL_STRENGTH, mInfoEmpty.getIwlanSignalStrength()); + assertEquals(-80, mInfoDefault.getIwlanSignalStrength()); + assertEquals(-50, mInfoCopy.getIwlanSignalStrength()); + } + + @Test + public void testGetSetSlotIndex() { + assertEquals(0, mInfoEmpty.getSlotIndex()); + assertEquals(0, mInfoDefault.getSlotIndex()); + assertEquals(0, mInfoCopy.getSlotIndex()); + + mInfoEmpty.setSlotIndex(1); + mInfoDefault.setSlotIndex(2); + mInfoCopy.setSlotIndex(3); + + assertEquals(1, mInfoEmpty.getSlotIndex()); + assertEquals(2, mInfoDefault.getSlotIndex()); + assertEquals(3, mInfoCopy.getSlotIndex()); + } + + @Test + public void testGetSetCellularNetworkType() { + assertEquals(0, mInfoEmpty.getCellularNetworkType()); + assertEquals(DEFAULT_CELLULAR_NETWORK_TYPE, mInfoDefault.getCellularNetworkType()); + assertEquals(DEFAULT_CELLULAR_NETWORK_TYPE, mInfoCopy.getCellularNetworkType()); + + mInfoEmpty.setCellularNetworkType(QnsProtoEnums.NGRAN); + mInfoDefault.setCellularNetworkType(QnsProtoEnums.UTRAN); + mInfoCopy.setCellularNetworkType(QnsProtoEnums.GERAN); + + assertEquals(QnsProtoEnums.NGRAN, mInfoEmpty.getCellularNetworkType()); + assertEquals(QnsProtoEnums.UTRAN, mInfoDefault.getCellularNetworkType()); + assertEquals(QnsProtoEnums.GERAN, mInfoCopy.getCellularNetworkType()); + } + + @Test + public void testToString() { + String strInfoEmpty = mInfoEmpty.toString(); + String strInfoDefault = mInfoDefault.toString(); + String strInfoCopy = mInfoCopy.toString(); + + assertNotNull(strInfoEmpty); + assertNotNull(strInfoDefault); + assertNotNull(strInfoCopy); + + assertTrue(strInfoDefault.startsWith("AtomsQnsImsCallDropStats")); + + assertEquals(strInfoDefault, strInfoCopy); + assertNotEquals(strInfoEmpty, strInfoDefault); + } + + @Test + public void testEquals() { + assertEquals(mInfoDefault, mInfoDefault); + assertNotEquals(mInfoDefault, new Object()); + assertEquals(mInfoDefault, mInfoCopy); + mInfoDefault.setSignalQuality(3); + mInfoCopy.setSignalQuality(1); + assertNotEquals(mInfoDefault, mInfoCopy); + } + + @Test + public void testHashCode() { + AtomsQnsImsCallDropStats a1, a2; + + a1 = + new AtomsQnsImsCallDropStats( + mInfoDefault.getTransportTypeCallDropped(), + mInfoDefault.getRtpThresholdBreached(), + mInfoDefault.getRestrictionsOnOtherTransportType(), + 0, + 0, + 0, + 0, + 0, + 0); + a2 = + new AtomsQnsImsCallDropStats( + mInfoDefault.getTransportTypeCallDropped(), + mInfoDefault.getRtpThresholdBreached(), + mInfoDefault.getRestrictionsOnOtherTransportType(), + 0, + 0, + 0, + 0, + 0, + 1); + assertNotEquals(a1.hashCode(), a2.hashCode()); + + a1 = + new AtomsQnsImsCallDropStats( + mTransportTypeCallDropped, + mRtpThresholdBreached, + mRestrictionsOnOtherTransportType, + mSignalStrength, + mSignalQuality, + mSignalNoise, + mIwlanSignalStrength, + mSlotIndex, + mCellularNetworkType); + a2 = + new AtomsQnsImsCallDropStats( + mTransportTypeCallDropped, + mRtpThresholdBreached, + mRestrictionsOnOtherTransportType, + mSignalStrength, + mSignalQuality, + mSignalNoise, + mIwlanSignalStrength, + mSlotIndex, + mCellularNetworkType); + assertEquals(a1.hashCode(), a2.hashCode()); + } + + @Test + public void testStatsId() { + final int statsId = 635; // QnsImsCallDropStats + assertEquals(statsId, mInfoDefault.copy().getStatsId()); + } + + @Test + public void testStatsEventBuilder() { + mInfoDefault.build(mStatsEventBuilder); + + verify(mStatsEventBuilder, times(1)).writeBoolean(anyBoolean()); + verify(mStatsEventBuilder, times(8)).writeInt(anyInt()); + } +} diff --git a/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/atoms/AtomsQnsRatPreferenceMismatchInfoTest.java b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/atoms/AtomsQnsRatPreferenceMismatchInfoTest.java new file mode 100644 index 0000000..4c5b469 --- /dev/null +++ b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/atoms/AtomsQnsRatPreferenceMismatchInfoTest.java @@ -0,0 +1,261 @@ +/* + * Copyright (C) 2022 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.telephony.qns.atoms; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import android.telephony.qns.QnsProtoEnums; +import android.util.StatsEvent; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@RunWith(JUnit4.class) +public class AtomsQnsRatPreferenceMismatchInfoTest { + + @Mock + private StatsEvent.Builder mStatsEventBuilder; + + private static final int DEFAULT_NET_CAPABILITY = QnsProtoEnums.NET_CAPABILITY_IMS; + private static final int DEFAULT_HANDOVER_FAIL_COUNT = 1; + private static final int DEFAULT_DURATION_OF_MISMATCH = 13500; + private static final int DEFAULT_CARRIER_ID = 1; // TMO + + private AtomsQnsRatPreferenceMismatchInfo mInfoEmpty; + private AtomsQnsRatPreferenceMismatchInfo mInfoDefault; + private AtomsQnsRatPreferenceMismatchInfo mInfoCopy; + + /** atom #1 : Net capability of this information. */ + private int mNetCapability; + + /** atom #2 : Count of handover failed. */ + private int mHandoverFailCount; + + /** atom #3 : Duration of this mismatch. */ + private int mDurationOfMismatch; + + /** atom #4 : Carrier ID */ + private int mCarrierId; + + /** atom #5 : Slot Index */ + private int mSlotIndex; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mNetCapability = DEFAULT_NET_CAPABILITY; + mHandoverFailCount = DEFAULT_HANDOVER_FAIL_COUNT; + mDurationOfMismatch = DEFAULT_DURATION_OF_MISMATCH; + mCarrierId = DEFAULT_CARRIER_ID; + mSlotIndex = 0; + mInfoEmpty = new AtomsQnsRatPreferenceMismatchInfo(); + mInfoDefault = + new AtomsQnsRatPreferenceMismatchInfo( + mNetCapability, + mHandoverFailCount, + mDurationOfMismatch, + mCarrierId, + mSlotIndex); + mInfoCopy = new AtomsQnsRatPreferenceMismatchInfo(mInfoDefault); + } + + @After + public void tearDown() { + mInfoEmpty = null; + mInfoDefault = null; + mInfoCopy = null; + } + + @Test + public void testGetSetNetCapability() { + assertEquals(0, mInfoEmpty.getNetCapability()); + assertEquals(DEFAULT_NET_CAPABILITY, mInfoDefault.getNetCapability()); + assertEquals(DEFAULT_NET_CAPABILITY, mInfoCopy.getNetCapability()); + + mInfoEmpty.setNetCapability(QnsProtoEnums.NET_CAPABILITY_MMS); + mInfoDefault.setNetCapability(QnsProtoEnums.NET_CAPABILITY_CBS); + mInfoCopy.setNetCapability(QnsProtoEnums.NET_CAPABILITY_XCAP); + + assertEquals(QnsProtoEnums.NET_CAPABILITY_MMS, mInfoEmpty.getNetCapability()); + assertEquals(QnsProtoEnums.NET_CAPABILITY_CBS, mInfoDefault.getNetCapability()); + assertEquals(QnsProtoEnums.NET_CAPABILITY_XCAP, mInfoCopy.getNetCapability()); + } + + @Test + public void testGetSetHandoverFailCount() { + assertEquals(0, mInfoEmpty.getHandoverFailCount()); + assertEquals(DEFAULT_HANDOVER_FAIL_COUNT, mInfoDefault.getHandoverFailCount()); + assertEquals(DEFAULT_HANDOVER_FAIL_COUNT, mInfoCopy.getHandoverFailCount()); + + mInfoEmpty.setHandoverFailCount(DEFAULT_HANDOVER_FAIL_COUNT); + mInfoDefault.setHandoverFailCount(4); + mInfoCopy.setHandoverFailCount(0); + + assertEquals(DEFAULT_HANDOVER_FAIL_COUNT, mInfoEmpty.getHandoverFailCount()); + assertEquals(4, mInfoDefault.getHandoverFailCount()); + assertEquals(0, mInfoCopy.getHandoverFailCount()); + } + + @Test + public void testGetSetDurationOfMismatch() { + assertEquals(0, mInfoEmpty.getDurationOfMismatch()); + assertEquals(DEFAULT_DURATION_OF_MISMATCH, mInfoDefault.getDurationOfMismatch()); + assertEquals(DEFAULT_DURATION_OF_MISMATCH, mInfoCopy.getDurationOfMismatch()); + + mInfoEmpty.setDurationOfMismatch(DEFAULT_DURATION_OF_MISMATCH); + mInfoDefault.setDurationOfMismatch(4000); + mInfoCopy.setDurationOfMismatch(0); + + assertEquals(DEFAULT_DURATION_OF_MISMATCH, mInfoEmpty.getDurationOfMismatch()); + assertEquals(4000, mInfoDefault.getDurationOfMismatch()); + assertEquals(0, mInfoCopy.getDurationOfMismatch()); + } + + @Test + public void testGetSetCarrierId() { + assertEquals(0, mInfoEmpty.getCarrierId()); + assertEquals(DEFAULT_CARRIER_ID, mInfoDefault.getCarrierId()); + assertEquals(DEFAULT_CARRIER_ID, mInfoCopy.getCarrierId()); + + mInfoEmpty.setCarrierId(1); + mInfoDefault.setCarrierId(2); + mInfoCopy.setCarrierId(3); + + assertEquals(1, mInfoEmpty.getCarrierId()); + assertEquals(2, mInfoDefault.getCarrierId()); + assertEquals(3, mInfoCopy.getCarrierId()); + } + + @Test + public void testGetSetSlotIndex() { + assertEquals(0, mInfoEmpty.getSlotIndex()); + assertEquals(0, mInfoDefault.getSlotIndex()); + assertEquals(0, mInfoCopy.getSlotIndex()); + + mInfoEmpty.setSlotIndex(1); + mInfoDefault.setSlotIndex(2); + mInfoCopy.setSlotIndex(3); + + assertEquals(1, mInfoEmpty.getSlotIndex()); + assertEquals(2, mInfoDefault.getSlotIndex()); + assertEquals(3, mInfoCopy.getSlotIndex()); + } + + @Test + public void testToString() { + String strInfoEmpty = mInfoEmpty.toString(); + String strInfoDefault = mInfoDefault.toString(); + String strInfoCopy = mInfoCopy.toString(); + + assertNotNull(strInfoEmpty); + assertNotNull(strInfoDefault); + assertNotNull(strInfoCopy); + + assertTrue(strInfoDefault.startsWith("AtomsQnsRatPreferenceMismatchInfo")); + + assertEquals(strInfoDefault, strInfoCopy); + assertNotEquals(strInfoEmpty, strInfoDefault); + } + + @Test + public void testEquals() { + assertEquals(mInfoDefault, mInfoDefault); + assertNotEquals(mInfoDefault, new Object()); + assertEquals(mInfoDefault, mInfoCopy); + mInfoDefault.setHandoverFailCount(0); + mInfoCopy.setHandoverFailCount(1); + assertNotEquals(mInfoDefault, mInfoCopy); + } + + @Test + public void testHashCode() { + AtomsQnsRatPreferenceMismatchInfo a1, a2; + + a1 = + new AtomsQnsRatPreferenceMismatchInfo( + QnsProtoEnums.NET_CAPABILITY_IMS, 0, 0, mCarrierId, mSlotIndex); + a2 = + new AtomsQnsRatPreferenceMismatchInfo( + QnsProtoEnums.NET_CAPABILITY_MMS, 0, 0, mCarrierId, mSlotIndex); + assertNotEquals(a1.hashCode(), a2.hashCode()); + + a1 = + new AtomsQnsRatPreferenceMismatchInfo( + mNetCapability, + mHandoverFailCount, + mDurationOfMismatch, + mCarrierId, + mSlotIndex); + a2 = + new AtomsQnsRatPreferenceMismatchInfo( + mNetCapability, + mHandoverFailCount, + mDurationOfMismatch, + mCarrierId, + mSlotIndex); + assertEquals(a1.hashCode(), a2.hashCode()); + } + + @Test + public void testDimension() { + AtomsQnsRatPreferenceMismatchInfo a1, a2; + + a1 = + new AtomsQnsRatPreferenceMismatchInfo( + mNetCapability, mHandoverFailCount, mDurationOfMismatch, 1, mSlotIndex); + a2 = + new AtomsQnsRatPreferenceMismatchInfo( + mNetCapability, mHandoverFailCount, mDurationOfMismatch, 3, mSlotIndex); + assertNotEquals(a1.getDimension(), a2.getDimension()); + + a1 = + new AtomsQnsRatPreferenceMismatchInfo( + mNetCapability, mHandoverFailCount, mDurationOfMismatch, mCarrierId, 0); + a2 = + new AtomsQnsRatPreferenceMismatchInfo( + mNetCapability, mHandoverFailCount, mDurationOfMismatch, mCarrierId, 1); + assertNotEquals(a1.getDimension(), a2.getDimension()); + + a1 = new AtomsQnsRatPreferenceMismatchInfo(9, 0, 100, mCarrierId, mSlotIndex); + a2 = new AtomsQnsRatPreferenceMismatchInfo(9, 1, 200, mCarrierId, mSlotIndex); + assertEquals(a1.getDimension(), a2.getDimension()); + } + + @Test + public void testStatsId() { + final int statsId = 10177; // QnsRatPreferenceMismatchInfo + assertEquals(statsId, mInfoDefault.copy().getStatsId()); + } + + @Test + public void testStatsEventBuilder() { + mInfoDefault.build(mStatsEventBuilder); + + verify(mStatsEventBuilder, times(5)).writeInt(anyInt()); + } +} diff --git a/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/atoms/AtomsQualifiedRatListChangedInfoTest.java b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/atoms/AtomsQualifiedRatListChangedInfoTest.java new file mode 100644 index 0000000..5eb6a42 --- /dev/null +++ b/services/QualifiedNetworksService/tests/src/com/android/telephony/qns/atoms/AtomsQualifiedRatListChangedInfoTest.java @@ -0,0 +1,534 @@ +/* + * Copyright (C) 2022 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.telephony.qns.atoms; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; +import static org.mockito.ArgumentMatchers.anyBoolean; +import static org.mockito.ArgumentMatchers.anyInt; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; + +import android.telephony.qns.QnsProtoEnums; +import android.util.StatsEvent; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.JUnit4; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; + +@RunWith(JUnit4.class) +public class AtomsQualifiedRatListChangedInfoTest { + + @Mock + private StatsEvent.Builder mStatsEventBuilder; + + private static final int DEFAULT_NET_CAPABILITY = QnsProtoEnums.NET_CAPABILITY_IMS; + private static final int DEFAULT_FIRST_QUALIFIED_RAT = QnsProtoEnums.EUTRAN; + private static final int DEFAULT_SECOND_QUALIFIED_RAT = QnsProtoEnums.IWLAN; + private static final int DEFAULT_CURRENT_TRANSPORT_TYPE = QnsProtoEnums.TRANSPORT_TYPE_WLAN; + private static final boolean DEFAULT_WFC_ENABLED = true; + private static final int DEFAULT_WFC_MODE = QnsProtoEnums.CELLULAR_PREFERRED; + private static final int DEFAULT_CELLULAR_NETWORK_TYPE = QnsProtoEnums.EUTRAN; + private static final int DEFAULT_IWLAN_NETWORK_TYPE = QnsProtoEnums.IWLAN_NETWORK_TYPE_WIFI; + private static final int DEFAULT_RESTRICTIONS_ON_WWAN = QnsProtoEnums.RESTRICT_TYPE_NONE; + private static final int DEFAULT_RESTRICTIONS_ON_WLAN = QnsProtoEnums.RESTRICT_TYPE_NONE; + private static final int DEFAULT_SIGNAL_STRENGTH = -100; + private static final int DEFAULT_SIGNAL_QUALITY = -10; + private static final int DEFAULT_SIGNAL_NOISE = -1; + private static final int DEFAULT_IWLAN_SIGNAL_STRENGTH = -70; + private static final int DEFAULT_UPDATE_REASON = 0; + + private AtomsQualifiedRatListChangedInfo mInfoEmpty; + private AtomsQualifiedRatListChangedInfo mInfoDefault; + private AtomsQualifiedRatListChangedInfo mInfoCopy; + + /** atom #1 : NetCapability of this Qualified RAT update */ + private int mNetCapability; + /** atom #2 : The most preferred qualified RAT */ + private int mFirstQualifiedRat; + /** atom #3 : Second preferred qualified RAT */ + private int mSecondQualifiedRat; + /** atom #4 : Current actual transport type of Data session for this NetCapability */ + private int mCurrentTransportType; + /** atom #5 : Indicates whether WFC is enabled */ + private boolean mWfcEnabled; + /** atom #6 : Indicates the user's WFC mode */ + private int mWfcMode; + /** atom #7 : Current Cellular AccessNetwork Type */ + private int mCellularNetworkType; + /** atom #8 : Available IWLAN AccessNetwork */ + private int mIwlanNetworkType; + /** atom #9 : Bit mask of restrictions on WWAN */ + private int mRestrictionsOnWwan; + /** atom #10 : Bit mask of restrictions on WLAN */ + private int mRestrictionsOnWlan; + /** + * atom #11 : Cellular network signal strength {e.g. SSRSRP in NR, RSRP in LTE, RSCP in UMTS} + */ + private int mSignalStrength; + /** atom #12 : Cellular network signal quality {e.g. SSRSRQ in NR, RSRQ in LTE} */ + private int mSignalQuality; + /** atom #13 : Cellular network signal noise ratio {e.g. SSSINR in NR, RSSNR in LTE} */ + private int mSignalNoise; + /** atom #14 : Iwlan network signal strength (Wi-Fi RSSI) */ + private int mIwlanSignalStrength; + /** atom #15 : Reason for preferred RAT update */ + private int mUpdateReason; + /** atom #16: IMS Call Type */ + private int mImsCallType; + /** atom #17 : IMS Call Quality */ + private int mImsCallQuality; + /** atom #18 : Slot Index */ + private int mSlotIndex; + + @Before + public void setUp() { + MockitoAnnotations.initMocks(this); + mNetCapability = DEFAULT_NET_CAPABILITY; + mFirstQualifiedRat = DEFAULT_FIRST_QUALIFIED_RAT; + mSecondQualifiedRat = DEFAULT_SECOND_QUALIFIED_RAT; + mCurrentTransportType = DEFAULT_CURRENT_TRANSPORT_TYPE; + mWfcEnabled = DEFAULT_WFC_ENABLED; + mWfcMode = DEFAULT_WFC_MODE; + mCellularNetworkType = DEFAULT_CELLULAR_NETWORK_TYPE; + mIwlanNetworkType = DEFAULT_IWLAN_NETWORK_TYPE; + mRestrictionsOnWwan = DEFAULT_RESTRICTIONS_ON_WWAN; + mRestrictionsOnWlan = DEFAULT_RESTRICTIONS_ON_WLAN; + mSignalStrength = DEFAULT_SIGNAL_STRENGTH; + mSignalQuality = DEFAULT_SIGNAL_QUALITY; + mSignalNoise = DEFAULT_SIGNAL_NOISE; + mIwlanSignalStrength = DEFAULT_IWLAN_SIGNAL_STRENGTH; + mUpdateReason = DEFAULT_UPDATE_REASON; + mImsCallType = 1; + mImsCallQuality = 0; + mSlotIndex = 0; + mInfoEmpty = new AtomsQualifiedRatListChangedInfo(); + mInfoDefault = + new AtomsQualifiedRatListChangedInfo( + mNetCapability, + mFirstQualifiedRat, + mSecondQualifiedRat, + mCurrentTransportType, + mWfcEnabled, + mWfcMode, + mCellularNetworkType, + mIwlanNetworkType, + mRestrictionsOnWwan, + mRestrictionsOnWlan, + mSignalStrength, + mSignalQuality, + mSignalNoise, + mIwlanSignalStrength, + mUpdateReason, + mImsCallType, + mImsCallQuality, + mSlotIndex); + mInfoCopy = new AtomsQualifiedRatListChangedInfo(mInfoDefault); + } + + @After + public void tearDown() { + mInfoEmpty = null; + mInfoDefault = null; + mInfoCopy = null; + } + + @Test + public void testGetSetNetCapability() { + assertEquals(0, mInfoEmpty.getNetCapability()); + assertEquals(DEFAULT_NET_CAPABILITY, mInfoDefault.getNetCapability()); + assertEquals(DEFAULT_NET_CAPABILITY, mInfoCopy.getNetCapability()); + + mInfoEmpty.setNetCapability(QnsProtoEnums.NET_CAPABILITY_IMS); + mInfoDefault.setNetCapability(QnsProtoEnums.NET_CAPABILITY_EIMS); + mInfoCopy.setNetCapability(QnsProtoEnums.NET_CAPABILITY_XCAP); + + assertEquals(QnsProtoEnums.NET_CAPABILITY_IMS, mInfoEmpty.getNetCapability()); + assertEquals(QnsProtoEnums.NET_CAPABILITY_EIMS, mInfoDefault.getNetCapability()); + assertEquals(QnsProtoEnums.NET_CAPABILITY_XCAP, mInfoCopy.getNetCapability()); + } + + @Test + public void testGetSetFirstQualifiedRat() { + assertEquals(0, mInfoEmpty.getFirstQualifiedRat()); + assertEquals(DEFAULT_FIRST_QUALIFIED_RAT, mInfoDefault.getFirstQualifiedRat()); + assertEquals(DEFAULT_FIRST_QUALIFIED_RAT, mInfoCopy.getFirstQualifiedRat()); + + mInfoEmpty.setFirstQualifiedRat(QnsProtoEnums.IWLAN); + mInfoDefault.setFirstQualifiedRat(QnsProtoEnums.EUTRAN); + mInfoCopy.setFirstQualifiedRat(QnsProtoEnums.NGRAN); + + assertEquals(QnsProtoEnums.IWLAN, mInfoEmpty.getFirstQualifiedRat()); + assertEquals(QnsProtoEnums.EUTRAN, mInfoDefault.getFirstQualifiedRat()); + assertEquals(QnsProtoEnums.NGRAN, mInfoCopy.getFirstQualifiedRat()); + } + + @Test + public void testGetSetSecondQualifiedRat() { + assertEquals(0, mInfoEmpty.getSecondQualifiedRat()); + assertEquals(DEFAULT_SECOND_QUALIFIED_RAT, mInfoDefault.getSecondQualifiedRat()); + assertEquals(DEFAULT_SECOND_QUALIFIED_RAT, mInfoCopy.getSecondQualifiedRat()); + + mInfoEmpty.setSecondQualifiedRat(QnsProtoEnums.IWLAN); + mInfoDefault.setSecondQualifiedRat(QnsProtoEnums.EUTRAN); + mInfoCopy.setSecondQualifiedRat(QnsProtoEnums.NGRAN); + + assertEquals(QnsProtoEnums.IWLAN, mInfoEmpty.getSecondQualifiedRat()); + assertEquals(QnsProtoEnums.EUTRAN, mInfoDefault.getSecondQualifiedRat()); + assertEquals(QnsProtoEnums.NGRAN, mInfoCopy.getSecondQualifiedRat()); + } + + @Test + public void testGetSetCurrentTransportType() { + assertEquals(0, mInfoEmpty.getCurrentTransportType()); + assertEquals(DEFAULT_CURRENT_TRANSPORT_TYPE, mInfoDefault.getCurrentTransportType()); + assertEquals(DEFAULT_CURRENT_TRANSPORT_TYPE, mInfoCopy.getCurrentTransportType()); + + mInfoEmpty.setCurrentTransportType(QnsProtoEnums.TRANSPORT_TYPE_INVALID); + mInfoDefault.setCurrentTransportType(QnsProtoEnums.TRANSPORT_TYPE_WWAN); + mInfoCopy.setCurrentTransportType(QnsProtoEnums.TRANSPORT_TYPE_WLAN); + + assertEquals(QnsProtoEnums.TRANSPORT_TYPE_INVALID, mInfoEmpty.getCurrentTransportType()); + assertEquals(QnsProtoEnums.TRANSPORT_TYPE_WWAN, mInfoDefault.getCurrentTransportType()); + assertEquals(QnsProtoEnums.TRANSPORT_TYPE_WLAN, mInfoCopy.getCurrentTransportType()); + } + + @Test + public void testGetSetWfcEnabled() { + assertFalse(mInfoEmpty.getWfcEnabled()); + assertTrue(mInfoDefault.getWfcEnabled()); + assertTrue(mInfoCopy.getWfcEnabled()); + + mInfoEmpty.setWfcEnabled(true); + mInfoDefault.setWfcEnabled(true); + mInfoCopy.setWfcEnabled(true); + + assertTrue(mInfoEmpty.getWfcEnabled()); + assertTrue(mInfoDefault.getWfcEnabled()); + assertTrue(mInfoCopy.getWfcEnabled()); + } + + @Test + public void testGetSetWfcMode() { + assertEquals(0, mInfoEmpty.getWfcMode()); + assertEquals(DEFAULT_WFC_MODE, mInfoDefault.getWfcMode()); + assertEquals(DEFAULT_WFC_MODE, mInfoCopy.getWfcMode()); + + mInfoEmpty.setWfcMode(QnsProtoEnums.CELLULAR_PREFERRED); + mInfoDefault.setWfcMode(QnsProtoEnums.WIFI_ONLY); + mInfoCopy.setWfcMode(QnsProtoEnums.WIFI_PREFERRED); + + assertEquals(QnsProtoEnums.CELLULAR_PREFERRED, mInfoEmpty.getWfcMode()); + assertEquals(QnsProtoEnums.WIFI_ONLY, mInfoDefault.getWfcMode()); + assertEquals(QnsProtoEnums.WIFI_PREFERRED, mInfoCopy.getWfcMode()); + } + + @Test + public void testGetSetCellularNetworkType() { + assertEquals(0, mInfoEmpty.getCellularNetworkType()); + assertEquals(DEFAULT_CELLULAR_NETWORK_TYPE, mInfoDefault.getCellularNetworkType()); + assertEquals(DEFAULT_CELLULAR_NETWORK_TYPE, mInfoCopy.getCellularNetworkType()); + + mInfoEmpty.setCellularNetworkType(QnsProtoEnums.EUTRAN); + mInfoDefault.setCellularNetworkType(QnsProtoEnums.NGRAN); + mInfoCopy.setCellularNetworkType(QnsProtoEnums.UTRAN); + + assertEquals(QnsProtoEnums.EUTRAN, mInfoEmpty.getCellularNetworkType()); + assertEquals(QnsProtoEnums.NGRAN, mInfoDefault.getCellularNetworkType()); + assertEquals(QnsProtoEnums.UTRAN, mInfoCopy.getCellularNetworkType()); + } + + @Test + public void testGetSetIwlanNetworkType() { + assertEquals(0, mInfoEmpty.getIwlanNetworkType()); + assertEquals(DEFAULT_IWLAN_NETWORK_TYPE, mInfoDefault.getIwlanNetworkType()); + assertEquals(DEFAULT_IWLAN_NETWORK_TYPE, mInfoCopy.getIwlanNetworkType()); + + mInfoEmpty.setIwlanNetworkType(QnsProtoEnums.EUTRAN); + mInfoDefault.setIwlanNetworkType(QnsProtoEnums.NGRAN); + mInfoCopy.setIwlanNetworkType(QnsProtoEnums.UTRAN); + + assertEquals(QnsProtoEnums.EUTRAN, mInfoEmpty.getIwlanNetworkType()); + assertEquals(QnsProtoEnums.NGRAN, mInfoDefault.getIwlanNetworkType()); + assertEquals(QnsProtoEnums.UTRAN, mInfoCopy.getIwlanNetworkType()); + } + + @Test + public void testGetSetRestrictionsOnWwan() { + assertEquals(0, mInfoEmpty.getRestrictionsOnWwan()); + assertEquals(DEFAULT_RESTRICTIONS_ON_WWAN, mInfoDefault.getRestrictionsOnWwan()); + assertEquals(DEFAULT_RESTRICTIONS_ON_WWAN, mInfoCopy.getRestrictionsOnWwan()); + + mInfoEmpty.setRestrictionsOnWwan(QnsProtoEnums.RESTRICT_TYPE_GUARDING); + mInfoDefault.setRestrictionsOnWwan(QnsProtoEnums.RESTRICT_TYPE_THROTTLING); + mInfoCopy.setRestrictionsOnWwan(QnsProtoEnums.RESTRICT_TYPE_NONE); + + assertEquals(QnsProtoEnums.RESTRICT_TYPE_GUARDING, mInfoEmpty.getRestrictionsOnWwan()); + assertEquals(QnsProtoEnums.RESTRICT_TYPE_THROTTLING, mInfoDefault.getRestrictionsOnWwan()); + assertEquals(QnsProtoEnums.RESTRICT_TYPE_NONE, mInfoCopy.getRestrictionsOnWwan()); + } + + @Test + public void testGetSetRestrictionsOnWlan() { + assertEquals(0, mInfoEmpty.getRestrictionsOnWlan()); + assertEquals(DEFAULT_RESTRICTIONS_ON_WWAN, mInfoDefault.getRestrictionsOnWlan()); + assertEquals(DEFAULT_RESTRICTIONS_ON_WWAN, mInfoCopy.getRestrictionsOnWlan()); + + mInfoEmpty.setRestrictionsOnWlan(QnsProtoEnums.RESTRICT_TYPE_GUARDING); + mInfoDefault.setRestrictionsOnWlan(QnsProtoEnums.RESTRICT_TYPE_THROTTLING); + mInfoCopy.setRestrictionsOnWlan(QnsProtoEnums.RESTRICT_TYPE_NONE); + + assertEquals(QnsProtoEnums.RESTRICT_TYPE_GUARDING, mInfoEmpty.getRestrictionsOnWlan()); + assertEquals(QnsProtoEnums.RESTRICT_TYPE_THROTTLING, mInfoDefault.getRestrictionsOnWlan()); + assertEquals(QnsProtoEnums.RESTRICT_TYPE_NONE, mInfoCopy.getRestrictionsOnWlan()); + } + + @Test + public void testGetSetSignalStrength() { + assertEquals(0, mInfoEmpty.getSignalStrength()); + assertEquals(DEFAULT_SIGNAL_STRENGTH, mInfoDefault.getSignalStrength()); + assertEquals(DEFAULT_SIGNAL_STRENGTH, mInfoCopy.getSignalStrength()); + + mInfoEmpty.setSignalStrength(DEFAULT_SIGNAL_STRENGTH); + mInfoDefault.setSignalStrength(-120); + mInfoCopy.setSignalStrength(-110); + + assertEquals(DEFAULT_SIGNAL_STRENGTH, mInfoEmpty.getSignalStrength()); + assertEquals(-120, mInfoDefault.getSignalStrength()); + assertEquals(-110, mInfoCopy.getSignalStrength()); + } + + @Test + public void testGetSetSignalQuality() { + assertEquals(0, mInfoEmpty.getSignalQuality()); + assertEquals(DEFAULT_SIGNAL_QUALITY, mInfoDefault.getSignalQuality()); + assertEquals(DEFAULT_SIGNAL_QUALITY, mInfoCopy.getSignalQuality()); + + mInfoEmpty.setSignalQuality(DEFAULT_SIGNAL_QUALITY); + mInfoDefault.setSignalQuality(-10); + mInfoCopy.setSignalQuality(-5); + + assertEquals(DEFAULT_SIGNAL_QUALITY, mInfoEmpty.getSignalQuality()); + assertEquals(-10, mInfoDefault.getSignalQuality()); + assertEquals(-5, mInfoCopy.getSignalQuality()); + } + + @Test + public void testGetSetSignalNoise() { + assertEquals(0, mInfoEmpty.getSignalNoise()); + assertEquals(DEFAULT_SIGNAL_NOISE, mInfoDefault.getSignalNoise()); + assertEquals(DEFAULT_SIGNAL_NOISE, mInfoCopy.getSignalNoise()); + + mInfoEmpty.setSignalNoise(DEFAULT_SIGNAL_NOISE); + mInfoDefault.setSignalNoise(1); + mInfoCopy.setSignalNoise(-1); + + assertEquals(DEFAULT_SIGNAL_NOISE, mInfoEmpty.getSignalNoise()); + assertEquals(1, mInfoDefault.getSignalNoise()); + assertEquals(-1, mInfoCopy.getSignalNoise()); + } + + @Test + public void testGetSetIwlanSignalStrength() { + assertEquals(0, mInfoEmpty.getIwlanSignalStrength()); + assertEquals(DEFAULT_IWLAN_SIGNAL_STRENGTH, mInfoDefault.getIwlanSignalStrength()); + assertEquals(DEFAULT_IWLAN_SIGNAL_STRENGTH, mInfoCopy.getIwlanSignalStrength()); + + mInfoEmpty.setIwlanSignalStrength(DEFAULT_IWLAN_SIGNAL_STRENGTH); + mInfoDefault.setIwlanSignalStrength(-80); + mInfoCopy.setIwlanSignalStrength(-50); + + assertEquals(DEFAULT_IWLAN_SIGNAL_STRENGTH, mInfoEmpty.getIwlanSignalStrength()); + assertEquals(-80, mInfoDefault.getIwlanSignalStrength()); + assertEquals(-50, mInfoCopy.getIwlanSignalStrength()); + } + + @Test + public void testGetSetUpdateReason() { + assertEquals(0, mInfoEmpty.getUpdateReason()); + assertEquals(DEFAULT_UPDATE_REASON, mInfoDefault.getUpdateReason()); + assertEquals(DEFAULT_UPDATE_REASON, mInfoCopy.getUpdateReason()); + + mInfoEmpty.setUpdateReason(0); + mInfoDefault.setUpdateReason(0); + mInfoCopy.setUpdateReason(0); + + assertEquals(0, mInfoEmpty.getUpdateReason()); + assertEquals(0, mInfoDefault.getUpdateReason()); + assertEquals(0, mInfoCopy.getUpdateReason()); + } + + @Test + public void testGetSetImsCallType() { + assertEquals(0, mInfoEmpty.getImsCallType()); + assertEquals(1, mInfoDefault.getImsCallType()); + assertEquals(1, mInfoCopy.getImsCallType()); + + mInfoEmpty.setImsCallType(1); + mInfoDefault.setImsCallType(2); + mInfoCopy.setImsCallType(3); + + assertEquals(1, mInfoEmpty.getImsCallType()); + assertEquals(2, mInfoDefault.getImsCallType()); + assertEquals(3, mInfoCopy.getImsCallType()); + } + + @Test + public void testGetSetImsCallQuality() { + assertEquals(0, mInfoEmpty.getImsCallQuality()); + assertEquals(0, mInfoDefault.getImsCallQuality()); + assertEquals(0, mInfoCopy.getImsCallQuality()); + + mInfoEmpty.setImsCallQuality(1); + mInfoDefault.setImsCallQuality(2); + mInfoCopy.setImsCallQuality(3); + + assertEquals(1, mInfoEmpty.getImsCallQuality()); + assertEquals(2, mInfoDefault.getImsCallQuality()); + assertEquals(3, mInfoCopy.getImsCallQuality()); + } + + @Test + public void testGetSetSlotIndex() { + assertEquals(0, mInfoEmpty.getSlotIndex()); + assertEquals(0, mInfoDefault.getSlotIndex()); + assertEquals(0, mInfoCopy.getSlotIndex()); + + mInfoEmpty.setSlotIndex(1); + mInfoDefault.setSlotIndex(2); + mInfoCopy.setSlotIndex(3); + + assertEquals(1, mInfoEmpty.getSlotIndex()); + assertEquals(2, mInfoDefault.getSlotIndex()); + assertEquals(3, mInfoCopy.getSlotIndex()); + } + + @Test + public void testToString() { + String strInfoEmpty = mInfoEmpty.toString(); + String strInfoDefault = mInfoDefault.toString(); + String strInfoCopy = mInfoCopy.toString(); + + assertNotNull(strInfoEmpty); + assertNotNull(strInfoDefault); + assertNotNull(strInfoCopy); + + assertTrue(strInfoDefault.startsWith("AtomsQualifiedRatListChangedInfo")); + + assertEquals(strInfoDefault, strInfoCopy); + assertNotEquals(strInfoEmpty, strInfoDefault); + } + + @Test + public void testEquals() { + assertEquals(mInfoDefault, mInfoDefault); + assertNotEquals(mInfoDefault, new Object()); + assertEquals(mInfoDefault, mInfoCopy); + mInfoDefault.setWfcEnabled(true); + mInfoCopy.setWfcEnabled(false); + assertNotEquals(mInfoDefault, mInfoCopy); + } + + @Test + public void testHashCode() { + AtomsQualifiedRatListChangedInfo a1, a2; + + a1 = + new AtomsQualifiedRatListChangedInfo( + mNetCapability, + mFirstQualifiedRat, + mSecondQualifiedRat, + mCurrentTransportType, + mWfcEnabled, + mWfcMode, + mCellularNetworkType, + mIwlanNetworkType, + mRestrictionsOnWwan, + mRestrictionsOnWlan, + mSignalStrength, + mSignalQuality, + mSignalNoise, + mIwlanSignalStrength, + mUpdateReason, + mImsCallType, + mImsCallQuality, + mSlotIndex); + a2 = + new AtomsQualifiedRatListChangedInfo( + mNetCapability, + mSecondQualifiedRat, + mFirstQualifiedRat, + mCurrentTransportType, + mWfcEnabled, + mWfcMode, + mCellularNetworkType, + mIwlanNetworkType, + mRestrictionsOnWwan, + mRestrictionsOnWlan, + mSignalStrength, + mSignalQuality, + mSignalNoise, + mIwlanSignalStrength, + mUpdateReason, + mImsCallType, + mImsCallQuality, + mSlotIndex); + assertNotEquals(a1.hashCode(), a2.hashCode()); + a2 = + new AtomsQualifiedRatListChangedInfo( + mNetCapability, + mFirstQualifiedRat, + mSecondQualifiedRat, + mCurrentTransportType, + mWfcEnabled, + mWfcMode, + mCellularNetworkType, + mIwlanNetworkType, + mRestrictionsOnWwan, + mRestrictionsOnWlan, + mSignalStrength, + mSignalQuality, + mSignalNoise, + mIwlanSignalStrength, + mUpdateReason, + mImsCallType, + mImsCallQuality, + mSlotIndex); + assertEquals(a1.hashCode(), a2.hashCode()); + } + + @Test + public void testStatsId() { + final int statsId = 634; // QualifiedRatListChanged + assertEquals(statsId, mInfoDefault.copy().getStatsId()); + } + + @Test + public void testStatsEventBuilder() { + mInfoDefault.build(mStatsEventBuilder); + + verify(mStatsEventBuilder, times(1)).writeBoolean(anyBoolean()); + verify(mStatsEventBuilder, times(17)).writeInt(anyInt()); + } +} |