• 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         /**
234          * Single data network arbitration. On certain RATs, only one data network is allowed at the
235          * same time.
236          */
237         SINGLE_DATA_NETWORK_ARBITRATION(true),
238         /** Query from {@link TelephonyManager#isDataConnectivityPossible()}. */
239         EXTERNAL_QUERY(false),
240         /** Tracking area code changed. */
241         TAC_CHANGED(true);
242 
243         /**
244          * {@code true} if the evaluation is due to environmental changes (i.e. SIM removal,
245          * registration state changes, etc....
246          */
247         private final boolean mIsConditionBased;
248 
249         /**
250          * @return {@code true} if the evaluation is due to environmental changes (i.e. SIM removal,
251          * registration state changes, etc....
252          */
isConditionBased()253         public boolean isConditionBased() {
254             return mIsConditionBased;
255         }
256 
257         /**
258          * Constructor
259          *
260          * @param isConditionBased {@code true} if the evaluation is due to environmental changes
261          * (i.e. SIM removal, registration state changes, etc....)
262          */
DataEvaluationReason(boolean isConditionBased)263         DataEvaluationReason(boolean isConditionBased) {
264             mIsConditionBased = isConditionBased;
265         }
266     }
267 
268     /** Disallowed reasons. There could be multiple reasons if it is not allowed. */
269     public enum DataDisallowedReason {
270         // Soft failure reasons. A soft reason means that in certain conditions, data is still
271         // allowed. Normally those reasons are due to users settings.
272         /** Data is disabled by the user or policy. */
273         DATA_DISABLED(false),
274         /** Data roaming is disabled by the user. */
275         ROAMING_DISABLED(false),
276         /** Default data not selected. */
277         DEFAULT_DATA_UNSELECTED(false),
278 
279         // Belows are all hard failure reasons. A hard reason means no matter what the data should
280         // not be allowed.
281         /** Data registration state is not in service. */
282         NOT_IN_SERVICE(true),
283         /** Data config is not ready. */
284         DATA_CONFIG_NOT_READY(true),
285         /** SIM is not ready. */
286         SIM_NOT_READY(true),
287         /** Concurrent voice and data is not allowed. */
288         CONCURRENT_VOICE_DATA_NOT_ALLOWED(true),
289         /** Carrier notified data should be restricted. */
290         DATA_RESTRICTED_BY_NETWORK(true),
291         /** Radio power is off (i.e. airplane mode on) */
292         RADIO_POWER_OFF(true),
293         /** Data setup now allowed due to pending tear down all networks. */
294         PENDING_TEAR_DOWN_ALL(true),
295         /** Airplane mode is forcibly turned on by the carrier. */
296         RADIO_DISABLED_BY_CARRIER(true),
297         /** Underlying data service is not bound. */
298         DATA_SERVICE_NOT_READY(true),
299         /** Unable to find a suitable data profile. */
300         NO_SUITABLE_DATA_PROFILE(true),
301         /** Current data network type not allowed. */
302         DATA_NETWORK_TYPE_NOT_ALLOWED(true),
303         /** Device is currently in CDMA ECBM. */
304         CDMA_EMERGENCY_CALLBACK_MODE(true),
305         /** There is already a retry setup/handover scheduled. */
306         RETRY_SCHEDULED(true),
307         /** Network has explicitly request to throttle setup attempt. */
308         DATA_THROTTLED(true),
309         /** Data profile becomes invalid. (could be removed by the user, or SIM refresh, etc..) */
310         DATA_PROFILE_INVALID(true),
311         /** Data profile not preferred (i.e. users switch preferred profile in APN editor.) */
312         DATA_PROFILE_NOT_PREFERRED(true),
313         /** Handover is not allowed by policy. */
314         NOT_ALLOWED_BY_POLICY(true),
315         /** Data network is not in the right state. */
316         ILLEGAL_STATE(true),
317         /** VoPS is not supported by the network. */
318         VOPS_NOT_SUPPORTED(true),
319         /** Only one data network is allowed at one time. */
320         ONLY_ALLOWED_SINGLE_NETWORK(true),
321         /** Data enabled settings are not ready. */
322         DATA_SETTINGS_NOT_READY(true);
323 
324         private final boolean mIsHardReason;
325 
326         /**
327          * @return {@code true} if the disallowed reason is a hard reason.
328          */
isHardReason()329         public boolean isHardReason() {
330             return mIsHardReason;
331         }
332 
333         /**
334          * Constructor
335          *
336          * @param isHardReason {@code true} if the disallowed reason is a hard reason. A hard reason
337          * means no matter what the data should not be allowed. A soft reason means that in certain
338          * conditions, data is still allowed.
339          */
DataDisallowedReason(boolean isHardReason)340         DataDisallowedReason(boolean isHardReason) {
341             mIsHardReason = isHardReason;
342         }
343     }
344 
345     /**
346      * Data allowed reasons. There will be only one reason if data is allowed.
347      */
348     public enum DataAllowedReason {
349         // Note that unlike disallowed reasons, we only have one allowed reason every time
350         // when we check data is allowed or not. The order of these allowed reasons is very
351         // important. The lower ones take precedence over the upper ones.
352         /**
353          * None. This is the initial value.
354          */
355         NONE,
356         /**
357          * The normal reason. This is the most common case.
358          */
359         NORMAL,
360         /**
361          * The network brought up by this network request is unmetered. Should allowed no matter
362          * the user enables or disables data.
363          */
364         UNMETERED_USAGE,
365         /**
366          * The network request supports MMS and MMS is always allowed.
367          */
368         MMS_REQUEST,
369         /**
370          * The network request is restricted (i.e. Only privilege apps can access the network.)
371          */
372         RESTRICTED_REQUEST,
373         /**
374          * SUPL is allowed while emergency call is ongoing.
375          */
376         EMERGENCY_SUPL,
377         /**
378          * Data is allowed because the network request is for emergency. This should be always at
379          * the bottom (i.e. highest priority)
380          */
381         EMERGENCY_REQUEST,
382     }
383 
384     @Override
toString()385     public String toString() {
386         StringBuilder evaluationStr = new StringBuilder();
387         evaluationStr.append("Data evaluation: evaluation reason:" + mDataEvaluationReason + ", ");
388         if (mDataDisallowedReasons.size() > 0) {
389             evaluationStr.append("Data disallowed reasons:");
390             for (DataDisallowedReason reason : mDataDisallowedReasons) {
391                 evaluationStr.append(" ").append(reason);
392             }
393         } else {
394             evaluationStr.append("Data allowed reason:");
395             evaluationStr.append(" ").append(mDataAllowedReason);
396         }
397         evaluationStr.append(", candidate profile=" + mCandidateDataProfile);
398         evaluationStr.append(", time=" + DataUtils.systemTimeToString(mEvaluatedTime));
399         return evaluationStr.toString();
400     }
401 
402 }
403