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.telephony.AccessNetworkConstants;
20 import android.util.Log;
21 
22 import java.util.ArrayList;
23 import java.util.List;
24 import java.util.Objects;
25 import java.util.concurrent.atomic.AtomicInteger;
26 
27 class AccessNetworkSelectionPolicy {
28     private static final AtomicInteger sAid = new AtomicInteger();
29 
30     private final int mPolicyId;
31     private final int mNetCapability;
32     private final int mTargetTransportType; // AccessNetworkConstants WWAN or WLAN
33     private final PreCondition mPreCondition;
34     private final PostCondition mPostCondition;
35     private final String mLogTag;
36     private ThresholdGroup mLastMatchedThresholdGroup;
37 
AccessNetworkSelectionPolicy( int netCapability, int targetTransportType, PreCondition preCondition, List<ThresholdGroup> thgroups)38     AccessNetworkSelectionPolicy(
39             int netCapability,
40             int targetTransportType,
41             PreCondition preCondition,
42             List<ThresholdGroup> thgroups) {
43         mPolicyId = sAid.getAndIncrement();
44         mLogTag =
45                 QnsConstants.QNS_TAG
46                         + "_"
47                         + AccessNetworkSelectionPolicy.class.getSimpleName()
48                         + "_"
49                         + mPolicyId
50                         + "_"
51                         + QnsUtils.getNameOfNetCapability(netCapability);
52         mNetCapability = netCapability;
53         mTargetTransportType = targetTransportType;
54         mPreCondition = preCondition;
55         mPostCondition = new PostCondition(thgroups);
56     }
57 
58     @Override
toString()59     public String toString() {
60         return "[AnsPolicy"
61                 + mPolicyId
62                 + ":"
63                 + QnsUtils.getNameOfNetCapability(mNetCapability)
64                 + "]"
65                 + QnsConstants.transportTypeToString(mTargetTransportType)
66                 + ","
67                 + mPreCondition.toString()
68                 + mPostCondition.toString();
69     }
70 
getTargetTransportType()71     int getTargetTransportType() {
72         return mTargetTransportType;
73     }
74 
satisfyPrecondition(PreCondition preCondition)75     boolean satisfyPrecondition(PreCondition preCondition) {
76         return mPreCondition.satisfied(preCondition);
77     }
78 
satisfiedByThreshold( QualityMonitor wifiMonitor, QualityMonitor cellMonitor, boolean iwlanAvailable, boolean cellAvailable, int cellularAccessNetworkType)79     boolean satisfiedByThreshold(
80             QualityMonitor wifiMonitor,
81             QualityMonitor cellMonitor,
82             boolean iwlanAvailable,
83             boolean cellAvailable,
84             int cellularAccessNetworkType) {
85         if (wifiMonitor == null || cellMonitor == null) {
86             return false;
87         }
88         return mPostCondition.satisfiedByThreshold(
89                 wifiMonitor, cellMonitor, iwlanAvailable, cellAvailable, cellularAccessNetworkType);
90     }
91 
findUnmatchedThresholds( QualityMonitor wifiMonitor, QualityMonitor cellMonitor)92     List<Threshold> findUnmatchedThresholds(
93             QualityMonitor wifiMonitor, QualityMonitor cellMonitor) {
94         if (wifiMonitor == null || cellMonitor == null) {
95             return null;
96         }
97         return mPostCondition.findUnmatchedThresholds(wifiMonitor, cellMonitor);
98     }
99 
log(String s)100     protected void log(String s) {
101         Log.d(mLogTag, s);
102     }
103 
hasWifiThresholdWithoutCellularCondition()104     boolean hasWifiThresholdWithoutCellularCondition() {
105         return mPostCondition.hasWifiThresholdWithoutCellularCondition();
106     }
107 
satisfiedWithWifiLowSignalStrength()108     boolean satisfiedWithWifiLowSignalStrength() {
109         List<Threshold> thList =
110                 mLastMatchedThresholdGroup.getThresholds(
111                         AccessNetworkConstants.AccessNetworkType.IWLAN);
112         if (thList != null) {
113             for (Threshold th : thList) {
114                 if (th.getMatchType() == QnsConstants.THRESHOLD_EQUAL_OR_SMALLER) {
115                     log("satisfiedWithWifiLowSignalStrength");
116                     return true;
117                 }
118             }
119         }
120         return false;
121     }
122 
getPreCondition()123     PreCondition getPreCondition() {
124         return mPreCondition;
125     }
126 
127     protected static class PreCondition {
128         @QnsConstants.QnsCallType private final int mCallType;
129         @QnsConstants.WfcModePreference private final int mPreference;
130         @QnsConstants.CellularCoverage private final int mCoverage;
131 
PreCondition( @nsConstants.QnsCallType int callType, @QnsConstants.WfcModePreference int preference, @QnsConstants.CellularCoverage int coverage)132         protected PreCondition(
133                 @QnsConstants.QnsCallType int callType,
134                 @QnsConstants.WfcModePreference int preference,
135                 @QnsConstants.CellularCoverage int coverage) {
136             mCallType = callType;
137             mCoverage = coverage;
138             mPreference = preference;
139         }
140 
satisfied(PreCondition preCondition)141         boolean satisfied(PreCondition preCondition) {
142             return (mCallType == preCondition.mCallType)
143                     && (mCoverage == preCondition.mCoverage)
144                     && (mPreference == preCondition.mPreference);
145         }
146 
getCallType()147         int getCallType() {
148             return mCallType;
149         }
150 
getPreference()151         int getPreference() {
152             return mPreference;
153         }
154 
getCoverage()155         int getCoverage() {
156             return mCoverage;
157         }
158 
159         @Override
toString()160         public String toString() {
161             return QnsConstants.callTypeToString(mCallType)
162                     + ","
163                     + QnsConstants.preferenceToString(mPreference)
164                     + ","
165                     + QnsConstants.coverageToString(mCoverage)
166                     + ",";
167         }
168 
169         @Override
equals(Object o)170         public boolean equals(Object o) {
171             if (this == o) return true;
172             if (!(o instanceof PreCondition)) return false;
173             PreCondition that = (PreCondition) o;
174             return mCallType == that.mCallType
175                     && mPreference == that.mPreference
176                     && mCoverage == that.mCoverage;
177         }
178 
179         @Override
hashCode()180         public int hashCode() {
181             return Objects.hash(mCallType, mPreference, mCoverage);
182         }
183     }
184 
185     protected static class GuardingPreCondition extends PreCondition {
186         @QnsConstants.QnsGuarding private final int mGuarding;
187 
GuardingPreCondition( @nsConstants.QnsCallType int callType, @QnsConstants.WfcModePreference int preference, @QnsConstants.CellularCoverage int coverage, @QnsConstants.QnsGuarding int guarding)188         protected GuardingPreCondition(
189                 @QnsConstants.QnsCallType int callType,
190                 @QnsConstants.WfcModePreference int preference,
191                 @QnsConstants.CellularCoverage int coverage,
192                 @QnsConstants.QnsGuarding int guarding) {
193             super(callType, preference, coverage);
194             mGuarding = guarding;
195         }
196 
satisfied(PreCondition preCondition)197         boolean satisfied(PreCondition preCondition) {
198             if (preCondition instanceof GuardingPreCondition) {
199                 return super.satisfied(preCondition)
200                         && mGuarding == ((GuardingPreCondition) preCondition).mGuarding;
201             }
202             return super.satisfied(preCondition);
203         }
204 
getGuarding()205         int getGuarding() {
206             return mGuarding;
207         }
208 
209         @Override
toString()210         public String toString() {
211             return QnsConstants.guardingToString(mGuarding) + "," + super.toString();
212         }
213 
214         @Override
equals(Object o)215         public boolean equals(Object o) {
216             if (this == o) return true;
217             if (!(o instanceof GuardingPreCondition)) return false;
218             if (!super.equals(o)) return false;
219             GuardingPreCondition that = (GuardingPreCondition) o;
220             return mGuarding == that.mGuarding;
221         }
222 
223         @Override
hashCode()224         public int hashCode() {
225             return Objects.hash(super.hashCode(), mGuarding);
226         }
227     }
228 
229     protected class PostCondition {
230         private final List<ThresholdGroup> mThresholdGroups;
231 
PostCondition(List<ThresholdGroup> thGroups)232         protected PostCondition(List<ThresholdGroup> thGroups) {
233             mThresholdGroups = thGroups;
234         }
235 
satisfiedByThreshold( QualityMonitor wifiMonitor, QualityMonitor cellMonitor, boolean iwlanAvailable, boolean cellAvailable, int cellularAccessNetworkType)236         protected boolean satisfiedByThreshold(
237                 QualityMonitor wifiMonitor,
238                 QualityMonitor cellMonitor,
239                 boolean iwlanAvailable,
240                 boolean cellAvailable,
241                 int cellularAccessNetworkType) {
242             // if one of thresholdgroup satisfies, return true;
243             if (mThresholdGroups != null) {
244                 for (ThresholdGroup thgroup : mThresholdGroups) {
245                     if (thgroup.satisfiedByThreshold(
246                             wifiMonitor,
247                             cellMonitor,
248                             iwlanAvailable,
249                             cellAvailable,
250                             cellularAccessNetworkType)) {
251                         mLastMatchedThresholdGroup = thgroup;
252                         return true;
253                     }
254                 }
255             }
256             return false;
257         }
258 
findUnmatchedThresholds( QualityMonitor wifiMonitor, QualityMonitor cellMonitor)259         protected List<Threshold> findUnmatchedThresholds(
260                 QualityMonitor wifiMonitor, QualityMonitor cellMonitor) {
261             List<Threshold> unmatchedThresholds = new ArrayList<>();
262             if (mThresholdGroups != null) {
263                 for (ThresholdGroup thgroup : mThresholdGroups) {
264                     unmatchedThresholds.addAll(
265                             thgroup.findUnmatchedThresholds(wifiMonitor, cellMonitor));
266                 }
267             }
268             return unmatchedThresholds;
269         }
270 
hasWifiThresholdWithoutCellularCondition()271         boolean hasWifiThresholdWithoutCellularCondition() {
272             if (mThresholdGroups == null) {
273                 return false;
274             }
275             for (ThresholdGroup thresholdGroup : mThresholdGroups) {
276                 if (thresholdGroup.hasWifiThresholdWithoutCellularCondition()) {
277                     return true;
278                 }
279             }
280             return false;
281         }
282 
283         @Override
toString()284         public String toString() {
285             StringBuilder sb = new StringBuilder();
286             if (mThresholdGroups != null && mThresholdGroups.size() > 0) {
287                 for (ThresholdGroup thgroup : mThresholdGroups) {
288                     sb.append(thgroup.toShortString()).append(",");
289                 }
290                 sb.deleteCharAt(sb.lastIndexOf(","));
291             }
292             return sb.toString();
293         }
294     }
295 }
296