1 /*
2  * Copyright (C) 2016 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.dataconnection;
18 
19 
20 import static android.telephony.PhoneStateListener.LISTEN_CALL_STATE;
21 import static android.telephony.PhoneStateListener.LISTEN_NONE;
22 
23 import android.annotation.IntDef;
24 import android.content.ContentResolver;
25 import android.content.Context;
26 import android.os.Handler;
27 import android.os.RegistrantList;
28 import android.os.SystemProperties;
29 import android.provider.Settings;
30 import android.sysprop.TelephonyProperties;
31 import android.telephony.Annotation.CallState;
32 import android.telephony.CarrierConfigManager;
33 import android.telephony.PhoneStateListener;
34 import android.telephony.SubscriptionInfo;
35 import android.telephony.SubscriptionManager;
36 import android.telephony.TelephonyManager;
37 import android.telephony.data.ApnSetting;
38 import android.util.LocalLog;
39 import android.util.Pair;
40 
41 import com.android.internal.telephony.GlobalSettingsHelper;
42 import com.android.internal.telephony.MultiSimSettingController;
43 import com.android.internal.telephony.Phone;
44 import com.android.internal.telephony.SubscriptionController;
45 import com.android.telephony.Rlog;
46 
47 import java.io.FileDescriptor;
48 import java.io.PrintWriter;
49 import java.lang.annotation.Retention;
50 import java.lang.annotation.RetentionPolicy;
51 
52 /**
53  * The class to hold different data enabled/disabled settings. Also it allows clients to register
54  * for overall data enabled setting changed event.
55  * @hide
56  */
57 public class DataEnabledSettings {
58 
59     private static final String LOG_TAG = "DataEnabledSettings";
60 
61     @Retention(RetentionPolicy.SOURCE)
62     @IntDef(prefix = {"REASON_"},
63             value = {
64                     REASON_REGISTERED,
65                     REASON_INTERNAL_DATA_ENABLED,
66                     REASON_USER_DATA_ENABLED,
67                     REASON_POLICY_DATA_ENABLED,
68                     REASON_DATA_ENABLED_BY_CARRIER,
69                     REASON_PROVISIONED_CHANGED,
70                     REASON_PROVISIONING_DATA_ENABLED_CHANGED,
71                     REASON_OVERRIDE_RULE_CHANGED,
72                     REASON_OVERRIDE_CONDITION_CHANGED
73             })
74     public @interface DataEnabledChangedReason {}
75 
76     public static final int REASON_REGISTERED = 0;
77 
78     public static final int REASON_INTERNAL_DATA_ENABLED = 1;
79 
80     public static final int REASON_USER_DATA_ENABLED = 2;
81 
82     public static final int REASON_POLICY_DATA_ENABLED = 3;
83 
84     public static final int REASON_DATA_ENABLED_BY_CARRIER = 4;
85 
86     public static final int REASON_PROVISIONED_CHANGED = 5;
87 
88     public static final int REASON_PROVISIONING_DATA_ENABLED_CHANGED = 6;
89 
90     public static final int REASON_OVERRIDE_RULE_CHANGED = 7;
91 
92     public static final int REASON_OVERRIDE_CONDITION_CHANGED = 8;
93 
94     /**
95      * responds to the setInternalDataEnabled call - used internally to turn off data.
96      * For example during emergency calls
97      */
98     private boolean mInternalDataEnabled = true;
99 
100     /**
101      * Flag indicating data allowed by network policy manager or not.
102      */
103     private boolean mPolicyDataEnabled = true;
104 
105     /**
106      * Indicate if metered APNs are enabled by the carrier. set false to block all the metered APNs
107      * from continuously sending requests, which causes undesired network load.
108      */
109     private boolean mCarrierDataEnabled = true;
110 
111     private boolean mIsDataEnabled = false;
112 
113     private final Phone mPhone;
114 
115     private int mSubId = SubscriptionManager.INVALID_SUBSCRIPTION_ID;
116 
117     private ContentResolver mResolver = null;
118 
119     private final RegistrantList mOverallDataEnabledChangedRegistrants = new RegistrantList();
120 
121     // TODO: Merge this with mOverallDataEnabledChangedRegistrants. In the future, notifying data
122     // enabled changed with APN types bitmask
123     private final RegistrantList mOverallDataEnabledOverrideChangedRegistrants =
124             new RegistrantList();
125 
126     private final LocalLog mSettingChangeLocalLog = new LocalLog(50);
127 
128     private DataEnabledOverride mDataEnabledOverride;
129 
130     private TelephonyManager mTelephonyManager;
131 
132     // for msim, user data enabled setting depends on subId.
133     private final SubscriptionManager.OnSubscriptionsChangedListener
134             mOnSubscriptionsChangeListener =
135             new SubscriptionManager.OnSubscriptionsChangedListener() {
136                 @Override
137                 public void onSubscriptionsChanged() {
138                     synchronized (this) {
139                         if (mSubId != mPhone.getSubId()) {
140                             log("onSubscriptionsChanged subId: " + mSubId + " to: "
141                                     + mPhone.getSubId());
142                             mSubId = mPhone.getSubId();
143                             mDataEnabledOverride = getDataEnabledOverride();
144                             updatePhoneStateListener();
145                             updateDataEnabledAndNotify(REASON_USER_DATA_ENABLED);
146                             mPhone.notifyUserMobileDataStateChanged(isUserDataEnabled());
147                         }
148                     }
149                 }
150             };
151 
updatePhoneStateListener()152     private void updatePhoneStateListener() {
153         mTelephonyManager.listen(mPhoneStateListener, LISTEN_NONE);
154         if (SubscriptionManager.isUsableSubscriptionId(mSubId)) {
155             mTelephonyManager = mTelephonyManager.createForSubscriptionId(mSubId);
156         }
157         mTelephonyManager.listen(mPhoneStateListener, LISTEN_CALL_STATE);
158     }
159 
160     private final PhoneStateListener mPhoneStateListener = new PhoneStateListener() {
161         @Override
162         public void onCallStateChanged(@CallState int state, String phoneNumber) {
163             updateDataEnabledAndNotify(REASON_OVERRIDE_CONDITION_CHANGED);
164         }
165     };
166 
167     @Override
toString()168     public String toString() {
169         return "[mInternalDataEnabled=" + mInternalDataEnabled
170                 + ", isUserDataEnabled=" + isUserDataEnabled()
171                 + ", isProvisioningDataEnabled=" + isProvisioningDataEnabled()
172                 + ", mPolicyDataEnabled=" + mPolicyDataEnabled
173                 + ", mCarrierDataEnabled=" + mCarrierDataEnabled
174                 + ", mIsDataEnabled=" + mIsDataEnabled
175                 + ", " + mDataEnabledOverride
176                 + "]";
177     }
178 
DataEnabledSettings(Phone phone)179     public DataEnabledSettings(Phone phone) {
180         mPhone = phone;
181         mResolver = mPhone.getContext().getContentResolver();
182         SubscriptionManager subscriptionManager = (SubscriptionManager) mPhone.getContext()
183                 .getSystemService(Context.TELEPHONY_SUBSCRIPTION_SERVICE);
184         subscriptionManager.addOnSubscriptionsChangedListener(mOnSubscriptionsChangeListener);
185         mTelephonyManager = (TelephonyManager) mPhone.getContext()
186                 .getSystemService(Context.TELEPHONY_SERVICE);
187         mDataEnabledOverride = getDataEnabledOverride();
188         updateDataEnabled();
189     }
190 
getDataEnabledOverride()191     private DataEnabledOverride getDataEnabledOverride() {
192         return new DataEnabledOverride(SubscriptionController.getInstance()
193                 .getDataEnabledOverrideRules(mPhone.getSubId()));
194     }
195 
setInternalDataEnabled(boolean enabled)196     public synchronized void setInternalDataEnabled(boolean enabled) {
197         if (mInternalDataEnabled != enabled) {
198             localLog("InternalDataEnabled", enabled);
199             mInternalDataEnabled = enabled;
200             updateDataEnabledAndNotify(REASON_INTERNAL_DATA_ENABLED);
201         }
202     }
isInternalDataEnabled()203     public synchronized boolean isInternalDataEnabled() {
204         return mInternalDataEnabled;
205     }
206 
setUserDataEnabled(boolean enabled)207     public synchronized void setUserDataEnabled(boolean enabled) {
208         // By default the change should propagate to the group.
209         setUserDataEnabled(enabled, true);
210     }
211 
212     /**
213      * @param notifyMultiSimSettingController if setUserDataEnabled is already from propagating
214      *        from MultiSimSettingController, don't notify MultiSimSettingController again.
215      *        For example, if sub1 and sub2 are in the same group and user enables data for sub
216      *        1, sub 2 will also be enabled but with propagateToGroup = false.
217      */
setUserDataEnabled(boolean enabled, boolean notifyMultiSimSettingController)218     public synchronized void setUserDataEnabled(boolean enabled,
219             boolean notifyMultiSimSettingController) {
220         // Can't disable data for stand alone opportunistic subscription.
221         if (isStandAloneOpportunistic(mPhone.getSubId(), mPhone.getContext()) && !enabled) return;
222 
223         boolean changed = GlobalSettingsHelper.setInt(mPhone.getContext(),
224                 Settings.Global.MOBILE_DATA, mPhone.getSubId(), (enabled ? 1 : 0));
225         if (changed) {
226             localLog("UserDataEnabled", enabled);
227             mPhone.notifyUserMobileDataStateChanged(enabled);
228             updateDataEnabledAndNotify(REASON_USER_DATA_ENABLED);
229             if (notifyMultiSimSettingController) {
230                 MultiSimSettingController.getInstance().notifyUserDataEnabled(
231                         mPhone.getSubId(), enabled);
232             }
233         }
234     }
235 
isUserDataEnabled()236     public synchronized boolean isUserDataEnabled() {
237         // User data should always be true for opportunistic subscription.
238         if (isStandAloneOpportunistic(mPhone.getSubId(), mPhone.getContext())) return true;
239 
240         boolean defaultVal = TelephonyProperties.mobile_data().orElse(true);
241 
242         return GlobalSettingsHelper.getBoolean(mPhone.getContext(),
243                 Settings.Global.MOBILE_DATA, mPhone.getSubId(), defaultVal);
244     }
245 
246     /**
247      * Set whether always allowing MMS data connection.
248      *
249      * @param alwaysAllow {@code true} if MMS data is always allowed.
250      *
251      * @return {@code false} if the setting is changed.
252      */
setAlwaysAllowMmsData(boolean alwaysAllow)253     public synchronized boolean setAlwaysAllowMmsData(boolean alwaysAllow) {
254         localLog("setAlwaysAllowMmsData", alwaysAllow);
255         mDataEnabledOverride.setAlwaysAllowMms(alwaysAllow);
256         boolean changed = SubscriptionController.getInstance()
257                 .setDataEnabledOverrideRules(mPhone.getSubId(), mDataEnabledOverride.getRules());
258         if (changed) {
259             updateDataEnabledAndNotify(REASON_OVERRIDE_RULE_CHANGED);
260             notifyDataEnabledOverrideChanged();
261         }
262 
263         return changed;
264     }
265 
266     /**
267      * Set allowing mobile data during voice call. This is used for allowing data on the non-default
268      * data SIM. When a voice call is placed on the non-default data SIM on DSDS devices, users will
269      * not be able to use mobile data. By calling this API, data will be temporarily enabled on the
270      * non-default data SIM during the life cycle of the voice call.
271      *
272      * @param allow {@code true} if allowing using data during voice call, {@code false} if
273      * disallowed
274      *
275      * @return {@code true} if operation is successful. otherwise {@code false}.
276      */
setAllowDataDuringVoiceCall(boolean allow)277     public synchronized boolean setAllowDataDuringVoiceCall(boolean allow) {
278         localLog("setAllowDataDuringVoiceCall", allow);
279         if (allow == isDataAllowedInVoiceCall()) {
280             return true;
281         }
282         mDataEnabledOverride.setDataAllowedInVoiceCall(allow);
283 
284         boolean changed = SubscriptionController.getInstance()
285                 .setDataEnabledOverrideRules(mPhone.getSubId(), mDataEnabledOverride.getRules());
286         if (changed) {
287             updateDataEnabledAndNotify(REASON_OVERRIDE_RULE_CHANGED);
288             notifyDataEnabledOverrideChanged();
289         }
290 
291         return changed;
292     }
293 
294     /**
295      * Check if data is allowed during voice call.
296      *
297      * @return {@code true} if data is allowed during voice call.
298      */
isDataAllowedInVoiceCall()299     public synchronized boolean isDataAllowedInVoiceCall() {
300         return mDataEnabledOverride.isDataAllowedInVoiceCall();
301     }
302 
setPolicyDataEnabled(boolean enabled)303     public synchronized void setPolicyDataEnabled(boolean enabled) {
304         if (mPolicyDataEnabled != enabled) {
305             localLog("PolicyDataEnabled", enabled);
306             mPolicyDataEnabled = enabled;
307             updateDataEnabledAndNotify(REASON_POLICY_DATA_ENABLED);
308         }
309     }
310 
isPolicyDataEnabled()311     public synchronized boolean isPolicyDataEnabled() {
312         return mPolicyDataEnabled;
313     }
314 
setCarrierDataEnabled(boolean enabled)315     public synchronized void setCarrierDataEnabled(boolean enabled) {
316         if (mCarrierDataEnabled != enabled) {
317             localLog("CarrierDataEnabled", enabled);
318             mCarrierDataEnabled = enabled;
319             updateDataEnabledAndNotify(REASON_DATA_ENABLED_BY_CARRIER);
320         }
321     }
322 
isCarrierDataEnabled()323     public synchronized boolean isCarrierDataEnabled() {
324         return mCarrierDataEnabled;
325     }
326 
updateProvisionedChanged()327     public synchronized void updateProvisionedChanged() {
328         updateDataEnabledAndNotify(REASON_PROVISIONED_CHANGED);
329     }
330 
updateProvisioningDataEnabled()331     public synchronized void updateProvisioningDataEnabled() {
332         updateDataEnabledAndNotify(REASON_PROVISIONING_DATA_ENABLED_CHANGED);
333     }
334 
isDataEnabled()335     public synchronized boolean isDataEnabled() {
336         return mIsDataEnabled;
337     }
338 
updateDataEnabledAndNotify(int reason)339     private synchronized void updateDataEnabledAndNotify(int reason) {
340         boolean prevDataEnabled = mIsDataEnabled;
341 
342         updateDataEnabled();
343 
344         if (prevDataEnabled != mIsDataEnabled) {
345             notifyDataEnabledChanged(!prevDataEnabled, reason);
346         }
347     }
348 
updateDataEnabled()349     private synchronized void updateDataEnabled() {
350         if (isProvisioning()) {
351             mIsDataEnabled = isProvisioningDataEnabled();
352         } else {
353             mIsDataEnabled = mInternalDataEnabled && (isUserDataEnabled() || mDataEnabledOverride
354                     .shouldOverrideDataEnabledSettings(mPhone, ApnSetting.TYPE_ALL))
355                     && mPolicyDataEnabled && mCarrierDataEnabled;
356         }
357     }
358 
isProvisioning()359     public boolean isProvisioning() {
360         return Settings.Global.getInt(mResolver, Settings.Global.DEVICE_PROVISIONED, 0) == 0;
361     }
362     /**
363      * In provisioning, we might want to have enable mobile data during provisioning. It depends
364      * on value of Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED which is set by
365      * setupwizard. It only matters if it's in provisioning stage.
366      * @return whether we are enabling userData during provisioning stage.
367      */
isProvisioningDataEnabled()368     public boolean isProvisioningDataEnabled() {
369         final String prov_property = SystemProperties.get("ro.com.android.prov_mobiledata",
370                 "false");
371         boolean retVal = "true".equalsIgnoreCase(prov_property);
372 
373         final int prov_mobile_data = Settings.Global.getInt(mResolver,
374                 Settings.Global.DEVICE_PROVISIONING_MOBILE_DATA_ENABLED,
375                 retVal ? 1 : 0);
376         retVal = prov_mobile_data != 0;
377         log("getDataEnabled during provisioning retVal=" + retVal + " - (" + prov_property
378                 + ", " + prov_mobile_data + ")");
379 
380         return retVal;
381     }
382 
setDataRoamingEnabled(boolean enabled)383     public synchronized void setDataRoamingEnabled(boolean enabled) {
384         // will trigger handleDataOnRoamingChange() through observer
385         boolean changed = GlobalSettingsHelper.setBoolean(mPhone.getContext(),
386                 Settings.Global.DATA_ROAMING, mPhone.getSubId(), enabled);
387 
388         if (changed) {
389             localLog("setDataRoamingEnabled", enabled);
390             MultiSimSettingController.getInstance().notifyRoamingDataEnabled(mPhone.getSubId(),
391                     enabled);
392         }
393     }
394 
395     /**
396      * Return current {@link android.provider.Settings.Global#DATA_ROAMING} value.
397      */
getDataRoamingEnabled()398     public synchronized boolean getDataRoamingEnabled() {
399         return GlobalSettingsHelper.getBoolean(mPhone.getContext(),
400                 Settings.Global.DATA_ROAMING, mPhone.getSubId(), getDefaultDataRoamingEnabled());
401     }
402 
403     /**
404      * get default values for {@link Settings.Global#DATA_ROAMING}
405      * return {@code true} if either
406      * {@link CarrierConfigManager#KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL} or
407      * system property ro.com.android.dataroaming is set to true. otherwise return {@code false}
408      */
getDefaultDataRoamingEnabled()409     public synchronized boolean getDefaultDataRoamingEnabled() {
410         final CarrierConfigManager configMgr = (CarrierConfigManager)
411                 mPhone.getContext().getSystemService(Context.CARRIER_CONFIG_SERVICE);
412         boolean isDataRoamingEnabled = "true".equalsIgnoreCase(SystemProperties.get(
413                 "ro.com.android.dataroaming", "false"));
414         isDataRoamingEnabled |= configMgr.getConfigForSubId(mPhone.getSubId()).getBoolean(
415                 CarrierConfigManager.KEY_CARRIER_DEFAULT_DATA_ROAMING_ENABLED_BOOL);
416         return isDataRoamingEnabled;
417     }
418 
notifyDataEnabledChanged(boolean enabled, int reason)419     private void notifyDataEnabledChanged(boolean enabled, int reason) {
420         mOverallDataEnabledChangedRegistrants.notifyResult(new Pair<>(enabled, reason));
421     }
422 
registerForDataEnabledChanged(Handler h, int what, Object obj)423     public void registerForDataEnabledChanged(Handler h, int what, Object obj) {
424         mOverallDataEnabledChangedRegistrants.addUnique(h, what, obj);
425         notifyDataEnabledChanged(isDataEnabled(), REASON_REGISTERED);
426     }
427 
unregisterForDataEnabledChanged(Handler h)428     public void unregisterForDataEnabledChanged(Handler h) {
429         mOverallDataEnabledChangedRegistrants.remove(h);
430     }
431 
notifyDataEnabledOverrideChanged()432     private void notifyDataEnabledOverrideChanged() {
433         mOverallDataEnabledOverrideChangedRegistrants.notifyRegistrants();
434     }
435 
436     /**
437      * Register for data enabled override changed event.
438      *
439      * @param h The handler
440      * @param what The event
441      */
registerForDataEnabledOverrideChanged(Handler h, int what)442     public void registerForDataEnabledOverrideChanged(Handler h, int what) {
443         mOverallDataEnabledOverrideChangedRegistrants.addUnique(h, what, null);
444         notifyDataEnabledOverrideChanged();
445     }
446 
447     /**
448      * Unregistered for data enabled override changed event.
449      *
450      * @param h The handler
451      */
unregisterForDataEnabledOverrideChanged(Handler h)452     public void unregisterForDataEnabledOverrideChanged(Handler h) {
453         mOverallDataEnabledOverrideChangedRegistrants.remove(h);
454     }
455 
isStandAloneOpportunistic(int subId, Context context)456     private static boolean isStandAloneOpportunistic(int subId, Context context) {
457         SubscriptionInfo info = SubscriptionController.getInstance().getActiveSubscriptionInfo(
458                 subId, context.getOpPackageName(), context.getAttributionTag());
459         return (info != null) && info.isOpportunistic() && info.getGroupUuid() == null;
460     }
461 
isDataEnabled(int apnType)462     public synchronized boolean isDataEnabled(int apnType) {
463         if (isProvisioning()) {
464             return isProvisioningDataEnabled();
465         } else {
466             boolean userDataEnabled = isUserDataEnabled();
467             // Check if we should temporarily enable data in certain conditions.
468             boolean isDataEnabledOverridden = mDataEnabledOverride
469                     .shouldOverrideDataEnabledSettings(mPhone, apnType);
470 
471             return (mInternalDataEnabled && mPolicyDataEnabled && mCarrierDataEnabled
472                     && (userDataEnabled || isDataEnabledOverridden));
473         }
474     }
475 
log(String s)476     private void log(String s) {
477         Rlog.d(LOG_TAG, "[" + mPhone.getPhoneId() + "]" + s);
478     }
479 
localLog(String name, boolean value)480     private void localLog(String name, boolean value) {
481         mSettingChangeLocalLog.log(name + " change to " + value);
482     }
483 
dump(FileDescriptor fd, PrintWriter pw, String[] args)484     protected void dump(FileDescriptor fd, PrintWriter pw, String[] args) {
485         pw.println(" DataEnabledSettings=");
486         mSettingChangeLocalLog.dump(fd, pw, args);
487     }
488 }
489