• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2021 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package com.android.internal.telephony.data;
18 
19 import android.annotation.CurrentTimeMillisLong;
20 import android.annotation.NonNull;
21 import android.annotation.Nullable;
22 import android.telephony.TelephonyManager;
23 import android.telephony.data.DataProfile;
24 
25 import com.android.internal.annotations.VisibleForTesting;
26 
27 import java.util.ArrayList;
28 import java.util.HashSet;
29 import java.util.List;
30 import java.util.Set;
31 
32 /**
33  * The class to describe a data evaluation for whether allowing or disallowing certain operations
34  * like setup a data network, sustaining existing data networks, or handover between IWLAN and
35  * cellular.
36  */
37 public class DataEvaluation {
38     /** The reason for this evaluation */
39     private final @NonNull DataEvaluationReason mDataEvaluationReason;
40 
41     /** Data disallowed reasons. There could be multiple reasons for not allowing data. */
42     private final @NonNull Set<DataDisallowedReason> mDataDisallowedReasons = new HashSet<>();
43 
44     /** Data allowed reason. It is intended to only have one allowed reason. */
45     private @NonNull DataAllowedReason mDataAllowedReason = DataAllowedReason.NONE;
46 
47     private @Nullable DataProfile mCandidateDataProfile = null;
48 
49     /** The timestamp of evaluation time */
50     private @CurrentTimeMillisLong long mEvaluatedTime = 0;
51 
52     /**
53      * Constructor
54      *
55      * @param reason The reason for this evaluation.
56      */
DataEvaluation(DataEvaluationReason reason)57     public DataEvaluation(DataEvaluationReason reason) {
58         mDataEvaluationReason = reason;
59     }
60 
61     /**
62      * Add a data disallowed reason. Note that adding a disallowed reason will clean up the
63      * allowed reason because they are mutual exclusive.
64      *
65      * @param reason Disallowed reason.
66      */
addDataDisallowedReason(DataDisallowedReason reason)67     public void addDataDisallowedReason(DataDisallowedReason reason) {
68         mDataAllowedReason = DataAllowedReason.NONE;
69         mDataDisallowedReasons.add(reason);
70         mEvaluatedTime = System.currentTimeMillis();
71     }
72 
73     /**
74      * Remove a data disallowed reason if one exists.
75      *
76      * @param reason Disallowed reason.
77      */
removeDataDisallowedReason(DataDisallowedReason reason)78     public void removeDataDisallowedReason(DataDisallowedReason reason) {
79         mDataDisallowedReasons.remove(reason);
80         mEvaluatedTime = System.currentTimeMillis();
81     }
82 
83     /**
84      * Add a data allowed reason. Note that adding an allowed reason will clean up the disallowed
85      * reasons because they are mutual exclusive.
86      *
87      * @param reason Allowed reason.
88      */
addDataAllowedReason(DataAllowedReason reason)89     public void addDataAllowedReason(DataAllowedReason reason) {
90         mDataDisallowedReasons.clear();
91 
92         // Only higher priority allowed reason can overwrite the old one. See
93         // DataAllowedReason for the oder.
94         if (reason.ordinal() > mDataAllowedReason.ordinal()) {
95             mDataAllowedReason = reason;
96         }
97         mEvaluatedTime = System.currentTimeMillis();
98     }
99 
100     /**
101      * @return List of data disallowed reasons.
102      */
getDataDisallowedReasons()103     public @NonNull List<DataDisallowedReason> getDataDisallowedReasons() {
104         return new ArrayList<>(mDataDisallowedReasons);
105     }
106 
107     /**
108      * @return The data allowed reason.
109      */
getDataAllowedReason()110     public @NonNull DataAllowedReason getDataAllowedReason() {
111         return mDataAllowedReason;
112     }
113 
114     /**
115      * Set the candidate data profile for setup data network.
116      *
117      * @param dataProfile The candidate data profile.
118      */
setCandidateDataProfile(@onNull DataProfile dataProfile)119     public void setCandidateDataProfile(@NonNull DataProfile dataProfile) {
120         mCandidateDataProfile = dataProfile;
121     }
122 
123     /**
124      * @return The candidate data profile for setup data network.
125      */
getCandidateDataProfile()126     public @Nullable DataProfile getCandidateDataProfile() {
127         return mCandidateDataProfile;
128     }
129 
130     /**
131      * @return {@code true} if the evaluation contains disallowed reasons.
132      */
containsDisallowedReasons()133     public boolean containsDisallowedReasons() {
134         return mDataDisallowedReasons.size() != 0;
135     }
136 
137     /**
138      * Check if it contains a certain disallowed reason.
139      *
140      * @param reason The disallowed reason to check.
141      * @return {@code true} if the provided reason matches one of the disallowed reasons.
142      */
contains(DataDisallowedReason reason)143     public boolean contains(DataDisallowedReason reason) {
144         return mDataDisallowedReasons.contains(reason);
145     }
146 
147     /**
148      * Check if only one disallowed reason prevent data connection.
149      *
150      * @param reason The given reason to check
151      * @return {@code true} if the given reason is the only one that prevents data connection
152      */
containsOnly(DataDisallowedReason reason)153     public boolean containsOnly(DataDisallowedReason reason) {
154         return mDataDisallowedReasons.size() == 1 && contains(reason);
155     }
156 
157     /**
158      * Check if the any of the disallowed reasons match one of the provided reason.
159      *
160      * @param reasons The given reasons to check.
161      * @return {@code true} if any of the given reasons matches one of the disallowed reasons.
162      */
containsAny(DataDisallowedReason... reasons)163     public boolean containsAny(DataDisallowedReason... reasons) {
164         for (DataDisallowedReason reason : reasons) {
165             if (mDataDisallowedReasons.contains(reason)) return true;
166         }
167         return false;
168     }
169 
170     /**
171      * Check if the allowed reason is the specified reason.
172      *
173      * @param reason The allowed reason.
174      * @return {@code true} if the specified reason matches the allowed reason.
175      */
contains(DataAllowedReason reason)176     public boolean contains(DataAllowedReason reason) {
177         return reason == mDataAllowedReason;
178     }
179 
180     /**
181      * @return {@code true} if the disallowed reasons contains hard reasons.
182      */
containsHardDisallowedReasons()183     public boolean containsHardDisallowedReasons() {
184         for (DataDisallowedReason reason : mDataDisallowedReasons) {
185             if (reason.isHardReason()) {
186                 return true;
187             }
188         }
189         return false;
190     }
191 
192     /**
193      * The reason for evaluating unsatisfied network requests, existing data networks, and handover.
194      */
195     @VisibleForTesting
196     public enum DataEvaluationReason {
197         /** New request from the apps. */
198         NEW_REQUEST(false),
199         /** Data config changed. */
200         DATA_CONFIG_CHANGED(true),
201         /** SIM is loaded. */
202         SIM_LOADED(true),
203         /** SIM is removed. */
204         SIM_REMOVAL(true),
205         /** Data profiles changed. */
206         DATA_PROFILES_CHANGED(true),
207         /** When service state changes.(For now only considering data RAT and data registration). */
208         DATA_SERVICE_STATE_CHANGED(true),
209         /** When data is enabled or disabled (by user, carrier, thermal, etc...) */
210         DATA_ENABLED_CHANGED(true),
211         /** When data enabled overrides are changed (MMS always allowed, data on non-DDS sub). */
212         DATA_ENABLED_OVERRIDE_CHANGED(true),
213         /** When data roaming is enabled or disabled. */
214         ROAMING_ENABLED_CHANGED(true),
215         /** When voice call ended (for concurrent voice/data not supported RAT). */
216         VOICE_CALL_ENDED(true),
217         /** When network restricts or no longer restricts mobile data. */
218         DATA_RESTRICTED_CHANGED(true),
219         /** Network capabilities changed. The unsatisfied requests might have chances to attach. */
220         DATA_NETWORK_CAPABILITIES_CHANGED(true),
221         /** When emergency call started or ended. */
222         EMERGENCY_CALL_CHANGED(true),
223         /** When data disconnected, re-evaluate later to see if data could be brought up again. */
224         RETRY_AFTER_DISCONNECTED(true),
225         /** Data setup retry. */
226         DATA_RETRY(false),
227         /** For handover evaluation, or for network tearing down after handover succeeds/fails. */
228         DATA_HANDOVER(true),
229         /** Preferred transport changed. */
230         PREFERRED_TRANSPORT_CHANGED(true),
231         /** Slice config changed. */
232         SLICE_CONFIG_CHANGED(true),
233         /** SRVCC state changed. */
234         SRVCC_STATE_CHANGED(true),
235         /**
236          * Single data network arbitration. On certain RATs, only one data network is allowed at the
237          * same time.
238          */
239         SINGLE_DATA_NETWORK_ARBITRATION(true),
240         /** Query from {@link TelephonyManager#isDataConnectivityPossible()}. */
241         EXTERNAL_QUERY(false),
242         /** Tracking area code changed. */
243         TAC_CHANGED(true),
244         /** Unsatisfied network request detached. */
245         UNSATISFIED_REQUEST_DETACHED(true);
246 
247         /**
248          * {@code true} if the evaluation is due to environmental changes (i.e. SIM removal,
249          * registration state changes, etc....
250          */
251         private final boolean mIsConditionBased;
252 
253         /**
254          * @return {@code true} if the evaluation is due to environmental changes (i.e. SIM removal,
255          * registration state changes, etc....
256          */
isConditionBased()257         public boolean isConditionBased() {
258             return mIsConditionBased;
259         }
260 
261         /**
262          * Constructor
263          *
264          * @param isConditionBased {@code true} if the evaluation is due to environmental changes
265          * (i.e. SIM removal, registration state changes, etc....)
266          */
DataEvaluationReason(boolean isConditionBased)267         DataEvaluationReason(boolean isConditionBased) {
268             mIsConditionBased = isConditionBased;
269         }
270     }
271 
272     /** Disallowed reasons. There could be multiple reasons if it is not allowed. */
273     public enum DataDisallowedReason {
274         // Soft failure reasons. A soft reason means that in certain conditions, data is still
275         // allowed. Normally those reasons are due to users settings.
276         /** Data is disabled by the user or policy. */
277         DATA_DISABLED(false),
278         /** Data roaming is disabled by the user. */
279         ROAMING_DISABLED(false),
280         /** Default data not selected. */
281         DEFAULT_DATA_UNSELECTED(false),
282 
283         // Belows are all hard failure reasons. A hard reason means no matter what the data should
284         // not be allowed.
285         /** Data registration state is not in service. */
286         NOT_IN_SERVICE(true),
287         /** Data config is not ready. */
288         DATA_CONFIG_NOT_READY(true),
289         /** SIM is not ready. */
290         SIM_NOT_READY(true),
291         /** Concurrent voice and data is not allowed. */
292         CONCURRENT_VOICE_DATA_NOT_ALLOWED(true),
293         /** Carrier notified data should be restricted. */
294         DATA_RESTRICTED_BY_NETWORK(true),
295         /** Radio power is off (i.e. airplane mode on) */
296         RADIO_POWER_OFF(true),
297         /** Data setup now allowed due to pending tear down all networks. */
298         PENDING_TEAR_DOWN_ALL(true),
299         /** Airplane mode is forcibly turned on by the carrier. */
300         RADIO_DISABLED_BY_CARRIER(true),
301         /** Underlying data service is not bound. */
302         DATA_SERVICE_NOT_READY(true),
303         /** Unable to find a suitable data profile. */
304         NO_SUITABLE_DATA_PROFILE(true),
305         /** Current data network type not allowed. */
306         DATA_NETWORK_TYPE_NOT_ALLOWED(true),
307         /** Device is currently in CDMA ECBM. */
308         CDMA_EMERGENCY_CALLBACK_MODE(true),
309         /** There is already a retry setup/handover scheduled. */
310         RETRY_SCHEDULED(true),
311         /** Network has explicitly request to throttle setup attempt. */
312         DATA_THROTTLED(true),
313         /** Data profile becomes invalid. (could be removed by the user, or SIM refresh, etc..) */
314         DATA_PROFILE_INVALID(true),
315         /** Data profile not preferred (i.e. users switch preferred profile in APN editor.) */
316         DATA_PROFILE_NOT_PREFERRED(true),
317         /** Handover is not allowed by policy. */
318         NOT_ALLOWED_BY_POLICY(true),
319         /** Data network is not in the right state. */
320         ILLEGAL_STATE(true),
321         /** VoPS is not supported by the network. */
322         VOPS_NOT_SUPPORTED(true),
323         /** Only one data network is allowed at one time. */
324         ONLY_ALLOWED_SINGLE_NETWORK(true),
325         /** Data enabled settings are not ready. */
326         DATA_SETTINGS_NOT_READY(true),
327         /** Handover max retry stopped but network is not on the preferred transport. */
328         HANDOVER_RETRY_STOPPED(true);
329 
330         private final boolean mIsHardReason;
331 
332         /**
333          * @return {@code true} if the disallowed reason is a hard reason.
334          */
isHardReason()335         public boolean isHardReason() {
336             return mIsHardReason;
337         }
338 
339         /**
340          * Constructor
341          *
342          * @param isHardReason {@code true} if the disallowed reason is a hard reason. A hard reason
343          * means no matter what the data should not be allowed. A soft reason means that in certain
344          * conditions, data is still allowed.
345          */
DataDisallowedReason(boolean isHardReason)346         DataDisallowedReason(boolean isHardReason) {
347             mIsHardReason = isHardReason;
348         }
349     }
350 
351     /**
352      * Data allowed reasons. There will be only one reason if data is allowed.
353      */
354     public enum DataAllowedReason {
355         // Note that unlike disallowed reasons, we only have one allowed reason every time
356         // when we check data is allowed or not. The order of these allowed reasons is very
357         // important. The lower ones take precedence over the upper ones.
358         /**
359          * None. This is the initial value.
360          */
361         NONE,
362         /**
363          * The normal reason. This is the most common case.
364          */
365         NORMAL,
366         /**
367          * Data is allowed because an ongoing VoPS call depends on this network
368          */
369         IN_VOICE_CALL,
370         /**
371          * The network brought up by this network request is unmetered. Should allowed no matter
372          * the user enables or disables data.
373          */
374         UNMETERED_USAGE,
375         /**
376          * The network request supports MMS and MMS is always allowed.
377          */
378         MMS_REQUEST,
379         /**
380          * The network request is restricted (i.e. Only privilege apps can access the network.)
381          */
382         RESTRICTED_REQUEST,
383         /**
384          * SUPL is allowed while emergency call is ongoing.
385          */
386         EMERGENCY_SUPL,
387         /**
388          * Data is allowed because the network request is for emergency. This should be always at
389          * the bottom (i.e. highest priority)
390          */
391         EMERGENCY_REQUEST,
392     }
393 
394     @Override
toString()395     public String toString() {
396         StringBuilder evaluationStr = new StringBuilder();
397         evaluationStr.append("Data evaluation: evaluation reason:" + mDataEvaluationReason + ", ");
398         if (mDataDisallowedReasons.size() > 0) {
399             evaluationStr.append("Data disallowed reasons:");
400             for (DataDisallowedReason reason : mDataDisallowedReasons) {
401                 evaluationStr.append(" ").append(reason);
402             }
403         } else {
404             evaluationStr.append("Data allowed reason:");
405             evaluationStr.append(" ").append(mDataAllowedReason);
406         }
407         evaluationStr.append(", candidate profile=" + mCandidateDataProfile);
408         evaluationStr.append(", time=" + DataUtils.systemTimeToString(mEvaluatedTime));
409         return evaluationStr.toString();
410     }
411 
412 }
413