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