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