summaryrefslogtreecommitdiff
path: root/services/QualifiedNetworksService/src
diff options
context:
space:
mode:
authorSewook Seo <sewookseo@google.com>2023-01-04 06:05:15 +0000
committerSewook Seo <sewookseo@google.com>2023-01-13 02:06:45 +0000
commitc10e99f8add0785dd00f9f41a1a35049385e47ec (patch)
tree01d97f378e95c07fc9d73f4dfde82df1398717c7 /services/QualifiedNetworksService/src
parent1a460e3fb092f0a7389a873e994526f7e7fd1d9f (diff)
downloadTelephony-c10e99f8add0785dd00f9f41a1a35049385e47ec.tar.gz
[QNS] HO decision with media quality changed CB
QNS will use media quality status callback to avoid low quality transport type during a call. Bug: 264338274 Test: atest QualifiedNetworksServiceTests Change-Id: I528ba652c21cd819c6d103eb0c34dfe8b71de4de
Diffstat (limited to 'services/QualifiedNetworksService/src')
-rw-r--r--services/QualifiedNetworksService/src/com/android/telephony/qns/QnsCallStatusTracker.java746
-rw-r--r--services/QualifiedNetworksService/src/com/android/telephony/qns/QnsCarrierConfigManager.java54
-rw-r--r--services/QualifiedNetworksService/src/com/android/telephony/qns/QnsComponents.java18
-rw-r--r--services/QualifiedNetworksService/src/com/android/telephony/qns/QnsConstants.java6
-rw-r--r--services/QualifiedNetworksService/src/com/android/telephony/qns/QnsTelephonyListener.java20
-rw-r--r--services/QualifiedNetworksService/src/com/android/telephony/qns/QnsUtils.java41
-rw-r--r--services/QualifiedNetworksService/src/com/android/telephony/qns/RestrictManager.java188
7 files changed, 954 insertions, 119 deletions
diff --git a/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsCallStatusTracker.java b/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsCallStatusTracker.java
index 0800787..095cf95 100644
--- a/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsCallStatusTracker.java
+++ b/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsCallStatusTracker.java
@@ -19,12 +19,20 @@ package com.android.telephony.qns;
import android.annotation.NonNull;
import android.net.NetworkCapabilities;
import android.os.Handler;
+import android.os.HandlerThread;
+import android.os.Looper;
+import android.os.Message;
+import android.telephony.AccessNetworkConstants;
+import android.telephony.Annotation;
+import android.telephony.CallQuality;
import android.telephony.CallState;
import android.telephony.PreciseCallState;
import android.telephony.PreciseDataConnectionState;
import android.telephony.TelephonyManager;
import android.telephony.ims.ImsCallProfile;
+import android.telephony.ims.MediaQualityStatus;
import android.util.Log;
+import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
@@ -38,19 +46,695 @@ import java.util.function.Consumer;
public class QnsCallStatusTracker {
private final String mLogTag;
private QnsTelephonyListener mTelephonyListener;
+ private QnsCarrierConfigManager mConfigManager;
private List<CallState> mCallStates = new ArrayList<>();
private QnsRegistrant mCallTypeChangedEventListener;
private QnsRegistrant mEmergencyCallTypeChangedEventListener;
private int mLastNormalCallType = QnsConstants.CALL_TYPE_IDLE;
private int mLastEmergencyCallType = QnsConstants.CALL_TYPE_IDLE;
private boolean mEmergencyOverIms;
+ private ActiveCallTracker mActiveCallTracker;
private Consumer<List<CallState>> mCallStatesConsumer =
callStateList -> updateCallState(callStateList);
private Consumer<Integer> mSrvccStateConsumer = state -> onSrvccStateChangedInternal(state);
+ private Consumer<MediaQualityStatus> mMediaQualityStatusConsumer =
+ status -> mActiveCallTracker.onMediaQualityStatusChanged(status);
- QnsCallStatusTracker(QnsTelephonyListener telephonyListener, int slotIndex) {
+ static class CallQualityBlock {
+ int mUpLinkLevel;
+ int mDownLinkLevel;
+ long mCreatedElapsedTime;
+ long mDurationMillis;
+ CallQualityBlock(int uplinkLevel, int downLinkLevel, long createdElapsedTime) {
+ mUpLinkLevel = uplinkLevel;
+ mDownLinkLevel = downLinkLevel;
+ mCreatedElapsedTime = createdElapsedTime;
+ }
+
+ long getUpLinkQualityVolume() {
+ if (mDurationMillis > 0) {
+ return mUpLinkLevel * mDurationMillis;
+ } else {
+ long now = QnsUtils.getSystemElapsedRealTime();
+ return (now - mCreatedElapsedTime) * mUpLinkLevel;
+ }
+ }
+
+ long getDownLinkQualityVolume() {
+ if (mDurationMillis > 0) {
+ return mDownLinkLevel * mDurationMillis;
+ } else {
+ long now = QnsUtils.getSystemElapsedRealTime();
+ return (now - mCreatedElapsedTime) * mDownLinkLevel;
+ }
+ }
+ }
+
+ class ActiveCallTracker {
+ private static final int EVENT_DATA_CONNECTION_STATUS_CHANGED = 3300;
+
+ @QnsConstants.QnsCallType
+ private int mCallType = QnsConstants.CALL_TYPE_IDLE;
+ @Annotation.NetCapability
+ private int mNetCapability = QnsConstants.INVALID_VALUE;
+ private QnsRegistrantList mLowMediaQualityListeners = new QnsRegistrantList();
+ private int mAccessNetwork = AccessNetworkConstants.AccessNetworkType.UNKNOWN;
+ private int mTransportType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
+ private SparseArray<CallQuality> mCallQualities = new SparseArray();
+ private TransportQuality mCurrentQuality;
+ /** A list of TransportQuality for each Transport type */
+ private SparseArray<List<TransportQuality>> mTransportQualityArray = new SparseArray<>();
+ private boolean mWwanAvailable = false;
+ private boolean mWlanAvailable = false;
+
+ private boolean mMediaThresholdBreached = false;
+ private HandlerThread mHandlerThread;
+ private ActiveCallTrackerHandler mActiveCallHandler;
+ private MediaLowQualityHandler mLowQualityHandler;
+ private String mLogTag;
+
+ private class ActiveCallTrackerHandler extends Handler {
+ ActiveCallTrackerHandler(Looper l) {
+ super(l);
+ }
+
+ @Override
+ public void handleMessage(Message message) {
+ QnsAsyncResult ar;
+ int transportType;
+ Log.d(mLogTag, "handleMessage : " + message.what);
+ switch (message.what) {
+ case EVENT_DATA_CONNECTION_STATUS_CHANGED:
+ ar = (QnsAsyncResult) message.obj;
+ onDataConnectionStatusChanged(
+ (PreciseDataConnectionState) ar.mResult);
+ break;
+
+ default:
+ Log.d(mLogTag, "unHandleMessage : " + message.what);
+ break;
+ }
+
+ }
+ }
+
+ /** Tracking low quality status */
+ private class MediaLowQualityHandler extends Handler {
+ private static final int EVENT_MEDIA_QUALITY_CHANGED = 3401;
+ private static final int EVENT_PACKET_LOSS_TIMER_EXPIRED = 3402;
+ private static final int EVENT_HYSTERESIS_FOR_NORMAL_QUALITY = 3403;
+ private static final int EVENT_POLLING_CHECK_LOW_QUALITY = 3404;
+ private static final int EVENT_LOW_QUALITY_HANDLER_MAX = 3405;
+
+ private static final int STATE_NORMAL_QUALITY = 0;
+ private static final int STATE_SUSPECT_LOW_QUALITY = 1;
+ private static final int STATE_LOW_QUALITY = 2;
+
+ private static final int HYSTERESIS_TIME_NORMAL_QUALITY_MILLIS = 3000;
+ private static final int LOW_QUALITY_CHECK_INTERVAL_MILLIS = 15000;
+ private static final int LOW_QUALITY_CHECK_AFTER_HO_MILLIS = 3000;
+ private static final int LOW_QUALITY_REPORTED_TIME_INITIAL_VALUE = -1;
+
+ private int mState = STATE_NORMAL_QUALITY;
+ private MediaQualityStatus mMediaQualityStatus;
+ private String mTag;
+
+ MediaLowQualityHandler(Looper l) {
+ super(l);
+ mTag = mLogTag + "_LQH";
+ }
+
+ @Override
+ public void handleMessage(Message message) {
+ Log.d(mTag, "handleMessage : " + message.what);
+ switch (message.what) {
+ case EVENT_MEDIA_QUALITY_CHANGED:
+ MediaQualityStatus status = (MediaQualityStatus) message.obj;
+ onMediaQualityChanged(status);
+ break;
+
+ case EVENT_PACKET_LOSS_TIMER_EXPIRED:
+ onPacketLossTimerExpired(message.arg1);
+ break;
+
+ case EVENT_HYSTERESIS_FOR_NORMAL_QUALITY:
+ exitLowQualityState();
+ break;
+
+ case EVENT_POLLING_CHECK_LOW_QUALITY:
+ checkLowQuality();
+ break;
+
+ default:
+ Log.d(mLogTag, "unHandleMessage : " + message.what);
+ break;
+ }
+ }
+
+ private void onMediaQualityChanged(MediaQualityStatus status) {
+ Log.d(mTag, "onMediaQualityChanged " + status);
+ int reason = thresholdBreached(status);
+ boolean needNotify = false;
+ if (reason == 0) {
+ // Threshold not breached.
+ mMediaQualityStatus = status;
+ if (mState == STATE_NORMAL_QUALITY) {
+ Log.d(mTag, "keeps normal quality.");
+ mMediaQualityStatus = status;
+ return;
+ } else {
+ // check normal quality is stable or not.
+ this.sendEmptyMessageDelayed(EVENT_HYSTERESIS_FOR_NORMAL_QUALITY,
+ HYSTERESIS_TIME_NORMAL_QUALITY_MILLIS);
+ }
+ } else {
+ // Threshold breached.
+ this.removeMessages(EVENT_HYSTERESIS_FOR_NORMAL_QUALITY);
+ switch (mState) {
+ case STATE_NORMAL_QUALITY:
+ case STATE_SUSPECT_LOW_QUALITY:
+ if (reason == (1 << QnsConstants.RTP_LOW_QUALITY_REASON_PACKET_LOSS)) {
+ int delayMillis = (mConfigManager.getRTPMetricsData()).mPktLossTime;
+ if (delayMillis > 0) {
+ if (mState == STATE_NORMAL_QUALITY) {
+ enterSuspectLowQualityState(delayMillis);
+ }
+ } else if (delayMillis == 0) {
+ needNotify = true;
+ }
+ } else {
+ removeMessages(EVENT_PACKET_LOSS_TIMER_EXPIRED);
+ enterLowQualityState(status);
+ needNotify = true;
+ }
+ break;
+
+ case STATE_LOW_QUALITY:
+ if (mMediaQualityStatus.getTransportType() == status.getTransportType()
+ && thresholdBreached(mMediaQualityStatus)
+ != thresholdBreached(status)) {
+ needNotify = true;
+ }
+ break;
+ }
+ mMediaQualityStatus = status;
+ }
+ if (needNotify) {
+ enterLowQualityState(status);
+ notifyLowMediaQuality(reason);
+ }
+
+ }
+
+ @VisibleForTesting
+ void enterLowQualityState(MediaQualityStatus status) {
+ Log.d(mTag, "enterLowQualityState " + status);
+ mState = STATE_LOW_QUALITY;
+ this.sendEmptyMessageDelayed(
+ EVENT_POLLING_CHECK_LOW_QUALITY, LOW_QUALITY_CHECK_INTERVAL_MILLIS);
+ }
+
+ void enterSuspectLowQualityState(int delayMillis) {
+ Log.d(mTag, "enterSuspectLowQualityState.");
+ if (!this.hasMessages(EVENT_PACKET_LOSS_TIMER_EXPIRED)) {
+ this.removeMessages(EVENT_PACKET_LOSS_TIMER_EXPIRED);
+ }
+ Log.d(mTag, "Packet loss timer start. " + delayMillis);
+ Message msg = this.obtainMessage(
+ EVENT_PACKET_LOSS_TIMER_EXPIRED, mTransportType, 0);
+ this.sendMessageDelayed(msg, delayMillis);
+ mState = STATE_SUSPECT_LOW_QUALITY;
+ }
+
+ void exitLowQualityState() {
+ mState = STATE_NORMAL_QUALITY;
+ for (int i = EVENT_PACKET_LOSS_TIMER_EXPIRED;
+ i < EVENT_LOW_QUALITY_HANDLER_MAX; i++) {
+ this.removeMessages(i);
+ }
+ notifyLowMediaQuality(0);
+ }
+
+ void checkLowQuality() {
+ if (mState == STATE_NORMAL_QUALITY) {
+ Log.w(mTag, "checkLowQuality on unexpected state(normal state).");
+ } else {
+ Log.d(mTag, "checkLowQuality");
+ int reason = thresholdBreached(mMediaQualityStatus);
+ if (reason > 0) {
+ notifyLowMediaQuality(thresholdBreached(mMediaQualityStatus));
+ } else if (this.hasMessages(EVENT_HYSTERESIS_FOR_NORMAL_QUALITY)) {
+ // hysteresis time to be normal state is running. let's check after that.
+ this.sendEmptyMessageDelayed(EVENT_POLLING_CHECK_LOW_QUALITY,
+ HYSTERESIS_TIME_NORMAL_QUALITY_MILLIS);
+ } else {
+ Log.w(mTag, "Unexpected case.");
+ }
+ }
+ }
+
+ void updateForHandover(int transportType) {
+ // restart timers that they need to be restarted on new transport type.
+ if (mState == STATE_SUSPECT_LOW_QUALITY) {
+ this.removeMessages(EVENT_PACKET_LOSS_TIMER_EXPIRED);
+ Message msg = this.obtainMessage(
+ EVENT_PACKET_LOSS_TIMER_EXPIRED, transportType, 0);
+ this.sendMessageDelayed(msg, (mConfigManager.getRTPMetricsData()).mPktLossTime);
+ }
+ if (this.hasMessages(EVENT_HYSTERESIS_FOR_NORMAL_QUALITY)) {
+ this.removeMessages(EVENT_HYSTERESIS_FOR_NORMAL_QUALITY);
+ this.sendEmptyMessageDelayed(EVENT_HYSTERESIS_FOR_NORMAL_QUALITY,
+ HYSTERESIS_TIME_NORMAL_QUALITY_MILLIS);
+ }
+ if (mState == STATE_LOW_QUALITY) {
+ this.removeMessages(EVENT_POLLING_CHECK_LOW_QUALITY);
+ this.sendEmptyMessageDelayed(EVENT_POLLING_CHECK_LOW_QUALITY,
+ LOW_QUALITY_CHECK_AFTER_HO_MILLIS);
+ }
+ }
+
+ private void onPacketLossTimerExpired(int transportType) {
+ if (mTransportType != transportType) {
+ Log.d(mTag, "onPacketLossTimerExpired transport type mismatched.");
+ if (mState == STATE_SUSPECT_LOW_QUALITY) {
+ mState = STATE_NORMAL_QUALITY;
+ }
+ return;
+ }
+ if (thresholdBreached(mMediaQualityStatus)
+ == (1 << QnsConstants.RTP_LOW_QUALITY_REASON_PACKET_LOSS)) {
+ enterLowQualityState(mMediaQualityStatus);
+ notifyLowMediaQuality(1 << QnsConstants.RTP_LOW_QUALITY_REASON_PACKET_LOSS);
+ }
+ }
+
+ private void notifyLowMediaQuality(int reason) {
+ long now = QnsUtils.getSystemElapsedRealTime();
+ TransportQuality tq = getLastTransportQuality(mTransportType);
+ if (tq != null) {
+ if (reason > 0) {
+ tq.mLowRtpQualityReportedTime = now;
+ } else {
+ tq.mLowRtpQualityReportedTime = LOW_QUALITY_REPORTED_TIME_INITIAL_VALUE;
+ }
+ }
+ Log.d(mTag, "notifyLowMediaQuality reason:" + reason + " transport type:"
+ + AccessNetworkConstants.transportTypeToString(mTransportType));
+ mLowMediaQualityListeners.notifyResult(reason);
+ }
+ }
+
+ class TransportQuality {
+ int mTransportType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
+ long mLowRtpQualityReportedTime =
+ MediaLowQualityHandler.LOW_QUALITY_REPORTED_TIME_INITIAL_VALUE;
+ List<CallQualityBlock> mCallQualityBlockList;
+
+ TransportQuality(int transportType) {
+ mTransportType = transportType;
+ mCallQualityBlockList = new ArrayList<>();
+ }
+
+ boolean isLowRtpQualityReported() {
+ return mLowRtpQualityReportedTime
+ != MediaLowQualityHandler.LOW_QUALITY_REPORTED_TIME_INITIAL_VALUE;
+ }
+
+ CallQualityBlock getLastCallQualityBlock() {
+ int length = mCallQualityBlockList.size();
+ if (length > 0) {
+ return mCallQualityBlockList.get(length - 1);
+ } else {
+ return null;
+ }
+ }
+ }
+
+ ActiveCallTracker(int slotIndex, Looper looper) {
+ mLogTag = ActiveCallTracker.class.getSimpleName() + "_" + slotIndex;
+ if (looper == null) {
+ mHandlerThread = new HandlerThread(ActiveCallTracker.class.getSimpleName());
+ mHandlerThread.start();
+ mActiveCallHandler = new ActiveCallTrackerHandler(mHandlerThread.getLooper());
+ mLowQualityHandler = new MediaLowQualityHandler(mHandlerThread.getLooper());
+ } else {
+ mActiveCallHandler = new ActiveCallTrackerHandler(looper);
+ mLowQualityHandler = new MediaLowQualityHandler(looper);
+ }
+ mTelephonyListener.addMediaQualityStatusCallback(mMediaQualityStatusConsumer);
+ mTransportQualityArray.put(
+ AccessNetworkConstants.TRANSPORT_TYPE_WLAN, new ArrayList<>());
+ mTransportQualityArray.put(
+ AccessNetworkConstants.TRANSPORT_TYPE_WWAN, new ArrayList<>());
+ }
+
+ void close() {
+ mTelephonyListener.removeMediaQualityStatusCallback(mMediaQualityStatusConsumer);
+ mTelephonyListener.unregisterPreciseDataConnectionStateChanged(
+ mNetCapability, mActiveCallHandler);
+ if (mHandlerThread != null) {
+ mHandlerThread.quitSafely();
+ }
+ }
+
+ @VisibleForTesting
+ void onDataConnectionStatusChanged(PreciseDataConnectionState state) {
+ if (state == null) {
+ Log.d(mLogTag, "onDataConnectionStatusChanged with null info");
+ return;
+ }
+ if (state.getState() == TelephonyManager.DATA_CONNECTED) {
+ int transportType = state.getTransportType();
+ if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_INVALID) {
+ Log.w(mLogTag, "Unexpected transport type on connected DataNetwork.");
+ return;
+ }
+ if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_INVALID) {
+ Log.d(mLogTag, "Call started with "
+ + AccessNetworkConstants.transportTypeToString(transportType));
+ mTransportType = transportType;
+ startTrackingTransportQuality(transportType);
+ } else if (mTransportType != transportType) {
+ Log.d(mLogTag, "Call Handed over to "
+ + AccessNetworkConstants.transportTypeToString(transportType));
+ mTransportType = transportType;
+ onHandoverCompleted(transportType);
+ }
+ }
+ }
+
+ private void onHandoverCompleted(
+ @AccessNetworkConstants.TransportType int dstTransportType) {
+ long now = QnsUtils.getSystemElapsedRealTime();
+ // complete to update TransportQuality for prev transport type
+ CallQualityBlock last = null;
+ int prevTransportType = QnsUtils.getOtherTransportType(dstTransportType);
+ TransportQuality prev = getLastTransportQuality(prevTransportType);
+ if (prev != null) {
+ last = prev.getLastCallQualityBlock();
+ }
+ // add a new TransportQuality for new transport type
+ mTransportQualityArray.get(dstTransportType)
+ .add(new TransportQuality(dstTransportType));
+ TransportQuality current = getLastTransportQuality(dstTransportType);
+ if (last != null) {
+ last.mDurationMillis = now - last.mCreatedElapsedTime;
+ current.mCallQualityBlockList
+ .add(new CallQualityBlock(last.mUpLinkLevel, last.mDownLinkLevel, now));
+ }
+ mLowQualityHandler.updateForHandover(dstTransportType);
+ }
+
+ private void startTrackingTransportQuality(int transportType) {
+ mTransportQualityArray.get(AccessNetworkConstants.TRANSPORT_TYPE_WLAN).clear();
+ mTransportQualityArray.get(AccessNetworkConstants.TRANSPORT_TYPE_WWAN).clear();
+ mTransportQualityArray.get(transportType)
+ .add(new TransportQuality(transportType));
+ }
+
+ void callStarted(@QnsConstants.QnsCallType int callType, int netCapability) {
+ if (mCallType != QnsConstants.CALL_TYPE_IDLE) {
+ if (mCallType != callType) {
+ callTypeUpdated(callType);
+ } else {
+ Log.w(mLogTag, "call type:" + callType + " already started.");
+ }
+ }
+ Log.d(mLogTag, "callStarted callType: " + callType + " netCapa:"
+ + QnsUtils.getNameOfNetCapability(netCapability));
+ mCallType = callType;
+ mNetCapability = netCapability;
+ //Transport type will be updated when EVENT_DATA_CONNECTION_STATUS_CHANGED occurs.
+ PreciseDataConnectionState dataState =
+ mTelephonyListener.getLastPreciseDataConnectionState(netCapability);
+ if (dataState != null && dataState.getTransportType()
+ != AccessNetworkConstants.TRANSPORT_TYPE_INVALID) {
+ mTransportType = dataState.getTransportType();
+ startTrackingTransportQuality(mTransportType);
+ }
+ mTelephonyListener.registerPreciseDataConnectionStateChanged(mNetCapability,
+ mActiveCallHandler, EVENT_DATA_CONNECTION_STATUS_CHANGED, null, true);
+ }
+
+ private void callTypeUpdated(@QnsConstants.QnsCallType int callType) {
+ Log.d(mLogTag, "callTypeUpdated from " + mCallType + " to " + callType);
+ mCallType = callType;
+ }
+
+ void callEnded() {
+ mLowQualityHandler.exitLowQualityState();
+ long now = QnsUtils.getSystemElapsedRealTime();
+ // complete to update TransportQuality for prev transport type
+ CallQualityBlock last = null;
+ TransportQuality prev = getLastTransportQuality(mTransportType);
+ if (prev != null) {
+ last = prev.getLastCallQualityBlock();
+ }
+ if (last != null) {
+ last.mDurationMillis = now - last.mCreatedElapsedTime;
+ }
+ long upLinkQualityOverWwan = mActiveCallTracker
+ .getUpLinkQualityLevelDuringCall(AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+ long upLinkQualityOverWlan = mActiveCallTracker
+ .getUpLinkQualityLevelDuringCall(AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
+ long downLinkQualityOverWwan = mActiveCallTracker
+ .getDownLinkQualityLevelDuringCall(AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
+ long downLinkQualityOverWlan = mActiveCallTracker
+ .getDownLinkQualityLevelDuringCall(AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
+ StringBuilder sb = new StringBuilder();
+ sb.append("CallQuality [WWAN:");
+ if (upLinkQualityOverWwan == QnsConstants.INVALID_VALUE
+ || downLinkQualityOverWwan == QnsConstants.INVALID_VALUE) {
+ sb.append("Not available] ");
+ } else {
+ sb.append("upLinkQualityOverWwan = ").append(upLinkQualityOverWwan)
+ .append(", downLinkQualityOverWwan = ").append(downLinkQualityOverWwan)
+ .append("] ");
+ }
+ sb.append("[WLAN:");
+ if (upLinkQualityOverWlan == QnsConstants.INVALID_VALUE
+ || downLinkQualityOverWlan == QnsConstants.INVALID_VALUE) {
+ sb.append("Not available] ");
+ } else {
+ sb.append("upLinkQualityOverWlan = ").append(upLinkQualityOverWwan)
+ .append(", downLinkQualityOverWlan = ").append(downLinkQualityOverWwan)
+ .append("] ");
+ }
+ Log.d(mLogTag, "callEnded callType: " + mCallType + " netCapa:"
+ + QnsUtils.getNameOfNetCapability(mNetCapability) + " " + sb.toString());
+ mCallType = QnsConstants.CALL_TYPE_IDLE;
+ mNetCapability = 0;
+ mAccessNetwork = AccessNetworkConstants.AccessNetworkType.UNKNOWN;
+ mTransportType = AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
+ mTelephonyListener.unregisterPreciseDataConnectionStateChanged(
+ mNetCapability, mActiveCallHandler);
+ }
+
+ void onMediaQualityStatusChanged(MediaQualityStatus status) {
+ if (status == null) {
+ Log.e(mLogTag, "null MediaQualityStatus received.");
+ return;
+ }
+ Message msg = mLowQualityHandler
+ .obtainMessage(MediaLowQualityHandler.EVENT_MEDIA_QUALITY_CHANGED, status);
+ mLowQualityHandler.sendMessage(msg);
+ }
+
+ int getTransportType() {
+ return this.mTransportType;
+ }
+
+ int getCallType() {
+ return this.mCallType;
+ }
+
+ int getNetCapability() {
+ return this.mNetCapability;
+ }
+
+ @VisibleForTesting
+ TransportQuality getLastTransportQuality(int transportType) {
+ if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_INVALID) {
+ Log.w(mLogTag, "getLastTransportQuality with invalid transport type.");
+ return null;
+ }
+ int size = mTransportQualityArray.get(transportType).size();
+ if (size > 0) {
+ return mTransportQualityArray.get(transportType).get(size - 1);
+ } else {
+ return null;
+ }
+ }
+
+ @VisibleForTesting
+ List<TransportQuality> getTransportQualityList(int transportType) {
+ return mTransportQualityArray.get(transportType);
+ }
+
+ long getUpLinkQualityLevelDuringCall(int transportType) {
+ List<TransportQuality> tqList = getTransportQualityList(transportType);
+ long sumUplinkQualityLevelVolume = 0;
+ long totalDuration = 0;
+ for (int i = 0; i < tqList.size(); i++) {
+ List<CallQualityBlock> callQualityBlockList = tqList.get(i).mCallQualityBlockList;
+ for (int j = 0; j < callQualityBlockList.size(); j++) {
+ CallQualityBlock cq = callQualityBlockList.get(j);
+ sumUplinkQualityLevelVolume += cq.getUpLinkQualityVolume();
+ long durationMillis = cq.mDurationMillis;
+ if (i == tqList.size() - 1 && j == callQualityBlockList.size() - 1) {
+ if (durationMillis == 0) {
+ durationMillis = QnsUtils.getSystemElapsedRealTime()
+ - cq.mCreatedElapsedTime;
+ }
+ }
+ if (durationMillis > 0) {
+ totalDuration += durationMillis;
+ } else {
+ return -1;
+ }
+ }
+ }
+ if (totalDuration <= 0) {
+ return QnsConstants.INVALID_VALUE;
+ }
+ long qualityLevel = sumUplinkQualityLevelVolume / totalDuration;
+ Log.d(mLogTag, "getUplinkQualityLevel for [" + AccessNetworkConstants
+ .transportTypeToString(transportType) + "] totalQualityVolume: "
+ + sumUplinkQualityLevelVolume + ", totalDuration: " + totalDuration
+ + " level:" + qualityLevel);
+ return qualityLevel;
+ }
+
+ long getDownLinkQualityLevelDuringCall(int transportType) {
+ List<TransportQuality> tqList = getTransportQualityList(transportType);
+ long sumDownLinkQualityLevelVolume = 0;
+ long totalDuration = 0;
+ for (int i = 0; i < tqList.size(); i++) {
+ List<CallQualityBlock> callQualityBlockList = tqList.get(i).mCallQualityBlockList;
+ for (int j = 0; j < callQualityBlockList.size(); j++) {
+ CallQualityBlock cq = callQualityBlockList.get(j);
+ sumDownLinkQualityLevelVolume += cq.getDownLinkQualityVolume();
+ long durationMillis = cq.mDurationMillis;
+ if (i == tqList.size() - 1 && j == callQualityBlockList.size() - 1) {
+ if (durationMillis == 0) {
+ durationMillis = QnsUtils.getSystemElapsedRealTime()
+ - cq.mCreatedElapsedTime;
+ }
+ }
+ if (durationMillis > 0) {
+ totalDuration += durationMillis;
+ } else {
+ return QnsConstants.INVALID_VALUE;
+ }
+ }
+ }
+ if (totalDuration <= 0) {
+ return QnsConstants.INVALID_VALUE;
+ }
+ long qualityLevel = sumDownLinkQualityLevelVolume / totalDuration;
+ Log.d(mLogTag, "getDownLinkQualityLevel for [" + AccessNetworkConstants
+ .transportTypeToString(transportType) + "] totalQualityVolume: "
+ + sumDownLinkQualityLevelVolume + ", totalDuration: " + totalDuration
+ + " level:" + qualityLevel);
+ return qualityLevel;
+ }
+
+ void updateCallQuality(CallState state) {
+ if (state == null) {
+ Log.w(mLogTag, "updateCallQuality Null CallState.");
+ return;
+ }
+ CallQuality cq = state.getCallQuality();
+ if (cq == null || isDummyCallQuality(cq)) {
+ return;
+ }
+ mActiveCallHandler.post(() -> onUpdateCallQuality(cq));
+ }
+
+ private void onUpdateCallQuality(CallQuality cq) {
+ long now = QnsUtils.getSystemElapsedRealTime();
+ CallQualityBlock prev = null;
+ TransportQuality transportQuality = getLastTransportQuality(mTransportType);
+ if (transportQuality != null) {
+ prev = transportQuality.getLastCallQualityBlock();
+ }
+ if (prev != null) {
+ prev.mDurationMillis = now - prev.mCreatedElapsedTime;
+ }
+ transportQuality.mCallQualityBlockList.add(
+ new CallQualityBlock(
+ cq.getUplinkCallQualityLevel(), cq.getDownlinkCallQualityLevel(), now));
+ }
+
+ private boolean isDummyCallQuality(CallQuality cq) {
+ return (cq.getNumRtpPacketsTransmitted() == 0
+ && cq.getNumRtpPacketsReceived() == 0
+ && cq.getUplinkCallQualityLevel() == 0
+ && cq.getDownlinkCallQualityLevel() == 0);
+ }
+ /**
+ * Register an event for low media quality report.
+ *
+ * @param h the Handler to get event.
+ * @param what the event.
+ * @param userObj user object.
+ */
+ void registerLowMediaQualityListener(
+ Handler h, int what, Object userObj) {
+ Log.d(mLogTag, "registerLowMediaQualityListener");
+ if (h != null) {
+ QnsRegistrant r = new QnsRegistrant(h, what, userObj);
+ mLowMediaQualityListeners.add(r);
+ }
+ }
+
+ /**
+ * Unregister an event for low media quality report.
+ *
+ * @param h the handler to get event.
+ */
+ void unregisterLowMediaQualityListener(Handler h) {
+ if (h != null) {
+ mLowMediaQualityListeners.remove(h);
+ }
+ }
+
+ int thresholdBreached(MediaQualityStatus status) {
+ int breachedReason = 0;
+ QnsCarrierConfigManager.RtpMetricsConfig rtpConfig = mConfigManager.getRTPMetricsData();
+ if (status.getRtpPacketLossRate() > 0
+ && status.getRtpPacketLossRate() > rtpConfig.mPktLossRate) {
+ breachedReason |= 1 << QnsConstants.RTP_LOW_QUALITY_REASON_PACKET_LOSS;
+ }
+ if (status.getRtpJitterMillis() > 0
+ && status.getRtpJitterMillis() > rtpConfig.mJitter) {
+ breachedReason |= 1 << QnsConstants.RTP_LOW_QUALITY_REASON_JITTER;
+ }
+ if (status.getRtpInactivityMillis() > 0
+ && status.getRtpInactivityMillis() > rtpConfig.mNoRtpInterval) {
+ breachedReason |= 1 << QnsConstants.RTP_LOW_QUALITY_REASON_NO_RTP;
+ }
+ return breachedReason;
+ }
+
+ boolean worseThanBefore(MediaQualityStatus before, MediaQualityStatus now) {
+ return thresholdBreached(now) > thresholdBreached(before);
+ }
+ }
+
+ QnsCallStatusTracker(QnsTelephonyListener telephonyListener,
+ QnsCarrierConfigManager configManager, int slotIndex) {
+ this(telephonyListener, configManager, slotIndex, null);
+ }
+
+ /** Only for test */
+ @VisibleForTesting
+ QnsCallStatusTracker(QnsTelephonyListener telephonyListener,
+ QnsCarrierConfigManager configManager, int slotIndex, Looper looper) {
mLogTag = QnsCallStatusTracker.class.getSimpleName() + "_" + slotIndex;
mTelephonyListener = telephonyListener;
+ mConfigManager = configManager;
+ mActiveCallTracker = new ActiveCallTracker(slotIndex, looper);
mTelephonyListener.addCallStatesChangedCallback(mCallStatesConsumer);
mTelephonyListener.addSrvccStateChangedCallback(mSrvccStateConsumer);
}
@@ -58,6 +742,9 @@ public class QnsCallStatusTracker {
void close() {
mTelephonyListener.removeCallStatesChangedCallback(mCallStatesConsumer);
mTelephonyListener.removeSrvccStateChangedCallback(mSrvccStateConsumer);
+ if (mActiveCallTracker != null) {
+ mActiveCallTracker.close();
+ }
}
void updateCallState(List<CallState> callStateList) {
@@ -82,7 +769,7 @@ public class QnsCallStatusTracker {
if (mLastNormalCallType != QnsConstants.CALL_TYPE_IDLE) {
mLastNormalCallType = QnsConstants.CALL_TYPE_IDLE;
if (mCallTypeChangedEventListener != null) {
- mCallTypeChangedEventListener.notifyResult(mLastNormalCallType);
+ notifyCallType(NetworkCapabilities.NET_CAPABILITY_IMS, mLastNormalCallType);
}
}
if (mLastEmergencyCallType != QnsConstants.CALL_TYPE_IDLE) {
@@ -90,11 +777,13 @@ public class QnsCallStatusTracker {
if (mEmergencyOverIms) {
mEmergencyOverIms = false;
if (mCallTypeChangedEventListener != null) {
- mCallTypeChangedEventListener.notifyResult(mLastNormalCallType);
+ notifyCallType(
+ NetworkCapabilities.NET_CAPABILITY_IMS, mLastEmergencyCallType);
}
} else {
if (mEmergencyCallTypeChangedEventListener != null) {
- mEmergencyCallTypeChangedEventListener.notifyResult(mLastEmergencyCallType);
+ notifyCallType(
+ NetworkCapabilities.NET_CAPABILITY_EIMS, mLastEmergencyCallType);
}
}
}
@@ -104,7 +793,7 @@ public class QnsCallStatusTracker {
&& !hasVideoCall() && !hasVoiceCall()) {
mLastNormalCallType = QnsConstants.CALL_TYPE_IDLE;
if (mCallTypeChangedEventListener != null) {
- mCallTypeChangedEventListener.notifyResult(mLastNormalCallType);
+ notifyCallType(NetworkCapabilities.NET_CAPABILITY_IMS, mLastNormalCallType);
}
}
if (mLastEmergencyCallType != QnsConstants.CALL_TYPE_IDLE && !hasEmergencyCall()) {
@@ -112,11 +801,13 @@ public class QnsCallStatusTracker {
if (mEmergencyOverIms) {
mEmergencyOverIms = false;
if (mCallTypeChangedEventListener != null) {
- mCallTypeChangedEventListener.notifyResult(mLastEmergencyCallType);
+ notifyCallType(
+ NetworkCapabilities.NET_CAPABILITY_IMS, mLastEmergencyCallType);
}
} else {
if (mEmergencyCallTypeChangedEventListener != null) {
- mEmergencyCallTypeChangedEventListener.notifyResult(mLastEmergencyCallType);
+ notifyCallType(
+ NetworkCapabilities.NET_CAPABILITY_EIMS, mLastEmergencyCallType);
}
}
}
@@ -126,25 +817,44 @@ public class QnsCallStatusTracker {
if (!isDataNetworkConnected(NetworkCapabilities.NET_CAPABILITY_EIMS)
&& isDataNetworkConnected(NetworkCapabilities.NET_CAPABILITY_IMS)) {
if (mCallTypeChangedEventListener != null) {
- mCallTypeChangedEventListener.notifyResult(mLastEmergencyCallType);
+ notifyCallType(
+ NetworkCapabilities.NET_CAPABILITY_IMS, mLastEmergencyCallType);
mEmergencyOverIms = true;
}
} else {
if (mEmergencyCallTypeChangedEventListener != null) {
- mEmergencyCallTypeChangedEventListener.notifyResult(mLastEmergencyCallType);
+ notifyCallType(
+ NetworkCapabilities.NET_CAPABILITY_EIMS, mLastEmergencyCallType);
}
}
} else if (hasVideoCall()) {
if (mLastNormalCallType != QnsConstants.CALL_TYPE_VIDEO) {
mLastNormalCallType = QnsConstants.CALL_TYPE_VIDEO;
- mCallTypeChangedEventListener.notifyResult(mLastNormalCallType);
+ notifyCallType(NetworkCapabilities.NET_CAPABILITY_IMS, mLastNormalCallType);
}
} else if (hasVoiceCall()) {
if (mLastNormalCallType != QnsConstants.CALL_TYPE_VOICE) {
mLastNormalCallType = QnsConstants.CALL_TYPE_VOICE;
- mCallTypeChangedEventListener.notifyResult(mLastNormalCallType);
+ notifyCallType(NetworkCapabilities.NET_CAPABILITY_IMS, mLastNormalCallType);
}
}
+ if (mActiveCallTracker.getCallType() != QnsConstants.CALL_TYPE_IDLE) {
+ mActiveCallTracker.updateCallQuality(getActiveCall());
+ }
+ }
+ }
+
+ private void notifyCallType(int netCapability, int callType) {
+ Log.d(mLogTag, "notifyCallType:" + netCapability + ", callType:" + callType);
+ if (netCapability == NetworkCapabilities.NET_CAPABILITY_IMS) {
+ mCallTypeChangedEventListener.notifyResult(callType);
+ } else if (netCapability == NetworkCapabilities.NET_CAPABILITY_EIMS) {
+ mEmergencyCallTypeChangedEventListener.notifyResult(callType);
+ }
+ if (callType == QnsConstants.CALL_TYPE_IDLE) {
+ mActiveCallTracker.callEnded();
+ } else {
+ mActiveCallTracker.callStarted(callType, netCapability);
}
}
@@ -161,6 +871,15 @@ public class QnsCallStatusTracker {
return false;
}
+ CallState getActiveCall() {
+ for (CallState cs : mCallStates) {
+ if (cs.getCallState() == PreciseCallState.PRECISE_CALL_STATE_ACTIVE) {
+ return cs;
+ }
+ }
+ return null;
+ }
+
boolean hasVideoCall() {
for (CallState cs : mCallStates) {
if (cs.getImsCallServiceType() == ImsCallProfile.SERVICE_TYPE_NORMAL
@@ -234,6 +953,10 @@ public class QnsCallStatusTracker {
}
}
+ ActiveCallTracker getActiveCallTracker() {
+ return mActiveCallTracker;
+ }
+
@VisibleForTesting
void onSrvccStateChangedInternal(int srvccState) {
if (srvccState == TelephonyManager.SRVCC_STATE_HANDOVER_COMPLETED) {
@@ -260,6 +983,7 @@ public class QnsCallStatusTracker {
}
}
+
private boolean isDataNetworkConnected(int netCapability) {
PreciseDataConnectionState preciseDataStatus =
mTelephonyListener.getLastPreciseDataConnectionState(netCapability);
diff --git a/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsCarrierConfigManager.java b/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsCarrierConfigManager.java
index b0d1cf6..318e031 100644
--- a/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsCarrierConfigManager.java
+++ b/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsCarrierConfigManager.java
@@ -495,28 +495,13 @@ class QnsCarrierConfigManager {
"qns.minimum_handover_guarding_timer_ms_int";
/**
- * List of 4 items indicating the RTP media metrics criteria to be set ,to make HO decision
- * during Call. The three items part of integer array is jitter , Packet loss rate & RTP
- * interval.
+ * This indicates time duration for packet loss rate sustained.
*
- * <p>{@link QnsConstants}. The values are set as below:
- *
- * <ul>
- * <li>0: {@link QnsConstants#KEY_DEFAULT_JITTER}
- * <li>1: {@link QnsConstants#KEY_DEFAULT_PACKET_LOSS_RATE}
- * <li>2: {@link QnsConstants#KEY_DEFAULT_PACKET_LOSS_TIME_MILLIS}
- * <li>3: {@link QnsConstants#KEY_DEFAULT_NO_RTP_INTERVAL_MILLIS}
- * </ul>
- *
- * {@code QnsConstants#KEY_DEFAULT_JITTER , QnsConstants#KEY_DEFAULT_PACKET_LOSS_RATE ,
- * QnsConstants#KEY_DEFAULT_NO_RTP_INTERVAL }: If set , indicates the jitter : Indicating the
- * latentcy , Packet loss rate : Indicating the percentage loss & RTP interval indicating the
- * interval in secs criteria to determine the HO decision . The default value for this key is
- * {@code QnsConstants#KEY_DEFAULT_JITTER, QnsConstants#KEY_DEFAULT_PACKET_LOSS_RATE,
- * QnsConstants#KEY_DEFAULT_PACKET_LOSS_TIME_MILLIS,
- * QnsConstants#KEY_DEFAULT_NO_RTP_INTERVAL_MILLIS}
+ * <p/> The default value for this key is {@code
+ * QnsConstants#KEY_DEFAULT_PACKET_LOSS_TIME_MILLIS}
*/
- static final String KEY_QNS_RTP_METRICS_INT_ARRAY = "qns.rtp_metrics_int_array";
+ static final String KEY_QNS_MEDIA_THRESHOLD_RTP_PACKET_LOSS_TIME_MILLIS_INT =
+ "qns.media_threshold_rtp_packet_loss_time_millis";
/**
* Specify a list of the waiting time(millisecond) for the preferred transport type when power
@@ -752,7 +737,7 @@ class QnsCarrierConfigManager {
private int[] mWlanHysteresisTimer;
private int[] mNonImsWwanHysteresisTimer;
private int[] mNonImsWlanHysteresisTimer;
- private int[] mRTPMetricsData;
+ private int[] mRTPMetricsData = new int[4];
private int[] mWaitingTimerForPreferredTransport;
private int[] mAllowMaxIwlanHoCountOnReason;
private int[] mHoRestrictTimeOnRtpQuality;
@@ -1173,6 +1158,8 @@ class QnsCarrierConfigManager {
loadDirectFromCarrierConfigManagerKey(carrierConfigBundle);
loadWfcConfigurations(carrierConfigBundle, assetConfigBundle);
+
+ loadMediaThreshold(carrierConfigBundle, assetConfigBundle);
}
/**
@@ -1364,7 +1351,6 @@ class QnsCarrierConfigManager {
bundleCarrier,
bundleAsset,
KEY_QNS_HO_RESTRICT_TIME_WITH_LOW_RTP_QUALITY_MILLIS_INT_ARRAY);
- mRTPMetricsData = getConfig(bundleCarrier, bundleAsset, KEY_QNS_RTP_METRICS_INT_ARRAY);
mWlanRttBackhaulCheckConfigsOnPing =
getConfig(
bundleCarrier,
@@ -1526,6 +1512,26 @@ class QnsCarrierConfigManager {
}
}
+ void loadMediaThreshold(PersistableBundle bundleCarrier, PersistableBundle assetConfigBundle) {
+ //read Jitter
+ mRTPMetricsData[0] = getConfig(
+ bundleCarrier, null,
+ CarrierConfigManager.ImsVoice.KEY_VOICE_RTP_JITTER_THRESHOLD_MILLIS_INT);
+ //read Packet Loss Rate
+ mRTPMetricsData[1] = getConfig(
+ bundleCarrier, null,
+ CarrierConfigManager.ImsVoice.KEY_VOICE_RTP_PACKET_LOSS_RATE_THRESHOLD_INT);
+ //read Inactivity Time
+ long inactivityTime = getConfig(
+ bundleCarrier, null,
+ CarrierConfigManager.ImsVoice.KEY_VOICE_RTP_INACTIVITY_TIME_THRESHOLD_MILLIS_LONG);
+ mRTPMetricsData[3] = (int) inactivityTime;
+ //read Packet Loss Duration
+ mRTPMetricsData[2] = getConfig(
+ bundleCarrier, assetConfigBundle,
+ KEY_QNS_MEDIA_THRESHOLD_RTP_PACKET_LOSS_TIME_MILLIS_INT);
+ }
+
/** Updated handover rules from carrier config. */
@VisibleForTesting
List<HandoverRule> updateHandoverRules(
@@ -2683,10 +2689,10 @@ class QnsCarrierConfigManager {
/** RTP packet loss rate in percentage */
final int mPktLossRate;
- /** Time interval of RTP packet loss rate */
+ /** Time interval(milliseconds) of RTP packet loss rate */
final int mPktLossTime;
- /** No RTP interval in seconds */
+ /** No RTP interval in milliseconds */
final int mNoRtpInterval;
RtpMetricsConfig(int jitter, int pktLossRate, int pktLossTime, int noRtpInterval) {
diff --git a/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsComponents.java b/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsComponents.java
index ad9a2e0..4d33f5a 100644
--- a/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsComponents.java
+++ b/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsComponents.java
@@ -77,10 +77,6 @@ class QnsComponents {
mCellularQualityMonitors.put(
slotId,
new CellularQualityMonitor(mContext, mQnsTelephonyListeners.get(slotId), slotId));
- mQnsCallStatusTracker.put(
- slotId,
- new QnsCallStatusTracker(mQnsTelephonyListeners.get(slotId), slotId));
-
mQnsProvisioningListeners.put(
slotId, new QnsProvisioningListener(mContext, mQnsImsManagers.get(slotId), slotId));
mQnsEventDispatchers.put(
@@ -93,6 +89,10 @@ class QnsComponents {
mQnsCarrierConfigManagers.put(
slotId,
new QnsCarrierConfigManager(mContext, mQnsEventDispatchers.get(slotId), slotId));
+ mQnsCallStatusTracker.put(
+ slotId,
+ new QnsCallStatusTracker(mQnsTelephonyListeners.get(slotId),
+ mQnsCarrierConfigManagers.get(slotId), slotId));
mWifiBackhaulMonitors.put(
slotId,
new WifiBackhaulMonitor(
@@ -238,6 +238,11 @@ class QnsComponents {
mWifiBackhaulMonitors.remove(slotId);
wifiBackhaulMonitor.close();
}
+ QnsCallStatusTracker qnsCallStatusTracker = mQnsCallStatusTracker.get(slotId);
+ if (qnsCallStatusTracker != null) {
+ mQnsCallStatusTracker.remove(slotId);
+ qnsCallStatusTracker.close();
+ }
QnsCarrierConfigManager qnsCarrierConfigManager = mQnsCarrierConfigManagers.get(slotId);
if (qnsCarrierConfigManager != null) {
mQnsCarrierConfigManagers.remove(slotId);
@@ -253,11 +258,6 @@ class QnsComponents {
mQnsProvisioningListeners.remove(slotId);
qnsProvisioningListener.close();
}
- QnsCallStatusTracker qnsCallStatusTracker = mQnsCallStatusTracker.get(slotId);
- if (qnsCallStatusTracker != null) {
- mQnsCallStatusTracker.remove(slotId);
- qnsCallStatusTracker.close();
- }
CellularQualityMonitor cellularQualityMonitor = mCellularQualityMonitors.get(slotId);
if (cellularQualityMonitor != null) {
mCellularQualityMonitors.remove(slotId);
diff --git a/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsConstants.java b/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsConstants.java
index 065aaee..ba2c2f1 100644
--- a/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsConstants.java
+++ b/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsConstants.java
@@ -29,6 +29,7 @@ class QnsConstants {
static final String QNS_TAG = "QNS";
+ static final int INVALID_VALUE = -1;
static final int INVALID_ID = -1;
static final int INVALID_SUB_ID = -1;
static final int KEY_DEFAULT_VALUE = 0;
@@ -37,10 +38,7 @@ class QnsConstants {
static final int CONFIG_DEFAULT_MIN_HANDOVER_GUARDING_TIMER = 0;
static final int CONFIG_DEFAULT_MIN_HANDOVER_GUARDING_TIMER_LIMIT = 5000;
- static final int KEY_DEFAULT_JITTER = 120;
- static final int KEY_DEFAULT_PACKET_LOSS_RATE = 40;
static final int KEY_DEFAULT_PACKET_LOSS_TIME_MILLIS = 5000;
- static final int KEY_DEFAULT_NO_RTP_INTERVAL_MILLIS = 2000;
static final int KEY_DEFAULT_IWLAN_AVOID_TIME_LOW_RTP_QUALITY_MILLIS = 60000;
static final int KEY_DEFAULT_THRESHOLD_SSRSRP_GOOD = -99;
@@ -77,6 +75,8 @@ class QnsConstants {
@IntDef(value = {COVERAGE_HOME, COVERAGE_ROAM, COVERAGE_BOTH})
@interface CellularCoverage {}
+ // These(RTP_LOW_QUALITY_) constants are used to @code worseThanBefore(),
+ // be caution before change.
static final int RTP_LOW_QUALITY_REASON_JITTER = 1;
static final int RTP_LOW_QUALITY_REASON_PACKET_LOSS = 2;
static final int RTP_LOW_QUALITY_REASON_NO_RTP = 3;
diff --git a/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsTelephonyListener.java b/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsTelephonyListener.java
index e890cf1..0945be6 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.MediaQualityStatus;
import android.util.Log;
import com.android.internal.annotations.VisibleForTesting;
@@ -69,6 +70,7 @@ class QnsTelephonyListener {
QnsRegistrantList mIwlanServiceStateListener = new QnsRegistrantList();
List<Consumer<List<CallState>>> mCallStatesConsumerList = new ArrayList<>();
List<Consumer<Integer>> mSrvccStateConsumerList = new ArrayList<>();
+ List<Consumer<MediaQualityStatus>> mMediaQualityConsumerList = new ArrayList<>();
protected HashMap<Integer, QnsRegistrantList> mQnsTelephonyInfoRegistrantMap = new HashMap<>();
protected HashMap<Integer, QnsRegistrantList> mNetCapabilityRegistrantMap = new HashMap<>();
protected QnsTelephonyInfo mLastQnsTelephonyInfo = new QnsTelephonyInfo();
@@ -1025,7 +1027,8 @@ class QnsTelephonyListener {
TelephonyCallback.BarringInfoListener,
TelephonyCallback.CallStateListener,
TelephonyCallback.SrvccStateListener,
- TelephonyCallback.CallAttributesListener {
+ TelephonyCallback.CallAttributesListener,
+ TelephonyCallback.MediaQualityStatusChangedListener {
private final Executor mExecutor;
private OnServiceStateListener mServiceStateListener;
private OnPreciseDataConnectionStateListener mPreciseDataConnectionStateListener;
@@ -1149,6 +1152,13 @@ class QnsTelephonyListener {
mCallStatesCallback.onCallStatesChanged(callStateList);
}
}
+
+ @Override
+ public void onMediaQualityStatusChanged(MediaQualityStatus status) {
+ for (Consumer<MediaQualityStatus> consumer : mMediaQualityConsumerList) {
+ consumer.accept(status);
+ }
+ }
}
void addCallStatesChangedCallback(Consumer<List<CallState>> consumer) {
@@ -1167,6 +1177,14 @@ class QnsTelephonyListener {
mSrvccStateConsumerList.remove(consumer);
}
+ void addMediaQualityStatusCallback(Consumer<MediaQualityStatus> consumer) {
+ mMediaQualityConsumerList.add(consumer);
+ }
+
+ void removeMediaQualityStatusCallback(Consumer<MediaQualityStatus> consumer) {
+ mMediaQualityConsumerList.remove(consumer);
+ }
+
/**
* Dumps the state of {@link QualityMonitor}
*
diff --git a/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsUtils.java b/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsUtils.java
index 5535bfa..c9745e4 100644
--- a/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsUtils.java
+++ b/services/QualifiedNetworksService/src/com/android/telephony/qns/QnsUtils.java
@@ -264,6 +264,17 @@ class QnsUtils {
return false;
}
+ @AccessNetworkConstants.TransportType
+ static int getTransportTypeFromAccessNetwork(
+ @AccessNetworkConstants.RadioAccessNetworkType int accessNetwork) {
+ if (accessNetwork == AccessNetworkConstants.AccessNetworkType.IWLAN) {
+ return AccessNetworkConstants.TRANSPORT_TYPE_WLAN;
+ } else if (accessNetwork != AccessNetworkConstants.AccessNetworkType.UNKNOWN) {
+ return AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
+ }
+ return AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
+ }
+
/**
* Get Set of network capabilities from string joined by {@code |}, space is ignored. If input
* string contains unknown capability or malformatted(e.g. empty string), -1 is included in the
@@ -285,6 +296,21 @@ class QnsUtils {
}
/**
+ * Returns another transport type.
+ * @param transportType transport type
+ * @return another transport type of input parameter
+ */
+ @AccessNetworkConstants.TransportType
+ static int getOtherTransportType(@AccessNetworkConstants.TransportType int transportType) {
+ if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
+ return AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
+ } else if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
+ return AccessNetworkConstants.TRANSPORT_TYPE_WLAN;
+ }
+ return AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
+ }
+
+ /**
* Convert network capabilities to string.
*
* <p>This is for debugging and logging purposes only.
@@ -608,6 +634,13 @@ class QnsUtils {
return (T) Integer.valueOf(QnsConstants.RAT_PREFERENCE_DEFAULT);
case KEY_QNS_VOWIFI_REGISTATION_TIMER_FOR_VOWIFI_ACTIVATION_INT:
return (T) Integer.valueOf(CONFIG_DEFAULT_VOWIFI_REGISTATION_TIMER);
+ case CarrierConfigManager.ImsVoice.KEY_VOICE_RTP_JITTER_THRESHOLD_MILLIS_INT:
+ case CarrierConfigManager.ImsVoice.KEY_VOICE_RTP_PACKET_LOSS_RATE_THRESHOLD_INT:
+ return (T) Integer.valueOf(QnsConstants.INVALID_VALUE);
+ case QnsCarrierConfigManager.KEY_QNS_MEDIA_THRESHOLD_RTP_PACKET_LOSS_TIME_MILLIS_INT:
+ return (T) Integer.valueOf(QnsConstants.KEY_DEFAULT_PACKET_LOSS_TIME_MILLIS);
+ case CarrierConfigManager.ImsVoice.KEY_VOICE_RTP_INACTIVITY_TIME_THRESHOLD_MILLIS_LONG:
+ return (T) Long.valueOf(QnsConstants.INVALID_VALUE);
case QnsCarrierConfigManager
.KEY_QNS_IN_CALL_ROVEIN_ALLOWED_COUNT_AND_FALLBACK_REASON_INT_ARRAY:
return (T)
@@ -639,14 +672,6 @@ class QnsUtils {
};
case QnsCarrierConfigManager.KEY_MINIMUM_HANDOVER_GUARDING_TIMER_MS_INT:
return (T) Integer.valueOf(QnsConstants.CONFIG_DEFAULT_MIN_HANDOVER_GUARDING_TIMER);
- case QnsCarrierConfigManager.KEY_QNS_RTP_METRICS_INT_ARRAY:
- return (T)
- new int[] {
- QnsConstants.KEY_DEFAULT_JITTER,
- QnsConstants.KEY_DEFAULT_PACKET_LOSS_RATE,
- QnsConstants.KEY_DEFAULT_PACKET_LOSS_TIME_MILLIS,
- QnsConstants.KEY_DEFAULT_NO_RTP_INTERVAL_MILLIS
- };
case QnsCarrierConfigManager
.KEY_CHOOSE_WFC_PREFERRED_TRANSPORT_IN_BOTH_BAD_CONDITION_INT_ARRAY:
return (T) new int[] {};
diff --git a/services/QualifiedNetworksService/src/com/android/telephony/qns/RestrictManager.java b/services/QualifiedNetworksService/src/com/android/telephony/qns/RestrictManager.java
index c49f674..0837f00 100644
--- a/services/QualifiedNetworksService/src/com/android/telephony/qns/RestrictManager.java
+++ b/services/QualifiedNetworksService/src/com/android/telephony/qns/RestrictManager.java
@@ -96,9 +96,8 @@ class RestrictManager {
private static final int EVENT_IMS_REGISTRATION_STATE_CHANGED = 3004;
private static final int EVENT_LOW_RTP_QUALITY_REPORTED = 3006;
private static final int EVENT_RELEASE_RESTRICTION = 3008;
- private static final int EVENT_REGISTER_LOW_RTP_QUALITY = 3009;
- protected static final int EVENT_INITIAL_DATA_CONNECTION_FAIL_RETRY_TIMER_EXPIRED = 3010;
- private static final int EVENT_WIFI_RTT_BACKHAUL_CHECK_STATUS = 3011;
+ protected static final int EVENT_INITIAL_DATA_CONNECTION_FAIL_RETRY_TIMER_EXPIRED = 3009;
+ private static final int EVENT_WIFI_RTT_BACKHAUL_CHECK_STATUS = 3010;
@VisibleForTesting static final int GUARDING_TIMER_HANDOVER_INIT = 30000;
@@ -159,7 +158,8 @@ class RestrictManager {
@VisibleForTesting QnsRegistrant mRestrictInfoRegistrant;
private DataConnectionStatusTracker mDataConnectionStatusTracker;
private CellularNetworkStatusTracker mCellularNetworkStatusTracker;
- private AlternativeEventListener mAltEventListener;
+ private QnsCallStatusTracker mQnsCallStatusTracker;
+ private QnsCallStatusTracker.ActiveCallTracker mActiveCallTracker;
private QnsImsManager mQnsImsManager;
private WifiBackhaulMonitor mWifiBackhaulMonitor;
private int mNetCapability;
@@ -215,7 +215,7 @@ class RestrictManager {
ar = (QnsAsyncResult) message.obj;
int reason = (int) ar.mResult;
Log.d(mLogTag, "EVENT_LOW_RTP_QUALITY_REPORTED reason: " + reason);
- onLowRtpQualityEvent();
+ onLowRtpQualityEvent(reason);
break;
case EVENT_IMS_REGISTRATION_STATE_CHANGED:
@@ -241,13 +241,6 @@ class RestrictManager {
}
break;
- case EVENT_REGISTER_LOW_RTP_QUALITY:
- int currTransportType = message.arg1;
- if (currTransportType == mTransportType) {
- registerLowRtpQualityEvent();
- }
- break;
-
case EVENT_INITIAL_DATA_CONNECTION_FAIL_RETRY_TIMER_EXPIRED:
Log.d(
mLogTag,
@@ -255,7 +248,7 @@ class RestrictManager {
+ mIsTimerRunningOnDataConnectionFail);
if (mIsTimerRunningOnDataConnectionFail) {
- currTransportType = message.arg1;
+ int currTransportType = message.arg1;
fallbackToOtherTransportOnDataConnectionFail(currTransportType);
}
break;
@@ -316,6 +309,17 @@ class RestrictManager {
}
}
+ class LowRtpQualityRestriction extends Restriction{
+ private int mReason;
+ LowRtpQualityRestriction(int type, int[] releaseEvents, int restrictTime, int reason) {
+ super(type, releaseEvents, restrictTime);
+ mReason = reason;
+ }
+ int getReason() {
+ return mReason;
+ }
+ }
+
class Restriction {
private final int mRestrictType;
final ArrayList<Integer> mReleaseEventList;
@@ -444,7 +448,8 @@ class RestrictManager {
mHandler = new RestrictManagerHandler(loop);
mNetCapability = netCapability;
mDataConnectionStatusTracker = dcst;
- mAltEventListener = qnsComponents.getAlternativeEventListener(mSlotId);
+ mQnsCallStatusTracker = qnsComponents.getQnsCallStatusTracker(mSlotId);
+ mActiveCallTracker = qnsComponents.getQnsCallStatusTracker(mSlotId).getActiveCallTracker();
mDataConnectionStatusTracker.registerDataConnectionStatusChanged(
mHandler, EVENT_DATA_CONNECTION_CHANGED);
if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) {
@@ -500,7 +505,9 @@ class RestrictManager {
mQnsEventDispatcher.unregisterEvent(mHandler);
if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS
|| mNetCapability == NetworkCapabilities.NET_CAPABILITY_EIMS) {
- mAltEventListener.unregisterLowRtpQualityEvent(mNetCapability, mHandler);
+ if (mActiveCallTracker != null) {
+ mActiveCallTracker.unregisterLowMediaQualityListener(mHandler);
+ }
}
if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) {
mQnsImsManager.unregisterImsRegistrationStatusChanged(mHandler);
@@ -539,7 +546,7 @@ class RestrictManager {
mQnsCarrierConfigManager.getWaitingTimerForPreferredTransportOnPowerOn(
transportType);
if (waitingTimer != QnsConstants.KEY_DEFAULT_VALUE) {
- int preventTransportType = getOtherTransport(transportType);
+ int preventTransportType = QnsUtils.getOtherTransportType(transportType);
Log.d(
mLogTag,
"prevent "
@@ -628,25 +635,53 @@ class RestrictManager {
}
@VisibleForTesting
- void onLowRtpQualityEvent() {
+ void onLowRtpQualityEvent(@QnsConstants.RtpLowQualityReason int reason) {
int lowRtpQualityRestrictTime =
mQnsCarrierConfigManager.getHoRestrictedTimeOnLowRTPQuality(mTransportType);
if ((mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN
|| mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
&& lowRtpQualityRestrictTime > 0
- && mImsCallType != QnsConstants.CALL_TYPE_IDLE) {
- addRestriction(
- mTransportType,
- RESTRICT_TYPE_RTP_LOW_QUALITY,
- sReleaseEventMap.get(RESTRICT_TYPE_RTP_LOW_QUALITY),
- lowRtpQualityRestrictTime);
- unregisterLowRtpQualityEvent();
-
- if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
- int fallbackReason = mQnsCarrierConfigManager.getQnsIwlanHoRestrictReason();
- if (fallbackReason == QnsConstants.FALLBACK_REASON_RTP_OR_WIFI
- || fallbackReason == QnsConstants.FALLBACK_REASON_RTP_ONLY) {
- increaseCounterToRestrictIwlanInCall();
+ && (mImsCallType == QnsConstants.CALL_TYPE_VOICE
+ || mImsCallType == QnsConstants.CALL_TYPE_EMERGENCY)) {
+ if (reason > 0) {
+ Restriction restriction =
+ new LowRtpQualityRestriction(RESTRICT_TYPE_RTP_LOW_QUALITY,
+ sReleaseEventMap.get(RESTRICT_TYPE_RTP_LOW_QUALITY),
+ lowRtpQualityRestrictTime,
+ reason);
+ // If current report has 'no RTP reason' and previous report at previous
+ // transport type doesn't have 'no RTP reason', let's move back to previous
+ // transport type.
+ if ((reason & 1 << QnsConstants.RTP_LOW_QUALITY_REASON_NO_RTP) != 0) {
+ HashMap<Integer, Restriction> restrictionMap = mRestrictInfos
+ .get(QnsUtils.getOtherTransportType(mTransportType))
+ .getRestrictionMap();
+ Restriction restrictionOtherSide = restrictionMap.get(
+ RESTRICT_TYPE_RTP_LOW_QUALITY);
+ if (restrictionOtherSide != null
+ && restrictionOtherSide instanceof LowRtpQualityRestriction) {
+ int reasonOtherSide =
+ ((LowRtpQualityRestriction) restrictionOtherSide).getReason();
+ if ((reasonOtherSide & 1 << QnsConstants.RTP_LOW_QUALITY_REASON_NO_RTP)
+ == 0) {
+ releaseRestriction(QnsUtils.getOtherTransportType(mTransportType),
+ RESTRICT_TYPE_RTP_LOW_QUALITY, true);
+ }
+ }
+ }
+ // If both transport have low RTP quality restriction, let ANE do final decision.
+ addRestriction(mTransportType, restriction, lowRtpQualityRestrictTime);
+
+ if (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
+ int fallbackReason = mQnsCarrierConfigManager.getQnsIwlanHoRestrictReason();
+ if (fallbackReason == QnsConstants.FALLBACK_REASON_RTP_OR_WIFI
+ || fallbackReason == QnsConstants.FALLBACK_REASON_RTP_ONLY) {
+ increaseCounterToRestrictIwlanInCall();
+ }
+ }
+ } else {
+ if (hasRestrictionType(mTransportType, RESTRICT_TYPE_RTP_LOW_QUALITY)) {
+ releaseRestriction(mTransportType, RESTRICT_TYPE_RTP_LOW_QUALITY);
}
}
}
@@ -695,7 +730,7 @@ class RestrictManager {
checkToCancelInitialPdnConnectionFailFallback();
clearInitialPdnConnectionFailFallbackRestriction();
- checkIfCancelNonPreferredRestriction(getOtherTransport(transportType));
+ checkIfCancelNonPreferredRestriction(QnsUtils.getOtherTransportType(transportType));
if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) {
if (mLastEvaluatedTransportType == AccessNetworkConstants.TRANSPORT_TYPE_INVALID
|| transportType == mLastEvaluatedTransportType) {
@@ -794,12 +829,6 @@ class RestrictManager {
// Return to the transport type restricted by low RTP. It may be singleRAT case, release
// the restriction.
releaseRestriction(mTransportType, RESTRICT_TYPE_RTP_LOW_QUALITY);
- Log.d(mLogTag, "Unregister & Register Low RTP quality for " + mTransportType);
- unregisterLowRtpQualityEvent();
-
- Message msg =
- mHandler.obtainMessage(EVENT_REGISTER_LOW_RTP_QUALITY, mTransportType, 0, null);
- mHandler.sendMessageDelayed(msg, (long) QnsConstants.DEFAULT_MSG_DELAY_TIMER);
}
}
@@ -808,7 +837,7 @@ class RestrictManager {
}
private void processHandoverGuardingOperation(int transportType) {
- int guardingTransport = getOtherTransport(transportType);
+ int guardingTransport = QnsUtils.getOtherTransportType(transportType);
int delayMillis = getGuardingTimeMillis(guardingTransport, mImsCallType);
int minimumGuardingTimer = mQnsCarrierConfigManager.getMinimumHandoverGuardingTimer();
if (delayMillis == 0 && minimumGuardingTimer > 0) {
@@ -1031,7 +1060,7 @@ class RestrictManager {
int transportType, int restrictType, int fallbackTimeMillis) {
Log.d(mLogTag, "release ignorable restrictions on WWAN to fallback.");
for (int restriction : ignorableRestrictionsOnSingleRat) {
- releaseRestriction(getOtherTransport(transportType), restriction, false);
+ releaseRestriction(QnsUtils.getOtherTransportType(transportType), restriction, false);
}
addRestriction(
transportType,
@@ -1050,7 +1079,8 @@ class RestrictManager {
}
mLastEvaluatedTransportType = transportType;
if (mDataConnectionStatusTracker.isActiveState() && mTransportType != transportType) {
- startGuarding(GUARDING_TIMER_HANDOVER_INIT, getOtherTransport(transportType));
+ startGuarding(GUARDING_TIMER_HANDOVER_INIT,
+ QnsUtils.getOtherTransportType(transportType));
}
}
@@ -1082,7 +1112,7 @@ class RestrictManager {
}
private void updateGuardingTimerConditionOnCallState(int prevCallType, int newCallType) {
- int currGuardingTransport = getOtherTransport(mTransportType);
+ int currGuardingTransport = QnsUtils.getOtherTransportType(mTransportType);
if (mRestrictInfos.get(currGuardingTransport) == null) return;
HashMap<Integer, Restriction> restrictionMap =
@@ -1141,6 +1171,49 @@ class RestrictManager {
}
}
+ void addRestriction(int transport, Restriction restrictObj, int timeMillis) {
+ boolean needNotify = false;
+ HashMap<Integer, Restriction> restrictionMap =
+ mRestrictInfos.get(transport).getRestrictionMap();
+ Restriction restriction = restrictionMap.get(restrictObj.mRestrictType);
+ Log.d(
+ mLogTag,
+ "addRestriction["
+ + QnsConstants.transportTypeToString(transport)
+ + "] "
+ + restrictTypeToString(restrictObj.mRestrictType)
+ + " was restrict:"
+ + (restriction != null));
+ if (restriction == null) {
+ restriction = restrictObj;
+ restrictionMap.put(restrictObj.mRestrictType, restriction);
+ Log.d(
+ mLogTag,
+ "addRestriction["
+ + QnsConstants.transportTypeToString(transport)
+ + "] "
+ + restriction);
+ needNotify = true;
+ } else {
+ if (timeMillis > 0) {
+ restriction.updateRestrictTime(timeMillis);
+ removeReleaseRestrictionMessage(restriction);
+ }
+ Log.d(
+ mLogTag,
+ "updateRestriction["
+ + QnsConstants.transportTypeToString(transport)
+ + "] "
+ + restriction);
+ }
+ if (timeMillis > 0) {
+ sendReleaseRestrictionMessage(transport, restriction);
+ }
+ if (needNotify) {
+ notifyRestrictInfoChanged();
+ }
+ }
+
void addRestriction(int transport, int type, int[] releaseEvents, int timeMillis) {
boolean needNotify = false;
HashMap<Integer, Restriction> restrictionMap =
@@ -1261,14 +1334,6 @@ class RestrictManager {
mHandler.removeMessages(EVENT_RELEASE_RESTRICTION, restriction);
}
- protected int getOtherTransport(int transportType) {
- if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
- return AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
- } else {
- return AccessNetworkConstants.TRANSPORT_TYPE_WLAN;
- }
- }
-
void registerRestrictInfoChanged(Handler h, int what) {
mRestrictInfoRegistrant = new QnsRegistrant(h, what, null);
}
@@ -1375,17 +1440,13 @@ class RestrictManager {
|| mImsCallType == QnsConstants.CALL_TYPE_EMERGENCY)
&& (mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN
|| mTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN)
- && mAltEventListener != null) {
+ && mActiveCallTracker != null) {
int hoRestrictTimeOnLowRtpQuality =
mQnsCarrierConfigManager.getHoRestrictedTimeOnLowRTPQuality(mTransportType);
if (hoRestrictTimeOnLowRtpQuality > 0) {
Log.d(mLogTag, "registerLowRtpQualityEvent");
- mAltEventListener.registerLowRtpQualityEvent(
- mNetCapability,
- mHandler,
- EVENT_LOW_RTP_QUALITY_REPORTED,
- null,
- mQnsCarrierConfigManager.getRTPMetricsData());
+ mActiveCallTracker.registerLowMediaQualityListener(
+ mHandler, EVENT_LOW_RTP_QUALITY_REPORTED, null);
}
}
}
@@ -1393,7 +1454,9 @@ class RestrictManager {
private void unregisterLowRtpQualityEvent() {
if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS
|| mNetCapability == NetworkCapabilities.NET_CAPABILITY_EIMS) {
- mAltEventListener.unregisterLowRtpQualityEvent(mNetCapability, mHandler);
+ if (mActiveCallTracker != null) {
+ mActiveCallTracker.unregisterLowMediaQualityListener(mHandler);
+ }
}
}
@@ -1444,9 +1507,7 @@ class RestrictManager {
case NetworkCapabilities.NET_CAPABILITY_MMS:
case NetworkCapabilities.NET_CAPABILITY_XCAP:
case NetworkCapabilities.NET_CAPABILITY_CBS:
- callType =
- mAltEventListener.isIdleState()
- ? QnsConstants.CALL_TYPE_IDLE
+ callType = mQnsCallStatusTracker.isCallIdle() ? QnsConstants.CALL_TYPE_IDLE
: QnsConstants.CALL_TYPE_VOICE;
if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
delayMillis =
@@ -1484,14 +1545,15 @@ class RestrictManager {
// Transport
// Type
if (transportType != AccessNetworkConstants.TRANSPORT_TYPE_INVALID
- && hasRestrictionType(
- getOtherTransport(transportType), RestrictManager.RESTRICT_TYPE_GUARDING)) {
+ && hasRestrictionType(QnsUtils.getOtherTransportType(transportType),
+ RestrictManager.RESTRICT_TYPE_GUARDING)) {
Log.d(
mLogTag,
"RESTRICT_TYPE_GUARDING cleared from Guarding for:"
+ QnsConstants.transportTypeToString(mTransportType));
// addRestriction() will take care to notify the ANE of Restrict Info status
- releaseRestriction(getOtherTransport(transportType), RESTRICT_TYPE_GUARDING, true);
+ releaseRestriction(
+ QnsUtils.getOtherTransportType(transportType), RESTRICT_TYPE_GUARDING, true);
}
addRestriction(