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