1 /* 2 * Copyright (C) 2017 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.networkstack.tethering; 18 19 import static android.content.Context.TELEPHONY_SERVICE; 20 import static android.net.ConnectivityManager.TYPE_ETHERNET; 21 import static android.net.ConnectivityManager.TYPE_MOBILE; 22 import static android.net.ConnectivityManager.TYPE_MOBILE_DUN; 23 import static android.net.ConnectivityManager.TYPE_MOBILE_HIPRI; 24 import static android.provider.DeviceConfig.NAMESPACE_CONNECTIVITY; 25 26 import static com.android.networkstack.apishim.ConstantsShim.KEY_CARRIER_SUPPORTS_TETHERING_BOOL; 27 import static com.android.net.module.util.SdkUtil.isAtLeast25Q2; 28 29 import android.content.ContentResolver; 30 import android.content.Context; 31 import android.content.res.Resources; 32 import android.net.TetheringConfigurationParcel; 33 import android.os.PersistableBundle; 34 import android.provider.DeviceConfig; 35 import android.provider.Settings; 36 import android.telephony.CarrierConfigManager; 37 import android.telephony.SubscriptionManager; 38 import android.telephony.TelephonyManager; 39 import android.text.TextUtils; 40 41 import androidx.annotation.NonNull; 42 43 import com.android.internal.annotations.VisibleForTesting; 44 import com.android.modules.utils.build.SdkLevel; 45 import com.android.net.module.util.DeviceConfigUtils; 46 import com.android.net.module.util.SharedLog; 47 48 import java.io.PrintWriter; 49 import java.util.ArrayList; 50 import java.util.Arrays; 51 import java.util.Collection; 52 import java.util.StringJoiner; 53 54 /** 55 * A utility class to encapsulate the various tethering configuration elements. 56 * 57 * This configuration data includes elements describing upstream properties 58 * (preferred and required types of upstream connectivity as well as default 59 * DNS servers to use if none are available) and downstream properties (such 60 * as regular expressions use to match suitable downstream interfaces and the 61 * DHCPv4 ranges to use). 62 * 63 * @hide 64 */ 65 public class TetheringConfiguration { 66 private static final String TAG = TetheringConfiguration.class.getSimpleName(); 67 68 private static final String[] EMPTY_STRING_ARRAY = new String[0]; 69 70 // Default ranges used for the legacy DHCP server. 71 // USB is 192.168.42.1 and 255.255.255.0 72 // Wifi is 192.168.43.1 and 255.255.255.0 73 // BT is limited to max default of 5 connections. 192.168.44.1 to 192.168.48.1 74 // with 255.255.255.0 75 // P2P is 192.168.49.1 and 255.255.255.0 76 private static final String[] LEGACY_DHCP_DEFAULT_RANGE = { 77 "192.168.42.2", "192.168.42.254", "192.168.43.2", "192.168.43.254", 78 "192.168.44.2", "192.168.44.254", "192.168.45.2", "192.168.45.254", 79 "192.168.46.2", "192.168.46.254", "192.168.47.2", "192.168.47.254", 80 "192.168.48.2", "192.168.48.254", "192.168.49.2", "192.168.49.254", 81 }; 82 83 private static final String[] DEFAULT_IPV4_DNS = {"8.8.4.4", "8.8.8.8"}; 84 85 @VisibleForTesting 86 public static final int TETHER_USB_RNDIS_FUNCTION = 0; 87 88 @VisibleForTesting 89 public static final int TETHER_USB_NCM_FUNCTION = 1; 90 91 /** 92 * Override enabling BPF offload configuration for tethering. 93 */ 94 public static final String OVERRIDE_TETHER_ENABLE_BPF_OFFLOAD = 95 "override_tether_enable_bpf_offload"; 96 97 /** 98 * Use the old dnsmasq DHCP server for tethering instead of the framework implementation. 99 */ 100 public static final String TETHER_ENABLE_LEGACY_DHCP_SERVER = 101 "tether_enable_legacy_dhcp_server"; 102 103 public static final String USE_LEGACY_WIFI_P2P_DEDICATED_IP = 104 "use_legacy_wifi_p2p_dedicated_ip"; 105 106 /** 107 * Experiment flag to force choosing upstreams automatically. 108 * 109 * This setting is intended to help force-enable the feature on OEM devices that disabled it 110 * via resource overlays, and later noticed issues. To that end, it overrides 111 * config_tether_upstream_automatic when set to true. 112 * 113 * This flag is enabled if !=0 and less than the module APEX version: see 114 * {@link DeviceConfigUtils#isTetheringFeatureEnabled}. It is also ignored after R, as later 115 * devices should just set config_tether_upstream_automatic to true instead. 116 */ 117 public static final String TETHER_FORCE_UPSTREAM_AUTOMATIC_VERSION = 118 "tether_force_upstream_automatic_version"; 119 120 /** 121 * Settings key to foce choosing usb functions for usb tethering. 122 * 123 * TODO: Remove this hard code string and make Settings#TETHER_FORCE_USB_FUNCTIONS as API. 124 */ 125 public static final String TETHER_FORCE_USB_FUNCTIONS = 126 "tether_force_usb_functions"; 127 128 /** 129 * Experiment flag to enable TETHERING_WEAR. 130 */ 131 public static final String TETHER_ENABLE_WEAR_TETHERING = 132 "tether_enable_wear_tethering"; 133 134 public static final String TETHER_ENABLE_SYNC_SM = "tether_enable_sync_sm"; 135 136 /** 137 * Default value that used to periodic polls tether offload stats from tethering offload HAL 138 * to make the data warnings work. 139 */ 140 public static final int DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS = 5000; 141 142 /** A flag for using synchronous or asynchronous state machine. */ 143 public static boolean USE_SYNC_SM = true; 144 145 /** 146 * A feature flag to control whether the active sessions metrics should be enabled. 147 * Disabled by default. 148 */ 149 public static final String TETHER_ACTIVE_SESSIONS_METRICS = "tether_active_sessions_metrics"; 150 151 /** 152 * A feature flag to control whether the tethering local network agent should be enabled. 153 * Disabled by default. 154 */ 155 public static final String TETHERING_LOCAL_NETWORK_AGENT = "tethering_local_network_agent"; 156 157 public final String[] tetherableUsbRegexs; 158 public final String[] tetherableWifiRegexs; 159 public final String[] tetherableWigigRegexs; 160 public final String[] tetherableWifiP2pRegexs; 161 public final String[] tetherableBluetoothRegexs; 162 public final String[] tetherableNcmRegexs; 163 public final boolean isDunRequired; 164 public final boolean chooseUpstreamAutomatically; 165 public final Collection<Integer> preferredUpstreamIfaceTypes; 166 public final String[] legacyDhcpRanges; 167 public final String[] defaultIPv4DNS; 168 169 public final String[] provisioningApp; 170 public final String provisioningAppNoUi; 171 public final int provisioningCheckPeriod; 172 public final String provisioningResponse; 173 174 public final boolean isCarrierSupportTethering; 175 public final boolean isCarrierConfigAffirmsEntitlementCheckRequired; 176 177 public final int activeDataSubId; 178 179 private final Dependencies mDeps; 180 181 private final boolean mEnableLegacyDhcpServer; 182 private final int mOffloadPollInterval; 183 // TODO: Add to TetheringConfigurationParcel if required. 184 private final boolean mEnableBpfOffload; 185 private final boolean mEnableWifiP2pDedicatedIp; 186 private final int mP2pLeasesSubnetPrefixLength; 187 188 private final boolean mEnableWearTethering; 189 190 private final int mUsbTetheringFunction; 191 protected final ContentResolver mContentResolver; 192 193 /** 194 * A class wrapping dependencies of {@link TetheringConfiguration}, useful for testing. 195 */ 196 @VisibleForTesting 197 public static class Dependencies { isFeatureEnabled(@onNull Context context, @NonNull String name)198 boolean isFeatureEnabled(@NonNull Context context, @NonNull String name) { 199 return DeviceConfigUtils.isTetheringFeatureEnabled(context, name); 200 } 201 isFeatureNotChickenedOut(@onNull Context context, @NonNull String name)202 boolean isFeatureNotChickenedOut(@NonNull Context context, @NonNull String name) { 203 return DeviceConfigUtils.isTetheringFeatureNotChickenedOut(context, name); 204 } 205 getDeviceConfigBoolean(@onNull String namespace, @NonNull String name, boolean defaultValue)206 boolean getDeviceConfigBoolean(@NonNull String namespace, @NonNull String name, 207 boolean defaultValue) { 208 return DeviceConfig.getBoolean(namespace, name, defaultValue); 209 } 210 211 /** 212 * TETHER_FORCE_UPSTREAM_AUTOMATIC_VERSION is used to force enable the feature on specific 213 * R devices. Just checking the flag value is enough since the flag has been pushed to 214 * enable the feature on the old version and any new binary will always have a version 215 * number newer than the flag. 216 * This flag is wrongly configured in the connectivity namespace so this method reads the 217 * flag value from the connectivity namespace. But the tethering module should use the 218 * tethering namespace. This method can be removed after R EOL. 219 */ isTetherForceUpstreamAutomaticFeatureEnabled()220 boolean isTetherForceUpstreamAutomaticFeatureEnabled() { 221 final int flagValue = DeviceConfigUtils.getDeviceConfigPropertyInt( 222 NAMESPACE_CONNECTIVITY, TETHER_FORCE_UPSTREAM_AUTOMATIC_VERSION, 223 0 /* defaultValue */); 224 return flagValue > 0; 225 } 226 } 227 TetheringConfiguration(@onNull Context ctx, @NonNull SharedLog log, int id)228 public TetheringConfiguration(@NonNull Context ctx, @NonNull SharedLog log, int id) { 229 this(ctx, log, id, new Dependencies()); 230 } 231 232 @VisibleForTesting TetheringConfiguration(@onNull Context ctx, @NonNull SharedLog log, int id, @NonNull Dependencies deps)233 public TetheringConfiguration(@NonNull Context ctx, @NonNull SharedLog log, int id, 234 @NonNull Dependencies deps) { 235 mDeps = deps; 236 final SharedLog configLog = log.forSubComponent("config"); 237 238 activeDataSubId = id; 239 Resources res = getResources(ctx, activeDataSubId); 240 mContentResolver = ctx.getContentResolver(); 241 242 mUsbTetheringFunction = getUsbTetheringFunction(res); 243 244 final String[] ncmRegexs = getResourceStringArray(res, R.array.config_tether_ncm_regexs); 245 // If usb tethering use NCM and config_tether_ncm_regexs is not empty, use 246 // config_tether_ncm_regexs for tetherableUsbRegexs. 247 if (isUsingNcm() && (ncmRegexs.length != 0)) { 248 tetherableUsbRegexs = ncmRegexs; 249 tetherableNcmRegexs = EMPTY_STRING_ARRAY; 250 } else { 251 tetherableUsbRegexs = getResourceStringArray(res, R.array.config_tether_usb_regexs); 252 tetherableNcmRegexs = ncmRegexs; 253 } 254 // TODO: Evaluate deleting this altogether now that Wi-Fi always passes 255 // us an interface name. Careful consideration needs to be given to 256 // implications for Settings and for provisioning checks. 257 tetherableWifiRegexs = getResourceStringArray(res, R.array.config_tether_wifi_regexs); 258 // TODO: Remove entire wigig code once tethering module no longer support R devices. 259 tetherableWigigRegexs = SdkLevel.isAtLeastS() 260 ? new String[0] : getResourceStringArray(res, R.array.config_tether_wigig_regexs); 261 tetherableWifiP2pRegexs = getResourceStringArray( 262 res, R.array.config_tether_wifi_p2p_regexs); 263 tetherableBluetoothRegexs = getResourceStringArray( 264 res, R.array.config_tether_bluetooth_regexs); 265 266 isDunRequired = checkDunRequired(ctx); 267 268 // Here is how automatic mode enable/disable support on different Android version: 269 // - R : can be enabled/disabled by resource config_tether_upstream_automatic. 270 // but can be force-enabled by flag TETHER_FORCE_UPSTREAM_AUTOMATIC_VERSION. 271 // - S, T: can be enabled/disabled by resource config_tether_upstream_automatic. 272 // - U+ : automatic mode only. 273 final boolean forceAutomaticUpstream = SdkLevel.isAtLeastU() || (!SdkLevel.isAtLeastS() 274 && mDeps.isTetherForceUpstreamAutomaticFeatureEnabled()); 275 chooseUpstreamAutomatically = forceAutomaticUpstream || getResourceBoolean( 276 res, R.bool.config_tether_upstream_automatic, false /** defaultValue */); 277 preferredUpstreamIfaceTypes = getUpstreamIfaceTypes(res, isDunRequired); 278 279 legacyDhcpRanges = getLegacyDhcpRanges(res); 280 defaultIPv4DNS = copy(DEFAULT_IPV4_DNS); 281 mEnableBpfOffload = getEnableBpfOffload(res); 282 mEnableLegacyDhcpServer = getEnableLegacyDhcpServer(res); 283 284 provisioningApp = getResourceStringArray(res, R.array.config_mobile_hotspot_provision_app); 285 provisioningAppNoUi = getResourceString(res, 286 R.string.config_mobile_hotspot_provision_app_no_ui); 287 provisioningCheckPeriod = getResourceInteger(res, 288 R.integer.config_mobile_hotspot_provision_check_period, 289 0 /* No periodic re-check */); 290 provisioningResponse = getResourceString(res, 291 R.string.config_mobile_hotspot_provision_response); 292 293 PersistableBundle carrierConfigs = getCarrierConfig(ctx, activeDataSubId); 294 isCarrierSupportTethering = carrierConfigAffirmsCarrierSupport(carrierConfigs); 295 isCarrierConfigAffirmsEntitlementCheckRequired = 296 carrierConfigAffirmsEntitlementCheckRequired(carrierConfigs); 297 298 mOffloadPollInterval = getResourceInteger(res, 299 R.integer.config_tether_offload_poll_interval, 300 DEFAULT_TETHER_OFFLOAD_POLL_INTERVAL_MS); 301 302 mEnableWifiP2pDedicatedIp = getResourceBoolean(res, 303 R.bool.config_tether_enable_legacy_wifi_p2p_dedicated_ip, 304 false /* defaultValue */); 305 306 mP2pLeasesSubnetPrefixLength = getP2pLeasesSubnetPrefixLengthFromRes(res, configLog); 307 308 mEnableWearTethering = shouldEnableWearTethering(ctx); 309 310 configLog.log(toString()); 311 } 312 getP2pLeasesSubnetPrefixLengthFromRes(final Resources res, final SharedLog log)313 private int getP2pLeasesSubnetPrefixLengthFromRes(final Resources res, final SharedLog log) { 314 if (!mEnableWifiP2pDedicatedIp) return 0; 315 316 int prefixLength = getResourceInteger(res, 317 R.integer.config_p2p_leases_subnet_prefix_length, 0 /* default value */); 318 319 // DhcpLeaseRepository ignores the first and last addresses of the range so the max prefix 320 // length is 30. 321 if (prefixLength < 0 || prefixLength > 30) { 322 log.e("Invalid p2p leases subnet prefix length configuration: " + prefixLength); 323 return 0; 324 } 325 326 return prefixLength; 327 } 328 329 /** Check whether using legacy dhcp server. */ useLegacyDhcpServer()330 public boolean useLegacyDhcpServer() { 331 return mEnableLegacyDhcpServer; 332 } 333 334 /** Check whether using ncm for usb tethering */ isUsingNcm()335 public boolean isUsingNcm() { 336 return mUsbTetheringFunction == TETHER_USB_NCM_FUNCTION; 337 } 338 339 /** Check whether input interface belong to usb.*/ isUsb(String iface)340 public boolean isUsb(String iface) { 341 return matchesDownstreamRegexs(iface, tetherableUsbRegexs); 342 } 343 344 /** Check whether input interface belong to wifi.*/ isWifi(String iface)345 public boolean isWifi(String iface) { 346 return matchesDownstreamRegexs(iface, tetherableWifiRegexs); 347 } 348 349 /** Check whether input interface belong to wigig.*/ isWigig(String iface)350 public boolean isWigig(String iface) { 351 return matchesDownstreamRegexs(iface, tetherableWigigRegexs); 352 } 353 354 /** Check whether this interface is Wifi P2P interface. */ isWifiP2p(String iface)355 public boolean isWifiP2p(String iface) { 356 return matchesDownstreamRegexs(iface, tetherableWifiP2pRegexs); 357 } 358 359 /** Check whether using legacy mode for wifi P2P. */ isWifiP2pLegacyTetheringMode()360 public boolean isWifiP2pLegacyTetheringMode() { 361 return (tetherableWifiP2pRegexs == null || tetherableWifiP2pRegexs.length == 0); 362 } 363 364 /** Check whether input interface belong to bluetooth.*/ isBluetooth(String iface)365 public boolean isBluetooth(String iface) { 366 return matchesDownstreamRegexs(iface, tetherableBluetoothRegexs); 367 } 368 369 /** Check if interface is ncm */ isNcm(String iface)370 public boolean isNcm(String iface) { 371 return matchesDownstreamRegexs(iface, tetherableNcmRegexs); 372 } 373 374 /** Check whether no ui entitlement application is available.*/ hasMobileHotspotProvisionApp()375 public boolean hasMobileHotspotProvisionApp() { 376 return !TextUtils.isEmpty(provisioningAppNoUi); 377 } 378 379 /** Check whether dedicated wifi p2p address is enabled. */ shouldEnableWifiP2pDedicatedIp()380 public boolean shouldEnableWifiP2pDedicatedIp() { 381 return mEnableWifiP2pDedicatedIp; 382 } 383 384 /** 385 * Get subnet prefix length of dhcp leases for wifi p2p. 386 * This feature only support when wifi p2p use dedicated address. If 387 * #shouldEnableWifiP2pDedicatedIp is false, this method would always return 0. 388 */ getP2pLeasesSubnetPrefixLength()389 public int getP2pLeasesSubnetPrefixLength() { 390 return mP2pLeasesSubnetPrefixLength; 391 } 392 393 /** Returns true if wearable device tethering is enabled. */ isWearTetheringEnabled()394 public boolean isWearTetheringEnabled() { 395 return mEnableWearTethering; 396 } 397 398 /** 399 * Check whether sync SM is enabled then set it to USE_SYNC_SM. This should be called once 400 * when tethering is created. Otherwise if the flag is pushed while tethering is enabled, 401 * then it's possible for some IpServer(s) running the new sync state machine while others 402 * use the async state machine. 403 */ readEnableSyncSM(final Context ctx)404 public void readEnableSyncSM(final Context ctx) { 405 USE_SYNC_SM = isAtLeast25Q2() || mDeps.isFeatureNotChickenedOut(ctx, TETHER_ENABLE_SYNC_SM); 406 } 407 408 /** Does the dumping.*/ dump(PrintWriter pw)409 public void dump(PrintWriter pw) { 410 pw.print("activeDataSubId: "); 411 pw.println(activeDataSubId); 412 413 dumpStringArray(pw, "tetherableUsbRegexs", tetherableUsbRegexs); 414 dumpStringArray(pw, "tetherableWifiRegexs", tetherableWifiRegexs); 415 dumpStringArray(pw, "tetherableWifiP2pRegexs", tetherableWifiP2pRegexs); 416 dumpStringArray(pw, "tetherableBluetoothRegexs", tetherableBluetoothRegexs); 417 dumpStringArray(pw, "tetherableNcmRegexs", tetherableNcmRegexs); 418 419 pw.print("isDunRequired: "); 420 pw.println(isDunRequired); 421 422 pw.print("chooseUpstreamAutomatically: "); 423 pw.println(chooseUpstreamAutomatically); 424 pw.print("legacyPreredUpstreamIfaceTypes: "); 425 pw.println(Arrays.toString(toIntArray(preferredUpstreamIfaceTypes))); 426 427 dumpStringArray(pw, "legacyDhcpRanges", legacyDhcpRanges); 428 dumpStringArray(pw, "defaultIPv4DNS", defaultIPv4DNS); 429 430 pw.print("offloadPollInterval: "); 431 pw.println(mOffloadPollInterval); 432 433 dumpStringArray(pw, "provisioningApp", provisioningApp); 434 pw.print("provisioningAppNoUi: "); 435 pw.println(provisioningAppNoUi); 436 437 pw.println("isCarrierSupportTethering: " + isCarrierSupportTethering); 438 pw.println("isCarrierConfigAffirmsEntitlementCheckRequired: " 439 + isCarrierConfigAffirmsEntitlementCheckRequired); 440 441 pw.print("enableBpfOffload: "); 442 pw.println(mEnableBpfOffload); 443 444 pw.print("enableLegacyDhcpServer: "); 445 pw.println(mEnableLegacyDhcpServer); 446 447 pw.print("enableWifiP2pDedicatedIp: "); 448 pw.println(mEnableWifiP2pDedicatedIp); 449 450 pw.print("p2pLeasesSubnetPrefixLength: "); 451 pw.println(mP2pLeasesSubnetPrefixLength); 452 453 pw.print("enableWearTethering: "); 454 pw.println(mEnableWearTethering); 455 456 pw.print("mUsbTetheringFunction: "); 457 pw.println(isUsingNcm() ? "NCM" : "RNDIS"); 458 459 pw.print("USE_SYNC_SM: "); 460 pw.println(USE_SYNC_SM); 461 } 462 463 /** Returns the string representation of this object.*/ toString()464 public String toString() { 465 final StringJoiner sj = new StringJoiner(" "); 466 sj.add(String.format("activeDataSubId:%d", activeDataSubId)); 467 sj.add(String.format("tetherableUsbRegexs:%s", makeString(tetherableUsbRegexs))); 468 sj.add(String.format("tetherableWifiRegexs:%s", makeString(tetherableWifiRegexs))); 469 sj.add(String.format("tetherableWifiP2pRegexs:%s", makeString(tetherableWifiP2pRegexs))); 470 sj.add(String.format("tetherableBluetoothRegexs:%s", 471 makeString(tetherableBluetoothRegexs))); 472 sj.add(String.format("isDunRequired:%s", isDunRequired)); 473 sj.add(String.format("chooseUpstreamAutomatically:%s", chooseUpstreamAutomatically)); 474 sj.add(String.format("offloadPollInterval:%d", mOffloadPollInterval)); 475 sj.add(String.format("preferredUpstreamIfaceTypes:%s", 476 toIntArray(preferredUpstreamIfaceTypes))); 477 sj.add(String.format("provisioningApp:%s", makeString(provisioningApp))); 478 sj.add(String.format("provisioningAppNoUi:%s", provisioningAppNoUi)); 479 sj.add(String.format("isCarrierSupportTethering:%s", isCarrierSupportTethering)); 480 sj.add(String.format("isCarrierConfigAffirmsEntitlementCheckRequired:%s", 481 isCarrierConfigAffirmsEntitlementCheckRequired)); 482 sj.add(String.format("enableBpfOffload:%s", mEnableBpfOffload)); 483 sj.add(String.format("enableLegacyDhcpServer:%s", mEnableLegacyDhcpServer)); 484 sj.add(String.format("enableWearTethering:%s", mEnableWearTethering)); 485 return String.format("TetheringConfiguration{%s}", sj.toString()); 486 } 487 dumpStringArray(PrintWriter pw, String label, String[] values)488 private static void dumpStringArray(PrintWriter pw, String label, String[] values) { 489 pw.print(label); 490 pw.print(": "); 491 492 if (values != null) { 493 final StringJoiner sj = new StringJoiner(", ", "[", "]"); 494 for (String value : values) sj.add(value); 495 pw.print(sj.toString()); 496 } else { 497 pw.print("null"); 498 } 499 500 pw.println(); 501 } 502 makeString(String[] strings)503 private static String makeString(String[] strings) { 504 if (strings == null) return "null"; 505 final StringJoiner sj = new StringJoiner(",", "[", "]"); 506 for (String s : strings) sj.add(s); 507 return sj.toString(); 508 } 509 510 /** Check whether dun is required. */ checkDunRequired(Context ctx)511 public static boolean checkDunRequired(Context ctx) { 512 final TelephonyManager tm = (TelephonyManager) ctx.getSystemService(TELEPHONY_SERVICE); 513 // TelephonyManager would uses the active data subscription, which should be the one used 514 // by tethering. 515 return (tm != null) ? tm.isTetheringApnRequired() : false; 516 } 517 getOffloadPollInterval()518 public int getOffloadPollInterval() { 519 return mOffloadPollInterval; 520 } 521 isBpfOffloadEnabled()522 public boolean isBpfOffloadEnabled() { 523 return mEnableBpfOffload; 524 } 525 getUsbTetheringFunction(Resources res)526 private int getUsbTetheringFunction(Resources res) { 527 final int valueFromRes = getResourceInteger(res, R.integer.config_tether_usb_functions, 528 TETHER_USB_RNDIS_FUNCTION /* defaultValue */); 529 return getSettingsIntValue(TETHER_FORCE_USB_FUNCTIONS, valueFromRes); 530 } 531 getSettingsIntValue(final String name, final int defaultValue)532 private int getSettingsIntValue(final String name, final int defaultValue) { 533 final String value = getSettingsValue(name); 534 try { 535 return value != null ? Integer.parseInt(value) : defaultValue; 536 } catch (NumberFormatException e) { 537 return defaultValue; 538 } 539 } 540 541 @VisibleForTesting getSettingsValue(final String name)542 protected String getSettingsValue(final String name) { 543 return Settings.Global.getString(mContentResolver, name); 544 } 545 getUpstreamIfaceTypes(Resources res, boolean dunRequired)546 private static Collection<Integer> getUpstreamIfaceTypes(Resources res, boolean dunRequired) { 547 final int[] ifaceTypes = res.getIntArray(R.array.config_tether_upstream_types); 548 final ArrayList<Integer> upstreamIfaceTypes = new ArrayList<>(ifaceTypes.length); 549 for (int i : ifaceTypes) { 550 switch (i) { 551 case TYPE_MOBILE: 552 case TYPE_MOBILE_HIPRI: 553 if (dunRequired) continue; 554 break; 555 case TYPE_MOBILE_DUN: 556 if (!dunRequired) continue; 557 break; 558 } 559 upstreamIfaceTypes.add(i); 560 } 561 562 // Fix up upstream interface types for DUN or mobile. NOTE: independent 563 // of the value of |dunRequired|, cell data of one form or another is 564 // *always* an upstream, regardless of the upstream interface types 565 // specified by configuration resources. 566 if (dunRequired) { 567 appendIfNotPresent(upstreamIfaceTypes, TYPE_MOBILE_DUN); 568 } else { 569 // Do not modify if a cellular interface type is already present in the 570 // upstream interface types. Add TYPE_MOBILE and TYPE_MOBILE_HIPRI if no 571 // cellular interface types are found in the upstream interface types. 572 // This preserves backwards compatibility and prevents the DUN and default 573 // mobile types incorrectly appearing together, which could happen on 574 // previous releases in the common case where checkDunRequired returned 575 // DUN_UNSPECIFIED. 576 if (!containsOneOf(upstreamIfaceTypes, TYPE_MOBILE, TYPE_MOBILE_HIPRI)) { 577 upstreamIfaceTypes.add(TYPE_MOBILE); 578 upstreamIfaceTypes.add(TYPE_MOBILE_HIPRI); 579 } 580 } 581 582 // Always make sure our good friend Ethernet is present. 583 // TODO: consider unilaterally forcing this at the front. 584 prependIfNotPresent(upstreamIfaceTypes, TYPE_ETHERNET); 585 586 return upstreamIfaceTypes; 587 } 588 matchesDownstreamRegexs(String iface, String[] regexs)589 private static boolean matchesDownstreamRegexs(String iface, String[] regexs) { 590 for (String regex : regexs) { 591 if (iface.matches(regex)) return true; 592 } 593 return false; 594 } 595 getLegacyDhcpRanges(Resources res)596 private static String[] getLegacyDhcpRanges(Resources res) { 597 final String[] fromResource = getResourceStringArray(res, R.array.config_tether_dhcp_range); 598 if ((fromResource.length > 0) && (fromResource.length % 2 == 0)) { 599 return fromResource; 600 } 601 return copy(LEGACY_DHCP_DEFAULT_RANGE); 602 } 603 getResourceString(Resources res, final int resId)604 private static String getResourceString(Resources res, final int resId) { 605 try { 606 return res.getString(resId); 607 } catch (Resources.NotFoundException e) { 608 return ""; 609 } 610 } 611 getResourceBoolean(Resources res, int resId, boolean defaultValue)612 private static boolean getResourceBoolean(Resources res, int resId, boolean defaultValue) { 613 try { 614 return res.getBoolean(resId); 615 } catch (Resources.NotFoundException e404) { 616 return defaultValue; 617 } 618 } 619 getResourceStringArray(Resources res, int resId)620 private static String[] getResourceStringArray(Resources res, int resId) { 621 try { 622 final String[] strArray = res.getStringArray(resId); 623 return (strArray != null) ? strArray : EMPTY_STRING_ARRAY; 624 } catch (Resources.NotFoundException e404) { 625 return EMPTY_STRING_ARRAY; 626 } 627 } 628 getResourceInteger(Resources res, int resId, int defaultValue)629 private static int getResourceInteger(Resources res, int resId, int defaultValue) { 630 try { 631 return res.getInteger(resId); 632 } catch (Resources.NotFoundException e404) { 633 return defaultValue; 634 } 635 } 636 getEnableBpfOffload(final Resources res)637 private boolean getEnableBpfOffload(final Resources res) { 638 // Get BPF offload config 639 // Priority 1: Device config 640 // Priority 2: Resource config 641 // Priority 3: Default value 642 final boolean defaultValue = getResourceBoolean( 643 res, R.bool.config_tether_enable_bpf_offload, true /** default value */); 644 645 return getDeviceConfigBoolean(OVERRIDE_TETHER_ENABLE_BPF_OFFLOAD, defaultValue); 646 } 647 getEnableLegacyDhcpServer(final Resources res)648 private boolean getEnableLegacyDhcpServer(final Resources res) { 649 return getResourceBoolean( 650 res, R.bool.config_tether_enable_legacy_dhcp_server, false /** defaultValue */) 651 || getDeviceConfigBoolean( 652 TETHER_ENABLE_LEGACY_DHCP_SERVER, false /** defaultValue */); 653 } 654 shouldEnableWearTethering(Context context)655 private boolean shouldEnableWearTethering(Context context) { 656 return SdkLevel.isAtLeastT() 657 && mDeps.isFeatureEnabled(context, TETHER_ENABLE_WEAR_TETHERING); 658 } 659 getDeviceConfigBoolean(final String name, final boolean defaultValue)660 private boolean getDeviceConfigBoolean(final String name, final boolean defaultValue) { 661 return mDeps.getDeviceConfigBoolean(NAMESPACE_CONNECTIVITY, name, defaultValue); 662 } 663 getResources(Context ctx, int subId)664 private Resources getResources(Context ctx, int subId) { 665 if (subId != SubscriptionManager.INVALID_SUBSCRIPTION_ID) { 666 return getResourcesForSubIdWrapper(ctx, subId); 667 } else { 668 return ctx.getResources(); 669 } 670 } 671 672 @VisibleForTesting getResourcesForSubIdWrapper(Context ctx, int subId)673 protected Resources getResourcesForSubIdWrapper(Context ctx, int subId) { 674 return SubscriptionManager.getResourcesForSubId(ctx, subId); 675 } 676 copy(String[] strarray)677 private static String[] copy(String[] strarray) { 678 return Arrays.copyOf(strarray, strarray.length); 679 } 680 prependIfNotPresent(ArrayList<Integer> list, int value)681 private static void prependIfNotPresent(ArrayList<Integer> list, int value) { 682 if (list.contains(value)) return; 683 list.add(0, value); 684 } 685 appendIfNotPresent(ArrayList<Integer> list, int value)686 private static void appendIfNotPresent(ArrayList<Integer> list, int value) { 687 if (list.contains(value)) return; 688 list.add(value); 689 } 690 containsOneOf(ArrayList<Integer> list, Integer... values)691 private static boolean containsOneOf(ArrayList<Integer> list, Integer... values) { 692 for (Integer value : values) { 693 if (list.contains(value)) return true; 694 } 695 return false; 696 } 697 toIntArray(Collection<Integer> values)698 private static int[] toIntArray(Collection<Integer> values) { 699 final int[] result = new int[values.size()]; 700 int index = 0; 701 for (Integer value : values) { 702 result[index++] = value; 703 } 704 return result; 705 } 706 carrierConfigAffirmsEntitlementCheckRequired( PersistableBundle carrierConfig)707 private static boolean carrierConfigAffirmsEntitlementCheckRequired( 708 PersistableBundle carrierConfig) { 709 if (carrierConfig == null) { 710 return true; 711 } 712 return carrierConfig.getBoolean( 713 CarrierConfigManager.KEY_REQUIRE_ENTITLEMENT_CHECKS_BOOL, true); 714 } 715 carrierConfigAffirmsCarrierSupport(PersistableBundle carrierConfig)716 private static boolean carrierConfigAffirmsCarrierSupport(PersistableBundle carrierConfig) { 717 if (!SdkLevel.isAtLeastT() || carrierConfig == null) { 718 return true; 719 } 720 return carrierConfig.getBoolean(KEY_CARRIER_SUPPORTS_TETHERING_BOOL, true); 721 } 722 723 /** 724 * Get carrier configuration bundle. 725 */ getCarrierConfig(Context context, int activeDataSubId)726 public static PersistableBundle getCarrierConfig(Context context, int activeDataSubId) { 727 final CarrierConfigManager configManager = 728 context.getSystemService(CarrierConfigManager.class); 729 if (configManager == null) { 730 return null; 731 } 732 733 final PersistableBundle carrierConfig = configManager.getConfigForSubId(activeDataSubId); 734 if (CarrierConfigManager.isConfigForIdentifiedCarrier(carrierConfig)) { 735 return carrierConfig; 736 } 737 return null; 738 } 739 740 /** 741 * Convert this TetheringConfiguration to a TetheringConfigurationParcel. 742 */ toStableParcelable()743 public TetheringConfigurationParcel toStableParcelable() { 744 final TetheringConfigurationParcel parcel = new TetheringConfigurationParcel(); 745 parcel.tetherableUsbRegexs = tetherableUsbRegexs; 746 parcel.tetherableWifiRegexs = tetherableWifiRegexs; 747 parcel.tetherableBluetoothRegexs = tetherableBluetoothRegexs; 748 parcel.legacyDhcpRanges = legacyDhcpRanges; 749 parcel.provisioningApp = provisioningApp; 750 parcel.provisioningAppNoUi = provisioningAppNoUi; 751 752 return parcel; 753 } 754 } 755