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