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