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 /services/QualifiedNetworksService/src/com | |
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
Diffstat (limited to 'services/QualifiedNetworksService/src/com')
11 files changed, 2627 insertions, 2 deletions
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); + } +} |