• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.telephony.qns;
18 
19 import android.content.Context;
20 import android.net.NetworkCapabilities;
21 import android.os.Handler;
22 import android.os.HandlerThread;
23 import android.os.Looper;
24 import android.os.Message;
25 import android.telephony.AccessNetworkConstants;
26 import android.telephony.AccessNetworkConstants.AccessNetworkType;
27 import android.telephony.TelephonyManager;
28 import android.telephony.data.ApnSetting;
29 import android.telephony.ims.ImsReasonInfo;
30 import android.telephony.ims.ProvisioningManager;
31 import android.util.Log;
32 
33 import com.android.internal.annotations.VisibleForTesting;
34 import com.android.telephony.qns.AccessNetworkSelectionPolicy.GuardingPreCondition;
35 import com.android.telephony.qns.AccessNetworkSelectionPolicy.PreCondition;
36 import com.android.telephony.qns.IwlanNetworkStatusTracker.IwlanAvailabilityInfo;
37 import com.android.telephony.qns.QualifiedNetworksServiceImpl.QualifiedNetworksInfo;
38 
39 import java.io.PrintWriter;
40 import java.util.ArrayList;
41 import java.util.Arrays;
42 import java.util.HashMap;
43 import java.util.LinkedHashSet;
44 import java.util.List;
45 import java.util.Map;
46 import java.util.Map.Entry;
47 import java.util.concurrent.Executor;
48 
49 /**
50  * AccessNetworkEvaluator evaluates prioritized AccessNetwork list base on Cellular/Wi-Fi network
51  * status and configurations from carrier/user.
52  */
53 class AccessNetworkEvaluator {
54     private static final boolean DBG = true;
55     private static final int EVENT_BASE = 10000;
56     private static final int EVENT_IWLAN_NETWORK_STATUS_CHANGED = EVENT_BASE;
57     private static final int EVENT_QNS_TELEPHONY_INFO_CHANGED = EVENT_BASE + 1;
58     private static final int EVENT_RESTRICT_INFO_CHANGED = EVENT_BASE + 4;
59     private static final int EVENT_SET_CALL_TYPE = EVENT_BASE + 5;
60     private static final int EVENT_DATA_CONNECTION_STATE_CHANGED = EVENT_BASE + 6;
61     private static final int EVENT_PROVISIONING_INFO_CHANGED = EVENT_BASE + 8;
62     private static final int EVENT_IMS_REGISTRATION_STATE_CHANGED = EVENT_BASE + 10;
63     private static final int EVENT_WIFI_RTT_STATUS_CHANGED = EVENT_BASE + 11;
64     private static final int EVENT_SIP_DIALOG_SESSION_STATE_CHANGED = EVENT_BASE + 12;
65     private static final int EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED = EVENT_BASE + 13;
66     private static final int EVALUATE_SPECIFIC_REASON_NONE = 0;
67     private static final int EVALUATE_SPECIFIC_REASON_IWLAN_DISABLE = 1;
68     private static final int EVALUATE_SPECIFIC_REASON_DATA_DISCONNECTED = 2;
69     private static final int EVALUATE_SPECIFIC_REASON_DATA_FAILED = 3;
70     private static final int EVALUATE_SPECIFIC_REASON_DATA_CONNECTED = 4;
71 
72     protected final int mSlotIndex;
73     protected final Context mContext;
74     private final String mLogTag;
75     private final int mNetCapability;
76     @VisibleForTesting
77     protected final Handler mHandler;
78     private final HandlerThread mHandlerThread;
79     private final RestrictManager mRestrictManager;
80     protected QnsCarrierConfigManager mConfigManager;
81     protected QnsComponents mQnsComponents;
82     protected QualityMonitor mWifiQualityMonitor;
83     protected QualityMonitor mCellularQualityMonitor;
84     protected CellularNetworkStatusTracker mCellularNetworkStatusTracker;
85     protected IwlanNetworkStatusTracker mIwlanNetworkStatusTracker;
86     protected DataConnectionStatusTracker mDataConnectionStatusTracker;
87     protected QnsEventDispatcher mQnsEventDispatcher;
88     protected QnsCallStatusTracker mCallStatusTracker;
89     protected QnsProvisioningListener mQnsProvisioningListener;
90     protected QnsImsManager mQnsImsManager;
91     protected WifiBackhaulMonitor mWifiBackhaulMonitor;
92     protected QnsTelephonyListener mQnsTelephonyListener;
93     // for metric
94     protected QnsMetrics mQnsMetrics;
95 
96     protected int mCellularAccessNetworkType = AccessNetworkType.UNKNOWN;
97     protected boolean mCellularAvailable = false;
98     protected boolean mIwlanAvailable = false;
99     private boolean mIsCrossWfc = false;
100 
101     protected QnsRegistrantList mQualifiedNetworksChangedRegistrants = new QnsRegistrantList();
102     // pre-conditions
103     private int mCallType;
104     private int mCoverage;
105     private int mLatestAvailableCellularAccessNetwork = AccessNetworkType.UNKNOWN;
106     private List<AccessNetworkSelectionPolicy> mAccessNetworkSelectionPolicies = new ArrayList<>();
107     private List<Integer> mLastQualifiedAccessNetworkTypes;
108     private boolean mIsNotifiedLastQualifiedAccessNetworkTypes = false;
109     private boolean mWfcPlatformEnabled = false;
110     private boolean mSettingWfcEnabled = false;
111     private int mSettingWfcMode = QnsConstants.CELL_PREF;
112     private boolean mSettingWfcRoamingEnabled = false;
113     private int mSettingWfcRoamingMode = QnsConstants.WIFI_PREF;
114     private boolean mAllowIwlanForWfcActivation = false;
115     private Map<PreCondition, List<AccessNetworkSelectionPolicy>> mAnspPolicyMap = null;
116     private ThresholdListener mThresholdListener;
117     private boolean mInitialized = false;
118     private boolean mIsRttCheckSuccess = false;
119     private QnsProvisioningListener.QnsProvisioningInfo mLastProvisioningInfo =
120             new QnsProvisioningListener.QnsProvisioningInfo();
121     private boolean mSipDialogSessionState = false;
122     private int mCachedTransportTypeForEmergencyInitialConnect =
123             AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
124     private int mLastEvaluateSpecificReason = EVALUATE_SPECIFIC_REASON_NONE;
125 
AccessNetworkEvaluator(QnsComponents qnsComponents, int netCapability, int slotIndex)126     AccessNetworkEvaluator(QnsComponents qnsComponents, int netCapability, int slotIndex) {
127         mNetCapability = netCapability;
128         mQnsComponents = qnsComponents;
129         mSlotIndex = slotIndex;
130         mContext = mQnsComponents.getContext();
131         mLogTag =
132                 QnsConstants.QNS_TAG
133                         + "_"
134                         + AccessNetworkEvaluator.class.getSimpleName()
135                         + "_"
136                         + mSlotIndex
137                         + "_"
138                         + QnsUtils.getNameOfNetCapability(netCapability);
139         // load configurations & sort by purpose.
140 
141         log("created AccessNetworkEvaluator");
142 
143         // make handler to handle events for evaluate available AccessNetworks.
144         mHandlerThread =
145                 new HandlerThread(AccessNetworkEvaluator.class.getSimpleName() + mNetCapability);
146         mHandlerThread.start();
147         mHandler = new EvaluatorEventHandler(mHandlerThread.getLooper());
148         Executor executor = new QnsUtils.QnsExecutor(mHandler);
149 
150         mConfigManager = mQnsComponents.getQnsCarrierConfigManager(mSlotIndex);
151         mCallStatusTracker = mQnsComponents.getQnsCallStatusTracker(mSlotIndex);
152         mQnsProvisioningListener = mQnsComponents.getQnsProvisioningListener(mSlotIndex);
153         mIwlanNetworkStatusTracker = mQnsComponents.getIwlanNetworkStatusTracker();
154         mDataConnectionStatusTracker =
155                 new DataConnectionStatusTracker(
156                         mQnsComponents.getQnsTelephonyListener(mSlotIndex),
157                         mHandlerThread.getLooper(),
158                         mSlotIndex,
159                         mNetCapability);
160         mQnsImsManager = mQnsComponents.getQnsImsManager(mSlotIndex);
161         mWifiBackhaulMonitor = mQnsComponents.getWifiBackhaulMonitor(mSlotIndex);
162         mQnsTelephonyListener = mQnsComponents.getQnsTelephonyListener(mSlotIndex);
163         mQnsMetrics = mQnsComponents.getQnsMetrics();
164 
165         // Pre-Conditions
166         mCellularNetworkStatusTracker = mQnsComponents.getCellularNetworkStatusTracker(mSlotIndex);
167         mQnsEventDispatcher = mQnsComponents.getQnsEventDispatcher(mSlotIndex);
168         mThresholdListener = new ThresholdListener(executor);
169 
170         // Post-Conditions
171         mWifiQualityMonitor = mQnsComponents.getWifiQualityMonitor();
172         mCellularQualityMonitor = mQnsComponents.getCellularQualityMonitor(mSlotIndex);
173 
174         // Evaluates
175         mRestrictManager =
176                 new RestrictManager(
177                         mQnsComponents,
178                         mHandler.getLooper(),
179                         mNetCapability,
180                         mDataConnectionStatusTracker,
181                         mSlotIndex);
182 
183         mHandler.post(() -> buildAccessNetworkSelectionPolicy(false));
184         initLastNotifiedQualifiedNetwork();
185         initSettings();
186         registerListeners();
187     }
188 
189     @VisibleForTesting
AccessNetworkEvaluator( QnsComponents qnsComponents, int netCapability, RestrictManager restrictManager, DataConnectionStatusTracker dataConnectionStatusTracker, int slotIndex)190     AccessNetworkEvaluator(
191             QnsComponents qnsComponents,
192             int netCapability,
193             RestrictManager restrictManager,
194             DataConnectionStatusTracker dataConnectionStatusTracker,
195             int slotIndex) {
196         mQnsComponents = qnsComponents;
197         mSlotIndex = slotIndex;
198         mLogTag =
199                 QnsConstants.QNS_TAG
200                         + "_"
201                         + AccessNetworkEvaluator.class.getSimpleName()
202                         + "_"
203                         + mSlotIndex
204                         + "_"
205                         + QnsUtils.getNameOfNetCapability(netCapability);
206         // load configurations & sort by purpose.
207         mNetCapability = netCapability;
208         mContext = mQnsComponents.getContext();
209         mRestrictManager = restrictManager;
210         mConfigManager = mQnsComponents.getQnsCarrierConfigManager(mSlotIndex);
211         mWifiQualityMonitor = mQnsComponents.getWifiQualityMonitor();
212         mCellularQualityMonitor = mQnsComponents.getCellularQualityMonitor(mSlotIndex);
213         mCellularNetworkStatusTracker = mQnsComponents.getCellularNetworkStatusTracker(mSlotIndex);
214         mIwlanNetworkStatusTracker = mQnsComponents.getIwlanNetworkStatusTracker();
215         mDataConnectionStatusTracker = dataConnectionStatusTracker;
216         mQnsEventDispatcher = mQnsComponents.getQnsEventDispatcher(mSlotIndex);
217         mCallStatusTracker = mQnsComponents.getQnsCallStatusTracker(mSlotIndex);
218         mQnsProvisioningListener = mQnsComponents.getQnsProvisioningListener(mSlotIndex);
219         mQnsImsManager = mQnsComponents.getQnsImsManager(mSlotIndex);
220         mWifiBackhaulMonitor = mQnsComponents.getWifiBackhaulMonitor(mSlotIndex);
221         mQnsTelephonyListener = mQnsComponents.getQnsTelephonyListener(mSlotIndex);
222         mQnsMetrics = mQnsComponents.getQnsMetrics();
223         mHandlerThread =
224                 new HandlerThread(AccessNetworkEvaluator.class.getSimpleName() + mNetCapability);
225         mHandlerThread.start();
226         mHandler = new EvaluatorEventHandler(mHandlerThread.getLooper());
227         mHandler.post(() -> buildAccessNetworkSelectionPolicy(false));
228         initLastNotifiedQualifiedNetwork();
229         initSettings();
230         registerListeners();
231     }
232 
rebuild()233     void rebuild() {
234         log("rebuild");
235         initSettings();
236         mLastProvisioningInfo.clear();
237         mConfigManager.setQnsProvisioningInfo(mLastProvisioningInfo);
238         mHandler.post(() -> buildAccessNetworkSelectionPolicy(true));
239         mRestrictManager.clearRestrictions();
240         if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) {
241             if (mWifiBackhaulMonitor.isRttCheckEnabled()) {
242                 mWifiBackhaulMonitor.registerForRttStatusChange(
243                         mHandler, EVENT_WIFI_RTT_STATUS_CHANGED);
244             } else {
245                 mWifiBackhaulMonitor.clearAll();
246             }
247         }
248         reportQualifiedNetwork(getInitialAccessNetworkTypes());
249         initLastNotifiedQualifiedNetwork();
250         unregisterThresholdToQualityMonitor();
251 
252         if (isAllowed(AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
253                 && evaluateAvailability(
254                         AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
255                         isAllowed(AccessNetworkConstants.TRANSPORT_TYPE_WWAN))) {
256             mHandler.post(this::evaluate);
257         }
258         mLastEvaluateSpecificReason = EVALUATE_SPECIFIC_REASON_NONE;
259     }
260 
close()261     void close() {
262         log("close");
263         mHandler.post(this::onClose);
264         mHandlerThread.quitSafely();
265     }
266 
onClose()267     private void onClose() {
268         notifyForQualifiedNetworksChanged(getInitialAccessNetworkTypes());
269         initLastNotifiedQualifiedNetwork();
270         unregisterListeners();
271         mQualifiedNetworksChangedRegistrants.removeAll();
272         mDataConnectionStatusTracker.close();
273         mRestrictManager.close();
274     }
275 
registerForQualifiedNetworksChanged(Handler h, int what)276     void registerForQualifiedNetworksChanged(Handler h, int what) {
277         mInitialized = true;
278         mQualifiedNetworksChangedRegistrants.addUnique(h, what, null);
279         if (isNotifiedQualifiedAccessNetworkTypes()) {
280             if (DBG) {
281                 log(
282                         "registerForQualifiedNetworksChanged, report:"
283                                 + QnsUtils.getStringAccessNetworkTypes(
284                                         mLastQualifiedAccessNetworkTypes));
285             }
286             notifyForQualifiedNetworksChanged(mLastQualifiedAccessNetworkTypes);
287         }
288         mHandler.post(this::evaluate);
289     }
290 
unregisterForQualifiedNetworksChanged(Handler h)291     void unregisterForQualifiedNetworksChanged(Handler h) {
292         mQualifiedNetworksChangedRegistrants.remove(h);
293     }
294 
getInitialAccessNetworkTypes()295     private List<Integer> getInitialAccessNetworkTypes() {
296         // The framework treats empty lists as WWAN.
297         return List.of();
298     }
299 
getLastQualifiedTransportType()300     protected int getLastQualifiedTransportType() {
301         if (mLastQualifiedAccessNetworkTypes.size() > 0
302                 && mLastQualifiedAccessNetworkTypes.get(0) == AccessNetworkType.IWLAN) {
303             return AccessNetworkConstants.TRANSPORT_TYPE_WLAN;
304         }
305         // otherwise, returns WWAN. (includes an empty list)
306         return AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
307     }
308 
isNotifiedQualifiedAccessNetworkTypes()309     protected boolean isNotifiedQualifiedAccessNetworkTypes() {
310         return mIsNotifiedLastQualifiedAccessNetworkTypes;
311     }
312 
initLastNotifiedQualifiedNetwork()313     protected void initLastNotifiedQualifiedNetwork() {
314         mIsNotifiedLastQualifiedAccessNetworkTypes = false;
315         mLastQualifiedAccessNetworkTypes = getInitialAccessNetworkTypes();
316         log(
317                 "initLastNotifiedQualifiedNetwork mLastQualifiedAccessNetworkTypes:"
318                         + QnsUtils.getStringAccessNetworkTypes(mLastQualifiedAccessNetworkTypes));
319     }
320 
equalsLastNotifiedQualifiedNetwork(List<Integer> accessNetworkTypes)321     protected boolean equalsLastNotifiedQualifiedNetwork(List<Integer> accessNetworkTypes) {
322         return mLastQualifiedAccessNetworkTypes.equals(accessNetworkTypes);
323     }
324 
updateLastNotifiedQualifiedNetwork(List<Integer> accessNetworkTypes)325     protected void updateLastNotifiedQualifiedNetwork(List<Integer> accessNetworkTypes) {
326         mLastQualifiedAccessNetworkTypes = accessNetworkTypes;
327         mRestrictManager.updateLastNotifiedTransportType(getLastQualifiedTransportType());
328         log(
329                 "updateLastNotifiedQualifiedNetwork mLastQualifiedAccessNetworkTypes:"
330                         + QnsUtils.getStringAccessNetworkTypes(mLastQualifiedAccessNetworkTypes));
331     }
332 
notifyForQualifiedNetworksChanged(List<Integer> accessNetworkTypes)333     protected void notifyForQualifiedNetworksChanged(List<Integer> accessNetworkTypes) {
334         mIsNotifiedLastQualifiedAccessNetworkTypes = true;
335         QualifiedNetworksInfo info = new QualifiedNetworksInfo(mNetCapability, accessNetworkTypes);
336         QnsAsyncResult ar = new QnsAsyncResult(null, info, null);
337         mQualifiedNetworksChangedRegistrants.notifyRegistrants(ar);
338 
339         // metrics
340         sendMetricsForQualifiedNetworks(info);
341     }
342 
initSettings()343     private void initSettings() {
344         mWfcPlatformEnabled = QnsUtils.isWfcEnabledByPlatform(mQnsImsManager);
345         mSettingWfcEnabled = QnsUtils.isWfcEnabled(mQnsImsManager, mQnsProvisioningListener, false);
346         mSettingWfcMode = QnsUtils.getWfcMode(mQnsImsManager, false);
347         mSettingWfcRoamingEnabled =
348                 QnsUtils.isWfcEnabled(mQnsImsManager, mQnsProvisioningListener, true);
349         mSettingWfcRoamingMode = QnsUtils.getWfcMode(mQnsImsManager, true);
350         mAllowIwlanForWfcActivation = false;
351         mSipDialogSessionState = false;
352         mCachedTransportTypeForEmergencyInitialConnect =
353                 AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
354         log(
355                 "WfcSettings. mWfcPlatformEnabled:"
356                         + mWfcPlatformEnabled
357                         + " WfcEnabled:"
358                         + mSettingWfcEnabled
359                         + " WfcMode:"
360                         + QnsConstants.preferenceToString(mSettingWfcMode)
361                         + " WfcRoamingEnabled:"
362                         + mSettingWfcRoamingEnabled
363                         + " WfcRoamingMode:"
364                         + QnsConstants.preferenceToString(mSettingWfcRoamingMode));
365     }
366 
registerListeners()367     protected void registerListeners() {
368         log("registerListeners");
369         mWifiQualityMonitor.registerThresholdChange(
370                 mThresholdListener, mNetCapability, null, mSlotIndex);
371         mCellularQualityMonitor.registerThresholdChange(
372                 mThresholdListener, mNetCapability, null, mSlotIndex);
373         mIwlanNetworkStatusTracker.registerIwlanNetworksChanged(
374                 mSlotIndex, mHandler, EVENT_IWLAN_NETWORK_STATUS_CHANGED);
375         mDataConnectionStatusTracker.registerDataConnectionStatusChanged(
376                 mHandler, EVENT_DATA_CONNECTION_STATE_CHANGED);
377         mQnsImsManager.registerImsRegistrationStatusChanged(
378                 mHandler, EVENT_IMS_REGISTRATION_STATE_CHANGED);
379         mQnsImsManager.registerSipDialogSessionStateChanged(
380                 mHandler, EVENT_SIP_DIALOG_SESSION_STATE_CHANGED);
381         mCellularNetworkStatusTracker.registerQnsTelephonyInfoChanged(
382                 mNetCapability, mHandler, EVENT_QNS_TELEPHONY_INFO_CHANGED);
383         if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS
384                 || mNetCapability == NetworkCapabilities.NET_CAPABILITY_EIMS) {
385             mCallStatusTracker.registerCallTypeChangedListener(
386                     mNetCapability, mHandler, EVENT_SET_CALL_TYPE, null);
387         }
388 
389         if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) {
390             if (mWifiBackhaulMonitor.isRttCheckEnabled()) {
391                 mWifiBackhaulMonitor.registerForRttStatusChange(
392                         mHandler, EVENT_WIFI_RTT_STATUS_CHANGED);
393             }
394         }
395         mQnsProvisioningListener.registerProvisioningItemInfoChanged(
396                 mHandler, EVENT_PROVISIONING_INFO_CHANGED, null, true);
397         if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) {
398             mQnsTelephonyListener.registerImsCallDropDisconnectCauseListener(
399                     mHandler, EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED, null);
400         }
401         List<Integer> events = new ArrayList<>();
402         events.add(QnsEventDispatcher.QNS_EVENT_WFC_ENABLED);
403         events.add(QnsEventDispatcher.QNS_EVENT_WFC_DISABLED);
404         events.add(QnsEventDispatcher.QNS_EVENT_WFC_MODE_TO_WIFI_ONLY);
405         events.add(QnsEventDispatcher.QNS_EVENT_WFC_MODE_TO_CELLULAR_PREFERRED);
406         events.add(QnsEventDispatcher.QNS_EVENT_WFC_MODE_TO_WIFI_PREFERRED);
407         events.add(QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_ENABLED);
408         events.add(QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_DISABLED);
409         events.add(QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_ONLY);
410         events.add(QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_MODE_TO_CELLULAR_PREFERRED);
411         events.add(QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_PREFERRED);
412         events.add(QnsEventDispatcher.QNS_EVENT_WFC_PLATFORM_ENABLED);
413         events.add(QnsEventDispatcher.QNS_EVENT_WFC_PLATFORM_DISABLED);
414         events.add(QnsEventDispatcher.QNS_EVENT_SIM_ABSENT);
415         events.add(QnsEventDispatcher.QNS_EVENT_TRY_WFC_ACTIVATION);
416         events.add(QnsEventDispatcher.QNS_EVENT_CANCEL_TRY_WFC_ACTIVATION);
417         mQnsEventDispatcher.registerEvent(events, mHandler);
418         mRestrictManager.registerRestrictInfoChanged(mHandler, EVENT_RESTRICT_INFO_CHANGED);
419     }
420 
unregisterListeners()421     protected void unregisterListeners() {
422         log("unregisterListeners");
423         mWifiQualityMonitor.unregisterThresholdChange(mNetCapability, mSlotIndex);
424         mCellularQualityMonitor.unregisterThresholdChange(mNetCapability, mSlotIndex);
425         mDataConnectionStatusTracker.unRegisterDataConnectionStatusChanged(mHandler);
426         mQnsImsManager.unregisterImsRegistrationStatusChanged(mHandler);
427         mQnsImsManager.unregisterSipDialogSessionStateChanged(mHandler);
428         mCellularNetworkStatusTracker.unregisterQnsTelephonyInfoChanged(mNetCapability, mHandler);
429         mIwlanNetworkStatusTracker.unregisterIwlanNetworksChanged(mSlotIndex, mHandler);
430         if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS
431                 || mNetCapability == NetworkCapabilities.NET_CAPABILITY_EIMS) {
432             mCallStatusTracker.unregisterCallTypeChangedListener(mNetCapability, mHandler);
433             if (mWifiBackhaulMonitor.isRttCheckEnabled()) {
434                 mWifiBackhaulMonitor.unRegisterForRttStatusChange(mHandler);
435             }
436         }
437         if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) {
438             mQnsTelephonyListener.unregisterImsCallDropDisconnectCauseListener(mHandler);
439         }
440         mQnsProvisioningListener.unregisterProvisioningItemInfoChanged(mHandler);
441         mQnsEventDispatcher.unregisterEvent(mHandler);
442         mRestrictManager.unRegisterRestrictInfoChanged(mHandler);
443     }
444 
isIwlanAvailableWithoutRestrict()445     private boolean isIwlanAvailableWithoutRestrict() {
446         return (mIwlanAvailable
447                 && !mRestrictManager.isRestricted(AccessNetworkConstants.TRANSPORT_TYPE_WLAN));
448     }
449 
isCellularAvailableWithoutRestrict()450     private boolean isCellularAvailableWithoutRestrict() {
451         return (mCellularAvailable
452                 && !mRestrictManager.isRestricted(AccessNetworkConstants.TRANSPORT_TYPE_WWAN));
453     }
454 
log(String s)455     protected void log(String s) {
456         Log.d(mLogTag, s);
457     }
458 
onQnsTelephonyInfoChanged(QnsTelephonyListener.QnsTelephonyInfo info)459     protected void onQnsTelephonyInfoChanged(QnsTelephonyListener.QnsTelephonyInfo info) {
460         boolean needEvaluate = false;
461 
462         if (info instanceof QnsTelephonyListener.QnsTelephonyInfoIms) {
463             QnsTelephonyListener.QnsTelephonyInfoIms infoIms =
464                     (QnsTelephonyListener.QnsTelephonyInfoIms) info;
465             boolean checkVoPs = false;
466             boolean volteRoamingSupported = true;
467             int cellularAccessNetworkType =
468                     QnsUtils.getCellularAccessNetworkType(
469                             infoIms.getDataRegState(), infoIms.getDataNetworkType());
470 
471             int coverage = getCoverage(infoIms);
472             if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS
473                     && infoIms.isCellularAvailable()) {
474                 checkVoPs = vopsCheckRequired(cellularAccessNetworkType, coverage, mCallType);
475                 volteRoamingSupported = mConfigManager.isVolteRoamingSupported(coverage);
476             }
477             boolean checkBarring = mConfigManager.isServiceBarringCheckSupported();
478             if (DBG) {
479                 log(
480                         "checkVoPs:"
481                                 + checkVoPs
482                                 + ", checkBarring:"
483                                 + checkBarring
484                                 + ", volteRoamingSupported:"
485                                 + volteRoamingSupported);
486             }
487             boolean cellAvailable =
488                     infoIms.isCellularAvailable(
489                             mNetCapability, checkVoPs, checkBarring, volteRoamingSupported);
490             if (mCellularAvailable != cellAvailable) {
491                 mCellularAvailable = cellAvailable;
492                 needEvaluate = true;
493                 log("onQnsTelephonyInfoChanged cellularAvailableIms:" + mCellularAvailable);
494             }
495         } else if (mCellularAvailable != info.isCellularAvailable()) {
496             mCellularAvailable = info.isCellularAvailable();
497             needEvaluate = true;
498             log("onQnsTelephonyInfoChanged cellularAvailable:" + mCellularAvailable);
499         }
500         if (mCellularAccessNetworkType
501                 != QnsUtils.getCellularAccessNetworkType(
502                         info.getDataRegState(), info.getDataNetworkType())) {
503             mCellularAccessNetworkType =
504                     QnsUtils.getCellularAccessNetworkType(
505                             info.getDataRegState(), info.getDataNetworkType());
506             mRestrictManager.setCellularAccessNetwork(mCellularAccessNetworkType);
507             if (mCellularAccessNetworkType != AccessNetworkType.UNKNOWN) {
508                 mLatestAvailableCellularAccessNetwork = mCellularAccessNetworkType;
509             }
510 
511             needEvaluate = true;
512             log(
513                     "onQnsTelephonyInfoChanged cellularAccessNetworkType:"
514                             + mCellularAccessNetworkType);
515         }
516         int coverage = getCoverage(info);
517         if (mCoverage != coverage) {
518             mCoverage = coverage;
519             needEvaluate = true;
520             mRestrictManager.setCellularCoverage(mCoverage);
521             log("onQnsTelephonyInfoChanged Coverage:" + mCoverage);
522         }
523 
524         if (needEvaluate) {
525             evaluate();
526         }
527     }
528 
529     @VisibleForTesting
getCoverage(QnsTelephonyListener.QnsTelephonyInfo info)530     int getCoverage(QnsTelephonyListener.QnsTelephonyInfo info) {
531         if (DBG) {
532             log("getCoverage roaming=" + info.isCoverage());
533         }
534         if (info.isCoverage()) {
535             return QnsConstants.COVERAGE_ROAM;
536         } else {
537             return QnsConstants.COVERAGE_HOME;
538         }
539     }
540 
onIwlanNetworkStatusChanged(IwlanAvailabilityInfo info)541     protected void onIwlanNetworkStatusChanged(IwlanAvailabilityInfo info) {
542         if (info != null) {
543             if (mIwlanAvailable != info.getIwlanAvailable()) {
544                 mIwlanAvailable = info.getIwlanAvailable();
545             }
546             mIsCrossWfc = info.isCrossWfc();
547             log("onIwlanNetworkStatusChanged IwlanAvailable:" + mIwlanAvailable);
548             if (info.getNotifyIwlanDisabled()) {
549                 evaluate(EVALUATE_SPECIFIC_REASON_IWLAN_DISABLE);
550             } else {
551                 evaluate();
552             }
553         }
554     }
555 
onWfcEnabledChanged(boolean enabled, boolean roaming)556     private void onWfcEnabledChanged(boolean enabled, boolean roaming) {
557         StringBuilder sb = new StringBuilder("onWfcEnabledChanged");
558         sb.append(" enabled:").append(enabled);
559         sb.append(" coverage:")
560                 .append(
561                         QnsConstants.coverageToString(
562                                 roaming ? QnsConstants.COVERAGE_ROAM : QnsConstants.COVERAGE_HOME));
563 
564         boolean needEvaluate = false;
565         if (!roaming && mSettingWfcEnabled != enabled) {
566             if (mCoverage == QnsConstants.COVERAGE_HOME) {
567                 needEvaluate = true;
568             }
569             mSettingWfcEnabled = enabled;
570             sb.append(" mSettingWfcEnabled:").append(mSettingWfcEnabled);
571         } else if (roaming && mSettingWfcRoamingEnabled != enabled) {
572             if (mCoverage == QnsConstants.COVERAGE_ROAM) {
573                 needEvaluate = true;
574             }
575             mSettingWfcRoamingEnabled = enabled;
576             sb.append(" mSettingWfcRoamingEnabled:").append(mSettingWfcRoamingEnabled);
577         }
578 
579         if (needEvaluate) {
580             sb.append(" evaluate.");
581             log(sb.toString());
582             if (enabled) {
583                 evaluate();
584             } else {
585                 evaluate(EVALUATE_SPECIFIC_REASON_IWLAN_DISABLE);
586             }
587         } else {
588             log(sb.toString());
589         }
590     }
591 
onWfcModeChanged(int mode, boolean roaming)592     private void onWfcModeChanged(int mode, boolean roaming) {
593         StringBuilder sb = new StringBuilder("onWfcModeChanged");
594         sb.append(" mode:").append(QnsConstants.preferenceToString(mode));
595         sb.append(" coverage:")
596                 .append(
597                         QnsConstants.coverageToString(
598                                 roaming ? QnsConstants.COVERAGE_ROAM : QnsConstants.COVERAGE_HOME));
599 
600         boolean needEvaluate = false;
601         if (!roaming && mSettingWfcMode != mode) {
602             if (mCoverage == QnsConstants.COVERAGE_HOME) {
603                 needEvaluate = true;
604             }
605             mSettingWfcMode = mode;
606             sb.append(" mSettingWfcMode:").append(QnsConstants.preferenceToString(mSettingWfcMode));
607         } else if (roaming && mSettingWfcRoamingMode != mode) {
608             if (mCoverage == QnsConstants.COVERAGE_ROAM) {
609                 needEvaluate = true;
610             }
611             mSettingWfcRoamingMode = mode;
612             sb.append(" mSettingWfcRoamingMode:");
613             sb.append(QnsConstants.preferenceToString(mSettingWfcRoamingMode));
614         }
615 
616         if (needEvaluate) {
617             sb.append(" evaluate.");
618             log(sb.toString());
619             evaluate();
620         } else {
621             log(sb.toString());
622         }
623     }
624 
onWfcPlatformChanged(boolean bWfcPlatformEnabled)625     private void onWfcPlatformChanged(boolean bWfcPlatformEnabled) {
626         StringBuilder sb = new StringBuilder("onWfcPlatformChanged");
627         sb.append(" bWfcPlatformEnabled:").append(bWfcPlatformEnabled);
628         if (mWfcPlatformEnabled == bWfcPlatformEnabled) {
629             sb.append(" no changes");
630             log(sb.toString());
631         } else {
632             mWfcPlatformEnabled = bWfcPlatformEnabled;
633             if (bWfcPlatformEnabled) {
634                 sb.append(" evaluate.");
635                 log(sb.toString());
636                 evaluate();
637             } else {
638                 sb.append(" report cellular as qualified network directly.");
639                 log(sb.toString());
640                 reportQualifiedNetwork(new ArrayList<>(List.of(mCellularAccessNetworkType)));
641             }
642         }
643     }
644 
onSimAbsent()645     private void onSimAbsent() {
646         log("onSimAbsent");
647 
648         // report default qualified access network.
649         reportQualifiedNetwork(getInitialAccessNetworkTypes());
650     }
651 
onRestrictInfoChanged()652     private void onRestrictInfoChanged() {
653         // TODO
654         log("onRestrictInfoChanged");
655         evaluate();
656     }
657 
658     @VisibleForTesting
onTryWfcConnectionStateChanged(boolean isEnabled)659     void onTryWfcConnectionStateChanged(boolean isEnabled) {
660         log("onTryWfcConnectionStateChanged enabled:" + isEnabled);
661         int timeout = mConfigManager.getVowifiRegistrationTimerForVowifiActivation();
662 
663         if (mAllowIwlanForWfcActivation == isEnabled) {
664             return;
665         }
666         if (isEnabled) {
667             mHandler.sendEmptyMessageDelayed(
668                     QnsEventDispatcher.QNS_EVENT_CANCEL_TRY_WFC_ACTIVATION,
669                     timeout + /* milliseconds */ 3000);
670         } else {
671             mHandler.removeMessages(QnsEventDispatcher.QNS_EVENT_CANCEL_TRY_WFC_ACTIVATION);
672         }
673         mAllowIwlanForWfcActivation = isEnabled;
674         evaluate();
675     }
676 
677     @VisibleForTesting
onSetCallType(@nsConstants.QnsCallType int callType)678     void onSetCallType(@QnsConstants.QnsCallType int callType) {
679         if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS
680                 && callType == QnsConstants.CALL_TYPE_EMERGENCY) {
681             if (!mDataConnectionStatusTracker.isActiveState()) return;
682         }
683 
684         // metrics
685         sendMetricsForCallTypeChanged(mCallType, callType);
686 
687         mCallType = callType;
688         mRestrictManager.setQnsCallType(mCallType);
689         log("onSetCallType CallType:" + mCallType);
690 
691         // call type from service manager API
692 
693         // TODO
694         evaluate();
695     }
696 
onEmergencyPreferredTransportTypeChanged( @ccessNetworkConstants.TransportType int transport)697     void onEmergencyPreferredTransportTypeChanged(
698             @AccessNetworkConstants.TransportType int transport) {
699         if (mNetCapability != NetworkCapabilities.NET_CAPABILITY_EIMS) {
700             return;
701         }
702         mHandler.post(() -> {
703                     log(
704                             "onEmergencyPreferredTransportTypeChanged transport:"
705                                     + QnsConstants.transportTypeToString(transport));
706                     if (mDataConnectionStatusTracker.isInactiveState()
707                             || (mDataConnectionStatusTracker.isActiveState()
708                                     && mCallType == QnsConstants.CALL_TYPE_IDLE)) {
709                         // If data network state is inactive OR active but call is not active yet,
710                         // QNS will follow domain selection's decision.
711                         enforceNotifyQualifiedNetworksWithTransportType(transport);
712                     } else {
713                         log(
714                                 "cache transportType for emergency: "
715                                         + QnsConstants.transportTypeToString(transport));
716                         mCachedTransportTypeForEmergencyInitialConnect = transport;
717                     }
718                 }
719         );
720     }
721 
enforceNotifyQualifiedNetworksWithTransportType( @ccessNetworkConstants.TransportType int transportType)722     private void enforceNotifyQualifiedNetworksWithTransportType(
723             @AccessNetworkConstants.TransportType int transportType) {
724         List<Integer> accessNetworkTypes = new ArrayList<>();
725         if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
726             accessNetworkTypes.add(AccessNetworkType.IWLAN);
727         } else if (mCellularAccessNetworkType != AccessNetworkType.UNKNOWN) {
728             accessNetworkTypes.add(mCellularAccessNetworkType);
729         }
730         updateLastNotifiedQualifiedNetwork(accessNetworkTypes);
731         notifyForQualifiedNetworksChanged(accessNetworkTypes);
732     }
733 
734     @VisibleForTesting
onDataConnectionStateChanged( DataConnectionStatusTracker.DataConnectionChangedInfo info)735     void onDataConnectionStateChanged(
736             DataConnectionStatusTracker.DataConnectionChangedInfo info) {
737         log("onDataConnectionStateChanged info:" + info);
738         boolean needEvaluate = false;
739         int evaluateSpecificReason = EVALUATE_SPECIFIC_REASON_NONE;
740         switch (info.getEvent()) {
741             case DataConnectionStatusTracker.EVENT_DATA_CONNECTION_DISCONNECTED:
742                 evaluateSpecificReason = EVALUATE_SPECIFIC_REASON_DATA_DISCONNECTED;
743                 if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_EIMS) {
744                     // If FWK guided emergency's transport type during data connected state, notify
745                     // the transport type when the data connection is disconnected.
746                     notifyCachedTransportTypeForEmergency();
747                     // When cellular is not available, CellularQualityMonitor will stop listening to
748                     // TelephonyCallback. Thresholds for Emergency apn may not be reset as ANE for
749                     // emergency only evaluates while data is connected. CellularQualityMonitor will
750                     // not listen to TelephonyCallback again until the set of threshold values
751                     // changed. Resetting thresholds for emergency after the emergency connection
752                     // disconnects.
753                     unregisterThresholdToQualityMonitor();
754                 } else {
755                     needEvaluate = true;
756                     initLastNotifiedQualifiedNetwork();
757                 }
758                 break;
759             case DataConnectionStatusTracker.EVENT_DATA_CONNECTION_CONNECTED:
760                 evaluateSpecificReason = EVALUATE_SPECIFIC_REASON_DATA_CONNECTED;
761                 mHandler.post(() -> onDataConnectionConnected(info.getTransportType()));
762                 break;
763             case DataConnectionStatusTracker.EVENT_DATA_CONNECTION_FAILED:
764                 evaluateSpecificReason = EVALUATE_SPECIFIC_REASON_DATA_FAILED;
765                 if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_EIMS) {
766                     // If FWK guided emergency's transport type during data connecting state, notify
767                     // the transport type when the data connection is failed.
768                     notifyCachedTransportTypeForEmergency();
769                     // When cellular is not available, CellularQualityMonitor will stop listening to
770                     // TelephonyCallback. Thresholds for Emergency apn may not be reset as ANE for
771                     // emergency only evaluates while data is connected. CellularQualityMonitor will
772                     // not listen to TelephonyCallback again until the set of threshold values
773                     // changed. Resetting thresholds for emergency after the emergency connection
774                     // disconnects.
775                     unregisterThresholdToQualityMonitor();
776                 } else {
777                     needEvaluate = true;
778                 }
779                 break;
780         }
781 
782         // metrics
783         sendMetricsForDataConnectionChanged(info);
784 
785         if (needEvaluate) {
786             evaluate(evaluateSpecificReason);
787         }
788     }
789 
notifyCachedTransportTypeForEmergency()790     private void notifyCachedTransportTypeForEmergency() {
791         if (mCachedTransportTypeForEmergencyInitialConnect
792                 != AccessNetworkConstants.TRANSPORT_TYPE_INVALID) {
793             enforceNotifyQualifiedNetworksWithTransportType(
794                     mCachedTransportTypeForEmergencyInitialConnect);
795             mCachedTransportTypeForEmergencyInitialConnect =
796                     AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
797         }
798     }
799 
onDataConnectionConnected(int transportType)800     private void onDataConnectionConnected(int transportType) {
801         int otherTransportType;
802         if (DBG) {
803             log("onDataConnectionConnected :" + QnsConstants.transportTypeToString(transportType));
804         }
805         if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_INVALID) {
806             log("Error: onDataConnectionConnected invalid transport type.");
807             return;
808         } else {
809             otherTransportType =
810                     transportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN
811                             ? AccessNetworkConstants.TRANSPORT_TYPE_WWAN
812                             : AccessNetworkConstants.TRANSPORT_TYPE_WLAN;
813         }
814         if (!mRestrictManager.isRestricted(otherTransportType)) {
815             evaluate();
816         } // else case : evaluate() will process when restrictions released.
817     }
818 
onProvisioningInfoChanged(QnsProvisioningListener.QnsProvisioningInfo info)819     protected void onProvisioningInfoChanged(QnsProvisioningListener.QnsProvisioningInfo info) {
820         boolean needBuildAnsp = false;
821         boolean needEvaluate = false;
822 
823         log("onProvisioningInfoChanged info:" + info);
824 
825         if (!info.equalsIntegerItem(
826                 mLastProvisioningInfo, ProvisioningManager.KEY_LTE_THRESHOLD_1)) {
827             log(
828                     "onProvisioningInfoChanged, KEY_LTE_THRESHOLD_1("
829                             + ProvisioningManager.KEY_LTE_THRESHOLD_1
830                             + ") is provisioned to "
831                             + info.getIntegerItem(ProvisioningManager.KEY_LTE_THRESHOLD_1));
832             mConfigManager.setQnsProvisioningInfo(info);
833             needBuildAnsp = true;
834             needEvaluate = true;
835         }
836         if (!info.equalsIntegerItem(
837                 mLastProvisioningInfo, ProvisioningManager.KEY_LTE_THRESHOLD_2)) {
838             log(
839                     "onProvisioningInfoChanged, KEY_LTE_THRESHOLD_2("
840                             + ProvisioningManager.KEY_LTE_THRESHOLD_2
841                             + ") is provisioned to "
842                             + info.getIntegerItem(ProvisioningManager.KEY_LTE_THRESHOLD_2));
843             mConfigManager.setQnsProvisioningInfo(info);
844             needBuildAnsp = true;
845             needEvaluate = true;
846         }
847         if (!info.equalsIntegerItem(
848                 mLastProvisioningInfo, ProvisioningManager.KEY_LTE_THRESHOLD_3)) {
849             log(
850                     "onProvisioningInfoChanged, KEY_LTE_THRESHOLD_3("
851                             + ProvisioningManager.KEY_LTE_THRESHOLD_3
852                             + ") is provisioned to "
853                             + info.getIntegerItem(ProvisioningManager.KEY_LTE_THRESHOLD_3));
854             mConfigManager.setQnsProvisioningInfo(info);
855             needBuildAnsp = true;
856             needEvaluate = true;
857         }
858         if (!info.equalsIntegerItem(
859                 mLastProvisioningInfo, ProvisioningManager.KEY_WIFI_THRESHOLD_A)) {
860             log(
861                     "onProvisioningInfoChanged, KEY_WIFI_THRESHOLD_A("
862                             + ProvisioningManager.KEY_WIFI_THRESHOLD_A
863                             + ") is provisioned to "
864                             + info.getIntegerItem(ProvisioningManager.KEY_WIFI_THRESHOLD_A));
865             mConfigManager.setQnsProvisioningInfo(info);
866             needBuildAnsp = true;
867             needEvaluate = true;
868         }
869         if (!info.equalsIntegerItem(
870                 mLastProvisioningInfo, ProvisioningManager.KEY_WIFI_THRESHOLD_B)) {
871             log(
872                     "onProvisioningInfoChanged, KEY_WIFI_THRESHOLD_B("
873                             + ProvisioningManager.KEY_WIFI_THRESHOLD_B
874                             + ") is provisioned to "
875                             + info.getIntegerItem(ProvisioningManager.KEY_WIFI_THRESHOLD_B));
876             mConfigManager.setQnsProvisioningInfo(info);
877             needBuildAnsp = true;
878             needEvaluate = true;
879         }
880 
881         if (!info.equalsIntegerItem(
882                 mLastProvisioningInfo, ProvisioningManager.KEY_LTE_EPDG_TIMER_SEC)) {
883             log(
884                     "onProvisioningInfoChanged, KEY_LTE_EPDG_TIMER_SEC("
885                             + ProvisioningManager.KEY_LTE_EPDG_TIMER_SEC
886                             + ") is provisioned to "
887                             + info.getIntegerItem(ProvisioningManager.KEY_LTE_EPDG_TIMER_SEC));
888             mConfigManager.setQnsProvisioningInfo(info);
889             needEvaluate = true;
890         }
891         if (!info.equalsIntegerItem(
892                 mLastProvisioningInfo, ProvisioningManager.KEY_WIFI_EPDG_TIMER_SEC)) {
893             log(
894                     "onProvisioningInfoChanged, KEY_WIFI_EPDG_TIMER_SEC("
895                             + ProvisioningManager.KEY_WIFI_EPDG_TIMER_SEC
896                             + ") is provisioned to "
897                             + info.getIntegerItem(ProvisioningManager.KEY_WIFI_EPDG_TIMER_SEC));
898             mConfigManager.setQnsProvisioningInfo(info);
899             needEvaluate = true;
900         }
901 
902         mLastProvisioningInfo = info;
903 
904         if (needBuildAnsp) {
905             buildAccessNetworkSelectionPolicy(true);
906         }
907         if (needEvaluate) {
908             evaluate();
909         }
910 
911         /* TODO to be checked
912         ProvisioningManager.KEY_VOLTE_PROVISIONING_STATUS
913         ProvisioningManager.KEY_VOICE_OVER_WIFI_ENTITLEMENT_ID
914         */
915     }
916 
onImsRegStateChanged(QnsImsManager.ImsRegistrationState imsRegEvent)917     private void onImsRegStateChanged(QnsImsManager.ImsRegistrationState imsRegEvent) {
918         if (mConfigManager.getRatPreference(mNetCapability)
919                 != QnsConstants.RAT_PREFERENCE_WIFI_WHEN_WFC_AVAILABLE) {
920             return;
921         }
922         int transportType = imsRegEvent.getTransportType();
923         int event = imsRegEvent.getEvent();
924         if (event == QnsConstants.IMS_REGISTRATION_CHANGED_REGISTERED
925                 || event == QnsConstants.IMS_REGISTRATION_CHANGED_UNREGISTERED) {
926             log(
927                     "onImsRegStateChanged, "
928                             + QnsConstants.transportTypeToString(transportType)
929                             + ","
930                             + QnsConstants.imsRegistrationEventToString(event));
931             evaluate();
932         }
933     }
934 
onSipDialogSessionStateChanged(boolean isActive)935     protected void onSipDialogSessionStateChanged(boolean isActive) {
936         if (mConfigManager.getSipDialogSessionPolicy()
937                 == QnsConstants.SIP_DIALOG_SESSION_POLICY_NONE) {
938             mSipDialogSessionState = false;
939             return;
940         }
941         if (mSipDialogSessionState != isActive) {
942             mSipDialogSessionState = isActive;
943             log("onSipDialogSessionStateChanged isActive:" + isActive);
944             evaluate();
945         }
946     }
947 
onImsCallDisconnectCauseChanged(ImsReasonInfo imsReasonInfo)948     protected void onImsCallDisconnectCauseChanged(ImsReasonInfo imsReasonInfo) {
949         if (imsReasonInfo == null) {
950             return;
951         }
952         if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS
953                 && imsReasonInfo.getCode() == ImsReasonInfo.CODE_MEDIA_NO_DATA) {
954             log(
955                     "onImsCallDisconnectCauseChanged: iwlanAvailable="
956                             + mIwlanAvailable
957                             + " cellularAvailable="
958                             + mCellularAvailable
959                             + " imsReasonInfo="
960                             + imsReasonInfo);
961             if (mIwlanAvailable && mCellularAvailable) {
962                 // metrics
963                 sendMetricsForImsCallDropStats();
964             }
965         }
966     }
967 
onCellularQualityChanged(Threshold[] ths)968     protected void onCellularQualityChanged(Threshold[] ths) {
969         if (ths == null || ths.length == 0) {
970             log("onCellularQualityChanged: E threshold is null");
971             return;
972         }
973         log("onCellularQualityChanged Threshold:" + Arrays.toString(ths));
974         // TODO
975         evaluate();
976     }
977 
onWiFiQualityChanged(Threshold[] ths)978     protected void onWiFiQualityChanged(Threshold[] ths) {
979         if (ths == null || ths.length == 0) {
980             log("onCellularQualityChanged: E threshold is null");
981             return;
982         }
983         log("onWiFiQualityChanged Threshold:" + Arrays.toString(ths));
984         // TODO
985         evaluate();
986     }
987 
onRttStatusChanged(boolean result)988     private void onRttStatusChanged(boolean result) {
989         log("onRttStatusChanged status: " + result);
990         if (result != mIsRttCheckSuccess) {
991             mIsRttCheckSuccess = result;
992             if (mIsRttCheckSuccess) {
993                 evaluate();
994             }
995         }
996     }
997 
isWfcEnabled()998     protected boolean isWfcEnabled() {
999 
1000         validateWfcSettingsAndUpdate();
1001 
1002         if (mAllowIwlanForWfcActivation) {
1003             return true;
1004         }
1005         if (!mWfcPlatformEnabled) {
1006             log("isWfcPlatformEnabled:false");
1007             return false;
1008         }
1009         if (mCoverage == QnsConstants.COVERAGE_HOME && mSettingWfcEnabled) {
1010             return true;
1011         }
1012         if ((mCoverage == QnsConstants.COVERAGE_ROAM
1013                         || mIwlanNetworkStatusTracker.isInternationalRoaming(mSlotIndex))
1014                 && mSettingWfcRoamingEnabled) {
1015             return true;
1016         }
1017 
1018         if (mConfigManager.allowImsOverIwlanCellularLimitedCase()
1019                 && !isAccessNetworkAllowed(mCellularAccessNetworkType, mNetCapability)
1020                 && mCallType == QnsConstants.CALL_TYPE_IDLE
1021                 && mIwlanAvailable) {
1022             log("isWfcEnabled:true for idle, allow wfc");
1023             return true;
1024         }
1025 
1026         if (mConfigManager.allowVideoOverIWLANWithCellularLimitedCase()
1027                 && mCallType == QnsConstants.CALL_TYPE_VIDEO
1028                 && mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) {
1029             log("isWfcEnabled:true for video");
1030             return true;
1031         }
1032 
1033         return false;
1034     }
1035 
validateWfcSettingsAndUpdate()1036     private void validateWfcSettingsAndUpdate() {
1037         boolean roaming = (mCoverage == QnsConstants.COVERAGE_ROAM);
1038         boolean wfcSetting =
1039                 QnsUtils.isWfcEnabled(mQnsImsManager, mQnsProvisioningListener, roaming);
1040         if (roaming && mSettingWfcRoamingEnabled != wfcSetting) {
1041             log("validateWfcSettingsAndUpdate, found wfc roaming setting mismatch");
1042             if (wfcSetting) {
1043                 mWfcPlatformEnabled = true;
1044                 mSettingWfcRoamingEnabled = true;
1045             } else {
1046                 mWfcPlatformEnabled = QnsUtils.isWfcEnabledByPlatform(mQnsImsManager);
1047                 mSettingWfcRoamingEnabled = false;
1048             }
1049             mSettingWfcRoamingMode = QnsUtils.getWfcMode(mQnsImsManager, true);
1050         } else if (!roaming && mSettingWfcEnabled != wfcSetting) {
1051             log("validateWfcSettingsAndUpdate, found wfc setting mismatch");
1052             if (wfcSetting) {
1053                 mWfcPlatformEnabled = true;
1054                 mSettingWfcEnabled = true;
1055             } else {
1056                 mWfcPlatformEnabled = QnsUtils.isWfcEnabledByPlatform(mQnsImsManager);
1057                 mSettingWfcEnabled = false;
1058             }
1059             mSettingWfcMode = QnsUtils.getWfcMode(mQnsImsManager, false);
1060         }
1061     }
1062 
isAccessNetworkAllowed(int accessNetwork, int netCapability)1063     private boolean isAccessNetworkAllowed(int accessNetwork, int netCapability) {
1064         switch (netCapability) {
1065             case NetworkCapabilities.NET_CAPABILITY_EIMS:
1066             case NetworkCapabilities.NET_CAPABILITY_IMS:
1067             case NetworkCapabilities.NET_CAPABILITY_XCAP:
1068                 return mConfigManager.isAccessNetworkAllowed(accessNetwork, netCapability);
1069             default:
1070                 if (accessNetwork == AccessNetworkType.UNKNOWN) {
1071                     return false;
1072                 }
1073         }
1074         return true;
1075     }
1076 
isAllowed(int transportType)1077     private boolean isAllowed(int transportType) {
1078         StringBuilder sb = new StringBuilder();
1079         sb.append(" evaluate isAllowed for transportType:")
1080                 .append(QnsConstants.transportTypeToString(transportType));
1081 
1082         if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
1083             boolean isWfcEnabled = isWfcEnabled();
1084             sb.append(" isWfcEnabled:").append(isWfcEnabled);
1085             if (!isWfcEnabled) {
1086                 log(sb.toString());
1087                 return false;
1088             }
1089 
1090             if (mQnsEventDispatcher.isAirplaneModeToggleOn()) {
1091                 boolean isWfcAllowInAirplaneMode = mConfigManager.allowWFCOnAirplaneModeOn();
1092                 sb.append(" isWfcAllowInAirplaneMode:").append(isWfcAllowInAirplaneMode);
1093                 if (!isWfcAllowInAirplaneMode) {
1094                     log(sb.toString());
1095                     return false;
1096                 }
1097             }
1098 
1099             if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS
1100                     && (mQnsEventDispatcher.isAirplaneModeToggleOn()
1101                             || !mQnsComponents
1102                                     .getQnsTelephonyListener(mSlotIndex)
1103                                     .getLastQnsTelephonyInfo()
1104                                     .isCellularAvailable())
1105                     && mIwlanNetworkStatusTracker.isInternationalRoaming(mSlotIndex)) {
1106                 boolean isBlockIwlan = mConfigManager.blockIwlanInInternationalRoamWithoutWwan();
1107                 sb.append(" isBlockIwlanInInternationalRoamWithoutWwan:").append(isBlockIwlan);
1108                 if (isBlockIwlan) {
1109                     log(sb.toString());
1110                     return false;
1111                 }
1112             }
1113         }
1114 
1115         if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
1116             if (mQnsEventDispatcher.isAirplaneModeToggleOn()) {
1117                 sb.append(" AirplaneModeOn");
1118                 log(sb.toString());
1119                 return false;
1120             }
1121 
1122             if (getPreferredMode() == QnsConstants.WIFI_ONLY) {
1123                 sb.append(" isWiFiOnly:false");
1124                 log(sb.toString());
1125                 return false;
1126             }
1127         }
1128 
1129         if (mConfigManager.getRatPreference(mNetCapability)
1130                 != QnsConstants.RAT_PREFERENCE_DEFAULT) {
1131             switch (mConfigManager.getRatPreference(mNetCapability)) {
1132                 case QnsConstants.RAT_PREFERENCE_WIFI_ONLY:
1133                     if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
1134                         sb.append(" isAllowRatPrefWiFiOnly:false");
1135                         log(sb.toString());
1136                         return false;
1137                     }
1138                     sb.append(" isAllowRatPrefWiFiOnly:true");
1139                     break;
1140                 case QnsConstants.RAT_PREFERENCE_WIFI_WHEN_WFC_AVAILABLE:
1141                     if ((transportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN
1142                                     && mQnsImsManager.isImsRegistered(
1143                                             AccessNetworkConstants.TRANSPORT_TYPE_WLAN))
1144                             || (transportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN
1145                                     && !mQnsImsManager.isImsRegistered(
1146                                             AccessNetworkConstants.TRANSPORT_TYPE_WLAN))) {
1147                         sb.append(" isAllowRatPrefWfcAvail:false");
1148                         log(sb.toString());
1149                         return false;
1150                     }
1151                     sb.append(" isAllowRatPrefWfcAvail:true");
1152                     break;
1153                 case QnsConstants.RAT_PREFERENCE_WIFI_WHEN_NO_CELLULAR:
1154                     if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN
1155                             && mCellularAvailable) {
1156                         sb.append(" isAllowRatPrefNoCell:false");
1157                         log(sb.toString());
1158                         return false;
1159                     }
1160                     sb.append(" isAllowRatPrefNoCell:true");
1161                     break;
1162                 case QnsConstants.RAT_PREFERENCE_WIFI_WHEN_HOME_IS_NOT_AVAILABLE:
1163                     if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_WWAN
1164                             && (!mCellularAvailable || mCoverage != QnsConstants.COVERAGE_HOME)) {
1165                         sb.append(" isAllowRatPrefNotHome:false");
1166                         log(sb.toString());
1167                         return false;
1168                     }
1169                     sb.append(" isAllowRatPrefNotHome:true");
1170                     break;
1171             }
1172         }
1173 
1174         log(sb.toString());
1175         return true;
1176     }
1177 
evaluateAvailability(int transportType, boolean isAllowedForOtherType)1178     private boolean evaluateAvailability(int transportType, boolean isAllowedForOtherType) {
1179         boolean isAvailable =
1180                 (transportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
1181                         ? mIwlanAvailable
1182                         : mCellularAvailable;
1183         boolean isOtherTypeAvailable =
1184                 isAllowedForOtherType
1185                         && ((transportType != AccessNetworkConstants.TRANSPORT_TYPE_WLAN)
1186                                 ? mIwlanAvailable
1187                                 : mCellularAvailable);
1188         boolean isRestricted = mRestrictManager.isRestricted(transportType);
1189         boolean isAllowedOnSingleTransport =
1190                 mRestrictManager.isAllowedOnSingleTransport(transportType);
1191 
1192         StringBuilder sb = new StringBuilder();
1193         sb.append(" evaluate Available for transportType:")
1194                 .append(QnsConstants.transportTypeToString(transportType));
1195 
1196         sb.append(" isAvailable:").append(isAvailable);
1197         if (!isAvailable) {
1198             log(sb.toString());
1199             return false;
1200         } else if (transportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN
1201                 && mIsCrossWfc
1202                 && !isCrossWfcAllowed(mCellularAvailable)) {
1203             sb.append(" CrossWfc is not allowed. mCellularAvailable:").append(mCellularAvailable);
1204             log(sb.toString());
1205             return false;
1206         }
1207 
1208         if (isRestricted) {
1209             PreCondition cond = getMatchingPreCondition();
1210             if (cond instanceof GuardingPreCondition
1211                     && ((GuardingPreCondition) cond).getGuarding() != QnsConstants.GUARDING_NONE) {
1212                 isRestricted = mRestrictManager.isRestrictedExceptGuarding(transportType);
1213                 sb.append(" isRestrictedExceptGuarding:").append(isRestricted);
1214             } else {
1215                 sb.append(" isRestricted:").append(isRestricted);
1216             }
1217         } else {
1218             sb.append(" isRestricted:").append(isRestricted);
1219         }
1220         if (!isRestricted) {
1221             log(sb.toString());
1222             return true;
1223         }
1224 
1225         sb.append(" hasIgnorableRestriction:").append(isAllowedOnSingleTransport);
1226         if (!isAllowedOnSingleTransport) {
1227             log(sb.toString());
1228             return false;
1229         }
1230 
1231         sb.append(" isOtherTypeAvailable:").append(isOtherTypeAvailable);
1232         log(sb.toString());
1233         return !isOtherTypeAvailable;
1234     }
1235 
evaluate()1236     protected void evaluate() {
1237         evaluate(EVALUATE_SPECIFIC_REASON_NONE);
1238     }
1239 
evaluate(int specificReason)1240     protected synchronized void evaluate(int specificReason) {
1241         if (!mInitialized) {
1242             if (DBG) log("ANE is not initialized yet.");
1243             return;
1244         }
1245         mLastEvaluateSpecificReason = specificReason;
1246         log("evaluate reason:" + evaluateSpecificReasonToString(specificReason));
1247         if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_EIMS) {
1248             if (!mDataConnectionStatusTracker.isActiveState()) {
1249                 log("QNS only handles HO of EMERGENCY data connection");
1250                 return;
1251             }
1252         }
1253 
1254         /* Check handover policy */
1255         if (needHandoverPolicyCheck()) {
1256             if (!moveTransportTypeAllowed()) {
1257                 log("Handover is not allowed. Skip this evaluation.");
1258                 return;
1259             }
1260         }
1261 
1262         /* Check network Availability */
1263         boolean isAllowedForIwlan = isAllowed(AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
1264         boolean isAllowedForCellular = isAllowed(AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
1265         boolean availabilityIwlan =
1266                 isAllowedForIwlan
1267                         && evaluateAvailability(
1268                                 AccessNetworkConstants.TRANSPORT_TYPE_WLAN, isAllowedForCellular);
1269         boolean availabilityCellular =
1270                 isAllowedForCellular
1271                         && evaluateAvailability(
1272                                 AccessNetworkConstants.TRANSPORT_TYPE_WWAN, isAllowedForIwlan);
1273         log(" availability Iwlan:" + availabilityIwlan + " Cellular:" + availabilityCellular);
1274 
1275         if (mWifiBackhaulMonitor.isRttCheckEnabled()
1276                 && mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) {
1277             mWifiBackhaulMonitor.setCellularAvailable(
1278                     availabilityCellular
1279                             && isAccessNetworkAllowed(mCellularAccessNetworkType, mNetCapability));
1280         }
1281         // QualifiedNetworksService checks AccessNetworkSelectionPolicy only in the case both
1282         // networks(cellular and iwlan) are available. If only one network is available, no
1283         // evaluation is run. Available network of accessNetworkType will be reported immediately.
1284         if (availabilityIwlan && availabilityCellular) {
1285             updateAccessNetworkSelectionPolicy();
1286             List<Integer> accessNetworkTypes =
1287                     evaluateAccessNetworkSelectionPolicy(availabilityIwlan, availabilityCellular);
1288             reportSatisfiedAccessNetworkTypesByState(accessNetworkTypes, true);
1289             reevaluateLastNotifiedSecondAccessNetwork();
1290         } else if (availabilityIwlan) {
1291             updateAccessNetworkSelectionPolicy();
1292             if (!mIsCrossWfc && hasWifiThresholdWithoutCellularCondition()) {
1293                 List<Integer> accessNetworkTypes =
1294                         evaluateAccessNetworkSelectionPolicy(
1295                                 availabilityIwlan, availabilityCellular);
1296                 reportSatisfiedAccessNetworkTypesByState(accessNetworkTypes, true);
1297             } else {
1298                 reportSatisfiedAccessNetworkTypesByState(List.of(AccessNetworkType.IWLAN), false);
1299             }
1300         } else if (availabilityCellular) {
1301             reportSatisfiedAccessNetworkTypesByState(
1302                     new ArrayList<>(List.of(mCellularAccessNetworkType)), false);
1303         } else {
1304             // TODO Is it better to report to cellular when there is nothing?
1305             log("evaluate nothing without an available network.");
1306             if (specificReason == EVALUATE_SPECIFIC_REASON_IWLAN_DISABLE) {
1307                 reportQualifiedNetwork(getInitialAccessNetworkTypes());
1308             }
1309         }
1310     }
1311 
1312     @VisibleForTesting
vopsCheckRequired(int cellularAccessNetworkType, int coverage, int callType)1313     boolean vopsCheckRequired(int cellularAccessNetworkType, int coverage, int callType) {
1314         boolean checkVoPs = false;
1315         if (mConfigManager.isMmtelCapabilityRequired(coverage)
1316                 && (cellularAccessNetworkType == AccessNetworkType.EUTRAN
1317                         || cellularAccessNetworkType == AccessNetworkType.NGRAN)) {
1318             if (mDataConnectionStatusTracker.isInactiveState()) {
1319                 checkVoPs = true;
1320             } else if (mDataConnectionStatusTracker.getLastTransportType()
1321                     == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
1322                 if (callType == QnsConstants.CALL_TYPE_IDLE
1323                         || !mConfigManager.isInCallHoDecisionWlanToWwanWithoutVopsCondition()) {
1324                     checkVoPs = true;
1325                 }
1326             } else if (mDataConnectionStatusTracker.getLastTransportType()
1327                     == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
1328                 // If there is an on-going call and UE is moving into an area which does not support
1329                 // VoPS, don't consider VoPS condition and let AccessNetworkEvaluator decide a
1330                 // preferred RAT.
1331                 if (callType == QnsConstants.CALL_TYPE_IDLE) {
1332                     checkVoPs = true;
1333                 }
1334             }
1335         }
1336         return checkVoPs;
1337     }
1338 
hasWifiThresholdWithoutCellularCondition()1339     private boolean hasWifiThresholdWithoutCellularCondition() {
1340         if (mAccessNetworkSelectionPolicies == null || mAccessNetworkSelectionPolicies.isEmpty()) {
1341             return false;
1342         }
1343         for (AccessNetworkSelectionPolicy policy : mAccessNetworkSelectionPolicies) {
1344             if (policy.hasWifiThresholdWithoutCellularCondition()) {
1345                 return true;
1346             }
1347         }
1348         return false;
1349     }
1350 
reportSatisfiedAccessNetworkTypesByState( List<Integer> satisfiedAccessNetworkTypes, boolean needMonitor)1351     protected synchronized void reportSatisfiedAccessNetworkTypesByState(
1352             List<Integer> satisfiedAccessNetworkTypes, boolean needMonitor) {
1353         if (needMonitor) {
1354             if (mDataConnectionStatusTracker.isInactiveState()) {
1355                 if (satisfiedAccessNetworkTypes.size() > 0) {
1356                     reportQualifiedNetwork(satisfiedAccessNetworkTypes);
1357                     updateAccessNetworkSelectionPolicy();
1358                 }
1359                 updateQualityMonitor();
1360             } else if (!mDataConnectionStatusTracker.isConnectionInProgress()) {
1361                 if (isHandoverNeeded(satisfiedAccessNetworkTypes)) {
1362                     reportQualifiedNetwork(satisfiedAccessNetworkTypes);
1363                     unregisterThresholdToQualityMonitor();
1364                 } else if (isFallbackCase(satisfiedAccessNetworkTypes)) {
1365                     reportQualifiedNetwork(satisfiedAccessNetworkTypes);
1366                     updateAccessNetworkSelectionPolicy();
1367                     updateQualityMonitor();
1368                 } else {
1369                     updateQualityMonitor();
1370                 }
1371             }
1372         } else {
1373             if (mDataConnectionStatusTracker.isInactiveState()) {
1374                 reportQualifiedNetwork(satisfiedAccessNetworkTypes);
1375             } else if (!mDataConnectionStatusTracker.isConnectionInProgress()) {
1376                 if (isHandoverNeeded(satisfiedAccessNetworkTypes)) {
1377                     reportQualifiedNetwork(satisfiedAccessNetworkTypes);
1378                 } else if (isFallbackCase(satisfiedAccessNetworkTypes)) {
1379                     reportQualifiedNetwork(satisfiedAccessNetworkTypes);
1380                 }
1381             }
1382             unregisterThresholdToQualityMonitor();
1383         }
1384     }
1385 
getTargetTransportType(List<Integer> accessNetworkTypes)1386     protected int getTargetTransportType(List<Integer> accessNetworkTypes) {
1387         if (accessNetworkTypes == null || accessNetworkTypes.size() == 0) {
1388             return AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
1389         }
1390         if (accessNetworkTypes.get(0) == AccessNetworkType.IWLAN) {
1391             return AccessNetworkConstants.TRANSPORT_TYPE_WLAN;
1392         }
1393         return AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
1394     }
1395 
1396     @VisibleForTesting
needHandoverPolicyCheck()1397     boolean needHandoverPolicyCheck() {
1398         if (mDataConnectionStatusTracker.isActiveState()) {
1399             int srcTransportType = mDataConnectionStatusTracker.getLastTransportType();
1400             boolean targetNetworkAvailable =
1401                     srcTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN
1402                             ? mCellularAvailable
1403                             : mIwlanAvailable;
1404             if (srcTransportType == getLastQualifiedTransportType() && targetNetworkAvailable) {
1405                 log("Need to check handover policy for this evaluation.");
1406                 return true;
1407             }
1408         }
1409         log("No need to check handover policy for this evaluation.");
1410         return false;
1411     }
1412 
1413     @VisibleForTesting
moveTransportTypeAllowed()1414     boolean moveTransportTypeAllowed() {
1415         int srcAccessNetwork =
1416                 mDataConnectionStatusTracker.getLastTransportType()
1417                                 == AccessNetworkConstants.TRANSPORT_TYPE_WLAN
1418                         ? AccessNetworkType.IWLAN
1419                         : mLatestAvailableCellularAccessNetwork;
1420         int dstAccessNetwork =
1421                 srcAccessNetwork == AccessNetworkType.IWLAN
1422                         ? mCellularAccessNetworkType
1423                         : AccessNetworkType.IWLAN;
1424         if (mConfigManager.isHandoverAllowedByPolicy(
1425                 mNetCapability, srcAccessNetwork, dstAccessNetwork, mCoverage)) {
1426             return true;
1427         } else {
1428             if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS
1429                     && mCallStatusTracker.isCallIdle(NetworkCapabilities.NET_CAPABILITY_IMS)) {
1430                 // Telephony will make new connection with preferred AccessNetwork
1431                 log("handover is not allowed. but need to move to target Transport.");
1432                 return true;
1433             }
1434             if (dstAccessNetwork == AccessNetworkType.IWLAN && useDifferentApnOverIwlan()) {
1435                 // Telephony will make new connection when change transport type
1436                 log(
1437                         "handover is not allowed. but need to move to target Transport using"
1438                                 + " different apn over IWLAN.");
1439                 return true;
1440             }
1441             if (dstAccessNetwork != AccessNetworkType.IWLAN
1442                     && mCellularAvailable
1443                     && mConfigManager.getRatPreference(mNetCapability)
1444                             == QnsConstants.RAT_PREFERENCE_WIFI_WHEN_NO_CELLULAR) {
1445                 // Telephony will make new connection when change transport type
1446                 log(
1447                         "handover is not allowed. but need to move to target Transport for the"
1448                                 + " RAT_PREFERENCE_WIFI_WHEN_NO_CELLULAR.");
1449                 return true;
1450             }
1451         }
1452         return false;
1453     }
1454 
useDifferentApnOverIwlan()1455     private boolean useDifferentApnOverIwlan() {
1456         // supports MMS, XCAP and CBS
1457         if (mNetCapability != NetworkCapabilities.NET_CAPABILITY_MMS
1458                 && mNetCapability != NetworkCapabilities.NET_CAPABILITY_XCAP
1459                 && mNetCapability != NetworkCapabilities.NET_CAPABILITY_CBS) {
1460             return false;
1461         }
1462 
1463         ApnSetting apnSetting =
1464                 mDataConnectionStatusTracker.getLastApnSetting(
1465                         AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
1466         if (apnSetting != null
1467                 && (apnSetting.getApnTypeBitmask() & ApnSetting.TYPE_DEFAULT) != 0
1468                 && (apnSetting.getNetworkTypeBitmask()
1469                                 & (1 << (TelephonyManager.NETWORK_TYPE_IWLAN - 1)))
1470                         == 0) {
1471             log("useDifferentApnOverIwlan true");
1472             return true;
1473         }
1474         log("useDifferentApnOverIwlan false");
1475         return false;
1476     }
1477 
isHandoverNeeded(List<Integer> accessNetworkTypes)1478     protected boolean isHandoverNeeded(List<Integer> accessNetworkTypes) {
1479         if (mDataConnectionStatusTracker.isInactiveState()
1480                 || mDataConnectionStatusTracker.isHandoverState()) {
1481             return false;
1482         }
1483 
1484         int targetTransportType = getTargetTransportType(accessNetworkTypes);
1485         if (targetTransportType == AccessNetworkConstants.TRANSPORT_TYPE_INVALID) {
1486             return false;
1487         }
1488 
1489         // Handover case
1490         int sourceTransportType = mDataConnectionStatusTracker.getLastTransportType();
1491         return sourceTransportType != targetTransportType;
1492     }
1493 
isFallbackCase(List<Integer> accessNetworkTypes)1494     protected boolean isFallbackCase(List<Integer> accessNetworkTypes) {
1495         if (mDataConnectionStatusTracker.isInactiveState()) {
1496             return false;
1497         }
1498 
1499         int targetTransportType = getTargetTransportType(accessNetworkTypes);
1500         if (targetTransportType == AccessNetworkConstants.TRANSPORT_TYPE_INVALID) {
1501             return false;
1502         }
1503         if (targetTransportType != mDataConnectionStatusTracker.getLastTransportType()) {
1504             return false;
1505         }
1506 
1507         if (getLastQualifiedTransportType() == targetTransportType) {
1508             return false;
1509         }
1510 
1511         log("isFallbackcase:true");
1512         return true;
1513     }
1514 
reportQualifiedNetwork(List<Integer> accessNetworkTypes)1515     protected void reportQualifiedNetwork(List<Integer> accessNetworkTypes) {
1516         if (accessNetworkTypes.contains(AccessNetworkType.UNKNOWN)) {
1517             log(
1518                     "reportQualifiedNetwork, remove UNKNOWN access network."
1519                             + QnsUtils.getStringAccessNetworkTypes(accessNetworkTypes));
1520             accessNetworkTypes.remove(AccessNetworkType.UNKNOWN);
1521         }
1522         List<Integer> supportAccessNetworkTypes = new ArrayList<>();
1523         if (mConfigManager.allowImsOverIwlanCellularLimitedCase()) {
1524             for (Integer accessNetwork : accessNetworkTypes) {
1525                 if (accessNetwork == AccessNetworkType.IWLAN
1526                         || isAccessNetworkAllowed(accessNetwork, mNetCapability)) {
1527                     supportAccessNetworkTypes.add(accessNetwork);
1528                 }
1529             }
1530             if (!accessNetworkTypes.isEmpty() && supportAccessNetworkTypes.isEmpty()) {
1531                 log("supportAccessNetworkTypes is empty");
1532                 return;
1533             }
1534         } else {
1535             supportAccessNetworkTypes.addAll(accessNetworkTypes);
1536         }
1537 
1538         log(
1539                 "reportQualifiedNetwork supportAccessNetworkTypes:"
1540                         + QnsUtils.getStringAccessNetworkTypes(supportAccessNetworkTypes));
1541 
1542         if (equalsLastNotifiedQualifiedNetwork(supportAccessNetworkTypes)) {
1543             return;
1544         } else {
1545             if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS
1546                     && mWifiBackhaulMonitor.isRttCheckEnabled()) {
1547                 if (supportAccessNetworkTypes.contains(AccessNetworkType.IWLAN)) {
1548                     if (!isRttSuccess()) {
1549                         mWifiBackhaulMonitor.requestRttCheck();
1550                         return;
1551                     }
1552                 } else {
1553                     mIsRttCheckSuccess = false;
1554                 }
1555             }
1556         }
1557 
1558         updateLastNotifiedQualifiedNetwork(supportAccessNetworkTypes);
1559         notifyForQualifiedNetworksChanged(supportAccessNetworkTypes);
1560     }
1561 
findUnmatchedThresholds()1562     private List<Threshold> findUnmatchedThresholds() {
1563         List<Threshold> unmatchedThresholds = new ArrayList<>();
1564         if (mAccessNetworkSelectionPolicies == null
1565                 || mAccessNetworkSelectionPolicies.size() == 0) {
1566             return unmatchedThresholds;
1567         }
1568 
1569         List<Integer> excludeThresholdGroup = new ArrayList<>();
1570         boolean bIwlanRegistrable = isIwlanAvailableWithoutRestrict();
1571         boolean bCellularRegistrable = isCellularAvailableWithoutRestrict();
1572         for (AccessNetworkSelectionPolicy policy : mAccessNetworkSelectionPolicies) {
1573             List<Threshold> policyUnmatchedThresholds =
1574                     policy.findUnmatchedThresholds(mWifiQualityMonitor, mCellularQualityMonitor);
1575             if (policyUnmatchedThresholds == null || policyUnmatchedThresholds.size() == 0) {
1576                 continue;
1577             }
1578             for (Threshold threshold : policyUnmatchedThresholds) {
1579                 if (bIwlanRegistrable && threshold.getAccessNetwork() == AccessNetworkType.IWLAN) {
1580                     unmatchedThresholds.add(threshold);
1581                 }
1582                 if (bCellularRegistrable
1583                         && threshold.getAccessNetwork() != AccessNetworkType.IWLAN) {
1584                     if (threshold.getAccessNetwork() == mCellularAccessNetworkType) {
1585                         unmatchedThresholds.add(threshold);
1586                     } else if (threshold.getGroupId() >= 0) {
1587                         // If the current cellular access network and the access network of
1588                         // cellular threshold are different, it is not necessary to monitor the
1589                         // entire threshold of this group.
1590                         excludeThresholdGroup.add(threshold.getGroupId());
1591                     }
1592                 }
1593             }
1594         }
1595         for (int excludeGid : excludeThresholdGroup) {
1596             unmatchedThresholds.removeIf(threshold -> threshold.getGroupId() == excludeGid);
1597         }
1598         return unmatchedThresholds;
1599     }
1600 
updateQualityMonitor()1601     private void updateQualityMonitor() {
1602         List<Threshold> unmatchedThresholds = findUnmatchedThresholds();
1603         if (unmatchedThresholds.size() == 0) {
1604             log("updateQualityMonitor empty unmatchedThresholds.");
1605             unregisterThresholdToQualityMonitor();
1606             return;
1607         }
1608 
1609         log("updateQualityMonitor");
1610 
1611         LinkedHashSet<Integer> unmatchedGroupIdSet = new LinkedHashSet<>();
1612         HashMap<Integer, Integer> unmatchedMonitorTypeMap = new HashMap<>();
1613         LinkedHashSet<Integer> unmatchedMonitorTypeSet = new LinkedHashSet<>();
1614         for (Threshold th : unmatchedThresholds) {
1615             if (th.getGroupId() < 0) {
1616                 continue;
1617             }
1618             unmatchedGroupIdSet.add(th.getGroupId());
1619             int key = th.getAccessNetwork() << 16 | th.getMeasurementType();
1620             unmatchedMonitorTypeMap.put(key, unmatchedMonitorTypeMap.getOrDefault(key, 0) + 1);
1621         }
1622 
1623         List<Map.Entry<Integer, Integer>> list_entries =
1624                 new ArrayList<>(unmatchedMonitorTypeMap.entrySet());
1625         list_entries.sort(Entry.comparingByValue());
1626         for (Entry<Integer, Integer> entry : list_entries) {
1627             unmatchedMonitorTypeSet.add(entry.getKey());
1628         }
1629 
1630         LinkedHashSet<Integer> reducedGroupIdSet = new LinkedHashSet<>();
1631         for (int type : unmatchedMonitorTypeSet) {
1632             reducedGroupIdSet.clear();
1633             boolean skipReduce = false;
1634             for (Threshold th : unmatchedThresholds) {
1635                 if (type == (th.getAccessNetwork() << 16 | th.getMeasurementType())) {
1636                     if (th.getGroupId() < 0) {
1637                         skipReduce = true;
1638                         break;
1639                     }
1640                 } else {
1641                     reducedGroupIdSet.add(th.getGroupId());
1642                 }
1643             }
1644             if (skipReduce) {
1645                 continue;
1646             }
1647 
1648             if (reducedGroupIdSet.containsAll(unmatchedGroupIdSet)) {
1649                 unmatchedThresholds.removeIf(
1650                         threshold ->
1651                                 type
1652                                         == (threshold.getAccessNetwork() << 16
1653                                                 | threshold.getMeasurementType()));
1654             }
1655         }
1656 
1657         registerThresholdsToQualityMonitor(unmatchedThresholds);
1658     }
1659 
unregisterThresholdToQualityMonitor()1660     private void unregisterThresholdToQualityMonitor() {
1661         mWifiQualityMonitor.updateThresholdsForNetCapability(mNetCapability, mSlotIndex, null);
1662         mCellularQualityMonitor.updateThresholdsForNetCapability(mNetCapability, mSlotIndex, null);
1663     }
1664 
registerThresholdsToQualityMonitor(List<Threshold> thresholds)1665     private void registerThresholdsToQualityMonitor(List<Threshold> thresholds) {
1666         if (thresholds == null) {
1667             thresholds = new ArrayList<>();
1668         }
1669 
1670         List<Threshold> monitorWiFiThresholds = new ArrayList<>();
1671         List<Threshold> monitorCellThresholds = new ArrayList<>();
1672         for (Threshold th : thresholds) {
1673             if (th.getAccessNetwork() == AccessNetworkType.IWLAN) {
1674                 monitorWiFiThresholds.add(th);
1675             } else {
1676                 monitorCellThresholds.add(th);
1677             }
1678         }
1679 
1680         for (Threshold th : monitorWiFiThresholds) {
1681             log("  monitorWiFiThresholds th:" + th.toShortString());
1682         }
1683         for (Threshold th : monitorCellThresholds) {
1684             log("  monitorCellThresholds th:" + th.toShortString());
1685         }
1686 
1687         // refresh threshold to be monitored.
1688         mWifiQualityMonitor.updateThresholdsForNetCapability(
1689                 mNetCapability, mSlotIndex, monitorWiFiThresholds.toArray(new Threshold[0]));
1690         mCellularQualityMonitor.updateThresholdsForNetCapability(
1691                 mNetCapability, mSlotIndex, monitorCellThresholds.toArray(new Threshold[0]));
1692     }
1693 
updateThrottleStatus( boolean isThrottle, long throttleTimeMillis, int transportType)1694     protected void updateThrottleStatus(
1695             boolean isThrottle, long throttleTimeMillis, int transportType) {
1696         mRestrictManager.notifyThrottling(isThrottle, throttleTimeMillis, transportType);
1697     }
1698 
getPreferredMode()1699     protected int getPreferredMode() {
1700         if (mAllowIwlanForWfcActivation) {
1701             return QnsConstants.WIFI_PREF;
1702         }
1703         if (mCoverage == QnsConstants.COVERAGE_ROAM) {
1704             return mSettingWfcRoamingMode;
1705         }
1706         return mSettingWfcMode;
1707     }
1708 
getPreferredAccessNetwork()1709     private int getPreferredAccessNetwork() {
1710         switch (getPreferredMode()) {
1711             case QnsConstants.CELL_PREF:
1712                 return mCellularAccessNetworkType;
1713             case QnsConstants.WIFI_PREF:
1714             case QnsConstants.WIFI_ONLY:
1715                 return AccessNetworkType.IWLAN;
1716         }
1717         return mCellularAccessNetworkType;
1718     }
1719 
isRttSuccess()1720     private boolean isRttSuccess() {
1721         return !isAccessNetworkAllowed(
1722                         mCellularAccessNetworkType, NetworkCapabilities.NET_CAPABILITY_IMS)
1723                 || mIsRttCheckSuccess;
1724     }
1725 
evaluateAccessNetworkSelectionPolicy( boolean availabilityIwlan, boolean availabilityCellular)1726     private List<Integer> evaluateAccessNetworkSelectionPolicy(
1727             boolean availabilityIwlan, boolean availabilityCellular) {
1728         log("evaluateAccessNetworkSelectionPolicy");
1729 
1730         if (mAccessNetworkSelectionPolicies == null || mAccessNetworkSelectionPolicies.isEmpty()) {
1731             return new ArrayList<>();
1732         }
1733         List<Integer> accessNetworkTypes = new ArrayList<>();
1734         for (AccessNetworkSelectionPolicy policy : mAccessNetworkSelectionPolicies) {
1735             if (policy.satisfiedByThreshold(
1736                     mWifiQualityMonitor,
1737                     mCellularQualityMonitor,
1738                     availabilityIwlan,
1739                     availabilityCellular,
1740                     mCellularAccessNetworkType)) {
1741                 log(
1742                         "  satisfiedByThreshold TargetTransportType:"
1743                                 + QnsConstants.transportTypeToString(
1744                                         policy.getTargetTransportType()));
1745                 if (policy.getTargetTransportType() == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
1746                     if (!accessNetworkTypes.contains(AccessNetworkType.IWLAN)) {
1747                         accessNetworkTypes.add(AccessNetworkType.IWLAN);
1748                     }
1749 
1750                 } else {
1751                     if (!accessNetworkTypes.contains(mCellularAccessNetworkType)) {
1752                         if (availabilityCellular) {
1753                             accessNetworkTypes.add(mCellularAccessNetworkType);
1754                         } else {
1755                             accessNetworkTypes.add(AccessNetworkType.UNKNOWN);
1756                         }
1757                     }
1758                     if ((mCallType == QnsConstants.CALL_TYPE_VOICE
1759                                     || mCallType == QnsConstants.CALL_TYPE_EMERGENCY)
1760                             && policy.satisfiedWithWifiLowSignalStrength()) {
1761                         int reason = mConfigManager.getQnsIwlanHoRestrictReason();
1762                         if (reason == QnsConstants.FALLBACK_REASON_RTP_OR_WIFI
1763                                 || reason == QnsConstants.FALLBACK_REASON_WIFI_ONLY) {
1764                             log("WWAN decision with Wi-Fi low signalStrength in Voice call");
1765                             mRestrictManager.increaseCounterToRestrictIwlanInCall();
1766                         }
1767                     }
1768                 }
1769             }
1770         }
1771 
1772         // If the evaluator has not yet reported a Qualified Networks, report preferred.
1773         if (!isNotifiedQualifiedAccessNetworkTypes()) {
1774             if (accessNetworkTypes.size() == 0) {
1775                 accessNetworkTypes.add(getPreferredAccessNetwork());
1776                 log(
1777                         "  no candidate access network, use preferred:"
1778                                 + QnsUtils.getStringAccessNetworkTypes(accessNetworkTypes));
1779             } else if (accessNetworkTypes.size() > 1) {
1780                 accessNetworkTypes.remove(Integer.valueOf(getPreferredAccessNetwork()));
1781                 accessNetworkTypes.add(0, getPreferredAccessNetwork());
1782                 log(
1783                         "  two more candidate access network, use preferred:"
1784                                 + QnsUtils.getStringAccessNetworkTypes(accessNetworkTypes));
1785             }
1786         }
1787 
1788         // TODO. need to be improved handling the second access network
1789         // Add a second access network, if the preferred access network does not exist in list.
1790         if (availabilityIwlan
1791                 && availabilityCellular
1792                 && mConfigManager.isOverrideImsPreferenceSupported()) {
1793             if (!accessNetworkTypes.isEmpty()
1794                     && accessNetworkTypes.get(0) != AccessNetworkType.IWLAN
1795                     && getPreferredMode() == QnsConstants.CELL_PREF
1796                     && isAccessNetworkAllowed(accessNetworkTypes.get(0), mNetCapability)) {
1797                 if (!accessNetworkTypes.contains(AccessNetworkType.IWLAN)) {
1798                     accessNetworkTypes.add(AccessNetworkType.IWLAN);
1799                     log(
1800                             "  add a second accessNetworkTypes : "
1801                                     + QnsUtils.getStringAccessNetworkTypes(accessNetworkTypes));
1802                 }
1803             } else if (accessNetworkTypes.isEmpty()
1804                     && !mLastQualifiedAccessNetworkTypes.isEmpty()
1805                     && mLastQualifiedAccessNetworkTypes.get(0) != AccessNetworkType.IWLAN
1806                     && getPreferredMode() == QnsConstants.CELL_PREF
1807                     && isAccessNetworkAllowed(
1808                             mLastQualifiedAccessNetworkTypes.get(0), mNetCapability)) {
1809                 if (!mLastQualifiedAccessNetworkTypes.contains(AccessNetworkType.IWLAN)) {
1810                     accessNetworkTypes.addAll(mLastQualifiedAccessNetworkTypes);
1811                     accessNetworkTypes.add(AccessNetworkType.IWLAN);
1812                     log(
1813                             "  add a second accessNetworkTypes in existing "
1814                                     + "mLastQualifiedAccessNetworkTypes : "
1815                                     + QnsUtils.getStringAccessNetworkTypes(accessNetworkTypes));
1816                 }
1817             }
1818         }
1819 
1820         log("  accessNetworkTypes:" + QnsUtils.getStringAccessNetworkTypes(accessNetworkTypes));
1821         return accessNetworkTypes;
1822     }
1823 
1824     // TODO. need to be improved handling the second access network
1825     // A qualified conditions are required for the second access network.
1826     // What threshold conditions are qualified for the second access network? (like rove in)
1827     // What are the threshold conditions for exiting the second access network? (like a rove out)
reevaluateLastNotifiedSecondAccessNetwork()1828     private void reevaluateLastNotifiedSecondAccessNetwork() {
1829         if (mConfigManager.isOverrideImsPreferenceSupported()
1830                 && mLastQualifiedAccessNetworkTypes.size() > 1
1831                 && mLastQualifiedAccessNetworkTypes.get(1) == AccessNetworkType.IWLAN) {
1832             if (!isAccessNetworkAllowed(mCellularAccessNetworkType, mNetCapability)
1833                     || getPreferredMode() != QnsConstants.CELL_PREF) {
1834                 log("reevaluateLastNotifiedSecondAccessNetwork, Removed a second access network");
1835                 reportQualifiedNetwork(
1836                         new ArrayList<>(List.of(mLastQualifiedAccessNetworkTypes.get(0))));
1837             }
1838         }
1839     }
1840 
buildAccessNetworkSelectionPolicy( boolean bForceUpdate)1841     private Map<PreCondition, List<AccessNetworkSelectionPolicy>> buildAccessNetworkSelectionPolicy(
1842             boolean bForceUpdate) {
1843         if (mAnspPolicyMap == null || bForceUpdate) {
1844             log("Building list of AccessNetworkSelectionPolicy.");
1845             mAnspPolicyMap =
1846                     AccessNetworkSelectionPolicyBuilder.build(mConfigManager, mNetCapability);
1847 
1848             if (DBG) {
1849                 mAnspPolicyMap
1850                         .values()
1851                         .forEach(
1852                                 list ->
1853                                         list.stream()
1854                                                 .map(policy -> " retriMap ANSP=" + policy)
1855                                                 .forEach(this::log));
1856             }
1857         }
1858         return mAnspPolicyMap;
1859     }
1860 
updateAccessNetworkSelectionPolicy()1861     private void updateAccessNetworkSelectionPolicy() {
1862         Map<PreCondition, List<AccessNetworkSelectionPolicy>> map =
1863                 buildAccessNetworkSelectionPolicy(false);
1864         if (map == null) {
1865             map = new HashMap<>();
1866         }
1867 
1868         log("Create a list of AccessNetworkSelectionPolicy that match the preconditions.");
1869 
1870         PreCondition preCondition = getMatchingPreCondition();
1871         List<AccessNetworkSelectionPolicy> matchedPolicies = new ArrayList<>();
1872         List<AccessNetworkSelectionPolicy> list = map.get(preCondition);
1873         if (list != null) {
1874             for (AccessNetworkSelectionPolicy policy : list) {
1875                 if (policy.satisfyPrecondition(preCondition)
1876                         && !mDataConnectionStatusTracker.isConnectionInProgress()
1877                         && (!isNotifiedQualifiedAccessNetworkTypes()
1878                                 || getLastQualifiedTransportType()
1879                                         != policy.getTargetTransportType())) {
1880                     matchedPolicies.add(policy);
1881                 }
1882             }
1883         }
1884 
1885         if (mAccessNetworkSelectionPolicies.equals(matchedPolicies)) {
1886             for (AccessNetworkSelectionPolicy policy : matchedPolicies) {
1887                 log("  Matched ANSP=" + policy);
1888             }
1889         }
1890 
1891         for (AccessNetworkSelectionPolicy policy : matchedPolicies) {
1892             log("  Found new ANSP=" + policy);
1893         }
1894 
1895         mAccessNetworkSelectionPolicies = matchedPolicies;
1896     }
1897 
getMatchingPreCondition()1898     private PreCondition getMatchingPreCondition() {
1899         int callType = mCallType;
1900         if ((mNetCapability == NetworkCapabilities.NET_CAPABILITY_EIMS
1901                         || mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS)
1902                 && mCallType == QnsConstants.CALL_TYPE_EMERGENCY) {
1903             callType = QnsConstants.CALL_TYPE_VOICE;
1904         }
1905         int sipDialogPolicy = mConfigManager.getSipDialogSessionPolicy();
1906         if (callType == QnsConstants.CALL_TYPE_IDLE && mSipDialogSessionState) {
1907             if (sipDialogPolicy > QnsConstants.SIP_DIALOG_SESSION_POLICY_NONE) {
1908                 log("apply sipDialogPolicy:"
1909                         + QnsConstants.qnsSipDialogSessionPolicyToString(sipDialogPolicy));
1910             }
1911             switch (sipDialogPolicy) {
1912                 case QnsConstants.SIP_DIALOG_SESSION_POLICY_FOLLOW_VOICE_CALL:
1913                     callType = QnsConstants.CALL_TYPE_VOICE;
1914                     break;
1915                 case QnsConstants.SIP_DIALOG_SESSION_POLICY_FOLLOW_VIDEO_CALL:
1916                     callType = QnsConstants.CALL_TYPE_VIDEO;
1917                     break;
1918                 case QnsConstants.SIP_DIALOG_SESSION_POLICY_NONE:
1919                     // fall-through
1920                 default:
1921                     // do-nothing
1922                     break;
1923             }
1924         }
1925 
1926         if (mConfigManager.hasThresholdGapWithGuardTimer()) {
1927             @QnsConstants.QnsGuarding int guarding = QnsConstants.GUARDING_NONE;
1928             int source = getLastQualifiedTransportType();
1929             if (source != AccessNetworkConstants.TRANSPORT_TYPE_WLAN
1930                     && mRestrictManager.hasRestrictionType(
1931                             AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
1932                             RestrictManager.RESTRICT_TYPE_GUARDING)) {
1933                 guarding = QnsConstants.GUARDING_WIFI;
1934             } else if (source != AccessNetworkConstants.TRANSPORT_TYPE_WWAN
1935                     && mRestrictManager.hasRestrictionType(
1936                             AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
1937                             RestrictManager.RESTRICT_TYPE_GUARDING)) {
1938                 guarding = QnsConstants.GUARDING_CELLULAR;
1939             }
1940             return new GuardingPreCondition(callType, getPreferredMode(), mCoverage, guarding);
1941         }
1942         return new PreCondition(callType, getPreferredMode(), mCoverage);
1943     }
1944 
evaluateSpecificReasonToString(int specificReason)1945     private String evaluateSpecificReasonToString(int specificReason) {
1946         if (specificReason == EVALUATE_SPECIFIC_REASON_NONE) {
1947             return "EVALUATE_SPECIFIC_REASON_NONE";
1948         } else if (specificReason == EVALUATE_SPECIFIC_REASON_IWLAN_DISABLE) {
1949             return "EVALUATE_SPECIFIC_REASON_IWLAN_DISABLE";
1950         } else if (specificReason == EVALUATE_SPECIFIC_REASON_DATA_DISCONNECTED) {
1951             return "EVALUATE_SPECIFIC_REASON_DATA_DISCONNECTED";
1952         } else if (specificReason == EVALUATE_SPECIFIC_REASON_DATA_FAILED) {
1953             return "EVALUATE_SPECIFIC_REASON_DATA_FAILED";
1954         } else if (specificReason == EVALUATE_SPECIFIC_REASON_DATA_CONNECTED) {
1955             return "EVALUATE_SPECIFIC_REASON_DATA_CONNECTED";
1956         }
1957         return "UNKNOWN";
1958     }
1959 
isCrossWfcAllowed(boolean cellularAvailable)1960     private boolean isCrossWfcAllowed(boolean cellularAvailable) {
1961         if (mConfigManager.getRatPreference(mNetCapability)
1962                 == QnsConstants.RAT_PREFERENCE_WIFI_WHEN_WFC_AVAILABLE) {
1963             // Should follow RAT_PREFERENCE_WIFI_WHEN_WFC_AVAILABLE and do not block CST when IMS
1964             // connected to CST
1965             return true;
1966         }
1967         return !cellularAvailable;
1968     }
1969 
1970     private class EvaluatorEventHandler extends Handler {
EvaluatorEventHandler(Looper l)1971         EvaluatorEventHandler(Looper l) {
1972             super(l);
1973         }
1974 
1975         @Override
handleMessage(Message message)1976         public void handleMessage(Message message) {
1977             log("handleMessage msg=" + message.what);
1978             QnsAsyncResult ar = (QnsAsyncResult) message.obj;
1979             switch (message.what) {
1980                 case EVENT_IWLAN_NETWORK_STATUS_CHANGED:
1981                     onIwlanNetworkStatusChanged((IwlanAvailabilityInfo) ar.mResult);
1982                     break;
1983                 case EVENT_QNS_TELEPHONY_INFO_CHANGED:
1984                     onQnsTelephonyInfoChanged((QnsTelephonyListener.QnsTelephonyInfo) ar.mResult);
1985                     break;
1986                 case EVENT_RESTRICT_INFO_CHANGED:
1987                     onRestrictInfoChanged();
1988                     break;
1989                 case EVENT_SET_CALL_TYPE:
1990                     onSetCallType((int) ar.mResult);
1991                     break;
1992                 case EVENT_DATA_CONNECTION_STATE_CHANGED:
1993                     onDataConnectionStateChanged(
1994                             (DataConnectionStatusTracker.DataConnectionChangedInfo) ar.mResult);
1995                     break;
1996                 case EVENT_PROVISIONING_INFO_CHANGED:
1997                     onProvisioningInfoChanged(
1998                             (QnsProvisioningListener.QnsProvisioningInfo) ar.mResult);
1999                     break;
2000                 case EVENT_IMS_REGISTRATION_STATE_CHANGED:
2001                     onImsRegStateChanged((QnsImsManager.ImsRegistrationState) ar.mResult);
2002                     break;
2003                 case EVENT_SIP_DIALOG_SESSION_STATE_CHANGED:
2004                     onSipDialogSessionStateChanged((boolean) ar.mResult);
2005                     break;
2006                 case EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED:
2007                     onImsCallDisconnectCauseChanged((ImsReasonInfo) ar.mResult);
2008                     break;
2009                 case QnsEventDispatcher.QNS_EVENT_WFC_ENABLED:
2010                     onWfcEnabledChanged(true, false);
2011                     break;
2012                 case QnsEventDispatcher.QNS_EVENT_WFC_DISABLED:
2013                     onWfcEnabledChanged(false, false);
2014                     break;
2015                 case QnsEventDispatcher.QNS_EVENT_WFC_MODE_TO_WIFI_ONLY:
2016                     onWfcModeChanged(QnsConstants.WIFI_ONLY, false);
2017                     break;
2018                 case QnsEventDispatcher.QNS_EVENT_WFC_MODE_TO_CELLULAR_PREFERRED:
2019                     onWfcModeChanged(QnsConstants.CELL_PREF, false);
2020                     break;
2021                 case QnsEventDispatcher.QNS_EVENT_WFC_MODE_TO_WIFI_PREFERRED:
2022                     onWfcModeChanged(QnsConstants.WIFI_PREF, false);
2023                     break;
2024                 case QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_ENABLED:
2025                     onWfcEnabledChanged(true, true);
2026                     break;
2027                 case QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_DISABLED:
2028                     onWfcEnabledChanged(false, true);
2029                     break;
2030                 case QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_ONLY:
2031                     onWfcModeChanged(QnsConstants.WIFI_ONLY, true);
2032                     break;
2033                 case QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_MODE_TO_CELLULAR_PREFERRED:
2034                     onWfcModeChanged(QnsConstants.CELL_PREF, true);
2035                     break;
2036                 case QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_PREFERRED:
2037                     onWfcModeChanged(QnsConstants.WIFI_PREF, true);
2038                     break;
2039                 case QnsEventDispatcher.QNS_EVENT_WFC_PLATFORM_ENABLED:
2040                     onWfcPlatformChanged(true);
2041                     break;
2042                 case QnsEventDispatcher.QNS_EVENT_WFC_PLATFORM_DISABLED:
2043                     onWfcPlatformChanged(false);
2044                     break;
2045                 case QnsEventDispatcher.QNS_EVENT_SIM_ABSENT:
2046                     onSimAbsent();
2047                     break;
2048                 case EVENT_WIFI_RTT_STATUS_CHANGED:
2049                     onRttStatusChanged((boolean) ar.mResult);
2050                     break;
2051                 case QnsEventDispatcher.QNS_EVENT_TRY_WFC_ACTIVATION:
2052                     onTryWfcConnectionStateChanged(true);
2053                     break;
2054                 case QnsEventDispatcher.QNS_EVENT_CANCEL_TRY_WFC_ACTIVATION:
2055                     onTryWfcConnectionStateChanged(false);
2056                     break;
2057                 default:
2058                     log("never reach here msg=" + message.what);
2059             }
2060         }
2061     }
2062 
2063     private class ThresholdListener extends ThresholdCallback
2064             implements ThresholdCallback.WifiThresholdListener,
2065                     ThresholdCallback.CellularThresholdListener {
2066 
ThresholdListener(Executor executor)2067         ThresholdListener(Executor executor) {
2068             this.init(executor);
2069         }
2070 
2071         @Override
onWifiThresholdChanged(Threshold[] thresholds)2072         public void onWifiThresholdChanged(Threshold[] thresholds) {
2073             onWiFiQualityChanged(thresholds);
2074         }
2075 
2076         @Override
onCellularThresholdChanged(Threshold[] thresholds)2077         public void onCellularThresholdChanged(Threshold[] thresholds) {
2078             onCellularQualityChanged(thresholds);
2079         }
2080     }
2081 
2082     /**
2083      * Dumps the state of {@link QualityMonitor}
2084      *
2085      * @param pw {@link PrintWriter} to write the state of the object.
2086      * @param prefix String to append at start of dumped log.
2087      */
dump(PrintWriter pw, String prefix)2088     void dump(PrintWriter pw, String prefix) {
2089         pw.println(prefix + "------------------------------");
2090         pw.println(
2091                 prefix
2092                         + "ANE["
2093                         + QnsUtils.getNameOfNetCapability(mNetCapability)
2094                         + "_"
2095                         + mSlotIndex
2096                         + "]:");
2097         pw.println(prefix + "mInitialized=" + mInitialized);
2098         pw.println(
2099                 prefix
2100                         + "mQualifiedNetworksChangedRegistrant size="
2101                         + mQualifiedNetworksChangedRegistrants.size());
2102         pw.println(
2103                 prefix
2104                         + "mCellularAccessNetworkType="
2105                         + QnsConstants.accessNetworkTypeToString(mCellularAccessNetworkType)
2106                         + ", mLatestAvailableCellularAccessNetwork="
2107                         + QnsConstants.accessNetworkTypeToString(
2108                                 mLatestAvailableCellularAccessNetwork)
2109                         + ", mIsNotifiedLastQualifiedAccessNetworkTypes="
2110                         + mIsNotifiedLastQualifiedAccessNetworkTypes);
2111         pw.print(prefix + "mLastQualifiedAccessNetworkTypes=");
2112         mLastQualifiedAccessNetworkTypes.forEach(
2113                 accessNetwork ->
2114                         pw.print(QnsConstants.accessNetworkTypeToString(accessNetwork) + "|"));
2115         pw.println(
2116                 ", mIsNotifiedLastQualifiedAccessNetworkTypes="
2117                         + mIsNotifiedLastQualifiedAccessNetworkTypes);
2118         pw.println(
2119                 prefix
2120                         + "mCellularAvailable="
2121                         + mCellularAvailable
2122                         + ", mIwlanAvailable="
2123                         + mIwlanAvailable
2124                         + ", mIsCrossWfc="
2125                         + QnsConstants.callTypeToString(mCallType)
2126                         + ", mCoverage"
2127                         + QnsConstants.coverageToString(mCoverage));
2128         pw.println(
2129                 prefix
2130                         + "mWfcPlatformEnabled="
2131                         + mWfcPlatformEnabled
2132                         + ", mSettingWfcEnabled="
2133                         + mSettingWfcEnabled
2134                         + ", mSettingWfcMode="
2135                         + QnsConstants.preferenceToString(mSettingWfcMode)
2136                         + ", mSettingWfcRoamingEnabled="
2137                         + mSettingWfcRoamingEnabled
2138                         + ", mSettingWfcRoamingMode="
2139                         + QnsConstants.preferenceToString(mSettingWfcRoamingMode)
2140                         + ", mAllowIwlanForWfcActivation="
2141                         + mAllowIwlanForWfcActivation);
2142         pw.println(prefix + "mLastProvisioningInfo=" + mLastProvisioningInfo);
2143         pw.println(prefix + "mAccessNetworkSelectionPolicies=" + mAccessNetworkSelectionPolicies);
2144         pw.println(prefix + "mAnspPolicyMap=" + mAnspPolicyMap);
2145         pw.println(prefix + "mCachedTransportTypeForEmergencyInitialConnect"
2146                 + mCachedTransportTypeForEmergencyInitialConnect);
2147         mRestrictManager.dump(pw, prefix + "  ");
2148     }
2149 
2150     @VisibleForTesting
getSipDialogSessionState()2151     boolean getSipDialogSessionState() {
2152         return mSipDialogSessionState;
2153     }
2154 
sendMetricsForQualifiedNetworks(QualifiedNetworksInfo info)2155     private void sendMetricsForQualifiedNetworks(QualifiedNetworksInfo info) {
2156         if (!mCellularAvailable
2157                 || !mIwlanAvailable
2158                 || mCellularAccessNetworkType == AccessNetworkType.UNKNOWN
2159                 || mLastEvaluateSpecificReason == EVALUATE_SPECIFIC_REASON_DATA_DISCONNECTED) {
2160             // b/268557926, decided to cut off if WWAN and WLAN are not in contention.
2161             return;
2162         }
2163         mQnsMetrics.reportAtomForQualifiedNetworks(
2164                 info,
2165                 mSlotIndex,
2166                 mDataConnectionStatusTracker.getLastTransportType(),
2167                 mCoverage,
2168                 mSettingWfcEnabled,
2169                 mSettingWfcRoamingEnabled,
2170                 mSettingWfcMode,
2171                 mSettingWfcRoamingMode,
2172                 mCellularAccessNetworkType,
2173                 mIwlanAvailable,
2174                 mIsCrossWfc,
2175                 mRestrictManager,
2176                 mCellularQualityMonitor,
2177                 mWifiQualityMonitor,
2178                 mCallType);
2179     }
2180 
sendMetricsForCallTypeChanged(int oldCallType, int newCallType)2181     private void sendMetricsForCallTypeChanged(int oldCallType, int newCallType) {
2182         int transportTypeOfCall = mDataConnectionStatusTracker.getLastTransportType();
2183         mQnsMetrics.reportAtomForCallTypeChanged(mNetCapability, mSlotIndex,
2184                 oldCallType, newCallType, mRestrictManager, transportTypeOfCall);
2185     }
2186 
sendMetricsForDataConnectionChanged( DataConnectionStatusTracker.DataConnectionChangedInfo info)2187     private void sendMetricsForDataConnectionChanged(
2188             DataConnectionStatusTracker.DataConnectionChangedInfo info) {
2189         mQnsMetrics.reportAtomForDataConnectionChanged(
2190                 mNetCapability, mSlotIndex, info, mConfigManager.getCarrierId());
2191     }
2192 
sendMetricsForImsCallDropStats()2193     private void sendMetricsForImsCallDropStats() {
2194         int transportTypeOfCall = mDataConnectionStatusTracker.getLastTransportType();
2195         mQnsMetrics.reportAtomForImsCallDropStats(mNetCapability, mSlotIndex, mRestrictManager,
2196                 mCellularQualityMonitor, mWifiQualityMonitor, transportTypeOfCall,
2197                 mCellularAccessNetworkType);
2198     }
2199 
2200 }
2201