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         if (mDataConnectionStatusTracker.isActiveState()) {
1255             /* Check handover policy */
1256             if (isHandoverPolicyCheckAvailable()) {
1257                 if (!moveTransportTypeAllowed()) {
1258                     log("Handover is not allowed. Skip this evaluation.");
1259                     return;
1260                 }
1261             } else {
1262                 if (specificReason == EVALUATE_SPECIFIC_REASON_IWLAN_DISABLE
1263                         && !mCellularAvailable) {
1264                     log("Allow evaluation without handover policy check");
1265                 } else {
1266                     log("Handover policy check is not available. Skip this evaluation.");
1267                     return;
1268                 }
1269             }
1270         }
1271 
1272         /* Check network Availability */
1273         boolean isAllowedForIwlan = isAllowed(AccessNetworkConstants.TRANSPORT_TYPE_WLAN);
1274         boolean isAllowedForCellular = isAllowed(AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
1275         boolean availabilityIwlan =
1276                 isAllowedForIwlan
1277                         && evaluateAvailability(
1278                                 AccessNetworkConstants.TRANSPORT_TYPE_WLAN, isAllowedForCellular);
1279         boolean availabilityCellular =
1280                 isAllowedForCellular
1281                         && evaluateAvailability(
1282                                 AccessNetworkConstants.TRANSPORT_TYPE_WWAN, isAllowedForIwlan);
1283         log(" availability Iwlan:" + availabilityIwlan + " Cellular:" + availabilityCellular);
1284 
1285         if (mWifiBackhaulMonitor.isRttCheckEnabled()
1286                 && mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS) {
1287             mWifiBackhaulMonitor.setCellularAvailable(
1288                     availabilityCellular
1289                             && isAccessNetworkAllowed(mCellularAccessNetworkType, mNetCapability));
1290         }
1291         // QualifiedNetworksService checks AccessNetworkSelectionPolicy only in the case both
1292         // networks(cellular and iwlan) are available. If only one network is available, no
1293         // evaluation is run. Available network of accessNetworkType will be reported immediately.
1294         if (availabilityIwlan && availabilityCellular) {
1295             updateAccessNetworkSelectionPolicy();
1296             List<Integer> accessNetworkTypes =
1297                     evaluateAccessNetworkSelectionPolicy(availabilityIwlan, availabilityCellular);
1298             reportSatisfiedAccessNetworkTypesByState(accessNetworkTypes, true);
1299             reevaluateLastNotifiedSecondAccessNetwork();
1300         } else if (availabilityIwlan) {
1301             updateAccessNetworkSelectionPolicy();
1302             if (!mIsCrossWfc && hasWifiThresholdWithoutCellularCondition()) {
1303                 List<Integer> accessNetworkTypes =
1304                         evaluateAccessNetworkSelectionPolicy(
1305                                 availabilityIwlan, availabilityCellular);
1306                 reportSatisfiedAccessNetworkTypesByState(accessNetworkTypes, true);
1307             } else {
1308                 reportSatisfiedAccessNetworkTypesByState(List.of(AccessNetworkType.IWLAN), false);
1309             }
1310         } else if (availabilityCellular) {
1311             reportSatisfiedAccessNetworkTypesByState(
1312                     new ArrayList<>(List.of(mCellularAccessNetworkType)), false);
1313         } else {
1314             // TODO Is it better to report to cellular when there is nothing?
1315             log("evaluate nothing without an available network.");
1316             if (specificReason == EVALUATE_SPECIFIC_REASON_IWLAN_DISABLE) {
1317                 reportQualifiedNetwork(getInitialAccessNetworkTypes());
1318             }
1319         }
1320     }
1321 
1322     @VisibleForTesting
vopsCheckRequired(int cellularAccessNetworkType, int coverage, int callType)1323     boolean vopsCheckRequired(int cellularAccessNetworkType, int coverage, int callType) {
1324         boolean checkVoPs = false;
1325         if (mConfigManager.isMmtelCapabilityRequired(coverage)
1326                 && (cellularAccessNetworkType == AccessNetworkType.EUTRAN
1327                         || cellularAccessNetworkType == AccessNetworkType.NGRAN)) {
1328             if (mDataConnectionStatusTracker.isInactiveState()) {
1329                 checkVoPs = true;
1330             } else if (mDataConnectionStatusTracker.getLastTransportType()
1331                     == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
1332                 if (callType == QnsConstants.CALL_TYPE_IDLE
1333                         || !mConfigManager.isInCallHoDecisionWlanToWwanWithoutVopsCondition()) {
1334                     checkVoPs = true;
1335                 }
1336             } else if (mDataConnectionStatusTracker.getLastTransportType()
1337                     == AccessNetworkConstants.TRANSPORT_TYPE_WWAN) {
1338                 // If there is an on-going call and UE is moving into an area which does not support
1339                 // VoPS, don't consider VoPS condition and let AccessNetworkEvaluator decide a
1340                 // preferred RAT.
1341                 if (callType == QnsConstants.CALL_TYPE_IDLE) {
1342                     checkVoPs = true;
1343                 }
1344             }
1345         }
1346         return checkVoPs;
1347     }
1348 
hasWifiThresholdWithoutCellularCondition()1349     private boolean hasWifiThresholdWithoutCellularCondition() {
1350         if (mAccessNetworkSelectionPolicies == null || mAccessNetworkSelectionPolicies.isEmpty()) {
1351             return false;
1352         }
1353         for (AccessNetworkSelectionPolicy policy : mAccessNetworkSelectionPolicies) {
1354             if (policy.hasWifiThresholdWithoutCellularCondition()) {
1355                 return true;
1356             }
1357         }
1358         return false;
1359     }
1360 
reportSatisfiedAccessNetworkTypesByState( List<Integer> satisfiedAccessNetworkTypes, boolean needMonitor)1361     protected synchronized void reportSatisfiedAccessNetworkTypesByState(
1362             List<Integer> satisfiedAccessNetworkTypes, boolean needMonitor) {
1363         if (needMonitor) {
1364             if (mDataConnectionStatusTracker.isInactiveState()) {
1365                 if (satisfiedAccessNetworkTypes.size() > 0) {
1366                     reportQualifiedNetwork(satisfiedAccessNetworkTypes);
1367                     updateAccessNetworkSelectionPolicy();
1368                 }
1369                 updateQualityMonitor();
1370             } else if (!mDataConnectionStatusTracker.isConnectionInProgress()) {
1371                 if (isHandoverNeeded(satisfiedAccessNetworkTypes)) {
1372                     reportQualifiedNetwork(satisfiedAccessNetworkTypes);
1373                     unregisterThresholdToQualityMonitor();
1374                 } else if (isFallbackCase(satisfiedAccessNetworkTypes)) {
1375                     reportQualifiedNetwork(satisfiedAccessNetworkTypes);
1376                     updateAccessNetworkSelectionPolicy();
1377                     updateQualityMonitor();
1378                 } else {
1379                     updateQualityMonitor();
1380                 }
1381             }
1382         } else {
1383             if (mDataConnectionStatusTracker.isInactiveState()) {
1384                 reportQualifiedNetwork(satisfiedAccessNetworkTypes);
1385             } else if (!mDataConnectionStatusTracker.isConnectionInProgress()) {
1386                 if (isHandoverNeeded(satisfiedAccessNetworkTypes)) {
1387                     reportQualifiedNetwork(satisfiedAccessNetworkTypes);
1388                 } else if (isFallbackCase(satisfiedAccessNetworkTypes)) {
1389                     reportQualifiedNetwork(satisfiedAccessNetworkTypes);
1390                 }
1391             }
1392             unregisterThresholdToQualityMonitor();
1393         }
1394     }
1395 
getTargetTransportType(List<Integer> accessNetworkTypes)1396     protected int getTargetTransportType(List<Integer> accessNetworkTypes) {
1397         if (accessNetworkTypes == null || accessNetworkTypes.size() == 0) {
1398             return AccessNetworkConstants.TRANSPORT_TYPE_INVALID;
1399         }
1400         if (accessNetworkTypes.get(0) == AccessNetworkType.IWLAN) {
1401             return AccessNetworkConstants.TRANSPORT_TYPE_WLAN;
1402         }
1403         return AccessNetworkConstants.TRANSPORT_TYPE_WWAN;
1404     }
1405 
1406     @VisibleForTesting
isHandoverPolicyCheckAvailable()1407     boolean isHandoverPolicyCheckAvailable() {
1408         if (mDataConnectionStatusTracker.isActiveState()) {
1409             int srcTransportType = mDataConnectionStatusTracker.getLastTransportType();
1410             boolean targetNetworkAvailable =
1411                     srcTransportType == AccessNetworkConstants.TRANSPORT_TYPE_WLAN
1412                             ? mCellularAvailable
1413                             : mIwlanAvailable;
1414             if (srcTransportType == getLastQualifiedTransportType() && targetNetworkAvailable) {
1415                 log(" handover policy check is available for this evaluation.");
1416                 return true;
1417             }
1418         }
1419         log("handover policy check is not available for this evaluation.");
1420         return false;
1421     }
1422 
1423     @VisibleForTesting
moveTransportTypeAllowed()1424     boolean moveTransportTypeAllowed() {
1425         int srcAccessNetwork =
1426                 mDataConnectionStatusTracker.getLastTransportType()
1427                                 == AccessNetworkConstants.TRANSPORT_TYPE_WLAN
1428                         ? AccessNetworkType.IWLAN
1429                         : mLatestAvailableCellularAccessNetwork;
1430         int dstAccessNetwork =
1431                 srcAccessNetwork == AccessNetworkType.IWLAN
1432                         ? mCellularAccessNetworkType
1433                         : AccessNetworkType.IWLAN;
1434         if (mConfigManager.isHandoverAllowedByPolicy(
1435                 mNetCapability, srcAccessNetwork, dstAccessNetwork, mCoverage)) {
1436             return true;
1437         } else {
1438             if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS
1439                     && mCallStatusTracker.isCallIdle(NetworkCapabilities.NET_CAPABILITY_IMS)) {
1440                 // Telephony will make new connection with preferred AccessNetwork
1441                 log("handover is not allowed. but need to move to target Transport.");
1442                 return true;
1443             }
1444             if (dstAccessNetwork == AccessNetworkType.IWLAN && useDifferentApnOverIwlan()) {
1445                 // Telephony will make new connection when change transport type
1446                 log(
1447                         "handover is not allowed. but need to move to target Transport using"
1448                                 + " different apn over IWLAN.");
1449                 return true;
1450             }
1451             if (dstAccessNetwork != AccessNetworkType.IWLAN
1452                     && mCellularAvailable
1453                     && mConfigManager.getRatPreference(mNetCapability)
1454                             == QnsConstants.RAT_PREFERENCE_WIFI_WHEN_NO_CELLULAR) {
1455                 // Telephony will make new connection when change transport type
1456                 log(
1457                         "handover is not allowed. but need to move to target Transport for the"
1458                                 + " RAT_PREFERENCE_WIFI_WHEN_NO_CELLULAR.");
1459                 return true;
1460             }
1461         }
1462         return false;
1463     }
1464 
useDifferentApnOverIwlan()1465     private boolean useDifferentApnOverIwlan() {
1466         // supports MMS, XCAP and CBS
1467         if (mNetCapability != NetworkCapabilities.NET_CAPABILITY_MMS
1468                 && mNetCapability != NetworkCapabilities.NET_CAPABILITY_XCAP
1469                 && mNetCapability != NetworkCapabilities.NET_CAPABILITY_CBS) {
1470             return false;
1471         }
1472 
1473         ApnSetting apnSetting =
1474                 mDataConnectionStatusTracker.getLastApnSetting(
1475                         AccessNetworkConstants.TRANSPORT_TYPE_WWAN);
1476         if (apnSetting != null
1477                 && (apnSetting.getApnTypeBitmask() & ApnSetting.TYPE_DEFAULT) != 0
1478                 && (apnSetting.getNetworkTypeBitmask()
1479                                 & (1 << (TelephonyManager.NETWORK_TYPE_IWLAN - 1)))
1480                         == 0) {
1481             log("useDifferentApnOverIwlan true");
1482             return true;
1483         }
1484         log("useDifferentApnOverIwlan false");
1485         return false;
1486     }
1487 
isHandoverNeeded(List<Integer> accessNetworkTypes)1488     protected boolean isHandoverNeeded(List<Integer> accessNetworkTypes) {
1489         if (mDataConnectionStatusTracker.isInactiveState()
1490                 || mDataConnectionStatusTracker.isHandoverState()) {
1491             return false;
1492         }
1493 
1494         int targetTransportType = getTargetTransportType(accessNetworkTypes);
1495         if (targetTransportType == AccessNetworkConstants.TRANSPORT_TYPE_INVALID) {
1496             return false;
1497         }
1498 
1499         // Handover case
1500         int sourceTransportType = mDataConnectionStatusTracker.getLastTransportType();
1501         return sourceTransportType != targetTransportType;
1502     }
1503 
isFallbackCase(List<Integer> accessNetworkTypes)1504     protected boolean isFallbackCase(List<Integer> accessNetworkTypes) {
1505         if (mDataConnectionStatusTracker.isInactiveState()) {
1506             return false;
1507         }
1508 
1509         int targetTransportType = getTargetTransportType(accessNetworkTypes);
1510         if (targetTransportType == AccessNetworkConstants.TRANSPORT_TYPE_INVALID) {
1511             return false;
1512         }
1513         if (targetTransportType != mDataConnectionStatusTracker.getLastTransportType()) {
1514             return false;
1515         }
1516 
1517         if (getLastQualifiedTransportType() == targetTransportType) {
1518             return false;
1519         }
1520 
1521         log("isFallbackcase:true");
1522         return true;
1523     }
1524 
reportQualifiedNetwork(List<Integer> accessNetworkTypes)1525     protected void reportQualifiedNetwork(List<Integer> accessNetworkTypes) {
1526         if (accessNetworkTypes.contains(AccessNetworkType.UNKNOWN)) {
1527             log(
1528                     "reportQualifiedNetwork, remove UNKNOWN access network."
1529                             + QnsUtils.getStringAccessNetworkTypes(accessNetworkTypes));
1530             accessNetworkTypes.remove(AccessNetworkType.UNKNOWN);
1531         }
1532         List<Integer> supportAccessNetworkTypes = new ArrayList<>();
1533         if (mConfigManager.allowImsOverIwlanCellularLimitedCase()) {
1534             for (Integer accessNetwork : accessNetworkTypes) {
1535                 if (accessNetwork == AccessNetworkType.IWLAN
1536                         || isAccessNetworkAllowed(accessNetwork, mNetCapability)) {
1537                     supportAccessNetworkTypes.add(accessNetwork);
1538                 }
1539             }
1540             if (!accessNetworkTypes.isEmpty() && supportAccessNetworkTypes.isEmpty()) {
1541                 log("supportAccessNetworkTypes is empty");
1542                 return;
1543             }
1544         } else {
1545             supportAccessNetworkTypes.addAll(accessNetworkTypes);
1546         }
1547 
1548         log(
1549                 "reportQualifiedNetwork supportAccessNetworkTypes:"
1550                         + QnsUtils.getStringAccessNetworkTypes(supportAccessNetworkTypes));
1551 
1552         if (equalsLastNotifiedQualifiedNetwork(supportAccessNetworkTypes)) {
1553             return;
1554         } else {
1555             if (mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS
1556                     && mWifiBackhaulMonitor.isRttCheckEnabled()) {
1557                 if (supportAccessNetworkTypes.contains(AccessNetworkType.IWLAN)) {
1558                     if (!isRttSuccess()) {
1559                         mWifiBackhaulMonitor.requestRttCheck();
1560                         return;
1561                     }
1562                 } else {
1563                     mIsRttCheckSuccess = false;
1564                 }
1565             }
1566         }
1567 
1568         updateLastNotifiedQualifiedNetwork(supportAccessNetworkTypes);
1569         notifyForQualifiedNetworksChanged(supportAccessNetworkTypes);
1570     }
1571 
findUnmatchedThresholds()1572     private List<Threshold> findUnmatchedThresholds() {
1573         List<Threshold> unmatchedThresholds = new ArrayList<>();
1574         if (mAccessNetworkSelectionPolicies == null
1575                 || mAccessNetworkSelectionPolicies.size() == 0) {
1576             return unmatchedThresholds;
1577         }
1578 
1579         List<Integer> excludeThresholdGroup = new ArrayList<>();
1580         boolean bIwlanRegistrable = isIwlanAvailableWithoutRestrict();
1581         boolean bCellularRegistrable = isCellularAvailableWithoutRestrict();
1582         for (AccessNetworkSelectionPolicy policy : mAccessNetworkSelectionPolicies) {
1583             List<Threshold> policyUnmatchedThresholds =
1584                     policy.findUnmatchedThresholds(mWifiQualityMonitor, mCellularQualityMonitor);
1585             if (policyUnmatchedThresholds == null || policyUnmatchedThresholds.size() == 0) {
1586                 continue;
1587             }
1588             for (Threshold threshold : policyUnmatchedThresholds) {
1589                 if (bIwlanRegistrable && threshold.getAccessNetwork() == AccessNetworkType.IWLAN) {
1590                     unmatchedThresholds.add(threshold);
1591                 }
1592                 if (bCellularRegistrable
1593                         && threshold.getAccessNetwork() != AccessNetworkType.IWLAN) {
1594                     if (threshold.getAccessNetwork() == mCellularAccessNetworkType) {
1595                         unmatchedThresholds.add(threshold);
1596                     } else if (threshold.getGroupId() >= 0) {
1597                         // If the current cellular access network and the access network of
1598                         // cellular threshold are different, it is not necessary to monitor the
1599                         // entire threshold of this group.
1600                         excludeThresholdGroup.add(threshold.getGroupId());
1601                     }
1602                 }
1603             }
1604         }
1605         for (int excludeGid : excludeThresholdGroup) {
1606             unmatchedThresholds.removeIf(threshold -> threshold.getGroupId() == excludeGid);
1607         }
1608         return unmatchedThresholds;
1609     }
1610 
updateQualityMonitor()1611     private void updateQualityMonitor() {
1612         List<Threshold> unmatchedThresholds = findUnmatchedThresholds();
1613         if (unmatchedThresholds.size() == 0) {
1614             log("updateQualityMonitor empty unmatchedThresholds.");
1615             unregisterThresholdToQualityMonitor();
1616             return;
1617         }
1618 
1619         log("updateQualityMonitor");
1620 
1621         LinkedHashSet<Integer> unmatchedGroupIdSet = new LinkedHashSet<>();
1622         HashMap<Integer, Integer> unmatchedMonitorTypeMap = new HashMap<>();
1623         LinkedHashSet<Integer> unmatchedMonitorTypeSet = new LinkedHashSet<>();
1624         for (Threshold th : unmatchedThresholds) {
1625             if (th.getGroupId() < 0) {
1626                 continue;
1627             }
1628             unmatchedGroupIdSet.add(th.getGroupId());
1629             int key = th.getAccessNetwork() << 16 | th.getMeasurementType();
1630             unmatchedMonitorTypeMap.put(key, unmatchedMonitorTypeMap.getOrDefault(key, 0) + 1);
1631         }
1632 
1633         List<Map.Entry<Integer, Integer>> list_entries =
1634                 new ArrayList<>(unmatchedMonitorTypeMap.entrySet());
1635         list_entries.sort(Entry.comparingByValue());
1636         for (Entry<Integer, Integer> entry : list_entries) {
1637             unmatchedMonitorTypeSet.add(entry.getKey());
1638         }
1639 
1640         LinkedHashSet<Integer> reducedGroupIdSet = new LinkedHashSet<>();
1641         for (int type : unmatchedMonitorTypeSet) {
1642             reducedGroupIdSet.clear();
1643             boolean skipReduce = false;
1644             for (Threshold th : unmatchedThresholds) {
1645                 if (type == (th.getAccessNetwork() << 16 | th.getMeasurementType())) {
1646                     if (th.getGroupId() < 0) {
1647                         skipReduce = true;
1648                         break;
1649                     }
1650                 } else {
1651                     reducedGroupIdSet.add(th.getGroupId());
1652                 }
1653             }
1654             if (skipReduce) {
1655                 continue;
1656             }
1657 
1658             if (reducedGroupIdSet.containsAll(unmatchedGroupIdSet)) {
1659                 unmatchedThresholds.removeIf(
1660                         threshold ->
1661                                 type
1662                                         == (threshold.getAccessNetwork() << 16
1663                                                 | threshold.getMeasurementType()));
1664             }
1665         }
1666 
1667         registerThresholdsToQualityMonitor(unmatchedThresholds);
1668     }
1669 
unregisterThresholdToQualityMonitor()1670     private void unregisterThresholdToQualityMonitor() {
1671         mWifiQualityMonitor.updateThresholdsForNetCapability(mNetCapability, mSlotIndex, null);
1672         mCellularQualityMonitor.updateThresholdsForNetCapability(mNetCapability, mSlotIndex, null);
1673     }
1674 
registerThresholdsToQualityMonitor(List<Threshold> thresholds)1675     private void registerThresholdsToQualityMonitor(List<Threshold> thresholds) {
1676         if (thresholds == null) {
1677             thresholds = new ArrayList<>();
1678         }
1679 
1680         List<Threshold> monitorWiFiThresholds = new ArrayList<>();
1681         List<Threshold> monitorCellThresholds = new ArrayList<>();
1682         for (Threshold th : thresholds) {
1683             if (th.getAccessNetwork() == AccessNetworkType.IWLAN) {
1684                 monitorWiFiThresholds.add(th);
1685             } else {
1686                 monitorCellThresholds.add(th);
1687             }
1688         }
1689 
1690         for (Threshold th : monitorWiFiThresholds) {
1691             log("  monitorWiFiThresholds th:" + th.toShortString());
1692         }
1693         for (Threshold th : monitorCellThresholds) {
1694             log("  monitorCellThresholds th:" + th.toShortString());
1695         }
1696 
1697         // refresh threshold to be monitored.
1698         mWifiQualityMonitor.updateThresholdsForNetCapability(
1699                 mNetCapability, mSlotIndex, monitorWiFiThresholds.toArray(new Threshold[0]));
1700         mCellularQualityMonitor.updateThresholdsForNetCapability(
1701                 mNetCapability, mSlotIndex, monitorCellThresholds.toArray(new Threshold[0]));
1702     }
1703 
updateThrottleStatus( boolean isThrottle, long throttleTimeMillis, int transportType)1704     protected void updateThrottleStatus(
1705             boolean isThrottle, long throttleTimeMillis, int transportType) {
1706         mRestrictManager.notifyThrottling(isThrottle, throttleTimeMillis, transportType);
1707     }
1708 
getPreferredMode()1709     protected int getPreferredMode() {
1710         if (mAllowIwlanForWfcActivation) {
1711             return QnsConstants.WIFI_PREF;
1712         }
1713         if (mCoverage == QnsConstants.COVERAGE_ROAM) {
1714             return mSettingWfcRoamingMode;
1715         }
1716         return mSettingWfcMode;
1717     }
1718 
getPreferredAccessNetwork()1719     private int getPreferredAccessNetwork() {
1720         switch (getPreferredMode()) {
1721             case QnsConstants.CELL_PREF:
1722                 return mCellularAccessNetworkType;
1723             case QnsConstants.WIFI_PREF:
1724             case QnsConstants.WIFI_ONLY:
1725                 return AccessNetworkType.IWLAN;
1726         }
1727         return mCellularAccessNetworkType;
1728     }
1729 
isRttSuccess()1730     private boolean isRttSuccess() {
1731         return !isAccessNetworkAllowed(
1732                         mCellularAccessNetworkType, NetworkCapabilities.NET_CAPABILITY_IMS)
1733                 || mIsRttCheckSuccess;
1734     }
1735 
evaluateAccessNetworkSelectionPolicy( boolean availabilityIwlan, boolean availabilityCellular)1736     private List<Integer> evaluateAccessNetworkSelectionPolicy(
1737             boolean availabilityIwlan, boolean availabilityCellular) {
1738         log("evaluateAccessNetworkSelectionPolicy");
1739 
1740         if (mAccessNetworkSelectionPolicies == null || mAccessNetworkSelectionPolicies.isEmpty()) {
1741             return new ArrayList<>();
1742         }
1743         List<Integer> accessNetworkTypes = new ArrayList<>();
1744         for (AccessNetworkSelectionPolicy policy : mAccessNetworkSelectionPolicies) {
1745             if (policy.satisfiedByThreshold(
1746                     mWifiQualityMonitor,
1747                     mCellularQualityMonitor,
1748                     availabilityIwlan,
1749                     availabilityCellular,
1750                     mCellularAccessNetworkType)) {
1751                 log(
1752                         "  satisfiedByThreshold TargetTransportType:"
1753                                 + QnsConstants.transportTypeToString(
1754                                         policy.getTargetTransportType()));
1755                 if (policy.getTargetTransportType() == AccessNetworkConstants.TRANSPORT_TYPE_WLAN) {
1756                     if (!accessNetworkTypes.contains(AccessNetworkType.IWLAN)) {
1757                         accessNetworkTypes.add(AccessNetworkType.IWLAN);
1758                     }
1759 
1760                 } else {
1761                     if (!accessNetworkTypes.contains(mCellularAccessNetworkType)) {
1762                         if (availabilityCellular) {
1763                             accessNetworkTypes.add(mCellularAccessNetworkType);
1764                         } else {
1765                             accessNetworkTypes.add(AccessNetworkType.UNKNOWN);
1766                         }
1767                     }
1768                     if ((mCallType == QnsConstants.CALL_TYPE_VOICE
1769                                     || mCallType == QnsConstants.CALL_TYPE_EMERGENCY)
1770                             && policy.satisfiedWithWifiLowSignalStrength()) {
1771                         int reason = mConfigManager.getQnsIwlanHoRestrictReason();
1772                         if (reason == QnsConstants.FALLBACK_REASON_RTP_OR_WIFI
1773                                 || reason == QnsConstants.FALLBACK_REASON_WIFI_ONLY) {
1774                             log("WWAN decision with Wi-Fi low signalStrength in Voice call");
1775                             mRestrictManager.increaseCounterToRestrictIwlanInCall();
1776                         }
1777                     }
1778                 }
1779             }
1780         }
1781 
1782         // If the evaluator has not yet reported a Qualified Networks, report preferred.
1783         if (!isNotifiedQualifiedAccessNetworkTypes()) {
1784             if (accessNetworkTypes.size() == 0) {
1785                 accessNetworkTypes.add(getPreferredAccessNetwork());
1786                 log(
1787                         "  no candidate access network, use preferred:"
1788                                 + QnsUtils.getStringAccessNetworkTypes(accessNetworkTypes));
1789             } else if (accessNetworkTypes.size() > 1) {
1790                 accessNetworkTypes.remove(Integer.valueOf(getPreferredAccessNetwork()));
1791                 accessNetworkTypes.add(0, getPreferredAccessNetwork());
1792                 log(
1793                         "  two more candidate access network, use preferred:"
1794                                 + QnsUtils.getStringAccessNetworkTypes(accessNetworkTypes));
1795             }
1796         }
1797 
1798         // TODO. need to be improved handling the second access network
1799         // Add a second access network, if the preferred access network does not exist in list.
1800         if (availabilityIwlan
1801                 && availabilityCellular
1802                 && mConfigManager.isOverrideImsPreferenceSupported()) {
1803             if (!accessNetworkTypes.isEmpty()
1804                     && accessNetworkTypes.get(0) != AccessNetworkType.IWLAN
1805                     && getPreferredMode() == QnsConstants.CELL_PREF
1806                     && isAccessNetworkAllowed(accessNetworkTypes.get(0), mNetCapability)) {
1807                 if (!accessNetworkTypes.contains(AccessNetworkType.IWLAN)) {
1808                     accessNetworkTypes.add(AccessNetworkType.IWLAN);
1809                     log(
1810                             "  add a second accessNetworkTypes : "
1811                                     + QnsUtils.getStringAccessNetworkTypes(accessNetworkTypes));
1812                 }
1813             } else if (accessNetworkTypes.isEmpty()
1814                     && !mLastQualifiedAccessNetworkTypes.isEmpty()
1815                     && mLastQualifiedAccessNetworkTypes.get(0) != AccessNetworkType.IWLAN
1816                     && getPreferredMode() == QnsConstants.CELL_PREF
1817                     && isAccessNetworkAllowed(
1818                             mLastQualifiedAccessNetworkTypes.get(0), mNetCapability)) {
1819                 if (!mLastQualifiedAccessNetworkTypes.contains(AccessNetworkType.IWLAN)) {
1820                     accessNetworkTypes.addAll(mLastQualifiedAccessNetworkTypes);
1821                     accessNetworkTypes.add(AccessNetworkType.IWLAN);
1822                     log(
1823                             "  add a second accessNetworkTypes in existing "
1824                                     + "mLastQualifiedAccessNetworkTypes : "
1825                                     + QnsUtils.getStringAccessNetworkTypes(accessNetworkTypes));
1826                 }
1827             }
1828         }
1829 
1830         log("  accessNetworkTypes:" + QnsUtils.getStringAccessNetworkTypes(accessNetworkTypes));
1831         return accessNetworkTypes;
1832     }
1833 
1834     // TODO. need to be improved handling the second access network
1835     // A qualified conditions are required for the second access network.
1836     // What threshold conditions are qualified for the second access network? (like rove in)
1837     // What are the threshold conditions for exiting the second access network? (like a rove out)
reevaluateLastNotifiedSecondAccessNetwork()1838     private void reevaluateLastNotifiedSecondAccessNetwork() {
1839         if (mConfigManager.isOverrideImsPreferenceSupported()
1840                 && mLastQualifiedAccessNetworkTypes.size() > 1
1841                 && mLastQualifiedAccessNetworkTypes.get(1) == AccessNetworkType.IWLAN) {
1842             if (!isAccessNetworkAllowed(mCellularAccessNetworkType, mNetCapability)
1843                     || getPreferredMode() != QnsConstants.CELL_PREF) {
1844                 log("reevaluateLastNotifiedSecondAccessNetwork, Removed a second access network");
1845                 reportQualifiedNetwork(
1846                         new ArrayList<>(List.of(mLastQualifiedAccessNetworkTypes.get(0))));
1847             }
1848         }
1849     }
1850 
buildAccessNetworkSelectionPolicy( boolean bForceUpdate)1851     private Map<PreCondition, List<AccessNetworkSelectionPolicy>> buildAccessNetworkSelectionPolicy(
1852             boolean bForceUpdate) {
1853         if (mAnspPolicyMap == null || bForceUpdate) {
1854             log("Building list of AccessNetworkSelectionPolicy.");
1855             mAnspPolicyMap =
1856                     AccessNetworkSelectionPolicyBuilder.build(mConfigManager, mNetCapability);
1857 
1858             if (DBG) {
1859                 mAnspPolicyMap
1860                         .values()
1861                         .forEach(
1862                                 list ->
1863                                         list.stream()
1864                                                 .map(policy -> " retriMap ANSP=" + policy)
1865                                                 .forEach(this::log));
1866             }
1867         }
1868         return mAnspPolicyMap;
1869     }
1870 
updateAccessNetworkSelectionPolicy()1871     private void updateAccessNetworkSelectionPolicy() {
1872         Map<PreCondition, List<AccessNetworkSelectionPolicy>> map =
1873                 buildAccessNetworkSelectionPolicy(false);
1874         if (map == null) {
1875             map = new HashMap<>();
1876         }
1877 
1878         log("Create a list of AccessNetworkSelectionPolicy that match the preconditions.");
1879 
1880         PreCondition preCondition = getMatchingPreCondition();
1881         List<AccessNetworkSelectionPolicy> matchedPolicies = new ArrayList<>();
1882         List<AccessNetworkSelectionPolicy> list = map.get(preCondition);
1883         if (list != null) {
1884             for (AccessNetworkSelectionPolicy policy : list) {
1885                 if (policy.satisfyPrecondition(preCondition)
1886                         && !mDataConnectionStatusTracker.isConnectionInProgress()
1887                         && (!isNotifiedQualifiedAccessNetworkTypes()
1888                                 || getLastQualifiedTransportType()
1889                                         != policy.getTargetTransportType())) {
1890                     matchedPolicies.add(policy);
1891                 }
1892             }
1893         }
1894 
1895         if (mAccessNetworkSelectionPolicies.equals(matchedPolicies)) {
1896             for (AccessNetworkSelectionPolicy policy : matchedPolicies) {
1897                 log("  Matched ANSP=" + policy);
1898             }
1899         }
1900 
1901         for (AccessNetworkSelectionPolicy policy : matchedPolicies) {
1902             log("  Found new ANSP=" + policy);
1903         }
1904 
1905         mAccessNetworkSelectionPolicies = matchedPolicies;
1906     }
1907 
getMatchingPreCondition()1908     private PreCondition getMatchingPreCondition() {
1909         int callType = mCallType;
1910         if ((mNetCapability == NetworkCapabilities.NET_CAPABILITY_EIMS
1911                         || mNetCapability == NetworkCapabilities.NET_CAPABILITY_IMS)
1912                 && mCallType == QnsConstants.CALL_TYPE_EMERGENCY) {
1913             callType = QnsConstants.CALL_TYPE_VOICE;
1914         }
1915         int sipDialogPolicy = mConfigManager.getSipDialogSessionPolicy();
1916         if (callType == QnsConstants.CALL_TYPE_IDLE && mSipDialogSessionState) {
1917             if (sipDialogPolicy > QnsConstants.SIP_DIALOG_SESSION_POLICY_NONE) {
1918                 log("apply sipDialogPolicy:"
1919                         + QnsConstants.qnsSipDialogSessionPolicyToString(sipDialogPolicy));
1920             }
1921             switch (sipDialogPolicy) {
1922                 case QnsConstants.SIP_DIALOG_SESSION_POLICY_FOLLOW_VOICE_CALL:
1923                     callType = QnsConstants.CALL_TYPE_VOICE;
1924                     break;
1925                 case QnsConstants.SIP_DIALOG_SESSION_POLICY_FOLLOW_VIDEO_CALL:
1926                     callType = QnsConstants.CALL_TYPE_VIDEO;
1927                     break;
1928                 case QnsConstants.SIP_DIALOG_SESSION_POLICY_NONE:
1929                     // fall-through
1930                 default:
1931                     // do-nothing
1932                     break;
1933             }
1934         }
1935 
1936         if (mConfigManager.hasThresholdGapWithGuardTimer()) {
1937             @QnsConstants.QnsGuarding int guarding = QnsConstants.GUARDING_NONE;
1938             int source = getLastQualifiedTransportType();
1939             if (source != AccessNetworkConstants.TRANSPORT_TYPE_WLAN
1940                     && mRestrictManager.hasRestrictionType(
1941                             AccessNetworkConstants.TRANSPORT_TYPE_WLAN,
1942                             RestrictManager.RESTRICT_TYPE_GUARDING)) {
1943                 guarding = QnsConstants.GUARDING_WIFI;
1944             } else if (source != AccessNetworkConstants.TRANSPORT_TYPE_WWAN
1945                     && mRestrictManager.hasRestrictionType(
1946                             AccessNetworkConstants.TRANSPORT_TYPE_WWAN,
1947                             RestrictManager.RESTRICT_TYPE_GUARDING)) {
1948                 guarding = QnsConstants.GUARDING_CELLULAR;
1949             }
1950             return new GuardingPreCondition(callType, getPreferredMode(), mCoverage, guarding);
1951         }
1952         return new PreCondition(callType, getPreferredMode(), mCoverage);
1953     }
1954 
evaluateSpecificReasonToString(int specificReason)1955     private String evaluateSpecificReasonToString(int specificReason) {
1956         if (specificReason == EVALUATE_SPECIFIC_REASON_NONE) {
1957             return "EVALUATE_SPECIFIC_REASON_NONE";
1958         } else if (specificReason == EVALUATE_SPECIFIC_REASON_IWLAN_DISABLE) {
1959             return "EVALUATE_SPECIFIC_REASON_IWLAN_DISABLE";
1960         } else if (specificReason == EVALUATE_SPECIFIC_REASON_DATA_DISCONNECTED) {
1961             return "EVALUATE_SPECIFIC_REASON_DATA_DISCONNECTED";
1962         } else if (specificReason == EVALUATE_SPECIFIC_REASON_DATA_FAILED) {
1963             return "EVALUATE_SPECIFIC_REASON_DATA_FAILED";
1964         } else if (specificReason == EVALUATE_SPECIFIC_REASON_DATA_CONNECTED) {
1965             return "EVALUATE_SPECIFIC_REASON_DATA_CONNECTED";
1966         }
1967         return "UNKNOWN";
1968     }
1969 
isCrossWfcAllowed(boolean cellularAvailable)1970     private boolean isCrossWfcAllowed(boolean cellularAvailable) {
1971         if (mConfigManager.getRatPreference(mNetCapability)
1972                 == QnsConstants.RAT_PREFERENCE_WIFI_WHEN_WFC_AVAILABLE) {
1973             // Should follow RAT_PREFERENCE_WIFI_WHEN_WFC_AVAILABLE and do not block CST when IMS
1974             // connected to CST
1975             return true;
1976         }
1977         return !cellularAvailable;
1978     }
1979 
1980     private class EvaluatorEventHandler extends Handler {
EvaluatorEventHandler(Looper l)1981         EvaluatorEventHandler(Looper l) {
1982             super(l);
1983         }
1984 
1985         @Override
handleMessage(Message message)1986         public void handleMessage(Message message) {
1987             log("handleMessage msg=" + message.what);
1988             QnsAsyncResult ar = (QnsAsyncResult) message.obj;
1989             switch (message.what) {
1990                 case EVENT_IWLAN_NETWORK_STATUS_CHANGED:
1991                     onIwlanNetworkStatusChanged((IwlanAvailabilityInfo) ar.mResult);
1992                     break;
1993                 case EVENT_QNS_TELEPHONY_INFO_CHANGED:
1994                     onQnsTelephonyInfoChanged((QnsTelephonyListener.QnsTelephonyInfo) ar.mResult);
1995                     break;
1996                 case EVENT_RESTRICT_INFO_CHANGED:
1997                     onRestrictInfoChanged();
1998                     break;
1999                 case EVENT_SET_CALL_TYPE:
2000                     onSetCallType((int) ar.mResult);
2001                     break;
2002                 case EVENT_DATA_CONNECTION_STATE_CHANGED:
2003                     onDataConnectionStateChanged(
2004                             (DataConnectionStatusTracker.DataConnectionChangedInfo) ar.mResult);
2005                     break;
2006                 case EVENT_PROVISIONING_INFO_CHANGED:
2007                     onProvisioningInfoChanged(
2008                             (QnsProvisioningListener.QnsProvisioningInfo) ar.mResult);
2009                     break;
2010                 case EVENT_IMS_REGISTRATION_STATE_CHANGED:
2011                     onImsRegStateChanged((QnsImsManager.ImsRegistrationState) ar.mResult);
2012                     break;
2013                 case EVENT_SIP_DIALOG_SESSION_STATE_CHANGED:
2014                     onSipDialogSessionStateChanged((boolean) ar.mResult);
2015                     break;
2016                 case EVENT_IMS_CALL_DISCONNECT_CAUSE_CHANGED:
2017                     onImsCallDisconnectCauseChanged((ImsReasonInfo) ar.mResult);
2018                     break;
2019                 case QnsEventDispatcher.QNS_EVENT_WFC_ENABLED:
2020                     onWfcEnabledChanged(true, false);
2021                     break;
2022                 case QnsEventDispatcher.QNS_EVENT_WFC_DISABLED:
2023                     onWfcEnabledChanged(false, false);
2024                     break;
2025                 case QnsEventDispatcher.QNS_EVENT_WFC_MODE_TO_WIFI_ONLY:
2026                     onWfcModeChanged(QnsConstants.WIFI_ONLY, false);
2027                     break;
2028                 case QnsEventDispatcher.QNS_EVENT_WFC_MODE_TO_CELLULAR_PREFERRED:
2029                     onWfcModeChanged(QnsConstants.CELL_PREF, false);
2030                     break;
2031                 case QnsEventDispatcher.QNS_EVENT_WFC_MODE_TO_WIFI_PREFERRED:
2032                     onWfcModeChanged(QnsConstants.WIFI_PREF, false);
2033                     break;
2034                 case QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_ENABLED:
2035                     onWfcEnabledChanged(true, true);
2036                     break;
2037                 case QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_DISABLED:
2038                     onWfcEnabledChanged(false, true);
2039                     break;
2040                 case QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_ONLY:
2041                     onWfcModeChanged(QnsConstants.WIFI_ONLY, true);
2042                     break;
2043                 case QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_MODE_TO_CELLULAR_PREFERRED:
2044                     onWfcModeChanged(QnsConstants.CELL_PREF, true);
2045                     break;
2046                 case QnsEventDispatcher.QNS_EVENT_WFC_ROAMING_MODE_TO_WIFI_PREFERRED:
2047                     onWfcModeChanged(QnsConstants.WIFI_PREF, true);
2048                     break;
2049                 case QnsEventDispatcher.QNS_EVENT_WFC_PLATFORM_ENABLED:
2050                     onWfcPlatformChanged(true);
2051                     break;
2052                 case QnsEventDispatcher.QNS_EVENT_WFC_PLATFORM_DISABLED:
2053                     onWfcPlatformChanged(false);
2054                     break;
2055                 case QnsEventDispatcher.QNS_EVENT_SIM_ABSENT:
2056                     onSimAbsent();
2057                     break;
2058                 case EVENT_WIFI_RTT_STATUS_CHANGED:
2059                     onRttStatusChanged((boolean) ar.mResult);
2060                     break;
2061                 case QnsEventDispatcher.QNS_EVENT_TRY_WFC_ACTIVATION:
2062                     onTryWfcConnectionStateChanged(true);
2063                     break;
2064                 case QnsEventDispatcher.QNS_EVENT_CANCEL_TRY_WFC_ACTIVATION:
2065                     onTryWfcConnectionStateChanged(false);
2066                     break;
2067                 default:
2068                     log("never reach here msg=" + message.what);
2069             }
2070         }
2071     }
2072 
2073     private class ThresholdListener extends ThresholdCallback
2074             implements ThresholdCallback.WifiThresholdListener,
2075                     ThresholdCallback.CellularThresholdListener {
2076 
ThresholdListener(Executor executor)2077         ThresholdListener(Executor executor) {
2078             this.init(executor);
2079         }
2080 
2081         @Override
onWifiThresholdChanged(Threshold[] thresholds)2082         public void onWifiThresholdChanged(Threshold[] thresholds) {
2083             onWiFiQualityChanged(thresholds);
2084         }
2085 
2086         @Override
onCellularThresholdChanged(Threshold[] thresholds)2087         public void onCellularThresholdChanged(Threshold[] thresholds) {
2088             onCellularQualityChanged(thresholds);
2089         }
2090     }
2091 
2092     /**
2093      * Dumps the state of {@link QualityMonitor}
2094      *
2095      * @param pw {@link PrintWriter} to write the state of the object.
2096      * @param prefix String to append at start of dumped log.
2097      */
dump(PrintWriter pw, String prefix)2098     void dump(PrintWriter pw, String prefix) {
2099         pw.println(prefix + "------------------------------");
2100         pw.println(
2101                 prefix
2102                         + "ANE["
2103                         + QnsUtils.getNameOfNetCapability(mNetCapability)
2104                         + "_"
2105                         + mSlotIndex
2106                         + "]:");
2107         pw.println(prefix + "mInitialized=" + mInitialized);
2108         pw.println(
2109                 prefix
2110                         + "mQualifiedNetworksChangedRegistrant size="
2111                         + mQualifiedNetworksChangedRegistrants.size());
2112         pw.println(
2113                 prefix
2114                         + "mCellularAccessNetworkType="
2115                         + QnsConstants.accessNetworkTypeToString(mCellularAccessNetworkType)
2116                         + ", mLatestAvailableCellularAccessNetwork="
2117                         + QnsConstants.accessNetworkTypeToString(
2118                                 mLatestAvailableCellularAccessNetwork)
2119                         + ", mIsNotifiedLastQualifiedAccessNetworkTypes="
2120                         + mIsNotifiedLastQualifiedAccessNetworkTypes);
2121         pw.print(prefix + "mLastQualifiedAccessNetworkTypes=");
2122         mLastQualifiedAccessNetworkTypes.forEach(
2123                 accessNetwork ->
2124                         pw.print(QnsConstants.accessNetworkTypeToString(accessNetwork) + "|"));
2125         pw.println(
2126                 ", mIsNotifiedLastQualifiedAccessNetworkTypes="
2127                         + mIsNotifiedLastQualifiedAccessNetworkTypes);
2128         pw.println(
2129                 prefix
2130                         + "mCellularAvailable="
2131                         + mCellularAvailable
2132                         + ", mIwlanAvailable="
2133                         + mIwlanAvailable
2134                         + ", mIsCrossWfc="
2135                         + QnsConstants.callTypeToString(mCallType)
2136                         + ", mCoverage"
2137                         + QnsConstants.coverageToString(mCoverage));
2138         pw.println(
2139                 prefix
2140                         + "mWfcPlatformEnabled="
2141                         + mWfcPlatformEnabled
2142                         + ", mSettingWfcEnabled="
2143                         + mSettingWfcEnabled
2144                         + ", mSettingWfcMode="
2145                         + QnsConstants.preferenceToString(mSettingWfcMode)
2146                         + ", mSettingWfcRoamingEnabled="
2147                         + mSettingWfcRoamingEnabled
2148                         + ", mSettingWfcRoamingMode="
2149                         + QnsConstants.preferenceToString(mSettingWfcRoamingMode)
2150                         + ", mAllowIwlanForWfcActivation="
2151                         + mAllowIwlanForWfcActivation);
2152         pw.println(prefix + "mLastProvisioningInfo=" + mLastProvisioningInfo);
2153         pw.println(prefix + "mAccessNetworkSelectionPolicies=" + mAccessNetworkSelectionPolicies);
2154         pw.println(prefix + "mAnspPolicyMap=" + mAnspPolicyMap);
2155         pw.println(prefix + "mCachedTransportTypeForEmergencyInitialConnect"
2156                 + mCachedTransportTypeForEmergencyInitialConnect);
2157         mRestrictManager.dump(pw, prefix + "  ");
2158     }
2159 
2160     @VisibleForTesting
getSipDialogSessionState()2161     boolean getSipDialogSessionState() {
2162         return mSipDialogSessionState;
2163     }
2164 
sendMetricsForQualifiedNetworks(QualifiedNetworksInfo info)2165     private void sendMetricsForQualifiedNetworks(QualifiedNetworksInfo info) {
2166         if (!mCellularAvailable
2167                 || !mIwlanAvailable
2168                 || mCellularAccessNetworkType == AccessNetworkType.UNKNOWN
2169                 || mLastEvaluateSpecificReason == EVALUATE_SPECIFIC_REASON_DATA_DISCONNECTED) {
2170             // b/268557926, decided to cut off if WWAN and WLAN are not in contention.
2171             return;
2172         }
2173         mQnsMetrics.reportAtomForQualifiedNetworks(
2174                 info,
2175                 mSlotIndex,
2176                 mDataConnectionStatusTracker.getLastTransportType(),
2177                 mCoverage,
2178                 mSettingWfcEnabled,
2179                 mSettingWfcRoamingEnabled,
2180                 mSettingWfcMode,
2181                 mSettingWfcRoamingMode,
2182                 mCellularAccessNetworkType,
2183                 mIwlanAvailable,
2184                 mIsCrossWfc,
2185                 mRestrictManager,
2186                 mCellularQualityMonitor,
2187                 mWifiQualityMonitor,
2188                 mCallType);
2189     }
2190 
sendMetricsForCallTypeChanged(int oldCallType, int newCallType)2191     private void sendMetricsForCallTypeChanged(int oldCallType, int newCallType) {
2192         int transportTypeOfCall = mDataConnectionStatusTracker.getLastTransportType();
2193         mQnsMetrics.reportAtomForCallTypeChanged(mNetCapability, mSlotIndex,
2194                 oldCallType, newCallType, mRestrictManager, transportTypeOfCall);
2195     }
2196 
sendMetricsForDataConnectionChanged( DataConnectionStatusTracker.DataConnectionChangedInfo info)2197     private void sendMetricsForDataConnectionChanged(
2198             DataConnectionStatusTracker.DataConnectionChangedInfo info) {
2199         mQnsMetrics.reportAtomForDataConnectionChanged(
2200                 mNetCapability, mSlotIndex, info, mConfigManager.getCarrierId());
2201     }
2202 
sendMetricsForImsCallDropStats()2203     private void sendMetricsForImsCallDropStats() {
2204         int transportTypeOfCall = mDataConnectionStatusTracker.getLastTransportType();
2205         mQnsMetrics.reportAtomForImsCallDropStats(mNetCapability, mSlotIndex, mRestrictManager,
2206                 mCellularQualityMonitor, mWifiQualityMonitor, transportTypeOfCall,
2207                 mCellularAccessNetworkType);
2208     }
2209 
2210 }
2211