• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright 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.CallbackExecutor;
20 import android.annotation.NonNull;
21 import android.content.ContentResolver;
22 import android.content.SharedPreferences;
23 import android.os.Handler;
24 import android.os.Looper;
25 import android.os.Message;
26 import android.os.SystemProperties;
27 import android.preference.PreferenceManager;
28 import android.provider.Settings;
29 import android.sysprop.TelephonyProperties;
30 import android.telephony.CarrierConfigManager;
31 import android.telephony.SubscriptionManager.OnSubscriptionsChangedListener;
32 import android.telephony.TelephonyManager;
33 import android.telephony.TelephonyManager.MobileDataPolicy;
34 import android.telephony.TelephonyRegistryManager;
35 import android.telephony.data.ApnSetting;
36 import android.telephony.data.ApnSetting.ApnType;
37 import android.text.TextUtils;
38 import android.util.ArrayMap;
39 import android.util.ArraySet;
40 import android.util.IndentingPrintWriter;
41 import android.util.LocalLog;
42 
43 import com.android.internal.telephony.GlobalSettingsHelper;
44 import com.android.internal.telephony.Phone;
45 import com.android.internal.telephony.PhoneConstants;
46 import com.android.internal.telephony.PhoneFactory;
47 import com.android.internal.telephony.SettingsObserver;
48 import com.android.internal.telephony.data.DataConfigManager.DataConfigManagerCallback;
49 import com.android.internal.telephony.metrics.DeviceTelephonyPropertiesStats;
50 import com.android.internal.telephony.subscription.SubscriptionInfoInternal;
51 import com.android.internal.telephony.subscription.SubscriptionManagerService;
52 import com.android.internal.telephony.util.TelephonyUtils;
53 import com.android.telephony.Rlog;
54 
55 import java.io.FileDescriptor;
56 import java.io.PrintWriter;
57 import java.util.HashSet;
58 import java.util.Map;
59 import java.util.Set;
60 import java.util.concurrent.Executor;
61 import java.util.stream.Collectors;
62 
63 /**
64  * DataSettingsManager maintains the data related settings, for example, data enabled settings,
65  * data roaming settings, etc...
66  */
67 public class DataSettingsManager extends Handler {
68     /** Invalid mobile data policy **/
69     private static final int INVALID_MOBILE_DATA_POLICY = -1;
70 
71     /** Event for call state changed. */
72     private static final int EVENT_CALL_STATE_CHANGED = 2;
73     /** Event for subscriptions updated. */
74     private static final int EVENT_SUBSCRIPTIONS_CHANGED = 4;
75     /** Event for set data enabled for reason. */
76     private static final int EVENT_SET_DATA_ENABLED_FOR_REASON = 5;
77     /** Event for set data roaming enabled. */
78     private static final int EVENT_SET_DATA_ROAMING_ENABLED = 6;
79     /** Event for set mobile data policy. */
80     private static final int EVENT_SET_MOBILE_DATA_POLICY = 7;
81 
82     /** Event for device provisioned changed. */
83     private static final int EVENT_PROVISIONED_CHANGED = 9;
84     /** Event for provisioning data enabled setting changed. */
85     private static final int EVENT_PROVISIONING_DATA_ENABLED_CHANGED = 10;
86     /** Event for initializing DataSettingsManager. */
87     private static final int EVENT_INITIALIZE = 11;
88 
89     private final Phone mPhone;
90     private final ContentResolver mResolver;
91     private final SettingsObserver mSettingsObserver;
92     private final String mLogTag;
93     private final LocalLog mLocalLog = new LocalLog(128);
94     private Set<Integer> mEnabledMobileDataPolicy = new HashSet<>();
95     private int mSubId;
96 
97     /** Data config manager */
98     private final @NonNull DataConfigManager mDataConfigManager;
99 
100     /** Data settings manager callbacks. */
101     private final @NonNull Set<DataSettingsManagerCallback> mDataSettingsManagerCallbacks =
102             new ArraySet<>();
103 
104     /** Mapping of {@link TelephonyManager.DataEnabledReason} to data enabled values. */
105     private final Map<Integer, Boolean> mDataEnabledSettings = new ArrayMap<>();
106 
107     /**
108      * Flag indicating whether data is allowed or not for the device.
109      * It can be disabled by user, carrier, policy or thermal.
110      */
111     private boolean mIsDataEnabled;
112 
113     /**
114      * Used to indicate that the initial value for mIsDataEnabled was set.
115      * Prevent race condition where the initial value might be incorrect.
116      */
117     private boolean mInitialized = false;
118 
119     /**
120      * Data settings manager callback. This should be only used by {@link DataNetworkController}.
121      */
122     public static class DataSettingsManagerCallback extends DataCallback {
123         /**
124          * Constructor
125          *
126          * @param executor The executor of the callback.
127          */
DataSettingsManagerCallback(@onNull @allbackExecutor Executor executor)128         public DataSettingsManagerCallback(@NonNull @CallbackExecutor Executor executor) {
129             super(executor);
130         }
131 
132         /**
133          * Called when user data enabled state changed.
134          *
135          * @param enabled {@code true} indicates user mobile data is enabled.
136          * @param callingPackage The package that changed the data enabled state.
137          */
onUserDataEnabledChanged(boolean enabled, @NonNull String callingPackage)138         public void onUserDataEnabledChanged(boolean enabled, @NonNull String callingPackage) {}
139 
140         /**
141          * Called when overall data enabled state changed.
142          *
143          * @param enabled {@code true} indicates mobile data is enabled.
144          * @param reason {@link TelephonyManager.DataEnabledChangedReason} indicating the reason why
145          *               mobile data enabled changed.
146          * @param callingPackage The package that changed the data enabled state.
147          */
onDataEnabledChanged(boolean enabled, @TelephonyManager.DataEnabledChangedReason int reason, @NonNull String callingPackage)148         public void onDataEnabledChanged(boolean enabled,
149                 @TelephonyManager.DataEnabledChangedReason int reason,
150                 @NonNull String callingPackage) {}
151 
152         /**
153          * Called when data enabled override changed.
154          *
155          * @param enabled {@code true} indicates data enabled override is enabled.
156          * @param policy {@link TelephonyManager.MobileDataPolicy} indicating the policy that was
157          *               enabled or disabled.
158          */
onDataEnabledOverrideChanged(boolean enabled, @TelephonyManager.MobileDataPolicy int policy)159         public void onDataEnabledOverrideChanged(boolean enabled,
160                 @TelephonyManager.MobileDataPolicy int policy) {}
161 
162         /**
163          * Called when data roaming enabled state changed.
164          *
165          * @param enabled {@code true} indicates data roaming is enabled.
166          */
onDataRoamingEnabledChanged(boolean enabled)167         public void onDataRoamingEnabledChanged(boolean enabled) {}
168     }
169 
170     /**
171      * Constructor
172      *
173      * @param phone The phone instance.
174      * @param dataNetworkController Data network controller.
175      * @param looper The looper to be used by the handler. Currently the handler thread is the
176      * phone process's main thread.
177      * @param callback Data settings manager callback.
178      */
DataSettingsManager(@onNull Phone phone, @NonNull DataNetworkController dataNetworkController, @NonNull Looper looper, @NonNull DataSettingsManagerCallback callback)179     public DataSettingsManager(@NonNull Phone phone,
180             @NonNull DataNetworkController dataNetworkController, @NonNull Looper looper,
181             @NonNull DataSettingsManagerCallback callback) {
182         super(looper);
183         mPhone = phone;
184         mLogTag = "DSMGR-" + mPhone.getPhoneId();
185         log("DataSettingsManager created.");
186         mSubId = mPhone.getSubId();
187         mResolver = mPhone.getContext().getContentResolver();
188         registerCallback(callback);
189         mDataConfigManager = dataNetworkController.getDataConfigManager();
190         refreshEnabledMobileDataPolicy();
191         mSettingsObserver = new SettingsObserver(mPhone.getContext(), this);
192         mDataEnabledSettings.put(TelephonyManager.DATA_ENABLED_REASON_POLICY, true);
193         mDataEnabledSettings.put(TelephonyManager.DATA_ENABLED_REASON_CARRIER, true);
194         mDataEnabledSettings.put(TelephonyManager.DATA_ENABLED_REASON_THERMAL, true);
195 
196         // Instead of calling onInitialize directly from the constructor, send the event.
197         // The reason is that getImsPhone is null when we are still in the constructor here.
198         sendEmptyMessage(EVENT_INITIALIZE);
199     }
200 
201     @Override
handleMessage(Message msg)202     public void handleMessage(Message msg) {
203         switch (msg.what) {
204             case EVENT_CALL_STATE_CHANGED: {
205                 updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_OVERRIDE);
206                 break;
207             }
208             case EVENT_SUBSCRIPTIONS_CHANGED: {
209                 mSubId = (int) msg.obj;
210                 refreshEnabledMobileDataPolicy();
211                 updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_USER);
212                 mPhone.notifyUserMobileDataStateChanged(isUserDataEnabled());
213                 break;
214             }
215             case EVENT_SET_DATA_ENABLED_FOR_REASON: {
216                 String callingPackage = (String) msg.obj;
217                 boolean enabled = msg.arg2 == 1;
218                 switch (msg.arg1) {
219                     case TelephonyManager.DATA_ENABLED_REASON_USER:
220                         setUserDataEnabled(enabled, callingPackage);
221                         break;
222                     case TelephonyManager.DATA_ENABLED_REASON_CARRIER:
223                         setCarrierDataEnabled(enabled, callingPackage);
224                         break;
225                     case TelephonyManager.DATA_ENABLED_REASON_POLICY:
226                         setPolicyDataEnabled(enabled, callingPackage);
227                         break;
228                     case TelephonyManager.DATA_ENABLED_REASON_THERMAL:
229                         setThermalDataEnabled(enabled, callingPackage);
230                         break;
231                     default:
232                         log("Cannot set data enabled for reason: "
233                                 + dataEnabledChangedReasonToString(msg.arg1));
234                         break;
235                 }
236                 break;
237             }
238             case EVENT_SET_DATA_ROAMING_ENABLED: {
239                 boolean enabled = (boolean) msg.obj;
240                 setDataRoamingEnabledInternal(enabled);
241                 setDataRoamingFromUserAction();
242                 break;
243             }
244             case EVENT_SET_MOBILE_DATA_POLICY: {
245                 int mobileDataPolicy = msg.arg1;
246                 boolean enable = msg.arg2 == 1;
247                 onSetMobileDataPolicy(mobileDataPolicy, enable);
248                 break;
249             }
250             case EVENT_PROVISIONED_CHANGED:
251             case EVENT_PROVISIONING_DATA_ENABLED_CHANGED: {
252                 updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_UNKNOWN);
253                 break;
254             }
255             case EVENT_INITIALIZE: {
256                 onInitialize();
257                 break;
258             }
259             default:
260                 loge("Unknown msg.what: " + msg.what);
261         }
262     }
263 
264     /**
265      * Called when needed to register for all events that data network controller is interested.
266      */
onInitialize()267     private void onInitialize() {
268         mDataConfigManager.registerCallback(new DataConfigManagerCallback(this::post) {
269             @Override
270             public void onCarrierConfigChanged() {
271                 if (mDataConfigManager.isConfigCarrierSpecific()) {
272                     setDefaultDataRoamingEnabled();
273                 }
274             }
275         });
276         mSettingsObserver.observe(Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
277                 EVENT_PROVISIONED_CHANGED);
278         mSettingsObserver.observe(
279                 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED),
280                 EVENT_PROVISIONING_DATA_ENABLED_CHANGED);
281         mPhone.getCallTracker().registerForVoiceCallStarted(this, EVENT_CALL_STATE_CHANGED, null);
282         mPhone.getCallTracker().registerForVoiceCallEnded(this, EVENT_CALL_STATE_CHANGED, null);
283         if (mPhone.getImsPhone() != null) {
284             mPhone.getImsPhone().getCallTracker().registerForVoiceCallStarted(
285                     this, EVENT_CALL_STATE_CHANGED, null);
286             mPhone.getImsPhone().getCallTracker().registerForVoiceCallEnded(
287                     this, EVENT_CALL_STATE_CHANGED, null);
288         }
289         mPhone.getContext().getSystemService(TelephonyRegistryManager.class)
290                 .addOnSubscriptionsChangedListener(new OnSubscriptionsChangedListener() {
291                     @Override
292                     public void onSubscriptionsChanged() {
293                         if (mSubId != mPhone.getSubId()) {
294                             log("onSubscriptionsChanged: " + mSubId + " to " + mPhone.getSubId());
295                             obtainMessage(EVENT_SUBSCRIPTIONS_CHANGED, mPhone.getSubId())
296                                     .sendToTarget();
297                         }
298                     }
299                 }, this::post);
300         // some overall mobile data override policy depend on whether DDS is user data enabled.
301         for (Phone phone : PhoneFactory.getPhones()) {
302             if (phone.getPhoneId() != mPhone.getPhoneId()) {
303                 phone.getDataSettingsManager().registerCallback(new DataSettingsManagerCallback(
304                         this::post) {
305                     @Override
306                     public void onUserDataEnabledChanged(boolean enabled,
307                             @NonNull String callingPackage) {
308                         log("phone" + phone.getPhoneId() + " onUserDataEnabledChanged "
309                                 + enabled + " by " + callingPackage
310                                 + ", reevaluating mobile data policies");
311                         DataSettingsManager.this.updateDataEnabledAndNotify(
312                                 TelephonyManager.DATA_ENABLED_REASON_OVERRIDE);
313                     }
314                 });
315             }
316         }
317         updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_UNKNOWN);
318     }
319 
320     /**
321      * Enable or disable data for a specific {@link TelephonyManager.DataEnabledReason}.
322      * @param reason The reason the data enabled change is taking place.
323      * @param enabled {@code true} to enable data for the given reason and {@code false} to disable.
324      * @param callingPackage The package that changed the data enabled state.
325      */
setDataEnabled(@elephonyManager.DataEnabledReason int reason, boolean enabled, String callingPackage)326     public void setDataEnabled(@TelephonyManager.DataEnabledReason int reason, boolean enabled,
327             String callingPackage) {
328         obtainMessage(EVENT_SET_DATA_ENABLED_FOR_REASON, reason, enabled ? 1 : 0, callingPackage)
329                 .sendToTarget();
330     }
331 
332     /**
333      * Check whether the data is enabled for a specific {@link TelephonyManager.DataEnabledReason}.
334      * @return {@code true} if data is enabled for the given reason and {@code false} otherwise.
335      */
isDataEnabledForReason(@elephonyManager.DataEnabledReason int reason)336     public boolean isDataEnabledForReason(@TelephonyManager.DataEnabledReason int reason) {
337         if (reason == TelephonyManager.DATA_ENABLED_REASON_USER) {
338             return isUserDataEnabled();
339         } else {
340             return mDataEnabledSettings.get(reason);
341         }
342     }
343 
updateDataEnabledAndNotify(@elephonyManager.DataEnabledChangedReason int reason)344     private void updateDataEnabledAndNotify(@TelephonyManager.DataEnabledChangedReason int reason) {
345         updateDataEnabledAndNotify(reason, mPhone.getContext().getOpPackageName());
346     }
347 
updateDataEnabledAndNotify(@elephonyManager.DataEnabledChangedReason int reason, @NonNull String callingPackage)348     private void updateDataEnabledAndNotify(@TelephonyManager.DataEnabledChangedReason int reason,
349             @NonNull String callingPackage) {
350         boolean prevDataEnabled = mIsDataEnabled;
351         mIsDataEnabled = isDataEnabled(ApnSetting.TYPE_ALL);
352         log("mIsDataEnabled=" + mIsDataEnabled + ", prevDataEnabled=" + prevDataEnabled);
353         if (!mInitialized || prevDataEnabled != mIsDataEnabled) {
354             if (!mInitialized) mInitialized = true;
355             notifyDataEnabledChanged(mIsDataEnabled, reason, callingPackage);
356         }
357     }
358 
359     /**
360      * Check whether the user data is enabled when the device is in the provisioning stage.
361      * In provisioning, we might want to enable mobile data depending on the value of
362      * Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED, which is set by setupwizard.
363      * @return {@code true} if user data is enabled when provisioning and {@code false} otherwise.
364      */
isProvisioningDataEnabled()365     private boolean isProvisioningDataEnabled() {
366         final String prov_property = SystemProperties.get("ro.com.android.prov_mobiledata",
367                 "false");
368         boolean retVal = "true".equalsIgnoreCase(prov_property);
369 
370         final int prov_mobile_data = Settings.Global.getInt(mResolver,
371                 Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED,
372                 retVal ? 1 : 0);
373         retVal = prov_mobile_data != 0;
374         log("getDataEnabled during provisioning retVal=" + retVal + " - (" + prov_property
375                 + ", " + prov_mobile_data + ")");
376 
377         return retVal;
378     }
379 
380     /**
381      * Check whether the overall data is enabled for the device. Note that this value will only
382      * be accurate if {@link #isDataInitialized} is {@code true}.
383      * @return {@code true} if the overall data is enabled and {@code false} otherwise.
384      */
isDataEnabled()385     public boolean isDataEnabled() {
386         return mIsDataEnabled;
387     }
388 
389     /**
390      * Check whether data enabled value has been initialized. If this is {@code false}, then
391      * {@link #isDataEnabled} is not guaranteed to be accurate. Once data is initialized,
392      * {@link DataSettingsManagerCallback#onDataEnabledChanged} will be invoked with reason
393      * {@link TelephonyManager#DATA_ENABLED_REASON_UNKNOWN}.
394      * @return {@code true} if the data enabled value is initialized and {@code false} otherwise.
395      */
isDataInitialized()396     public boolean isDataInitialized() {
397         // TODO: Create a new DATA_ENABLED_REASON_INITIALIZED for initial value broadcast
398         return mInitialized;
399     }
400 
401     /**
402      * Check whether the overall data is enabled for the device for the given APN type.
403      * @param apnType A single APN type to check data enabled for.
404      * @return {@code true} if the overall data is enabled for the APN and {@code false} otherwise.
405      */
isDataEnabled(@pnType int apnType)406     public boolean isDataEnabled(@ApnType int apnType) {
407         if (Settings.Global.getInt(mResolver, Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
408             return isProvisioningDataEnabled();
409         } else {
410             boolean userDataEnabled = isUserDataEnabled();
411             // Check if we should temporarily enable data based on mobile data policy.
412             boolean isDataEnabledOverridden = isDataEnabledOverriddenForApn(apnType);
413 
414 
415             return ((userDataEnabled || isDataEnabledOverridden)
416                     && mDataEnabledSettings.get(TelephonyManager.DATA_ENABLED_REASON_POLICY)
417                     && mDataEnabledSettings.get(TelephonyManager.DATA_ENABLED_REASON_CARRIER)
418                     && mDataEnabledSettings.get(TelephonyManager.DATA_ENABLED_REASON_THERMAL));
419         }
420     }
421 
isStandAloneOpportunistic(int subId)422     private boolean isStandAloneOpportunistic(int subId) {
423         SubscriptionInfoInternal subInfo = SubscriptionManagerService.getInstance()
424                 .getSubscriptionInfoInternal(subId);
425         return subInfo != null && subInfo.isOpportunistic()
426                 && TextUtils.isEmpty(subInfo.getGroupUuid());
427     }
428 
429     /**
430      * Enable or disable user data.
431      * @param enabled {@code true} to enable user data and {@code false} to disable.
432      * @param callingPackage The package that changed the data enabled state.
433      */
setUserDataEnabled(boolean enabled, String callingPackage)434     private void setUserDataEnabled(boolean enabled, String callingPackage) {
435         // Can't disable data for stand alone opportunistic subscription.
436         if (isStandAloneOpportunistic(mSubId) && !enabled) return;
437         boolean changed = GlobalSettingsHelper.setInt(mPhone.getContext(),
438                 Settings.Global.MOBILE_DATA, mSubId, (enabled ? 1 : 0));
439         log("Set user data enabled to " + enabled + ", changed=" + changed + ", callingPackage="
440                 + callingPackage);
441         if (changed) {
442             logl("UserDataEnabled changed to " + enabled);
443             mPhone.notifyUserMobileDataStateChanged(enabled);
444             mDataSettingsManagerCallbacks.forEach(callback -> callback.invokeFromExecutor(
445                     () -> callback.onUserDataEnabledChanged(enabled, callingPackage)));
446             updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_USER, callingPackage);
447         }
448     }
449 
450     /**
451      * Check whether user data is enabled for the device.
452      * @return {@code true} if user data is enabled and {@code false} otherwise.
453      */
isUserDataEnabled()454     private boolean isUserDataEnabled() {
455         if (Settings.Global.getInt(mResolver, Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
456             return isProvisioningDataEnabled();
457         }
458 
459         // User data should always be true for opportunistic subscription.
460         if (isStandAloneOpportunistic(mSubId)) return true;
461 
462         boolean defaultVal = TelephonyProperties.mobile_data().orElse(true);
463 
464         return GlobalSettingsHelper.getBoolean(mPhone.getContext(),
465                 Settings.Global.MOBILE_DATA, mSubId, defaultVal);
466     }
467 
468     /**
469      * Enable or disable policy data.
470      * @param enabled {@code true} to enable policy data and {@code false} to disable.
471      * @param callingPackage The package that changed the data enabled state.
472      */
setPolicyDataEnabled(boolean enabled, String callingPackage)473     private void setPolicyDataEnabled(boolean enabled, String callingPackage) {
474         if (mDataEnabledSettings.get(TelephonyManager.DATA_ENABLED_REASON_POLICY) != enabled) {
475             logl("PolicyDataEnabled changed to " + enabled + ", callingPackage=" + callingPackage);
476             mDataEnabledSettings.put(TelephonyManager.DATA_ENABLED_REASON_POLICY, enabled);
477             updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_POLICY, callingPackage);
478         }
479     }
480 
481     /**
482      * Enable or disable carrier data.
483      * @param enabled {@code true} to enable carrier data and {@code false} to disable.
484      * @param callingPackage The package that changed the data enabled state.
485      */
setCarrierDataEnabled(boolean enabled, String callingPackage)486     private void setCarrierDataEnabled(boolean enabled, String callingPackage) {
487         if (mDataEnabledSettings.get(TelephonyManager.DATA_ENABLED_REASON_CARRIER) != enabled) {
488             logl("CarrierDataEnabled changed to " + enabled + ", callingPackage=" + callingPackage);
489             mDataEnabledSettings.put(TelephonyManager.DATA_ENABLED_REASON_CARRIER, enabled);
490             updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_CARRIER,
491                     callingPackage);
492         }
493     }
494 
495     /**
496      * Enable or disable thermal data.
497      * @param enabled {@code true} to enable thermal data and {@code false} to disable.
498      * @param callingPackage The package that changed the data enabled state.
499      */
setThermalDataEnabled(boolean enabled, String callingPackage)500     private void setThermalDataEnabled(boolean enabled, String callingPackage) {
501         if (mDataEnabledSettings.get(TelephonyManager.DATA_ENABLED_REASON_THERMAL) != enabled) {
502             logl("ThermalDataEnabled changed to " + enabled + ", callingPackage=" + callingPackage);
503             mDataEnabledSettings.put(TelephonyManager.DATA_ENABLED_REASON_THERMAL, enabled);
504             updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_THERMAL,
505                     callingPackage);
506         }
507     }
508 
509     /**
510      * Enable or disable data roaming from user settings.
511      * @param enabled {@code true} to enable data roaming and {@code false} to disable.
512      */
setDataRoamingEnabled(boolean enabled)513     public void setDataRoamingEnabled(boolean enabled) {
514         obtainMessage(EVENT_SET_DATA_ROAMING_ENABLED, enabled).sendToTarget();
515     }
516 
517     /**
518      * Enable or disable data roaming.
519      * @param enabled {@code true} to enable data roaming and {@code false} to disable.
520      */
setDataRoamingEnabledInternal(boolean enabled)521     private void setDataRoamingEnabledInternal(boolean enabled) {
522         // Will trigger handleDataOnRoamingChange() through observer
523         boolean changed = GlobalSettingsHelper.setBoolean(mPhone.getContext(),
524                 Settings.Global.DATA_ROAMING, mSubId, enabled);
525         if (changed) {
526             logl("DataRoamingEnabled changed to " + enabled);
527             mDataSettingsManagerCallbacks.forEach(callback -> callback.invokeFromExecutor(
528                     () -> callback.onDataRoamingEnabledChanged(enabled)));
529         }
530     }
531 
532     /**
533      * Check whether data roaming is enabled for the device based on the current
534      * {@link Settings.Global#DATA_ROAMING} value.
535      * @return {@code true} if data roaming is enabled and {@code false} otherwise.
536      */
isDataRoamingEnabled()537     public boolean isDataRoamingEnabled() {
538         return GlobalSettingsHelper.getBoolean(mPhone.getContext(),
539                 Settings.Global.DATA_ROAMING, mSubId, isDefaultDataRoamingEnabled());
540     }
541 
542     /**
543      * Check whether data roaming is enabled by default.
544      * This is true if {@link CarrierConfigManager#KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL}
545      * or the system property "ro.com.android.dataroaming" are true.
546      * @return {@code true} if data roaming is enabled by default and {@code false} otherwise.
547      */
isDefaultDataRoamingEnabled()548     public boolean isDefaultDataRoamingEnabled() {
549         return "true".equalsIgnoreCase(SystemProperties.get("ro.com.android.dataroaming", "false"))
550                 || mPhone.getDataNetworkController().getDataConfigManager()
551                         .isDataRoamingEnabledByDefault();
552     }
553 
554     /**
555      * Set default value for {@link android.provider.Settings.Global#DATA_ROAMING} if the user
556      * has not manually set the value. The default value is {@link #isDefaultDataRoamingEnabled()}.
557      */
setDefaultDataRoamingEnabled()558     public void setDefaultDataRoamingEnabled() {
559         // If the user has not manually set the value, use the default value.
560         if (!isDataRoamingFromUserAction()) {
561             setDataRoamingEnabledInternal(isDefaultDataRoamingEnabled());
562         }
563     }
564 
565     /**
566      * Get whether the user has manually enabled or disabled data roaming from settings for the
567      * current subscription.
568      * @return {@code true} if the user has manually enabled data roaming for the current
569      *         subscription and {@code false} if they have not.
570      */
isDataRoamingFromUserAction()571     private boolean isDataRoamingFromUserAction() {
572         String key = Phone.DATA_ROAMING_IS_USER_SETTING_KEY + mPhone.getSubId();
573         final SharedPreferences sp =
574                 PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
575 
576         // Set the default roaming from user action value if the preference doesn't exist
577         if (!sp.contains(key)) {
578             if (sp.contains(Phone.DATA_ROAMING_IS_USER_SETTING_KEY)) {
579                 log("Reusing previous roaming from user action value for backwards compatibility.");
580                 sp.edit().putBoolean(key, true).commit();
581             } else {
582                 log("Clearing roaming from user action value for new or upgrading devices.");
583                 sp.edit().putBoolean(key, false).commit();
584             }
585         }
586 
587         boolean isUserSetting = sp.getBoolean(key, true);
588         log("isDataRoamingFromUserAction: key=" + key + ", isUserSetting=" + isUserSetting);
589         return isUserSetting;
590     }
591 
592     /**
593      * Indicate that the user has manually enabled or disabled the data roaming value from settings.
594      * If the user has not manually set the data roaming value, the default value from
595      * {@link #isDefaultDataRoamingEnabled()} will continue to be used.
596      */
setDataRoamingFromUserAction()597     private void setDataRoamingFromUserAction() {
598         String key = Phone.DATA_ROAMING_IS_USER_SETTING_KEY + mPhone.getSubId();
599         log("setDataRoamingFromUserAction: key=" + key);
600         final SharedPreferences.Editor sp =
601                 PreferenceManager.getDefaultSharedPreferences(mPhone.getContext()).edit();
602         sp.putBoolean(key, true).commit();
603     }
604 
605     /** Refresh the enabled mobile data policies from Telephony database */
refreshEnabledMobileDataPolicy()606     private void refreshEnabledMobileDataPolicy() {
607         SubscriptionInfoInternal subInfo = SubscriptionManagerService.getInstance()
608                 .getSubscriptionInfoInternal(mSubId);
609         if (subInfo != null) {
610             mEnabledMobileDataPolicy = getMobileDataPolicyEnabled(
611                     subInfo.getEnabledMobileDataPolicies());
612         }
613     }
614 
615     /**
616      * @return {@code true} If the mobile data policy is enabled
617      */
isMobileDataPolicyEnabled(@obileDataPolicy int mobileDataPolicy)618     public boolean isMobileDataPolicyEnabled(@MobileDataPolicy int mobileDataPolicy) {
619         return mEnabledMobileDataPolicy.contains(mobileDataPolicy);
620     }
621 
622     /**
623      * Set mobile data policy enabled status
624      * @param mobileDataPolicy The mobile data policy to set
625      * @param enable {@code true} to enable the policy; {@code false} to disable.
626      */
setMobileDataPolicy(@obileDataPolicy int mobileDataPolicy, boolean enable)627     public void setMobileDataPolicy(@MobileDataPolicy int mobileDataPolicy, boolean enable) {
628         obtainMessage(EVENT_SET_MOBILE_DATA_POLICY, mobileDataPolicy, enable ? 1 : 0)
629                 .sendToTarget();
630     }
631 
632     /**
633      * Store data mobile policy to Telephony database.
634      *
635      * @param mobileDataPolicy The mobile data policy that overrides user data enabled setting.
636      * @param enable {@code true} to enable the policy; {@code false} to remove the policy.
637      */
onSetMobileDataPolicy(@obileDataPolicy int mobileDataPolicy, boolean enable)638     private void onSetMobileDataPolicy(@MobileDataPolicy int mobileDataPolicy, boolean enable) {
639         if (enable == isMobileDataPolicyEnabled(mobileDataPolicy)) {
640             return;
641         }
642         metricsRecordSetMobileDataPolicy(mobileDataPolicy);
643 
644         if (enable) {
645             mEnabledMobileDataPolicy.add(mobileDataPolicy);
646         } else {
647             mEnabledMobileDataPolicy.remove(mobileDataPolicy);
648         }
649 
650         String enabledMobileDataPolicies = mEnabledMobileDataPolicy.stream().map(String::valueOf)
651                 .collect(Collectors.joining(","));
652         SubscriptionManagerService.getInstance().setEnabledMobileDataPolicies(mSubId,
653                 enabledMobileDataPolicies);
654         logl(TelephonyUtils.mobileDataPolicyToString(mobileDataPolicy) + " changed to "
655                 + enable);
656         updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_OVERRIDE);
657         notifyDataEnabledOverrideChanged(enable, mobileDataPolicy);
658     }
659 
660     /**
661      * Record the number of times a mobile data policy is toggled to metrics.
662      * @param mobileDataPolicy The mobile data policy that's toggled
663      */
metricsRecordSetMobileDataPolicy(@obileDataPolicy int mobileDataPolicy)664     private void metricsRecordSetMobileDataPolicy(@MobileDataPolicy int mobileDataPolicy) {
665         if (mobileDataPolicy == TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH) {
666             DeviceTelephonyPropertiesStats.recordAutoDataSwitchFeatureToggle();
667         }
668     }
669 
670     /**
671      * Check whether data stall recovery on bad network is enabled.
672      * @return {@code true} if data stall recovery is enabled and {@code false} otherwise.
673      */
isRecoveryOnBadNetworkEnabled()674     public boolean isRecoveryOnBadNetworkEnabled() {
675         return Settings.Global.getInt(mResolver,
676                 Settings.Global.DATA_STALL_RECOVERY_ON_BAD_NETWORK, 1) == 1;
677     }
678 
notifyDataEnabledChanged(boolean enabled, @TelephonyManager.DataEnabledChangedReason int reason, @NonNull String callingPackage)679     private void notifyDataEnabledChanged(boolean enabled,
680             @TelephonyManager.DataEnabledChangedReason int reason, @NonNull String callingPackage) {
681         logl("notifyDataEnabledChanged: enabled=" + enabled + ", reason="
682                 + dataEnabledChangedReasonToString(reason) + ", callingPackage=" + callingPackage);
683         mDataSettingsManagerCallbacks.forEach(callback -> callback.invokeFromExecutor(
684                 () -> callback.onDataEnabledChanged(enabled, reason, callingPackage)));
685         mPhone.notifyDataEnabled(enabled, reason);
686     }
687 
notifyDataEnabledOverrideChanged(boolean enabled, @TelephonyManager.MobileDataPolicy int policy)688     private void notifyDataEnabledOverrideChanged(boolean enabled,
689             @TelephonyManager.MobileDataPolicy int policy) {
690         logl("notifyDataEnabledOverrideChanged: enabled=" + enabled);
691         mDataSettingsManagerCallbacks.forEach(callback -> callback.invokeFromExecutor(
692                 () -> callback.onDataEnabledOverrideChanged(enabled, policy)));
693     }
694 
695     /**
696      * Return the parsed mobile data policies.
697      *
698      * @param policies New mobile data policies in String format.
699      * @return A Set of parsed mobile data policies.
700      */
getMobileDataPolicyEnabled( @onNull String policies)701     public @NonNull @MobileDataPolicy Set<Integer> getMobileDataPolicyEnabled(
702             @NonNull String policies) {
703         Set<Integer> mobileDataPolicies = new HashSet<>();
704         String[] rulesString = policies.trim().split("\\s*,\\s*");
705         for (String rule : rulesString) {
706             if (!TextUtils.isEmpty(rule)) {
707                 int parsedDataPolicy = parsePolicyFrom(rule);
708                 if (parsedDataPolicy != INVALID_MOBILE_DATA_POLICY) {
709                     mobileDataPolicies.add(parsedDataPolicy);
710                 }
711             }
712         }
713         return mobileDataPolicies;
714     }
715 
716     /**
717      * Parse a mobile data policy retrieved from Telephony db.
718      * If the policy is in legacy format, convert it into the corresponding mobile data policy.
719      *
720      * @param policy Mobile data policy to be parsed from.
721      * @return Parsed mobile data policy. {@link #INVALID_MOBILE_DATA_POLICY} if string can't be
722      * parsed into a mobile data policy.
723      */
parsePolicyFrom(@onNull String policy)724     private @MobileDataPolicy int parsePolicyFrom(@NonNull String policy) {
725         int dataPolicy;
726         try {
727             // parse as new override policy
728             dataPolicy = Integer.parseInt(policy);
729         } catch (NumberFormatException e) {
730             dataPolicy = INVALID_MOBILE_DATA_POLICY;
731             loge("parsePolicyFrom: invalid mobile data policy format: "  + policy);
732         }
733         return dataPolicy;
734     }
735 
736     /**
737      * Check if data enabled is temporarily overridden in certain conditions.
738      *
739      * @param apnType The APN type to check.
740      * @return {@code true} if data enabled should be overridden.
741      */
isDataEnabledOverriddenForApn(@pnType int apnType)742     private boolean isDataEnabledOverriddenForApn(@ApnType int apnType) {
743         boolean overridden = false;
744 
745         // mobile data policy : MMS always allowed
746         if (isMobileDataPolicyEnabled(TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED)) {
747             overridden = apnType == ApnSetting.TYPE_MMS;
748         }
749 
750         boolean isNonDds = mPhone.getSubId() != SubscriptionManagerService.getInstance()
751                 .getDefaultDataSubId();
752 
753         // mobile data policy : data during call
754         if (isMobileDataPolicyEnabled(TelephonyManager
755                 .MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL)) {
756             overridden = overridden || isNonDds && mPhone.getState() != PhoneConstants.State.IDLE;
757         }
758 
759         // mobile data policy : auto data switch
760         if (isMobileDataPolicyEnabled(TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH)) {
761             // check user enabled data on the default data phone
762             Phone defaultDataPhone = PhoneFactory.getPhone(SubscriptionManagerService.getInstance()
763                     .getPhoneId(SubscriptionManagerService.getInstance()
764                             .getDefaultDataSubId()));
765             if (defaultDataPhone == null) {
766                 loge("isDataEnabledOverriddenForApn: unexpected defaultDataPhone is null");
767             } else {
768                 overridden = overridden || isNonDds && defaultDataPhone.isUserDataEnabled();
769             }
770         }
771         return overridden;
772     }
773 
774     /**
775      * Register the callback for receiving information from {@link DataSettingsManager}.
776      *
777      * @param callback The callback.
778      */
registerCallback(@onNull DataSettingsManagerCallback callback)779     public void registerCallback(@NonNull DataSettingsManagerCallback callback) {
780         mDataSettingsManagerCallbacks.add(callback);
781     }
782 
783     /**
784      * Unregister the callback for receiving information from {@link DataSettingsManager}.
785      *
786      * @param callback The callback.
787      */
unregisterCallback(@onNull DataSettingsManagerCallback callback)788     public void unregisterCallback(@NonNull DataSettingsManagerCallback callback) {
789         mDataSettingsManagerCallbacks.remove(callback);
790     }
791 
dataEnabledChangedReasonToString( @elephonyManager.DataEnabledChangedReason int reason)792     private static String dataEnabledChangedReasonToString(
793             @TelephonyManager.DataEnabledChangedReason int reason) {
794         switch (reason) {
795             case TelephonyManager.DATA_ENABLED_REASON_USER:
796                 return "USER";
797             case TelephonyManager.DATA_ENABLED_REASON_POLICY:
798                 return "POLICY";
799             case TelephonyManager.DATA_ENABLED_REASON_CARRIER:
800                 return "CARRIER";
801             case TelephonyManager.DATA_ENABLED_REASON_THERMAL:
802                 return "THERMAL";
803             case TelephonyManager.DATA_ENABLED_REASON_OVERRIDE:
804                 return "OVERRIDE";
805             default:
806                 return "UNKNOWN";
807         }
808     }
809 
810     @Override
toString()811     public String toString() {
812         return "[isUserDataEnabled=" + isUserDataEnabled()
813                 + ", isProvisioningDataEnabled=" + isProvisioningDataEnabled()
814                 + ", mIsDataEnabled=" + mIsDataEnabled
815                 + ", mDataEnabledSettings=" + mDataEnabledSettings
816                 + ", mEnabledMobileDataPolicy=" + mEnabledMobileDataPolicy.stream()
817                 .map(TelephonyUtils::mobileDataPolicyToString).collect(Collectors.joining(","))
818                 + "]";
819     }
820 
821     /**
822      * Log debug messages.
823      * @param s debug messages
824      */
log(@onNull String s)825     private void log(@NonNull String s) {
826         Rlog.d(mLogTag, s);
827     }
828 
829     /**
830      * Log error messages.
831      * @param s error messages
832      */
loge(@onNull String s)833     private void loge(@NonNull String s) {
834         Rlog.e(mLogTag, s);
835     }
836 
837     /**
838      * Log debug messages and also log into the local log.
839      * @param s debug messages
840      */
logl(@onNull String s)841     private void logl(@NonNull String s) {
842         log(s);
843         mLocalLog.log(s);
844     }
845 
846     /**
847      * Dump the state of DataSettingsManager
848      *
849      * @param fd File descriptor
850      * @param printWriter Print writer
851      * @param args Arguments
852      */
dump(FileDescriptor fd, PrintWriter printWriter, String[] args)853     public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
854         IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
855         pw.println(DataSettingsManager.class.getSimpleName() + "-" + mPhone.getPhoneId() + ":");
856         pw.increaseIndent();
857         pw.println("mIsDataEnabled=" + mIsDataEnabled);
858         pw.println("isDataEnabled(internet)=" + isDataEnabled(ApnSetting.TYPE_DEFAULT));
859         pw.println("isDataEnabled(mms)=" + isDataEnabled(ApnSetting.TYPE_MMS));
860         pw.println("isUserDataEnabled=" + isUserDataEnabled());
861         pw.println("isDataRoamingEnabled=" + isDataRoamingEnabled());
862         pw.println("isDefaultDataRoamingEnabled=" + isDefaultDataRoamingEnabled());
863         pw.println("isDataRoamingFromUserAction=" + isDataRoamingFromUserAction());
864         pw.println("device_provisioned=" + Settings.Global.getInt(
865                 mResolver, Settings.Global.DEVICE_PROVISIONED, 0));
866         pw.println("isProvisioningDataEnabled=" + isProvisioningDataEnabled());
867         pw.println("data_stall_recovery_on_bad_network=" + Settings.Global.getInt(
868                 mResolver, Settings.Global.DATA_STALL_RECOVERY_ON_BAD_NETWORK, 1));
869         pw.println("mDataEnabledSettings=" + mDataEnabledSettings.entrySet().stream()
870                 .map(entry ->
871                         dataEnabledChangedReasonToString(entry.getKey()) + "=" + entry.getValue())
872                 .collect(Collectors.joining(", ")));
873         pw.println("mEnabledMobileDataPolicy=" + mEnabledMobileDataPolicy.stream()
874                 .map(TelephonyUtils::mobileDataPolicyToString).collect(Collectors.joining(",")));
875         pw.println("Local logs:");
876         pw.increaseIndent();
877         mLocalLog.dump(fd, pw, args);
878         pw.decreaseIndent();
879         pw.decreaseIndent();
880     }
881 }
882