• 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.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                 refreshEnabledMobileDataPolicy();
220                 updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_USER,
221                         mPhone.getContext().getOpPackageName(),
222                         SubscriptionManager.isValidSubscriptionId(mSubId));
223                 mPhone.notifyUserMobileDataStateChanged(isUserDataEnabled());
224                 break;
225             }
226             case EVENT_SET_DATA_ENABLED_FOR_REASON: {
227                 String callingPackage = (String) msg.obj;
228                 boolean enabled = msg.arg2 == 1;
229                 switch (msg.arg1) {
230                     case TelephonyManager.DATA_ENABLED_REASON_USER:
231                         setUserDataEnabled(enabled, callingPackage);
232                         break;
233                     case TelephonyManager.DATA_ENABLED_REASON_CARRIER:
234                         setCarrierDataEnabled(enabled, callingPackage);
235                         break;
236                     case TelephonyManager.DATA_ENABLED_REASON_POLICY:
237                         setPolicyDataEnabled(enabled, callingPackage);
238                         break;
239                     case TelephonyManager.DATA_ENABLED_REASON_THERMAL:
240                         setThermalDataEnabled(enabled, callingPackage);
241                         break;
242                     default:
243                         log("Cannot set data enabled for reason: "
244                                 + dataEnabledChangedReasonToString(msg.arg1));
245                         break;
246                 }
247                 break;
248             }
249             case EVENT_SET_DATA_ROAMING_ENABLED: {
250                 boolean enabled = (boolean) msg.obj;
251                 setDataRoamingEnabledInternal(enabled);
252                 setDataRoamingFromUserAction();
253                 break;
254             }
255             case EVENT_SET_MOBILE_DATA_POLICY: {
256                 int mobileDataPolicy = msg.arg1;
257                 boolean enable = msg.arg2 == 1;
258                 onSetMobileDataPolicy(mobileDataPolicy, enable);
259                 break;
260             }
261             case EVENT_PROVISIONED_CHANGED:
262             case EVENT_PROVISIONING_DATA_ENABLED_CHANGED: {
263                 updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_UNKNOWN);
264                 break;
265             }
266             case EVENT_INITIALIZE: {
267                 onInitialize();
268                 break;
269             }
270             default:
271                 loge("Unknown msg.what: " + msg.what);
272         }
273     }
274 
hasCalling()275     private boolean hasCalling() {
276         if (!TelephonyCapabilities.minimalTelephonyCdmCheck(mFeatureFlags)) return true;
277         return mPhone.getContext().getPackageManager().hasSystemFeature(
278             PackageManager.FEATURE_TELEPHONY_CALLING);
279     }
280 
281     /**
282      * Called when needed to register for all events that data network controller is interested.
283      */
onInitialize()284     private void onInitialize() {
285         mDataConfigManager.registerCallback(new DataConfigManagerCallback(this::post) {
286             @Override
287             public void onCarrierConfigChanged() {
288                 if (mDataConfigManager.isConfigCarrierSpecific()) {
289                     setDefaultDataRoamingEnabled();
290                 }
291             }
292         });
293         mSettingsObserver.observe(Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONED),
294                 EVENT_PROVISIONED_CHANGED);
295         mSettingsObserver.observe(
296                 Settings.Global.getUriFor(Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED),
297                 EVENT_PROVISIONING_DATA_ENABLED_CHANGED);
298         if (hasCalling()) {
299             mPhone.getCallTracker().registerForVoiceCallStarted(this, EVENT_CALL_STATE_CHANGED,
300                     null);
301             mPhone.getCallTracker().registerForVoiceCallEnded(this, EVENT_CALL_STATE_CHANGED, null);
302         }
303         if (hasCalling() && mPhone.getImsPhone() != null) {
304             mPhone.getImsPhone().getCallTracker().registerForVoiceCallStarted(
305                     this, EVENT_CALL_STATE_CHANGED, null);
306             mPhone.getImsPhone().getCallTracker().registerForVoiceCallEnded(
307                     this, EVENT_CALL_STATE_CHANGED, null);
308         }
309         mPhone.getContext().getSystemService(TelephonyRegistryManager.class)
310                 .addOnSubscriptionsChangedListener(new OnSubscriptionsChangedListener() {
311                     @Override
312                     public void onSubscriptionsChanged() {
313                         if (mSubId != mPhone.getSubId()) {
314                             log("onSubscriptionsChanged: " + mSubId + " to " + mPhone.getSubId());
315                             mSubId = mPhone.getSubId();
316                             obtainMessage(EVENT_SUBSCRIPTIONS_CHANGED, mPhone.getSubId())
317                                     .sendToTarget();
318                         }
319                     }
320                 }, Runnable::run);
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         SubscriptionManagerService.getInstance().registerCallback(
339                 new SubscriptionManagerService.SubscriptionManagerServiceCallback(this::post) {
340                     @Override
341                     public void onDefaultDataSubscriptionChanged(int subId) {
342                         log((subId == mSubId ? "Became" : "Not")
343                                 + " default data sub, reevaluating mobile data policies");
344                         DataSettingsManager.this.updateDataEnabledAndNotify(
345                                 TelephonyManager.DATA_ENABLED_REASON_OVERRIDE);
346                     }
347                 });
348         updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_UNKNOWN);
349     }
350 
351     /**
352      * Enable or disable data for a specific {@link TelephonyManager.DataEnabledReason}.
353      * @param reason The reason the data enabled change is taking place.
354      * @param enabled {@code true} to enable data for the given reason and {@code false} to disable.
355      * @param callingPackage The package that changed the data enabled state.
356      */
setDataEnabled(@elephonyManager.DataEnabledReason int reason, boolean enabled, String callingPackage)357     public void setDataEnabled(@TelephonyManager.DataEnabledReason int reason, boolean enabled,
358             String callingPackage) {
359         obtainMessage(EVENT_SET_DATA_ENABLED_FOR_REASON, reason, enabled ? 1 : 0, callingPackage)
360                 .sendToTarget();
361     }
362 
363     /**
364      * Check whether the data is enabled for a specific {@link TelephonyManager.DataEnabledReason}.
365      * @return {@code true} if data is enabled for the given reason and {@code false} otherwise.
366      */
isDataEnabledForReason(@elephonyManager.DataEnabledReason int reason)367     public boolean isDataEnabledForReason(@TelephonyManager.DataEnabledReason int reason) {
368         if (reason == TelephonyManager.DATA_ENABLED_REASON_USER) {
369             return isUserDataEnabled();
370         } else {
371             return mDataEnabledSettings.get(reason);
372         }
373     }
374 
updateDataEnabledAndNotify(@elephonyManager.DataEnabledChangedReason int reason)375     private void updateDataEnabledAndNotify(@TelephonyManager.DataEnabledChangedReason int reason) {
376         updateDataEnabledAndNotify(reason, mPhone.getContext().getOpPackageName(), false);
377     }
378 
updateDataEnabledAndNotify(@elephonyManager.DataEnabledChangedReason int reason, @NonNull String callingPackage, boolean shouldNotify)379     private void updateDataEnabledAndNotify(@TelephonyManager.DataEnabledChangedReason int reason,
380             @NonNull String callingPackage, boolean shouldNotify) {
381         boolean prevDataEnabled = mIsDataEnabled;
382         mIsDataEnabled = isDataEnabled(ApnSetting.TYPE_ALL);
383         log("mIsDataEnabled=" + mIsDataEnabled + ", prevDataEnabled=" + prevDataEnabled);
384         if (!mInitialized || shouldNotify || prevDataEnabled != mIsDataEnabled) {
385             if (!mInitialized) mInitialized = true;
386             notifyDataEnabledChanged(mIsDataEnabled, reason, callingPackage);
387         }
388     }
389 
390     /**
391      * Check whether the user data is enabled when the device is in the provisioning stage.
392      * In provisioning, we might want to enable mobile data depending on the value of
393      * Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED, which is set by setupwizard.
394      * @return {@code true} if user data is enabled when provisioning and {@code false} otherwise.
395      */
isProvisioningDataEnabled()396     private boolean isProvisioningDataEnabled() {
397         final String prov_property = SystemProperties.get("ro.com.android.prov_mobiledata",
398                 "false");
399         boolean retVal = "true".equalsIgnoreCase(prov_property);
400 
401         final int prov_mobile_data = Settings.Global.getInt(mResolver,
402                 Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED,
403                 retVal ? 1 : 0);
404         retVal = prov_mobile_data != 0;
405         log("getDataEnabled during provisioning retVal=" + retVal + " - (" + prov_property
406                 + ", " + prov_mobile_data + ")");
407 
408         return retVal;
409     }
410 
411     /**
412      * Check whether the overall data is enabled for the device. Note that this value will only
413      * be accurate if {@link #isDataInitialized} is {@code true}.
414      * @return {@code true} if the overall data is enabled and {@code false} otherwise.
415      */
isDataEnabled()416     public boolean isDataEnabled() {
417         return mIsDataEnabled;
418     }
419 
420     /**
421      * Check whether data enabled value has been initialized. If this is {@code false}, then
422      * {@link #isDataEnabled} is not guaranteed to be accurate. Once data is initialized,
423      * {@link DataSettingsManagerCallback#onDataEnabledChanged} will be invoked with reason
424      * {@link TelephonyManager#DATA_ENABLED_REASON_UNKNOWN}.
425      * @return {@code true} if the data enabled value is initialized and {@code false} otherwise.
426      */
isDataInitialized()427     public boolean isDataInitialized() {
428         // TODO: Create a new DATA_ENABLED_REASON_INITIALIZED for initial value broadcast
429         return mInitialized;
430     }
431 
432     /**
433      * Check whether the overall data is enabled for the device for the given APN type.
434      * @param apnType A single APN type to check data enabled for.
435      * @return {@code true} if the overall data is enabled for the APN and {@code false} otherwise.
436      */
isDataEnabled(@pnType int apnType)437     public boolean isDataEnabled(@ApnType int apnType) {
438         if (Settings.Global.getInt(mResolver, Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
439             return isProvisioningDataEnabled();
440         } else {
441             boolean userDataEnabled = isUserDataEnabled();
442             // Check if we should temporarily enable data based on mobile data policy.
443             boolean isDataEnabledOverridden = isDataEnabledOverriddenForApn(apnType);
444 
445 
446             return ((userDataEnabled || isDataEnabledOverridden)
447                     && mDataEnabledSettings.get(TelephonyManager.DATA_ENABLED_REASON_POLICY)
448                     && mDataEnabledSettings.get(TelephonyManager.DATA_ENABLED_REASON_CARRIER)
449                     && mDataEnabledSettings.get(TelephonyManager.DATA_ENABLED_REASON_THERMAL));
450         }
451     }
452 
isStandAloneOpportunistic(int subId)453     private boolean isStandAloneOpportunistic(int subId) {
454         SubscriptionInfoInternal subInfo = SubscriptionManagerService.getInstance()
455                 .getSubscriptionInfoInternal(subId);
456         return subInfo != null && subInfo.isOpportunistic()
457                 && TextUtils.isEmpty(subInfo.getGroupUuid());
458     }
459 
460     /**
461      * Enable or disable user data.
462      * @param enabled {@code true} to enable user data and {@code false} to disable.
463      * @param callingPackage The package that changed the data enabled state.
464      */
setUserDataEnabled(boolean enabled, String callingPackage)465     private void setUserDataEnabled(boolean enabled, String callingPackage) {
466         // Can't disable data for stand alone opportunistic subscription.
467         if (isStandAloneOpportunistic(mSubId) && !enabled) return;
468         boolean changed = GlobalSettingsHelper.setInt(mPhone.getContext(),
469                 Settings.Global.MOBILE_DATA, mSubId, (enabled ? 1 : 0));
470         logl("Set user data enabled to " + enabled + " on sub " + mSubId + ", changed="
471                 + changed + ", callingPackage=" + callingPackage);
472         if (changed) {
473             logl("UserDataEnabled changed to " + enabled);
474             mPhone.notifyUserMobileDataStateChanged(enabled);
475             mDataSettingsManagerCallbacks.forEach(callback -> callback.invokeFromExecutor(
476                     () -> callback.onUserDataEnabledChanged(enabled, callingPackage)));
477             updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_USER,
478                     callingPackage, false);
479         }
480     }
481 
482     /**
483      * Check whether user data is enabled for the device.
484      * @return {@code true} if user data is enabled and {@code false} otherwise.
485      */
isUserDataEnabled()486     private boolean isUserDataEnabled() {
487         if (Settings.Global.getInt(mResolver, Settings.Global.DEVICE_PROVISIONED, 0) == 0) {
488             return isProvisioningDataEnabled();
489         }
490 
491         // User data should always be true for opportunistic subscription.
492         if (isStandAloneOpportunistic(mSubId)) return true;
493 
494         boolean defaultVal = TelephonyProperties.mobile_data().orElse(true);
495 
496         return GlobalSettingsHelper.getBoolean(mPhone.getContext(),
497                 Settings.Global.MOBILE_DATA, mSubId, defaultVal);
498     }
499 
500     /**
501      * Enable or disable policy data.
502      * @param enabled {@code true} to enable policy data and {@code false} to disable.
503      * @param callingPackage The package that changed the data enabled state.
504      */
setPolicyDataEnabled(boolean enabled, String callingPackage)505     private void setPolicyDataEnabled(boolean enabled, String callingPackage) {
506         if (mDataEnabledSettings.get(TelephonyManager.DATA_ENABLED_REASON_POLICY) != enabled) {
507             logl("PolicyDataEnabled changed to " + enabled + ", callingPackage=" + callingPackage);
508             mDataEnabledSettings.put(TelephonyManager.DATA_ENABLED_REASON_POLICY, enabled);
509             updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_POLICY,
510                     callingPackage, false);
511         }
512     }
513 
514     /**
515      * Enable or disable carrier data.
516      * @param enabled {@code true} to enable carrier data and {@code false} to disable.
517      * @param callingPackage The package that changed the data enabled state.
518      */
setCarrierDataEnabled(boolean enabled, String callingPackage)519     private void setCarrierDataEnabled(boolean enabled, String callingPackage) {
520         if (mDataEnabledSettings.get(TelephonyManager.DATA_ENABLED_REASON_CARRIER) != enabled) {
521             logl("CarrierDataEnabled changed to " + enabled + ", callingPackage=" + callingPackage);
522             mDataEnabledSettings.put(TelephonyManager.DATA_ENABLED_REASON_CARRIER, enabled);
523             updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_CARRIER,
524                     callingPackage, false);
525         }
526     }
527 
528     /**
529      * Enable or disable thermal data.
530      * @param enabled {@code true} to enable thermal data and {@code false} to disable.
531      * @param callingPackage The package that changed the data enabled state.
532      */
setThermalDataEnabled(boolean enabled, String callingPackage)533     private void setThermalDataEnabled(boolean enabled, String callingPackage) {
534         if (mDataEnabledSettings.get(TelephonyManager.DATA_ENABLED_REASON_THERMAL) != enabled) {
535             logl("ThermalDataEnabled changed to " + enabled + ", callingPackage=" + callingPackage);
536             mDataEnabledSettings.put(TelephonyManager.DATA_ENABLED_REASON_THERMAL, enabled);
537             updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_THERMAL,
538                     callingPackage, false);
539         }
540     }
541 
542     /**
543      * Enable or disable data roaming from user settings.
544      * @param enabled {@code true} to enable data roaming and {@code false} to disable.
545      */
setDataRoamingEnabled(boolean enabled)546     public void setDataRoamingEnabled(boolean enabled) {
547         obtainMessage(EVENT_SET_DATA_ROAMING_ENABLED, enabled).sendToTarget();
548     }
549 
550     /**
551      * Enable or disable data roaming.
552      * @param enabled {@code true} to enable data roaming and {@code false} to disable.
553      */
setDataRoamingEnabledInternal(boolean enabled)554     private void setDataRoamingEnabledInternal(boolean enabled) {
555         // Will trigger handleDataOnRoamingChange() through observer
556         boolean changed = GlobalSettingsHelper.setBoolean(mPhone.getContext(),
557                 Settings.Global.DATA_ROAMING, mSubId, enabled);
558         logl("DataRoamingEnabled set to " + enabled + " on sub " + mSubId
559                 + ", changed=" + changed);
560         if (changed) {
561             mDataSettingsManagerCallbacks.forEach(callback -> callback.invokeFromExecutor(
562                     () -> callback.onDataRoamingEnabledChanged(enabled)));
563         }
564     }
565 
566     /**
567      * Check whether data roaming is enabled for the device based on the current
568      * {@link Settings.Global#DATA_ROAMING} value.
569      * @return {@code true} if data roaming is enabled and {@code false} otherwise.
570      */
isDataRoamingEnabled()571     public boolean isDataRoamingEnabled() {
572         return GlobalSettingsHelper.getBoolean(mPhone.getContext(),
573                 Settings.Global.DATA_ROAMING, mSubId, isDefaultDataRoamingEnabled());
574     }
575 
576     /**
577      * Check whether data roaming is enabled by default.
578      * This is true if {@link CarrierConfigManager#KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL}
579      * or the system property "ro.com.android.dataroaming" are true.
580      * @return {@code true} if data roaming is enabled by default and {@code false} otherwise.
581      */
isDefaultDataRoamingEnabled()582     public boolean isDefaultDataRoamingEnabled() {
583         return "true".equalsIgnoreCase(SystemProperties.get("ro.com.android.dataroaming", "false"))
584                 || mPhone.getDataNetworkController().getDataConfigManager()
585                         .isDataRoamingEnabledByDefault();
586     }
587 
588     /**
589      * Set default value for {@link android.provider.Settings.Global#DATA_ROAMING} if the user
590      * has not manually set the value. The default value is {@link #isDefaultDataRoamingEnabled()}.
591      */
setDefaultDataRoamingEnabled()592     public void setDefaultDataRoamingEnabled() {
593         // If the user has not manually set the value, use the default value.
594         if (!isDataRoamingFromUserAction()) {
595             setDataRoamingEnabledInternal(isDefaultDataRoamingEnabled());
596         }
597     }
598 
599     /**
600      * Get whether the user has manually enabled or disabled data roaming from settings for the
601      * current subscription.
602      * @return {@code true} if the user has manually enabled data roaming for the current
603      *         subscription and {@code false} if they have not.
604      */
isDataRoamingFromUserAction()605     private boolean isDataRoamingFromUserAction() {
606         String key = Phone.DATA_ROAMING_IS_USER_SETTING_KEY + mPhone.getSubId();
607         final SharedPreferences sp =
608                 PreferenceManager.getDefaultSharedPreferences(mPhone.getContext());
609 
610         // Set the default roaming from user action value if the preference doesn't exist
611         if (!sp.contains(key)) {
612             if (sp.contains(Phone.DATA_ROAMING_IS_USER_SETTING_KEY)) {
613                 log("Reusing previous roaming from user action value for backwards compatibility.");
614                 sp.edit().putBoolean(key, true).commit();
615             } else {
616                 log("Clearing roaming from user action value for new or upgrading devices.");
617                 sp.edit().putBoolean(key, false).commit();
618             }
619         }
620 
621         boolean isUserSetting = sp.getBoolean(key, true);
622         log("isDataRoamingFromUserAction: key=" + key + ", isUserSetting=" + isUserSetting);
623         return isUserSetting;
624     }
625 
626     /**
627      * Indicate that the user has manually enabled or disabled the data roaming value from settings.
628      * If the user has not manually set the data roaming value, the default value from
629      * {@link #isDefaultDataRoamingEnabled()} will continue to be used.
630      */
setDataRoamingFromUserAction()631     private void setDataRoamingFromUserAction() {
632         String key = Phone.DATA_ROAMING_IS_USER_SETTING_KEY + mPhone.getSubId();
633         log("setDataRoamingFromUserAction: key=" + key);
634         final SharedPreferences.Editor sp =
635                 PreferenceManager.getDefaultSharedPreferences(mPhone.getContext()).edit();
636         sp.putBoolean(key, true).commit();
637     }
638 
639     /** Refresh the enabled mobile data policies from Telephony database */
refreshEnabledMobileDataPolicy()640     private void refreshEnabledMobileDataPolicy() {
641         SubscriptionInfoInternal subInfo = SubscriptionManagerService.getInstance()
642                 .getSubscriptionInfoInternal(mSubId);
643         if (subInfo != null) {
644             mEnabledMobileDataPolicy = getMobileDataPolicyEnabled(
645                     subInfo.getEnabledMobileDataPolicies());
646         }
647     }
648 
649     /**
650      * @return {@code true} If the mobile data policy is enabled
651      */
isMobileDataPolicyEnabled(@obileDataPolicy int mobileDataPolicy)652     public boolean isMobileDataPolicyEnabled(@MobileDataPolicy int mobileDataPolicy) {
653         return mEnabledMobileDataPolicy.contains(mobileDataPolicy);
654     }
655 
656     /**
657      * Set mobile data policy enabled status
658      * @param mobileDataPolicy The mobile data policy to set
659      * @param enable {@code true} to enable the policy; {@code false} to disable.
660      */
setMobileDataPolicy(@obileDataPolicy int mobileDataPolicy, boolean enable)661     public void setMobileDataPolicy(@MobileDataPolicy int mobileDataPolicy, boolean enable) {
662         obtainMessage(EVENT_SET_MOBILE_DATA_POLICY, mobileDataPolicy, enable ? 1 : 0)
663                 .sendToTarget();
664     }
665 
666     /**
667      * Store data mobile policy to Telephony database.
668      *
669      * @param mobileDataPolicy The mobile data policy that overrides user data enabled setting.
670      * @param enable {@code true} to enable the policy; {@code false} to remove the policy.
671      */
onSetMobileDataPolicy(@obileDataPolicy int mobileDataPolicy, boolean enable)672     private void onSetMobileDataPolicy(@MobileDataPolicy int mobileDataPolicy, boolean enable) {
673         if (enable == isMobileDataPolicyEnabled(mobileDataPolicy)) {
674             return;
675         }
676         metricsRecordSetMobileDataPolicy(mobileDataPolicy);
677 
678         if (enable) {
679             mEnabledMobileDataPolicy.add(mobileDataPolicy);
680         } else {
681             mEnabledMobileDataPolicy.remove(mobileDataPolicy);
682         }
683 
684         String enabledMobileDataPolicies = mEnabledMobileDataPolicy.stream().map(String::valueOf)
685                 .collect(Collectors.joining(","));
686         SubscriptionManagerService.getInstance().setEnabledMobileDataPolicies(mSubId,
687                 enabledMobileDataPolicies);
688         logl(TelephonyUtils.mobileDataPolicyToString(mobileDataPolicy) + " changed to "
689                 + enable);
690         updateDataEnabledAndNotify(TelephonyManager.DATA_ENABLED_REASON_OVERRIDE);
691         notifyDataEnabledOverrideChanged(enable, mobileDataPolicy);
692     }
693 
694     /**
695      * Record the number of times a mobile data policy is toggled to metrics.
696      * @param mobileDataPolicy The mobile data policy that's toggled
697      */
metricsRecordSetMobileDataPolicy(@obileDataPolicy int mobileDataPolicy)698     private void metricsRecordSetMobileDataPolicy(@MobileDataPolicy int mobileDataPolicy) {
699         if (mobileDataPolicy == TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH) {
700             DeviceTelephonyPropertiesStats.recordAutoDataSwitchFeatureToggle();
701         }
702     }
703 
704     /**
705      * Check whether data stall recovery on bad network is enabled.
706      * @return {@code true} if data stall recovery is enabled and {@code false} otherwise.
707      */
isRecoveryOnBadNetworkEnabled()708     public boolean isRecoveryOnBadNetworkEnabled() {
709         return Settings.Global.getInt(mResolver,
710                 Settings.Global.DATA_STALL_RECOVERY_ON_BAD_NETWORK, 1) == 1;
711     }
712 
notifyDataEnabledChanged(boolean enabled, @TelephonyManager.DataEnabledChangedReason int reason, @NonNull String callingPackage)713     private void notifyDataEnabledChanged(boolean enabled,
714             @TelephonyManager.DataEnabledChangedReason int reason, @NonNull String callingPackage) {
715         logl("notifyDataEnabledChanged: enabled=" + enabled + ", reason="
716                 + dataEnabledChangedReasonToString(reason) + ", callingPackage=" + callingPackage);
717         mDataSettingsManagerCallbacks.forEach(callback -> callback.invokeFromExecutor(
718                 () -> callback.onDataEnabledChanged(enabled, reason, callingPackage)));
719         mPhone.notifyDataEnabled(enabled, reason);
720     }
721 
notifyDataEnabledOverrideChanged(boolean enabled, @TelephonyManager.MobileDataPolicy int policy)722     private void notifyDataEnabledOverrideChanged(boolean enabled,
723             @TelephonyManager.MobileDataPolicy int policy) {
724         logl("notifyDataEnabledOverrideChanged: enabled=" + enabled);
725         mDataSettingsManagerCallbacks.forEach(callback -> callback.invokeFromExecutor(
726                 () -> callback.onDataEnabledOverrideChanged(enabled, policy)));
727     }
728 
729     /**
730      * Return the parsed mobile data policies.
731      *
732      * @param policies New mobile data policies in String format.
733      * @return A Set of parsed mobile data policies.
734      */
735     @NonNull
736     @MobileDataPolicy
getMobileDataPolicyEnabled(@onNull String policies)737     public Set<Integer> getMobileDataPolicyEnabled(@NonNull String policies) {
738         Set<Integer> mobileDataPolicies = new HashSet<>();
739         String[] rulesString = policies.trim().split("\\s*,\\s*");
740         for (String rule : rulesString) {
741             if (!TextUtils.isEmpty(rule)) {
742                 int parsedDataPolicy = parsePolicyFrom(rule);
743                 if (parsedDataPolicy != INVALID_MOBILE_DATA_POLICY) {
744                     mobileDataPolicies.add(parsedDataPolicy);
745                 }
746             }
747         }
748         return mobileDataPolicies;
749     }
750 
751     /**
752      * Parse a mobile data policy retrieved from Telephony db.
753      * If the policy is in legacy format, convert it into the corresponding mobile data policy.
754      *
755      * @param policy Mobile data policy to be parsed from.
756      * @return Parsed mobile data policy. {@link #INVALID_MOBILE_DATA_POLICY} if string can't be
757      * parsed into a mobile data policy.
758      */
759     @MobileDataPolicy
parsePolicyFrom(@onNull String policy)760     private int parsePolicyFrom(@NonNull String policy) {
761         int dataPolicy;
762         try {
763             // parse as new override policy
764             dataPolicy = Integer.parseInt(policy);
765         } catch (NumberFormatException e) {
766             dataPolicy = INVALID_MOBILE_DATA_POLICY;
767             loge("parsePolicyFrom: invalid mobile data policy format: "  + policy);
768         }
769         return dataPolicy;
770     }
771 
772     /**
773      * Check if data enabled is temporarily overridden in certain conditions.
774      *
775      * @param apnType The APN type to check.
776      * @return {@code true} if data enabled should be overridden.
777      */
isDataEnabledOverriddenForApn(@pnType int apnType)778     private boolean isDataEnabledOverriddenForApn(@ApnType int apnType) {
779         boolean overridden = false;
780 
781         // mobile data policy : MMS always allowed
782         if (isMobileDataPolicyEnabled(TelephonyManager.MOBILE_DATA_POLICY_MMS_ALWAYS_ALLOWED)) {
783             overridden = apnType == ApnSetting.TYPE_MMS;
784         }
785 
786         boolean isNonDds = mPhone.getSubId() != SubscriptionManagerService.getInstance()
787                 .getDefaultDataSubId();
788 
789         Phone defaultDataPhone = PhoneFactory.getPhone(SubscriptionManagerService.getInstance()
790                 .getPhoneId(SubscriptionManagerService.getInstance()
791                         .getDefaultDataSubId()));
792         boolean isDdsUserEnabled = defaultDataPhone != null && defaultDataPhone.isUserDataEnabled();
793 
794         // mobile data policy : data during call
795         if (isMobileDataPolicyEnabled(TelephonyManager
796                 .MOBILE_DATA_POLICY_DATA_ON_NON_DEFAULT_DURING_VOICE_CALL)) {
797             overridden |= isNonDds && isDdsUserEnabled
798                     && mPhone.getState() != PhoneConstants.State.IDLE;
799         }
800 
801         // mobile data policy : auto data switch
802         if (isMobileDataPolicyEnabled(TelephonyManager.MOBILE_DATA_POLICY_AUTO_DATA_SWITCH)) {
803             // check user enabled data on the default data phone
804             overridden |= isNonDds && isDdsUserEnabled;
805         }
806         return overridden;
807     }
808 
809     /**
810      * Register the callback for receiving information from {@link DataSettingsManager}.
811      *
812      * @param callback The callback.
813      */
registerCallback(@onNull DataSettingsManagerCallback callback)814     public void registerCallback(@NonNull DataSettingsManagerCallback callback) {
815         mDataSettingsManagerCallbacks.add(callback);
816     }
817 
818     /**
819      * Unregister the callback for receiving information from {@link DataSettingsManager}.
820      *
821      * @param callback The callback.
822      */
unregisterCallback(@onNull DataSettingsManagerCallback callback)823     public void unregisterCallback(@NonNull DataSettingsManagerCallback callback) {
824         mDataSettingsManagerCallbacks.remove(callback);
825     }
826 
dataEnabledChangedReasonToString( @elephonyManager.DataEnabledChangedReason int reason)827     private static String dataEnabledChangedReasonToString(
828             @TelephonyManager.DataEnabledChangedReason int reason) {
829         return switch (reason) {
830             case TelephonyManager.DATA_ENABLED_REASON_USER -> "USER";
831             case TelephonyManager.DATA_ENABLED_REASON_POLICY -> "POLICY";
832             case TelephonyManager.DATA_ENABLED_REASON_CARRIER -> "CARRIER";
833             case TelephonyManager.DATA_ENABLED_REASON_THERMAL -> "THERMAL";
834             case TelephonyManager.DATA_ENABLED_REASON_OVERRIDE -> "OVERRIDE";
835             default -> "UNKNOWN";
836         };
837     }
838 
839     @Override
toString()840     public String toString() {
841         return "[isUserDataEnabled=" + isUserDataEnabled()
842                 + ", isProvisioningDataEnabled=" + isProvisioningDataEnabled()
843                 + ", mIsDataEnabled=" + mIsDataEnabled
844                 + ", mDataEnabledSettings=" + mDataEnabledSettings
845                 + ", mEnabledMobileDataPolicy=" + mEnabledMobileDataPolicy.stream()
846                 .map(TelephonyUtils::mobileDataPolicyToString).collect(Collectors.joining(","))
847                 + "]";
848     }
849 
850     /**
851      * Log debug messages.
852      * @param s debug messages
853      */
log(@onNull String s)854     private void log(@NonNull String s) {
855         Rlog.d(mLogTag, s);
856     }
857 
858     /**
859      * Log error messages.
860      * @param s error messages
861      */
loge(@onNull String s)862     private void loge(@NonNull String s) {
863         Rlog.e(mLogTag, s);
864     }
865 
866     /**
867      * Log debug messages and also log into the local log.
868      * @param s debug messages
869      */
logl(@onNull String s)870     private void logl(@NonNull String s) {
871         log(s);
872         mLocalLog.log(s);
873     }
874 
875     /**
876      * Dump the state of DataSettingsManager
877      *
878      * @param fd File descriptor
879      * @param printWriter Print writer
880      * @param args Arguments
881      */
dump(FileDescriptor fd, PrintWriter printWriter, String[] args)882     public void dump(FileDescriptor fd, PrintWriter printWriter, String[] args) {
883         IndentingPrintWriter pw = new IndentingPrintWriter(printWriter, "  ");
884         pw.println(DataSettingsManager.class.getSimpleName() + "-" + mPhone.getPhoneId() + ":");
885         pw.increaseIndent();
886         pw.println("mIsDataEnabled=" + mIsDataEnabled);
887         pw.println("isDataEnabled(internet)=" + isDataEnabled(ApnSetting.TYPE_DEFAULT));
888         pw.println("isDataEnabled(mms)=" + isDataEnabled(ApnSetting.TYPE_MMS));
889         pw.println("isUserDataEnabled=" + isUserDataEnabled());
890         pw.println("isDataRoamingEnabled=" + isDataRoamingEnabled());
891         pw.println("isDefaultDataRoamingEnabled=" + isDefaultDataRoamingEnabled());
892         pw.println("isDataRoamingFromUserAction=" + isDataRoamingFromUserAction());
893         pw.println("device_provisioned=" + Settings.Global.getInt(
894                 mResolver, Settings.Global.DEVICE_PROVISIONED, 0));
895         pw.println("isProvisioningDataEnabled=" + isProvisioningDataEnabled());
896         pw.println("data_stall_recovery_on_bad_network=" + Settings.Global.getInt(
897                 mResolver, Settings.Global.DATA_STALL_RECOVERY_ON_BAD_NETWORK, 1));
898         pw.println("mDataEnabledSettings=" + mDataEnabledSettings.entrySet().stream()
899                 .map(entry ->
900                         dataEnabledChangedReasonToString(entry.getKey()) + "=" + entry.getValue())
901                 .collect(Collectors.joining(", ")));
902         pw.println("mEnabledMobileDataPolicy=" + mEnabledMobileDataPolicy.stream()
903                 .map(TelephonyUtils::mobileDataPolicyToString).collect(Collectors.joining(",")));
904         pw.println("Local logs:");
905         pw.increaseIndent();
906         mLocalLog.dump(fd, pw, args);
907         pw.decreaseIndent();
908         pw.decreaseIndent();
909     }
910 }
911