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