1 /* 2 * Copyright (C) 2019 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 package android.net; 17 18 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES; 19 20 import android.Manifest; 21 import android.annotation.IntDef; 22 import android.annotation.NonNull; 23 import android.annotation.Nullable; 24 import android.annotation.RequiresPermission; 25 import android.annotation.SystemApi; 26 import android.annotation.TestApi; 27 import android.content.Context; 28 import android.os.Bundle; 29 import android.os.ConditionVariable; 30 import android.os.IBinder; 31 import android.os.RemoteException; 32 import android.os.ResultReceiver; 33 import android.util.ArrayMap; 34 import android.util.Log; 35 36 import com.android.internal.annotations.GuardedBy; 37 38 import java.lang.annotation.Retention; 39 import java.lang.annotation.RetentionPolicy; 40 import java.util.ArrayList; 41 import java.util.Arrays; 42 import java.util.Collection; 43 import java.util.Collections; 44 import java.util.HashMap; 45 import java.util.List; 46 import java.util.Objects; 47 import java.util.concurrent.Executor; 48 import java.util.function.Supplier; 49 50 /** 51 * This class provides the APIs to control the tethering service. 52 * <p> The primary responsibilities of this class are to provide the APIs for applications to 53 * start tethering, stop tethering, query configuration and query status. 54 * 55 * @hide 56 */ 57 @SystemApi 58 @SystemApi(client = MODULE_LIBRARIES) 59 @TestApi 60 public class TetheringManager { 61 private static final String TAG = TetheringManager.class.getSimpleName(); 62 private static final int DEFAULT_TIMEOUT_MS = 60_000; 63 private static final long CONNECTOR_POLL_INTERVAL_MILLIS = 200L; 64 65 @GuardedBy("mConnectorWaitQueue") 66 @Nullable 67 private ITetheringConnector mConnector; 68 @GuardedBy("mConnectorWaitQueue") 69 @NonNull 70 private final List<ConnectorConsumer> mConnectorWaitQueue = new ArrayList<>(); 71 private final Supplier<IBinder> mConnectorSupplier; 72 73 private final TetheringCallbackInternal mCallback; 74 private final Context mContext; 75 private final ArrayMap<TetheringEventCallback, ITetheringEventCallback> 76 mTetheringEventCallbacks = new ArrayMap<>(); 77 78 private volatile TetheringConfigurationParcel mTetheringConfiguration; 79 private volatile TetherStatesParcel mTetherStatesParcel; 80 81 /** 82 * Broadcast Action: A tetherable connection has come or gone. 83 * Uses {@code TetheringManager.EXTRA_AVAILABLE_TETHER}, 84 * {@code TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY}, 85 * {@code TetheringManager.EXTRA_ACTIVE_TETHER}, and 86 * {@code TetheringManager.EXTRA_ERRORED_TETHER} to indicate 87 * the current state of tethering. Each include a list of 88 * interface names in that state (may be empty). 89 */ 90 public static final String ACTION_TETHER_STATE_CHANGED = 91 "android.net.conn.TETHER_STATE_CHANGED"; 92 93 /** 94 * gives a String[] listing all the interfaces configured for 95 * tethering and currently available for tethering. 96 */ 97 public static final String EXTRA_AVAILABLE_TETHER = "availableArray"; 98 99 /** 100 * gives a String[] listing all the interfaces currently in local-only 101 * mode (ie, has DHCPv4+IPv6-ULA support and no packet forwarding) 102 */ 103 public static final String EXTRA_ACTIVE_LOCAL_ONLY = "android.net.extra.ACTIVE_LOCAL_ONLY"; 104 105 /** 106 * gives a String[] listing all the interfaces currently tethered 107 * (ie, has DHCPv4 support and packets potentially forwarded/NATed) 108 */ 109 public static final String EXTRA_ACTIVE_TETHER = "tetherArray"; 110 111 /** 112 * gives a String[] listing all the interfaces we tried to tether and 113 * failed. Use {@link #getLastTetherError} to find the error code 114 * for any interfaces listed here. 115 */ 116 public static final String EXTRA_ERRORED_TETHER = "erroredArray"; 117 118 /** @hide */ 119 @Retention(RetentionPolicy.SOURCE) 120 @IntDef(flag = false, value = { 121 TETHERING_WIFI, 122 TETHERING_USB, 123 TETHERING_BLUETOOTH, 124 TETHERING_WIFI_P2P, 125 TETHERING_NCM, 126 TETHERING_ETHERNET, 127 }) 128 public @interface TetheringType { 129 } 130 131 /** 132 * Invalid tethering type. 133 * @see #startTethering. 134 */ 135 public static final int TETHERING_INVALID = -1; 136 137 /** 138 * Wifi tethering type. 139 * @see #startTethering. 140 */ 141 public static final int TETHERING_WIFI = 0; 142 143 /** 144 * USB tethering type. 145 * @see #startTethering. 146 */ 147 public static final int TETHERING_USB = 1; 148 149 /** 150 * Bluetooth tethering type. 151 * @see #startTethering. 152 */ 153 public static final int TETHERING_BLUETOOTH = 2; 154 155 /** 156 * Wifi P2p tethering type. 157 * Wifi P2p tethering is set through events automatically, and don't 158 * need to start from #startTethering. 159 */ 160 public static final int TETHERING_WIFI_P2P = 3; 161 162 /** 163 * Ncm local tethering type. 164 * @see #startTethering(TetheringRequest, Executor, StartTetheringCallback) 165 */ 166 public static final int TETHERING_NCM = 4; 167 168 /** 169 * Ethernet tethering type. 170 * @see #startTethering(TetheringRequest, Executor, StartTetheringCallback) 171 */ 172 public static final int TETHERING_ETHERNET = 5; 173 174 /** 175 * WIGIG tethering type. Use a separate type to prevent 176 * conflicts with TETHERING_WIFI 177 * This type is only used internally by the tethering module 178 * @hide 179 */ 180 public static final int TETHERING_WIGIG = 6; 181 182 /** @hide */ 183 @Retention(RetentionPolicy.SOURCE) 184 @IntDef(value = { 185 TETHER_ERROR_NO_ERROR, 186 TETHER_ERROR_PROVISIONING_FAILED, 187 TETHER_ERROR_ENTITLEMENT_UNKNOWN, 188 }) 189 public @interface EntitlementResult { 190 } 191 192 /** @hide */ 193 @Retention(RetentionPolicy.SOURCE) 194 @IntDef(value = { 195 TETHER_ERROR_NO_ERROR, 196 TETHER_ERROR_UNKNOWN_IFACE, 197 TETHER_ERROR_SERVICE_UNAVAIL, 198 TETHER_ERROR_INTERNAL_ERROR, 199 TETHER_ERROR_TETHER_IFACE_ERROR, 200 TETHER_ERROR_ENABLE_FORWARDING_ERROR, 201 TETHER_ERROR_DISABLE_FORWARDING_ERROR, 202 TETHER_ERROR_IFACE_CFG_ERROR, 203 TETHER_ERROR_DHCPSERVER_ERROR, 204 }) 205 public @interface TetheringIfaceError { 206 } 207 208 /** @hide */ 209 @Retention(RetentionPolicy.SOURCE) 210 @IntDef(value = { 211 TETHER_ERROR_SERVICE_UNAVAIL, 212 TETHER_ERROR_INTERNAL_ERROR, 213 TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION, 214 TETHER_ERROR_UNKNOWN_TYPE, 215 }) 216 public @interface StartTetheringError { 217 } 218 219 public static final int TETHER_ERROR_NO_ERROR = 0; 220 public static final int TETHER_ERROR_UNKNOWN_IFACE = 1; 221 public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2; 222 public static final int TETHER_ERROR_UNSUPPORTED = 3; 223 public static final int TETHER_ERROR_UNAVAIL_IFACE = 4; 224 public static final int TETHER_ERROR_INTERNAL_ERROR = 5; 225 public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6; 226 public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7; 227 public static final int TETHER_ERROR_ENABLE_FORWARDING_ERROR = 8; 228 public static final int TETHER_ERROR_DISABLE_FORWARDING_ERROR = 9; 229 public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10; 230 public static final int TETHER_ERROR_PROVISIONING_FAILED = 11; 231 public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12; 232 public static final int TETHER_ERROR_ENTITLEMENT_UNKNOWN = 13; 233 public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14; 234 public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15; 235 public static final int TETHER_ERROR_UNKNOWN_TYPE = 16; 236 237 /** @hide */ 238 @Retention(RetentionPolicy.SOURCE) 239 @IntDef(flag = false, value = { 240 TETHER_HARDWARE_OFFLOAD_STOPPED, 241 TETHER_HARDWARE_OFFLOAD_STARTED, 242 TETHER_HARDWARE_OFFLOAD_FAILED, 243 }) 244 public @interface TetherOffloadStatus { 245 } 246 247 /** Tethering offload status is stopped. */ 248 public static final int TETHER_HARDWARE_OFFLOAD_STOPPED = 0; 249 /** Tethering offload status is started. */ 250 public static final int TETHER_HARDWARE_OFFLOAD_STARTED = 1; 251 /** Fail to start tethering offload. */ 252 public static final int TETHER_HARDWARE_OFFLOAD_FAILED = 2; 253 254 /** 255 * Create a TetheringManager object for interacting with the tethering service. 256 * 257 * @param context Context for the manager. 258 * @param connectorSupplier Supplier for the manager connector; may return null while the 259 * service is not connected. 260 * {@hide} 261 */ 262 @SystemApi(client = MODULE_LIBRARIES) TetheringManager(@onNull final Context context, @NonNull Supplier<IBinder> connectorSupplier)263 public TetheringManager(@NonNull final Context context, 264 @NonNull Supplier<IBinder> connectorSupplier) { 265 mContext = context; 266 mCallback = new TetheringCallbackInternal(); 267 mConnectorSupplier = connectorSupplier; 268 269 final String pkgName = mContext.getOpPackageName(); 270 271 final IBinder connector = mConnectorSupplier.get(); 272 // If the connector is available on start, do not start a polling thread. This introduces 273 // differences in the thread that sends the oneway binder calls to the service between the 274 // first few seconds after boot and later, but it avoids always having differences between 275 // the first usage of TetheringManager from a process and subsequent usages (so the 276 // difference is only on boot). On boot binder calls may be queued until the service comes 277 // up and be sent from a worker thread; later, they are always sent from the caller thread. 278 // Considering that it's just oneway binder calls, and ordering is preserved, this seems 279 // better than inconsistent behavior persisting after boot. 280 if (connector != null) { 281 mConnector = ITetheringConnector.Stub.asInterface(connector); 282 } else { 283 startPollingForConnector(); 284 } 285 286 Log.i(TAG, "registerTetheringEventCallback:" + pkgName); 287 getConnector(c -> c.registerTetheringEventCallback(mCallback, pkgName)); 288 } 289 startPollingForConnector()290 private void startPollingForConnector() { 291 new Thread(() -> { 292 while (true) { 293 try { 294 Thread.sleep(CONNECTOR_POLL_INTERVAL_MILLIS); 295 } catch (InterruptedException e) { 296 // Not much to do here, the system needs to wait for the connector 297 } 298 299 final IBinder connector = mConnectorSupplier.get(); 300 if (connector != null) { 301 onTetheringConnected(ITetheringConnector.Stub.asInterface(connector)); 302 return; 303 } 304 } 305 }).start(); 306 } 307 308 private interface ConnectorConsumer { onConnectorAvailable(ITetheringConnector connector)309 void onConnectorAvailable(ITetheringConnector connector) throws RemoteException; 310 } 311 onTetheringConnected(ITetheringConnector connector)312 private void onTetheringConnected(ITetheringConnector connector) { 313 // Process the connector wait queue in order, including any items that are added 314 // while processing. 315 // 316 // 1. Copy the queue to a local variable under lock. 317 // 2. Drain the local queue with the lock released (otherwise, enqueuing future commands 318 // would block on the lock). 319 // 3. Acquire the lock again. If any new tasks were queued during step 2, goto 1. 320 // If not, set mConnector to non-null so future tasks are run immediately, not queued. 321 // 322 // For this to work, all calls to the tethering service must use getConnector(), which 323 // ensures that tasks are added to the queue with the lock held. 324 // 325 // Once mConnector is set to non-null, it will never be null again. If the network stack 326 // process crashes, no recovery is possible. 327 // TODO: evaluate whether it is possible to recover from network stack process crashes 328 // (though in most cases the system will have crashed when the network stack process 329 // crashes). 330 do { 331 final List<ConnectorConsumer> localWaitQueue; 332 synchronized (mConnectorWaitQueue) { 333 localWaitQueue = new ArrayList<>(mConnectorWaitQueue); 334 mConnectorWaitQueue.clear(); 335 } 336 337 // Allow more tasks to be added at the end without blocking while draining the queue. 338 for (ConnectorConsumer task : localWaitQueue) { 339 try { 340 task.onConnectorAvailable(connector); 341 } catch (RemoteException e) { 342 // Most likely the network stack process crashed, which is likely to crash the 343 // system. Keep processing other requests but report the error loudly. 344 Log.wtf(TAG, "Error processing request for the tethering connector", e); 345 } 346 } 347 348 synchronized (mConnectorWaitQueue) { 349 if (mConnectorWaitQueue.size() == 0) { 350 mConnector = connector; 351 return; 352 } 353 } 354 } while (true); 355 } 356 357 /** 358 * Asynchronously get the ITetheringConnector to execute some operation. 359 * 360 * <p>If the connector is already available, the operation will be executed on the caller's 361 * thread. Otherwise it will be queued and executed on a worker thread. The operation should be 362 * limited to performing oneway binder calls to minimize differences due to threading. 363 */ getConnector(ConnectorConsumer consumer)364 private void getConnector(ConnectorConsumer consumer) { 365 final ITetheringConnector connector; 366 synchronized (mConnectorWaitQueue) { 367 connector = mConnector; 368 if (connector == null) { 369 mConnectorWaitQueue.add(consumer); 370 return; 371 } 372 } 373 374 try { 375 consumer.onConnectorAvailable(connector); 376 } catch (RemoteException e) { 377 throw new IllegalStateException(e); 378 } 379 } 380 381 private interface RequestHelper { runRequest(ITetheringConnector connector, IIntResultListener listener)382 void runRequest(ITetheringConnector connector, IIntResultListener listener); 383 } 384 385 // Used to dispatch legacy ConnectivityManager methods that expect tethering to be able to 386 // return results and perform operations synchronously. 387 // TODO: remove once there are no callers of these legacy methods. 388 private class RequestDispatcher { 389 private final ConditionVariable mWaiting; 390 public volatile int mRemoteResult; 391 392 private final IIntResultListener mListener = new IIntResultListener.Stub() { 393 @Override 394 public void onResult(final int resultCode) { 395 mRemoteResult = resultCode; 396 mWaiting.open(); 397 } 398 }; 399 RequestDispatcher()400 RequestDispatcher() { 401 mWaiting = new ConditionVariable(); 402 } 403 waitForResult(final RequestHelper request)404 int waitForResult(final RequestHelper request) { 405 getConnector(c -> request.runRequest(c, mListener)); 406 if (!mWaiting.block(DEFAULT_TIMEOUT_MS)) { 407 throw new IllegalStateException("Callback timeout"); 408 } 409 410 throwIfPermissionFailure(mRemoteResult); 411 412 return mRemoteResult; 413 } 414 } 415 throwIfPermissionFailure(final int errorCode)416 private void throwIfPermissionFailure(final int errorCode) { 417 switch (errorCode) { 418 case TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION: 419 throw new SecurityException("No android.permission.TETHER_PRIVILEGED" 420 + " or android.permission.WRITE_SETTINGS permission"); 421 case TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION: 422 throw new SecurityException( 423 "No android.permission.ACCESS_NETWORK_STATE permission"); 424 } 425 } 426 427 private class TetheringCallbackInternal extends ITetheringEventCallback.Stub { 428 private volatile int mError = TETHER_ERROR_NO_ERROR; 429 private final ConditionVariable mWaitForCallback = new ConditionVariable(); 430 431 @Override onCallbackStarted(TetheringCallbackStartedParcel parcel)432 public void onCallbackStarted(TetheringCallbackStartedParcel parcel) { 433 mTetheringConfiguration = parcel.config; 434 mTetherStatesParcel = parcel.states; 435 mWaitForCallback.open(); 436 } 437 438 @Override onCallbackStopped(int errorCode)439 public void onCallbackStopped(int errorCode) { 440 mError = errorCode; 441 mWaitForCallback.open(); 442 } 443 444 @Override onUpstreamChanged(Network network)445 public void onUpstreamChanged(Network network) { } 446 447 @Override onConfigurationChanged(TetheringConfigurationParcel config)448 public void onConfigurationChanged(TetheringConfigurationParcel config) { 449 mTetheringConfiguration = config; 450 } 451 452 @Override onTetherStatesChanged(TetherStatesParcel states)453 public void onTetherStatesChanged(TetherStatesParcel states) { 454 mTetherStatesParcel = states; 455 } 456 457 @Override onTetherClientsChanged(List<TetheredClient> clients)458 public void onTetherClientsChanged(List<TetheredClient> clients) { } 459 460 @Override onOffloadStatusChanged(int status)461 public void onOffloadStatusChanged(int status) { } 462 waitForStarted()463 public void waitForStarted() { 464 mWaitForCallback.block(DEFAULT_TIMEOUT_MS); 465 throwIfPermissionFailure(mError); 466 } 467 } 468 469 /** 470 * Attempt to tether the named interface. This will setup a dhcp server 471 * on the interface, forward and NAT IP v4 packets and forward DNS requests 472 * to the best active upstream network interface. Note that if no upstream 473 * IP network interface is available, dhcp will still run and traffic will be 474 * allowed between the tethered devices and this device, though upstream net 475 * access will of course fail until an upstream network interface becomes 476 * active. 477 * 478 * @deprecated The only usages is PanService. It uses this for legacy reasons 479 * and will migrate away as soon as possible. 480 * 481 * @param iface the interface name to tether. 482 * @return error a {@code TETHER_ERROR} value indicating success or failure type 483 * 484 * {@hide} 485 */ 486 @Deprecated 487 @SystemApi(client = MODULE_LIBRARIES) tether(@onNull final String iface)488 public int tether(@NonNull final String iface) { 489 final String callerPkg = mContext.getOpPackageName(); 490 Log.i(TAG, "tether caller:" + callerPkg); 491 final RequestDispatcher dispatcher = new RequestDispatcher(); 492 493 return dispatcher.waitForResult((connector, listener) -> { 494 try { 495 connector.tether(iface, callerPkg, listener); 496 } catch (RemoteException e) { 497 throw new IllegalStateException(e); 498 } 499 }); 500 } 501 502 /** 503 * Stop tethering the named interface. 504 * 505 * @deprecated The only usages is PanService. It uses this for legacy reasons 506 * and will migrate away as soon as possible. 507 * 508 * {@hide} 509 */ 510 @Deprecated 511 @SystemApi(client = MODULE_LIBRARIES) 512 public int untether(@NonNull final String iface) { 513 final String callerPkg = mContext.getOpPackageName(); 514 Log.i(TAG, "untether caller:" + callerPkg); 515 516 final RequestDispatcher dispatcher = new RequestDispatcher(); 517 518 return dispatcher.waitForResult((connector, listener) -> { 519 try { 520 connector.untether(iface, callerPkg, listener); 521 } catch (RemoteException e) { 522 throw new IllegalStateException(e); 523 } 524 }); 525 } 526 527 /** 528 * Attempt to both alter the mode of USB and Tethering of USB. 529 * 530 * @deprecated New client should not use this API anymore. All clients should use 531 * #startTethering or #stopTethering which encapsulate proper entitlement logic. If the API is 532 * used and an entitlement check is needed, downstream USB tethering will be enabled but will 533 * not have any upstream. 534 * 535 * {@hide} 536 */ 537 @Deprecated 538 @SystemApi(client = MODULE_LIBRARIES) 539 public int setUsbTethering(final boolean enable) { 540 final String callerPkg = mContext.getOpPackageName(); 541 Log.i(TAG, "setUsbTethering caller:" + callerPkg); 542 543 final RequestDispatcher dispatcher = new RequestDispatcher(); 544 545 return dispatcher.waitForResult((connector, listener) -> { 546 try { 547 connector.setUsbTethering(enable, callerPkg, listener); 548 } catch (RemoteException e) { 549 throw new IllegalStateException(e); 550 } 551 }); 552 } 553 554 /** 555 * Use with {@link #startTethering} to specify additional parameters when starting tethering. 556 */ 557 public static class TetheringRequest { 558 /** A configuration set for TetheringRequest. */ 559 private final TetheringRequestParcel mRequestParcel; 560 561 private TetheringRequest(final TetheringRequestParcel request) { 562 mRequestParcel = request; 563 } 564 565 /** Builder used to create TetheringRequest. */ 566 public static class Builder { 567 private final TetheringRequestParcel mBuilderParcel; 568 569 /** Default constructor of Builder. */ 570 public Builder(@TetheringType final int type) { 571 mBuilderParcel = new TetheringRequestParcel(); 572 mBuilderParcel.tetheringType = type; 573 mBuilderParcel.localIPv4Address = null; 574 mBuilderParcel.staticClientAddress = null; 575 mBuilderParcel.exemptFromEntitlementCheck = false; 576 mBuilderParcel.showProvisioningUi = true; 577 } 578 579 /** 580 * Configure tethering with static IPv4 assignment. 581 * 582 * A DHCP server will be started, but will only be able to offer the client address. 583 * The two addresses must be in the same prefix. 584 * 585 * @param localIPv4Address The preferred local IPv4 link address to use. 586 * @param clientAddress The static client address. 587 */ 588 @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) 589 @NonNull 590 public Builder setStaticIpv4Addresses(@NonNull final LinkAddress localIPv4Address, 591 @NonNull final LinkAddress clientAddress) { 592 Objects.requireNonNull(localIPv4Address); 593 Objects.requireNonNull(clientAddress); 594 if (!checkStaticAddressConfiguration(localIPv4Address, clientAddress)) { 595 throw new IllegalArgumentException("Invalid server or client addresses"); 596 } 597 598 mBuilderParcel.localIPv4Address = localIPv4Address; 599 mBuilderParcel.staticClientAddress = clientAddress; 600 return this; 601 } 602 603 /** Start tethering without entitlement checks. */ 604 @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) 605 @NonNull 606 public Builder setExemptFromEntitlementCheck(boolean exempt) { 607 mBuilderParcel.exemptFromEntitlementCheck = exempt; 608 return this; 609 } 610 611 /** 612 * If an entitlement check is needed, sets whether to show the entitlement UI or to 613 * perform a silent entitlement check. By default, the entitlement UI is shown. 614 */ 615 @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED) 616 @NonNull 617 public Builder setShouldShowEntitlementUi(boolean showUi) { 618 mBuilderParcel.showProvisioningUi = showUi; 619 return this; 620 } 621 622 /** Build {@link TetheringRequest] with the currently set configuration. */ 623 @NonNull 624 public TetheringRequest build() { 625 return new TetheringRequest(mBuilderParcel); 626 } 627 } 628 629 /** 630 * Get the local IPv4 address, if one was configured with 631 * {@link Builder#setStaticIpv4Addresses}. 632 */ 633 @Nullable 634 public LinkAddress getLocalIpv4Address() { 635 return mRequestParcel.localIPv4Address; 636 } 637 638 /** 639 * Get the static IPv4 address of the client, if one was configured with 640 * {@link Builder#setStaticIpv4Addresses}. 641 */ 642 @Nullable 643 public LinkAddress getClientStaticIpv4Address() { 644 return mRequestParcel.staticClientAddress; 645 } 646 647 /** Get tethering type. */ 648 @TetheringType 649 public int getTetheringType() { 650 return mRequestParcel.tetheringType; 651 } 652 653 /** Check if exempt from entitlement check. */ 654 public boolean isExemptFromEntitlementCheck() { 655 return mRequestParcel.exemptFromEntitlementCheck; 656 } 657 658 /** Check if show entitlement ui. */ 659 public boolean getShouldShowEntitlementUi() { 660 return mRequestParcel.showProvisioningUi; 661 } 662 663 /** 664 * Check whether the two addresses are ipv4 and in the same prefix. 665 * @hide 666 */ 667 public static boolean checkStaticAddressConfiguration( 668 @NonNull final LinkAddress localIPv4Address, 669 @NonNull final LinkAddress clientAddress) { 670 return localIPv4Address.getPrefixLength() == clientAddress.getPrefixLength() 671 && localIPv4Address.isIpv4() && clientAddress.isIpv4() 672 && new IpPrefix(localIPv4Address.toString()).equals( 673 new IpPrefix(clientAddress.toString())); 674 } 675 676 /** 677 * Get a TetheringRequestParcel from the configuration 678 * @hide 679 */ 680 public TetheringRequestParcel getParcel() { 681 return mRequestParcel; 682 } 683 684 /** String of TetheringRequest detail. */ 685 public String toString() { 686 return "TetheringRequest [ type= " + mRequestParcel.tetheringType 687 + ", localIPv4Address= " + mRequestParcel.localIPv4Address 688 + ", staticClientAddress= " + mRequestParcel.staticClientAddress 689 + ", exemptFromEntitlementCheck= " 690 + mRequestParcel.exemptFromEntitlementCheck + ", showProvisioningUi= " 691 + mRequestParcel.showProvisioningUi + " ]"; 692 } 693 } 694 695 /** 696 * Callback for use with {@link #startTethering} to find out whether tethering succeeded. 697 */ 698 public interface StartTetheringCallback { 699 /** 700 * Called when tethering has been successfully started. 701 */ 702 default void onTetheringStarted() {} 703 704 /** 705 * Called when starting tethering failed. 706 * 707 * @param error The error that caused the failure. 708 */ 709 default void onTetheringFailed(@StartTetheringError final int error) {} 710 } 711 712 /** 713 * Starts tethering and runs tether provisioning for the given type if needed. If provisioning 714 * fails, stopTethering will be called automatically. 715 * 716 * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will 717 * fail if a tethering entitlement check is required. 718 * 719 * @param request a {@link TetheringRequest} which can specify the preferred configuration. 720 * @param executor {@link Executor} to specify the thread upon which the callback of 721 * TetheringRequest will be invoked. 722 * @param callback A callback that will be called to indicate the success status of the 723 * tethering start request. 724 */ 725 @RequiresPermission(anyOf = { 726 android.Manifest.permission.TETHER_PRIVILEGED, 727 android.Manifest.permission.WRITE_SETTINGS 728 }) 729 public void startTethering(@NonNull final TetheringRequest request, 730 @NonNull final Executor executor, @NonNull final StartTetheringCallback callback) { 731 final String callerPkg = mContext.getOpPackageName(); 732 Log.i(TAG, "startTethering caller:" + callerPkg); 733 734 final IIntResultListener listener = new IIntResultListener.Stub() { 735 @Override 736 public void onResult(final int resultCode) { 737 executor.execute(() -> { 738 if (resultCode == TETHER_ERROR_NO_ERROR) { 739 callback.onTetheringStarted(); 740 } else { 741 callback.onTetheringFailed(resultCode); 742 } 743 }); 744 } 745 }; 746 getConnector(c -> c.startTethering(request.getParcel(), callerPkg, listener)); 747 } 748 749 /** 750 * Starts tethering and runs tether provisioning for the given type if needed. If provisioning 751 * fails, stopTethering will be called automatically. 752 * 753 * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will 754 * fail if a tethering entitlement check is required. 755 * 756 * @param type The tethering type, on of the {@code TetheringManager#TETHERING_*} constants. 757 * @param executor {@link Executor} to specify the thread upon which the callback of 758 * TetheringRequest will be invoked. 759 * @hide 760 */ 761 @RequiresPermission(anyOf = { 762 android.Manifest.permission.TETHER_PRIVILEGED, 763 android.Manifest.permission.WRITE_SETTINGS 764 }) 765 @SystemApi(client = MODULE_LIBRARIES) 766 public void startTethering(int type, @NonNull final Executor executor, 767 @NonNull final StartTetheringCallback callback) { 768 startTethering(new TetheringRequest.Builder(type).build(), executor, callback); 769 } 770 771 /** 772 * Stops tethering for the given type. Also cancels any provisioning rechecks for that type if 773 * applicable. 774 * 775 * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will 776 * fail if a tethering entitlement check is required. 777 */ 778 @RequiresPermission(anyOf = { 779 android.Manifest.permission.TETHER_PRIVILEGED, 780 android.Manifest.permission.WRITE_SETTINGS 781 }) 782 public void stopTethering(@TetheringType final int type) { 783 final String callerPkg = mContext.getOpPackageName(); 784 Log.i(TAG, "stopTethering caller:" + callerPkg); 785 786 getConnector(c -> c.stopTethering(type, callerPkg, new IIntResultListener.Stub() { 787 @Override 788 public void onResult(int resultCode) { 789 // TODO: provide an API to obtain result 790 // This has never been possible as stopTethering has always been void and never 791 // taken a callback object. The only indication that callers have is if the call 792 // results in a TETHER_STATE_CHANGE broadcast. 793 } 794 })); 795 } 796 797 /** 798 * Callback for use with {@link #getLatestTetheringEntitlementResult} to find out whether 799 * entitlement succeeded. 800 */ 801 public interface OnTetheringEntitlementResultListener { 802 /** 803 * Called to notify entitlement result. 804 * 805 * @param resultCode an int value of entitlement result. It may be one of 806 * {@link #TETHER_ERROR_NO_ERROR}, 807 * {@link #TETHER_ERROR_PROVISIONING_FAILED}, or 808 * {@link #TETHER_ERROR_ENTITLEMENT_UNKNOWN}. 809 */ 810 void onTetheringEntitlementResult(@EntitlementResult int result); 811 } 812 813 /** 814 * Request the latest value of the tethering entitlement check. 815 * 816 * <p>This method will only return the latest entitlement result if it is available. If no 817 * cached entitlement result is available, and {@code showEntitlementUi} is false, 818 * {@link #TETHER_ERROR_ENTITLEMENT_UNKNOWN} will be returned. If {@code showEntitlementUi} is 819 * true, entitlement will be run. 820 * 821 * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will 822 * fail if a tethering entitlement check is required. 823 * 824 * @param type the downstream type of tethering. Must be one of {@code #TETHERING_*} constants. 825 * @param showEntitlementUi a boolean indicating whether to check result for the UI-based 826 * entitlement check or the silent entitlement check. 827 * @param executor the executor on which callback will be invoked. 828 * @param listener an {@link OnTetheringEntitlementResultListener} which will be called to 829 * notify the caller of the result of entitlement check. The listener may be called zero 830 * or one time. 831 */ 832 @RequiresPermission(anyOf = { 833 android.Manifest.permission.TETHER_PRIVILEGED, 834 android.Manifest.permission.WRITE_SETTINGS 835 }) 836 public void requestLatestTetheringEntitlementResult(@TetheringType int type, 837 boolean showEntitlementUi, 838 @NonNull Executor executor, 839 @NonNull final OnTetheringEntitlementResultListener listener) { 840 if (listener == null) { 841 throw new IllegalArgumentException( 842 "OnTetheringEntitlementResultListener cannot be null."); 843 } 844 845 ResultReceiver wrappedListener = new ResultReceiver(null /* handler */) { 846 @Override 847 protected void onReceiveResult(int resultCode, Bundle resultData) { 848 executor.execute(() -> { 849 listener.onTetheringEntitlementResult(resultCode); 850 }); 851 } 852 }; 853 854 requestLatestTetheringEntitlementResult(type, wrappedListener, 855 showEntitlementUi); 856 } 857 858 /** 859 * Helper function of #requestLatestTetheringEntitlementResult to remain backwards compatible 860 * with ConnectivityManager#getLatestTetheringEntitlementResult 861 * 862 * {@hide} 863 */ 864 // TODO: improve the usage of ResultReceiver, b/145096122 865 @SystemApi(client = MODULE_LIBRARIES) 866 public void requestLatestTetheringEntitlementResult(@TetheringType final int type, 867 @NonNull final ResultReceiver receiver, final boolean showEntitlementUi) { 868 final String callerPkg = mContext.getOpPackageName(); 869 Log.i(TAG, "getLatestTetheringEntitlementResult caller:" + callerPkg); 870 871 getConnector(c -> c.requestLatestTetheringEntitlementResult( 872 type, receiver, showEntitlementUi, callerPkg)); 873 } 874 875 /** 876 * Callback for use with {@link registerTetheringEventCallback} to find out tethering 877 * upstream status. 878 */ 879 public interface TetheringEventCallback { 880 /** 881 * Called when tethering supported status changed. 882 * 883 * <p>This will be called immediately after the callback is registered, and may be called 884 * multiple times later upon changes. 885 * 886 * <p>Tethering may be disabled via system properties, device configuration, or device 887 * policy restrictions. 888 * 889 * @param supported The new supported status 890 */ 891 default void onTetheringSupported(boolean supported) {} 892 893 /** 894 * Called when tethering upstream changed. 895 * 896 * <p>This will be called immediately after the callback is registered, and may be called 897 * multiple times later upon changes. 898 * 899 * @param network the {@link Network} of tethering upstream. Null means tethering doesn't 900 * have any upstream. 901 */ 902 default void onUpstreamChanged(@Nullable Network network) {} 903 904 /** 905 * Called when there was a change in tethering interface regular expressions. 906 * 907 * <p>This will be called immediately after the callback is registered, and may be called 908 * multiple times later upon changes. 909 * @param reg The new regular expressions. 910 * 911 * @hide 912 */ 913 @SystemApi(client = MODULE_LIBRARIES) 914 default void onTetherableInterfaceRegexpsChanged(@NonNull TetheringInterfaceRegexps reg) {} 915 916 /** 917 * Called when there was a change in the list of tetherable interfaces. Tetherable 918 * interface means this interface is available and can be used for tethering. 919 * 920 * <p>This will be called immediately after the callback is registered, and may be called 921 * multiple times later upon changes. 922 * @param interfaces The list of tetherable interface names. 923 */ 924 default void onTetherableInterfacesChanged(@NonNull List<String> interfaces) {} 925 926 /** 927 * Called when there was a change in the list of tethered interfaces. 928 * 929 * <p>This will be called immediately after the callback is registered, and may be called 930 * multiple times later upon changes. 931 * @param interfaces The list of 0 or more String of currently tethered interface names. 932 */ 933 default void onTetheredInterfacesChanged(@NonNull List<String> interfaces) {} 934 935 /** 936 * Called when an error occurred configuring tethering. 937 * 938 * <p>This will be called immediately after the callback is registered if the latest status 939 * on the interface is an error, and may be called multiple times later upon changes. 940 * @param ifName Name of the interface. 941 * @param error One of {@code TetheringManager#TETHER_ERROR_*}. 942 */ 943 default void onError(@NonNull String ifName, @TetheringIfaceError int error) {} 944 945 /** 946 * Called when the list of tethered clients changes. 947 * 948 * <p>This callback provides best-effort information on connected clients based on state 949 * known to the system, however the list cannot be completely accurate (and should not be 950 * used for security purposes). For example, clients behind a bridge and using static IP 951 * assignments are not visible to the tethering device; or even when using DHCP, such 952 * clients may still be reported by this callback after disconnection as the system cannot 953 * determine if they are still connected. 954 * @param clients The new set of tethered clients; the collection is not ordered. 955 */ 956 default void onClientsChanged(@NonNull Collection<TetheredClient> clients) {} 957 958 /** 959 * Called when tethering offload status changes. 960 * 961 * <p>This will be called immediately after the callback is registered. 962 * @param status The offload status. 963 */ 964 default void onOffloadStatusChanged(@TetherOffloadStatus int status) {} 965 } 966 967 /** 968 * Regular expressions used to identify tethering interfaces. 969 * @hide 970 */ 971 @SystemApi(client = MODULE_LIBRARIES) 972 public static class TetheringInterfaceRegexps { 973 private final String[] mTetherableBluetoothRegexs; 974 private final String[] mTetherableUsbRegexs; 975 private final String[] mTetherableWifiRegexs; 976 977 /** @hide */ 978 public TetheringInterfaceRegexps(@NonNull String[] tetherableBluetoothRegexs, 979 @NonNull String[] tetherableUsbRegexs, @NonNull String[] tetherableWifiRegexs) { 980 mTetherableBluetoothRegexs = tetherableBluetoothRegexs.clone(); 981 mTetherableUsbRegexs = tetherableUsbRegexs.clone(); 982 mTetherableWifiRegexs = tetherableWifiRegexs.clone(); 983 } 984 985 @NonNull 986 public List<String> getTetherableBluetoothRegexs() { 987 return Collections.unmodifiableList(Arrays.asList(mTetherableBluetoothRegexs)); 988 } 989 990 @NonNull 991 public List<String> getTetherableUsbRegexs() { 992 return Collections.unmodifiableList(Arrays.asList(mTetherableUsbRegexs)); 993 } 994 995 @NonNull 996 public List<String> getTetherableWifiRegexs() { 997 return Collections.unmodifiableList(Arrays.asList(mTetherableWifiRegexs)); 998 } 999 1000 @Override 1001 public int hashCode() { 1002 return Objects.hash(mTetherableBluetoothRegexs, mTetherableUsbRegexs, 1003 mTetherableWifiRegexs); 1004 } 1005 1006 @Override 1007 public boolean equals(@Nullable Object obj) { 1008 if (!(obj instanceof TetheringInterfaceRegexps)) return false; 1009 final TetheringInterfaceRegexps other = (TetheringInterfaceRegexps) obj; 1010 return Arrays.equals(mTetherableBluetoothRegexs, other.mTetherableBluetoothRegexs) 1011 && Arrays.equals(mTetherableUsbRegexs, other.mTetherableUsbRegexs) 1012 && Arrays.equals(mTetherableWifiRegexs, other.mTetherableWifiRegexs); 1013 } 1014 } 1015 1016 /** 1017 * Start listening to tethering change events. Any new added callback will receive the last 1018 * tethering status right away. If callback is registered, 1019 * {@link TetheringEventCallback#onUpstreamChanged} will immediately be called. If tethering 1020 * has no upstream or disabled, the argument of callback will be null. The same callback object 1021 * cannot be registered twice. 1022 * 1023 * @param executor the executor on which callback will be invoked. 1024 * @param callback the callback to be called when tethering has change events. 1025 */ 1026 @RequiresPermission(Manifest.permission.ACCESS_NETWORK_STATE) 1027 public void registerTetheringEventCallback(@NonNull Executor executor, 1028 @NonNull TetheringEventCallback callback) { 1029 final String callerPkg = mContext.getOpPackageName(); 1030 Log.i(TAG, "registerTetheringEventCallback caller:" + callerPkg); 1031 1032 synchronized (mTetheringEventCallbacks) { 1033 if (mTetheringEventCallbacks.containsKey(callback)) { 1034 throw new IllegalArgumentException("callback was already registered."); 1035 } 1036 final ITetheringEventCallback remoteCallback = new ITetheringEventCallback.Stub() { 1037 // Only accessed with a lock on this object 1038 private final HashMap<String, Integer> mErrorStates = new HashMap<>(); 1039 private String[] mLastTetherableInterfaces = null; 1040 private String[] mLastTetheredInterfaces = null; 1041 1042 @Override 1043 public void onUpstreamChanged(Network network) throws RemoteException { 1044 executor.execute(() -> { 1045 callback.onUpstreamChanged(network); 1046 }); 1047 } 1048 1049 private synchronized void sendErrorCallbacks(final TetherStatesParcel newStates) { 1050 for (int i = 0; i < newStates.erroredIfaceList.length; i++) { 1051 final String iface = newStates.erroredIfaceList[i]; 1052 final Integer lastError = mErrorStates.get(iface); 1053 final int newError = newStates.lastErrorList[i]; 1054 if (newError != TETHER_ERROR_NO_ERROR 1055 && !Objects.equals(lastError, newError)) { 1056 callback.onError(iface, newError); 1057 } 1058 mErrorStates.put(iface, newError); 1059 } 1060 } 1061 1062 private synchronized void maybeSendTetherableIfacesChangedCallback( 1063 final TetherStatesParcel newStates) { 1064 if (Arrays.equals(mLastTetherableInterfaces, newStates.availableList)) return; 1065 mLastTetherableInterfaces = newStates.availableList.clone(); 1066 callback.onTetherableInterfacesChanged( 1067 Collections.unmodifiableList(Arrays.asList(mLastTetherableInterfaces))); 1068 } 1069 1070 private synchronized void maybeSendTetheredIfacesChangedCallback( 1071 final TetherStatesParcel newStates) { 1072 if (Arrays.equals(mLastTetheredInterfaces, newStates.tetheredList)) return; 1073 mLastTetheredInterfaces = newStates.tetheredList.clone(); 1074 callback.onTetheredInterfacesChanged( 1075 Collections.unmodifiableList(Arrays.asList(mLastTetheredInterfaces))); 1076 } 1077 1078 // Called immediately after the callbacks are registered. 1079 @Override 1080 public void onCallbackStarted(TetheringCallbackStartedParcel parcel) { 1081 executor.execute(() -> { 1082 callback.onTetheringSupported(parcel.tetheringSupported); 1083 callback.onUpstreamChanged(parcel.upstreamNetwork); 1084 sendErrorCallbacks(parcel.states); 1085 sendRegexpsChanged(parcel.config); 1086 maybeSendTetherableIfacesChangedCallback(parcel.states); 1087 maybeSendTetheredIfacesChangedCallback(parcel.states); 1088 callback.onClientsChanged(parcel.tetheredClients); 1089 callback.onOffloadStatusChanged(parcel.offloadStatus); 1090 }); 1091 } 1092 1093 @Override 1094 public void onCallbackStopped(int errorCode) { 1095 executor.execute(() -> { 1096 throwIfPermissionFailure(errorCode); 1097 }); 1098 } 1099 1100 private void sendRegexpsChanged(TetheringConfigurationParcel parcel) { 1101 callback.onTetherableInterfaceRegexpsChanged(new TetheringInterfaceRegexps( 1102 parcel.tetherableBluetoothRegexs, 1103 parcel.tetherableUsbRegexs, 1104 parcel.tetherableWifiRegexs)); 1105 } 1106 1107 @Override 1108 public void onConfigurationChanged(TetheringConfigurationParcel config) { 1109 executor.execute(() -> sendRegexpsChanged(config)); 1110 } 1111 1112 @Override 1113 public void onTetherStatesChanged(TetherStatesParcel states) { 1114 executor.execute(() -> { 1115 sendErrorCallbacks(states); 1116 maybeSendTetherableIfacesChangedCallback(states); 1117 maybeSendTetheredIfacesChangedCallback(states); 1118 }); 1119 } 1120 1121 @Override 1122 public void onTetherClientsChanged(final List<TetheredClient> clients) { 1123 executor.execute(() -> callback.onClientsChanged(clients)); 1124 } 1125 1126 @Override 1127 public void onOffloadStatusChanged(final int status) { 1128 executor.execute(() -> callback.onOffloadStatusChanged(status)); 1129 } 1130 }; 1131 getConnector(c -> c.registerTetheringEventCallback(remoteCallback, callerPkg)); 1132 mTetheringEventCallbacks.put(callback, remoteCallback); 1133 } 1134 } 1135 1136 /** 1137 * Remove tethering event callback previously registered with 1138 * {@link #registerTetheringEventCallback}. 1139 * 1140 * @param callback previously registered callback. 1141 */ 1142 @RequiresPermission(anyOf = { 1143 Manifest.permission.TETHER_PRIVILEGED, 1144 Manifest.permission.ACCESS_NETWORK_STATE 1145 }) 1146 public void unregisterTetheringEventCallback(@NonNull final TetheringEventCallback callback) { 1147 final String callerPkg = mContext.getOpPackageName(); 1148 Log.i(TAG, "unregisterTetheringEventCallback caller:" + callerPkg); 1149 1150 synchronized (mTetheringEventCallbacks) { 1151 ITetheringEventCallback remoteCallback = mTetheringEventCallbacks.remove(callback); 1152 if (remoteCallback == null) { 1153 throw new IllegalArgumentException("callback was not registered."); 1154 } 1155 1156 getConnector(c -> c.unregisterTetheringEventCallback(remoteCallback, callerPkg)); 1157 } 1158 } 1159 1160 /** 1161 * Get a more detailed error code after a Tethering or Untethering 1162 * request asynchronously failed. 1163 * 1164 * @param iface The name of the interface of interest 1165 * @return error The error code of the last error tethering or untethering the named 1166 * interface 1167 * @hide 1168 */ 1169 @SystemApi(client = MODULE_LIBRARIES) 1170 public int getLastTetherError(@NonNull final String iface) { 1171 mCallback.waitForStarted(); 1172 if (mTetherStatesParcel == null) return TETHER_ERROR_NO_ERROR; 1173 1174 int i = 0; 1175 for (String errored : mTetherStatesParcel.erroredIfaceList) { 1176 if (iface.equals(errored)) return mTetherStatesParcel.lastErrorList[i]; 1177 1178 i++; 1179 } 1180 return TETHER_ERROR_NO_ERROR; 1181 } 1182 1183 /** 1184 * Get the list of regular expressions that define any tetherable 1185 * USB network interfaces. If USB tethering is not supported by the 1186 * device, this list should be empty. 1187 * 1188 * @return an array of 0 or more regular expression Strings defining 1189 * what interfaces are considered tetherable usb interfaces. 1190 * @hide 1191 */ 1192 @SystemApi(client = MODULE_LIBRARIES) 1193 public @NonNull String[] getTetherableUsbRegexs() { 1194 mCallback.waitForStarted(); 1195 return mTetheringConfiguration.tetherableUsbRegexs; 1196 } 1197 1198 /** 1199 * Get the list of regular expressions that define any tetherable 1200 * Wifi network interfaces. If Wifi tethering is not supported by the 1201 * device, this list should be empty. 1202 * 1203 * @return an array of 0 or more regular expression Strings defining 1204 * what interfaces are considered tetherable wifi interfaces. 1205 * @hide 1206 */ 1207 @SystemApi(client = MODULE_LIBRARIES) 1208 public @NonNull String[] getTetherableWifiRegexs() { 1209 mCallback.waitForStarted(); 1210 return mTetheringConfiguration.tetherableWifiRegexs; 1211 } 1212 1213 /** 1214 * Get the list of regular expressions that define any tetherable 1215 * Bluetooth network interfaces. If Bluetooth tethering is not supported by the 1216 * device, this list should be empty. 1217 * 1218 * @return an array of 0 or more regular expression Strings defining 1219 * what interfaces are considered tetherable bluetooth interfaces. 1220 * @hide 1221 */ 1222 @SystemApi(client = MODULE_LIBRARIES) 1223 public @NonNull String[] getTetherableBluetoothRegexs() { 1224 mCallback.waitForStarted(); 1225 return mTetheringConfiguration.tetherableBluetoothRegexs; 1226 } 1227 1228 /** 1229 * Get the set of tetherable, available interfaces. This list is limited by 1230 * device configuration and current interface existence. 1231 * 1232 * @return an array of 0 or more Strings of tetherable interface names. 1233 * @hide 1234 */ 1235 @SystemApi(client = MODULE_LIBRARIES) 1236 public @NonNull String[] getTetherableIfaces() { 1237 mCallback.waitForStarted(); 1238 if (mTetherStatesParcel == null) return new String[0]; 1239 1240 return mTetherStatesParcel.availableList; 1241 } 1242 1243 /** 1244 * Get the set of tethered interfaces. 1245 * 1246 * @return an array of 0 or more String of currently tethered interface names. 1247 * @hide 1248 */ 1249 @SystemApi(client = MODULE_LIBRARIES) 1250 public @NonNull String[] getTetheredIfaces() { 1251 mCallback.waitForStarted(); 1252 if (mTetherStatesParcel == null) return new String[0]; 1253 1254 return mTetherStatesParcel.tetheredList; 1255 } 1256 1257 /** 1258 * Get the set of interface names which attempted to tether but 1259 * failed. Re-attempting to tether may cause them to reset to the Tethered 1260 * state. Alternatively, causing the interface to be destroyed and recreated 1261 * may cause them to reset to the available state. 1262 * {@link TetheringManager#getLastTetherError} can be used to get more 1263 * information on the cause of the errors. 1264 * 1265 * @return an array of 0 or more String indicating the interface names 1266 * which failed to tether. 1267 * @hide 1268 */ 1269 @SystemApi(client = MODULE_LIBRARIES) 1270 public @NonNull String[] getTetheringErroredIfaces() { 1271 mCallback.waitForStarted(); 1272 if (mTetherStatesParcel == null) return new String[0]; 1273 1274 return mTetherStatesParcel.erroredIfaceList; 1275 } 1276 1277 /** 1278 * Get the set of tethered dhcp ranges. 1279 * 1280 * @deprecated This API just return the default value which is not used in DhcpServer. 1281 * @hide 1282 */ 1283 @Deprecated 1284 public @NonNull String[] getTetheredDhcpRanges() { 1285 mCallback.waitForStarted(); 1286 return mTetheringConfiguration.legacyDhcpRanges; 1287 } 1288 1289 /** 1290 * Check if the device allows for tethering. It may be disabled via 1291 * {@code ro.tether.denied} system property, Settings.TETHER_SUPPORTED or 1292 * due to device configuration. 1293 * 1294 * @return a boolean - {@code true} indicating Tethering is supported. 1295 * @hide 1296 */ 1297 @SystemApi(client = MODULE_LIBRARIES) 1298 public boolean isTetheringSupported() { 1299 final String callerPkg = mContext.getOpPackageName(); 1300 1301 return isTetheringSupported(callerPkg); 1302 } 1303 1304 /** 1305 * Check if the device allows for tethering. It may be disabled via {@code ro.tether.denied} 1306 * system property, Settings.TETHER_SUPPORTED or due to device configuration. This is useful 1307 * for system components that query this API on behalf of an app. In particular, Bluetooth 1308 * has @UnsupportedAppUsage calls that will let apps turn on bluetooth tethering if they have 1309 * the right permissions, but such an app needs to know whether it can (permissions as well 1310 * as support from the device) turn on tethering in the first place to show the appropriate UI. 1311 * 1312 * @param callerPkg The caller package name, if it is not matching the calling uid, 1313 * SecurityException would be thrown. 1314 * @return a boolean - {@code true} indicating Tethering is supported. 1315 * @hide 1316 */ 1317 @SystemApi(client = MODULE_LIBRARIES) 1318 public boolean isTetheringSupported(@NonNull final String callerPkg) { 1319 1320 final RequestDispatcher dispatcher = new RequestDispatcher(); 1321 final int ret = dispatcher.waitForResult((connector, listener) -> { 1322 try { 1323 connector.isTetheringSupported(callerPkg, listener); 1324 } catch (RemoteException e) { 1325 throw new IllegalStateException(e); 1326 } 1327 }); 1328 1329 return ret == TETHER_ERROR_NO_ERROR; 1330 } 1331 1332 /** 1333 * Stop all active tethering. 1334 * 1335 * <p>Without {@link android.Manifest.permission.TETHER_PRIVILEGED} permission, the call will 1336 * fail if a tethering entitlement check is required. 1337 */ 1338 @RequiresPermission(anyOf = { 1339 android.Manifest.permission.TETHER_PRIVILEGED, 1340 android.Manifest.permission.WRITE_SETTINGS 1341 }) 1342 public void stopAllTethering() { 1343 final String callerPkg = mContext.getOpPackageName(); 1344 Log.i(TAG, "stopAllTethering caller:" + callerPkg); 1345 1346 getConnector(c -> c.stopAllTethering(callerPkg, new IIntResultListener.Stub() { 1347 @Override 1348 public void onResult(int resultCode) { 1349 // TODO: add an API parameter to send result to caller. 1350 // This has never been possible as stopAllTethering has always been void and never 1351 // taken a callback object. The only indication that callers have is if the call 1352 // results in a TETHER_STATE_CHANGE broadcast. 1353 } 1354 })); 1355 } 1356 } 1357