• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.FlaggedApi;
22 import android.annotation.IntDef;
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.annotation.RequiresPermission;
26 import android.annotation.SuppressLint;
27 import android.annotation.SystemApi;
28 import android.content.Context;
29 import android.net.wifi.SoftApConfiguration;
30 import android.net.wifi.WifiManager;
31 import android.os.Build;
32 import android.os.Bundle;
33 import android.os.ConditionVariable;
34 import android.os.IBinder;
35 import android.os.Parcel;
36 import android.os.Parcelable;
37 import android.os.Process;
38 import android.os.RemoteException;
39 import android.os.ResultReceiver;
40 import android.text.TextUtils;
41 import android.util.ArrayMap;
42 import android.util.ArraySet;
43 import android.util.Log;
44 
45 import com.android.internal.annotations.GuardedBy;
46 import com.android.modules.utils.build.SdkLevel;
47 import com.android.net.flags.Flags;
48 
49 import java.lang.annotation.Retention;
50 import java.lang.annotation.RetentionPolicy;
51 import java.lang.ref.WeakReference;
52 import java.util.ArrayList;
53 import java.util.Arrays;
54 import java.util.Collection;
55 import java.util.Collections;
56 import java.util.HashMap;
57 import java.util.List;
58 import java.util.Objects;
59 import java.util.Set;
60 import java.util.StringJoiner;
61 import java.util.concurrent.Executor;
62 import java.util.function.Supplier;
63 
64 /**
65  * This class provides the APIs to control the tethering service.
66  * <p> The primary responsibilities of this class are to provide the APIs for applications to
67  * start tethering, stop tethering, query configuration and query status.
68  *
69  */
70 @SuppressLint({"NotCloseable", "UnflaggedApi"})
71 public class TetheringManager {
72     private static final String TAG = TetheringManager.class.getSimpleName();
73     private static final int DEFAULT_TIMEOUT_MS = 60_000;
74     private static final long CONNECTOR_POLL_INTERVAL_MILLIS = 200L;
75 
76     @GuardedBy("mConnectorWaitQueue")
77     @Nullable
78     private ITetheringConnector mConnector;
79     @GuardedBy("mConnectorWaitQueue")
80     @NonNull
81     private final List<ConnectorConsumer> mConnectorWaitQueue = new ArrayList<>();
82     private final Supplier<IBinder> mConnectorSupplier;
83 
84     private final TetheringCallbackInternal mCallback;
85     private final Context mContext;
86     private final ArrayMap<TetheringEventCallback, ITetheringEventCallback>
87             mTetheringEventCallbacks = new ArrayMap<>();
88 
89     private volatile TetheringConfigurationParcel mTetheringConfiguration;
90     private volatile TetherStatesParcel mTetherStatesParcel;
91 
92     /**
93      * Broadcast Action: A tetherable connection has come or gone.
94      * Uses {@code TetheringManager.EXTRA_AVAILABLE_TETHER},
95      * {@code TetheringManager.EXTRA_ACTIVE_LOCAL_ONLY},
96      * {@code TetheringManager.EXTRA_ACTIVE_TETHER}, and
97      * {@code TetheringManager.EXTRA_ERRORED_TETHER} to indicate
98      * the current state of tethering.  Each include a list of
99      * interface names in that state (may be empty).
100      * @hide
101      *
102      * @deprecated New client should use TetheringEventCallback instead.
103      */
104     @Deprecated
105     @SystemApi
106     public static final String ACTION_TETHER_STATE_CHANGED =
107             "android.net.conn.TETHER_STATE_CHANGED";
108 
109     /**
110      * gives a String[] listing all the interfaces configured for
111      * tethering and currently available for tethering.
112      * @hide
113      */
114     @SystemApi
115     public static final String EXTRA_AVAILABLE_TETHER = "availableArray";
116 
117     /**
118      * gives a String[] listing all the interfaces currently in local-only
119      * mode (ie, has DHCPv4+IPv6-ULA support and no packet forwarding)
120      * @hide
121      */
122     @SystemApi
123     public static final String EXTRA_ACTIVE_LOCAL_ONLY = "android.net.extra.ACTIVE_LOCAL_ONLY";
124 
125     /**
126      * gives a String[] listing all the interfaces currently tethered
127      * (ie, has DHCPv4 support and packets potentially forwarded/NATed)
128      * @hide
129      */
130     @SystemApi
131     public static final String EXTRA_ACTIVE_TETHER = "tetherArray";
132 
133     /**
134      * gives a String[] listing all the interfaces we tried to tether and
135      * failed.  Use {@link #getLastTetherError} to find the error code
136      * for any interfaces listed here.
137      * @hide
138      */
139     @SystemApi
140     public static final String EXTRA_ERRORED_TETHER = "erroredArray";
141 
142     /** @hide */
143     @Retention(RetentionPolicy.SOURCE)
144     @IntDef(flag = false, value = {
145             TETHERING_WIFI,
146             TETHERING_USB,
147             TETHERING_BLUETOOTH,
148             TETHERING_WIFI_P2P,
149             TETHERING_NCM,
150             TETHERING_ETHERNET,
151             TETHERING_VIRTUAL,
152     })
153     public @interface TetheringType {
154     }
155 
156     /**
157      * Invalid tethering type.
158      * @see #startTethering.
159      * @hide
160      */
161     @SystemApi
162     public static final int TETHERING_INVALID   = -1;
163 
164     /**
165      * Wifi tethering type.
166      * @see #startTethering.
167      */
168     @SuppressLint("UnflaggedApi")
169     public static final int TETHERING_WIFI      = 0;
170 
171     /**
172      * USB tethering type.
173      * @see #startTethering.
174      * @hide
175      */
176     @SystemApi
177     public static final int TETHERING_USB       = 1;
178 
179     /**
180      * Bluetooth tethering type.
181      * @see #startTethering.
182      * @hide
183      */
184     @SystemApi
185     public static final int TETHERING_BLUETOOTH = 2;
186 
187     /**
188      * Wifi P2p tethering type.
189      * Wifi P2p tethering is set through events automatically, and don't
190      * need to start from #startTethering.
191      * @hide
192      */
193     @SystemApi
194     public static final int TETHERING_WIFI_P2P = 3;
195 
196     /**
197      * Ncm local tethering type.
198      * @see #startTethering(TetheringRequest, Executor, StartTetheringCallback)
199      * @hide
200      */
201     @SystemApi
202     public static final int TETHERING_NCM = 4;
203 
204     /**
205      * Ethernet tethering type.
206      * @see #startTethering(TetheringRequest, Executor, StartTetheringCallback)
207      * @hide
208      */
209     @SystemApi
210     public static final int TETHERING_ETHERNET = 5;
211 
212     /**
213      * WIGIG tethering type. Use a separate type to prevent
214      * conflicts with TETHERING_WIFI
215      * This type is only used internally by the tethering module
216      * @hide
217      */
218     public static final int TETHERING_WIGIG = 6;
219 
220     /**
221      * VIRTUAL tethering type.
222      *
223      * This tethering type is for providing external network to virtual machines
224      * running on top of Android devices, which are created and managed by
225      * AVF(Android Virtualization Framework).
226      * @hide
227      */
228     @FlaggedApi(Flags.FLAG_TETHERING_REQUEST_VIRTUAL)
229     @SystemApi
230     public static final int TETHERING_VIRTUAL = 7;
231 
232     /**
233      * The int value of last tethering type.
234      * @hide
235      */
236     public static final int MAX_TETHERING_TYPE = TETHERING_VIRTUAL;
237 
typeToString(@etheringType int type)238     private static String typeToString(@TetheringType int type) {
239         switch (type) {
240             case TETHERING_INVALID: return "TETHERING_INVALID";
241             case TETHERING_WIFI: return "TETHERING_WIFI";
242             case TETHERING_USB: return "TETHERING_USB";
243             case TETHERING_BLUETOOTH: return "TETHERING_BLUETOOTH";
244             case TETHERING_WIFI_P2P: return "TETHERING_WIFI_P2P";
245             case TETHERING_NCM: return "TETHERING_NCM";
246             case TETHERING_ETHERNET: return "TETHERING_ETHERNET";
247             default:
248                 return "TETHERING_UNKNOWN(" + type + ")";
249         }
250     }
251 
252     /** @hide */
253     @Retention(RetentionPolicy.SOURCE)
254     @IntDef(value = {
255             TETHER_ERROR_NO_ERROR,
256             TETHER_ERROR_PROVISIONING_FAILED,
257             TETHER_ERROR_ENTITLEMENT_UNKNOWN,
258     })
259     public @interface EntitlementResult {
260     }
261 
262     /** @hide */
263     @Retention(RetentionPolicy.SOURCE)
264     @IntDef(value = {
265             TETHER_ERROR_NO_ERROR,
266             TETHER_ERROR_UNKNOWN_IFACE,
267             TETHER_ERROR_SERVICE_UNAVAIL,
268             TETHER_ERROR_INTERNAL_ERROR,
269             TETHER_ERROR_TETHER_IFACE_ERROR,
270             TETHER_ERROR_ENABLE_FORWARDING_ERROR,
271             TETHER_ERROR_DISABLE_FORWARDING_ERROR,
272             TETHER_ERROR_IFACE_CFG_ERROR,
273             TETHER_ERROR_DHCPSERVER_ERROR,
274     })
275     public @interface TetheringIfaceError {
276     }
277 
278     /** @hide */
279     @Retention(RetentionPolicy.SOURCE)
280     @IntDef(value = {
281             TETHER_ERROR_SERVICE_UNAVAIL,
282             TETHER_ERROR_UNSUPPORTED,
283             TETHER_ERROR_INTERNAL_ERROR,
284             TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION,
285             TETHER_ERROR_UNKNOWN_TYPE,
286             TETHER_ERROR_DUPLICATE_REQUEST,
287     })
288     public @interface StartTetheringError {
289     }
290 
291     /** @hide */
292     @Retention(RetentionPolicy.SOURCE)
293     @IntDef(value = {
294             TETHER_ERROR_NO_ERROR,
295             TETHER_ERROR_UNKNOWN_REQUEST,
296     })
297     public @interface StopTetheringError {
298     }
299 
300     @SuppressLint("UnflaggedApi")
301     public static final int TETHER_ERROR_NO_ERROR = 0;
302     @SuppressLint("UnflaggedApi")
303     public static final int TETHER_ERROR_UNKNOWN_IFACE = 1;
304     @SuppressLint("UnflaggedApi")
305     public static final int TETHER_ERROR_SERVICE_UNAVAIL = 2;
306     @SuppressLint("UnflaggedApi")
307     public static final int TETHER_ERROR_UNSUPPORTED = 3;
308     @SuppressLint("UnflaggedApi")
309     public static final int TETHER_ERROR_UNAVAIL_IFACE = 4;
310     @SuppressLint("UnflaggedApi")
311     public static final int TETHER_ERROR_INTERNAL_ERROR = 5;
312     @SuppressLint("UnflaggedApi")
313     public static final int TETHER_ERROR_TETHER_IFACE_ERROR = 6;
314     @SuppressLint("UnflaggedApi")
315     public static final int TETHER_ERROR_UNTETHER_IFACE_ERROR = 7;
316     @SuppressLint("UnflaggedApi")
317     public static final int TETHER_ERROR_ENABLE_FORWARDING_ERROR = 8;
318     @SuppressLint("UnflaggedApi")
319     public static final int TETHER_ERROR_DISABLE_FORWARDING_ERROR = 9;
320     @SuppressLint("UnflaggedApi")
321     public static final int TETHER_ERROR_IFACE_CFG_ERROR = 10;
322     @SuppressLint("UnflaggedApi")
323     public static final int TETHER_ERROR_PROVISIONING_FAILED = 11;
324     @SuppressLint("UnflaggedApi")
325     public static final int TETHER_ERROR_DHCPSERVER_ERROR = 12;
326     @SuppressLint("UnflaggedApi")
327     public static final int TETHER_ERROR_ENTITLEMENT_UNKNOWN = 13;
328     @SuppressLint("UnflaggedApi")
329     public static final int TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION = 14;
330     @SuppressLint("UnflaggedApi")
331     public static final int TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION = 15;
332     @SuppressLint("UnflaggedApi")
333     public static final int TETHER_ERROR_UNKNOWN_TYPE = 16;
334     @FlaggedApi(Flags.FLAG_TETHERING_WITH_SOFT_AP_CONFIG)
335     public static final int TETHER_ERROR_UNKNOWN_REQUEST = 17;
336     @FlaggedApi(Flags.FLAG_TETHERING_WITH_SOFT_AP_CONFIG)
337     public static final int TETHER_ERROR_DUPLICATE_REQUEST = 18;
338     /**
339      * Never used outside Tethering.java.
340      * @hide
341      */
342     public static final int TETHER_ERROR_BLUETOOTH_SERVICE_PENDING = 19;
343     /**
344      * Never used outside Tethering.java.
345      * @hide
346      */
347     public static final int TETHER_ERROR_SOFT_AP_CALLBACK_PENDING = 20;
348 
349     /** @hide */
350     @Retention(RetentionPolicy.SOURCE)
351     @IntDef(flag = false, value = {
352             TETHER_HARDWARE_OFFLOAD_STOPPED,
353             TETHER_HARDWARE_OFFLOAD_STARTED,
354             TETHER_HARDWARE_OFFLOAD_FAILED,
355     })
356     public @interface TetherOffloadStatus {
357     }
358 
359     /**
360      * Tethering offload status is stopped.
361      * @hide
362      */
363     @SystemApi
364     public static final int TETHER_HARDWARE_OFFLOAD_STOPPED = 0;
365     /**
366      * Tethering offload status is started.
367      * @hide
368      */
369     @SystemApi
370     public static final int TETHER_HARDWARE_OFFLOAD_STARTED = 1;
371     /**
372      * Fail to start tethering offload.
373      * @hide
374      */
375     @SystemApi
376     public static final int TETHER_HARDWARE_OFFLOAD_FAILED = 2;
377 
378     /**
379      * Create a TetheringManager object for interacting with the tethering service.
380      *
381      * @param context Context for the manager.
382      * @param connectorSupplier Supplier for the manager connector; may return null while the
383      *                          service is not connected.
384      * {@hide}
385      */
386     @SystemApi(client = MODULE_LIBRARIES)
TetheringManager(@onNull final Context context, @NonNull Supplier<IBinder> connectorSupplier)387     public TetheringManager(@NonNull final Context context,
388             @NonNull Supplier<IBinder> connectorSupplier) {
389         mContext = context;
390         mCallback = new TetheringCallbackInternal(this);
391         mConnectorSupplier = connectorSupplier;
392 
393         final String pkgName = mContext.getOpPackageName();
394 
395         final IBinder connector = mConnectorSupplier.get();
396         // If the connector is available on start, do not start a polling thread. This introduces
397         // differences in the thread that sends the oneway binder calls to the service between the
398         // first few seconds after boot and later, but it avoids always having differences between
399         // the first usage of TetheringManager from a process and subsequent usages (so the
400         // difference is only on boot). On boot binder calls may be queued until the service comes
401         // up and be sent from a worker thread; later, they are always sent from the caller thread.
402         // Considering that it's just oneway binder calls, and ordering is preserved, this seems
403         // better than inconsistent behavior persisting after boot.
404         // If system server restarted, mConnectorSupplier might temporarily return a stale (i.e.
405         // dead) version of TetheringService.
406         if (connector != null && connector.isBinderAlive()) {
407             mConnector = ITetheringConnector.Stub.asInterface(connector);
408         } else {
409             startPollingForConnector();
410         }
411 
412         Log.i(TAG, "registerTetheringEventCallback:" + pkgName);
413         getConnector(c -> c.registerTetheringEventCallback(mCallback, pkgName));
414     }
415 
416     /** @hide */
417     @Override
finalize()418     protected void finalize() throws Throwable {
419         final String pkgName = mContext.getOpPackageName();
420         Log.i(TAG, "unregisterTetheringEventCallback:" + pkgName);
421         // 1. It's generally not recommended to perform long operations in finalize, but while
422         // unregisterTetheringEventCallback does an IPC, it's a oneway IPC so should not block.
423         // 2. If the connector is not yet connected, TetheringManager is impossible to finalize
424         // because the connector polling thread strong reference the TetheringManager object. So
425         // it's guaranteed that registerTetheringEventCallback was already called before calling
426         // unregisterTetheringEventCallback in finalize.
427         if (mConnector == null) Log.wtf(TAG, "null connector in finalize!");
428         getConnector(c -> c.unregisterTetheringEventCallback(mCallback, pkgName));
429 
430         super.finalize();
431     }
432 
startPollingForConnector()433     private void startPollingForConnector() {
434         new Thread(() -> {
435             while (true) {
436                 try {
437                     Thread.sleep(CONNECTOR_POLL_INTERVAL_MILLIS);
438                 } catch (InterruptedException e) {
439                     // Not much to do here, the system needs to wait for the connector
440                 }
441                 final IBinder connector = mConnectorSupplier.get();
442                 if (connector != null && connector.isBinderAlive()) {
443                     onTetheringConnected(ITetheringConnector.Stub.asInterface(connector));
444                     return;
445                 }
446             }
447         }).start();
448     }
449 
450     private interface ConnectorConsumer {
onConnectorAvailable(ITetheringConnector connector)451         void onConnectorAvailable(ITetheringConnector connector) throws RemoteException;
452     }
453 
onTetheringConnected(ITetheringConnector connector)454     private void onTetheringConnected(ITetheringConnector connector) {
455         // Process the connector wait queue in order, including any items that are added
456         // while processing.
457         //
458         // 1. Copy the queue to a local variable under lock.
459         // 2. Drain the local queue with the lock released (otherwise, enqueuing future commands
460         //    would block on the lock).
461         // 3. Acquire the lock again. If any new tasks were queued during step 2, goto 1.
462         //    If not, set mConnector to non-null so future tasks are run immediately, not queued.
463         //
464         // For this to work, all calls to the tethering service must use getConnector(), which
465         // ensures that tasks are added to the queue with the lock held.
466         //
467         // Once mConnector is set to non-null, it will never be null again. If the network stack
468         // process crashes, no recovery is possible.
469         // TODO: evaluate whether it is possible to recover from network stack process crashes
470         // (though in most cases the system will have crashed when the network stack process
471         // crashes).
472         do {
473             final List<ConnectorConsumer> localWaitQueue;
474             synchronized (mConnectorWaitQueue) {
475                 localWaitQueue = new ArrayList<>(mConnectorWaitQueue);
476                 mConnectorWaitQueue.clear();
477             }
478 
479             // Allow more tasks to be added at the end without blocking while draining the queue.
480             for (ConnectorConsumer task : localWaitQueue) {
481                 try {
482                     task.onConnectorAvailable(connector);
483                 } catch (RemoteException e) {
484                     // Most likely the network stack process crashed, which is likely to crash the
485                     // system. Keep processing other requests but report the error loudly.
486                     Log.wtf(TAG, "Error processing request for the tethering connector", e);
487                 }
488             }
489 
490             synchronized (mConnectorWaitQueue) {
491                 if (mConnectorWaitQueue.size() == 0) {
492                     mConnector = connector;
493                     return;
494                 }
495             }
496         } while (true);
497     }
498 
499     /**
500      * Asynchronously get the ITetheringConnector to execute some operation.
501      *
502      * <p>If the connector is already available, the operation will be executed on the caller's
503      * thread. Otherwise it will be queued and executed on a worker thread. The operation should be
504      * limited to performing oneway binder calls to minimize differences due to threading.
505      */
getConnector(ConnectorConsumer consumer)506     private void getConnector(ConnectorConsumer consumer) {
507         final ITetheringConnector connector;
508         synchronized (mConnectorWaitQueue) {
509             connector = mConnector;
510             if (connector == null) {
511                 mConnectorWaitQueue.add(consumer);
512                 return;
513             }
514         }
515 
516         try {
517             consumer.onConnectorAvailable(connector);
518         } catch (RemoteException e) {
519             throw new IllegalStateException(e);
520         }
521     }
522 
523     private interface RequestHelper {
runRequest(ITetheringConnector connector, IIntResultListener listener)524         void runRequest(ITetheringConnector connector, IIntResultListener listener);
525     }
526 
527     // Used to dispatch legacy ConnectivityManager methods that expect tethering to be able to
528     // return results and perform operations synchronously.
529     // TODO: remove once there are no callers of these legacy methods.
530     private static class RequestDispatcher {
531         private final ConditionVariable mWaiting;
532         public volatile int mRemoteResult;
533 
534         private final IIntResultListener mListener = new IIntResultListener.Stub() {
535                 @Override
536                 public void onResult(final int resultCode) {
537                     mRemoteResult = resultCode;
538                     mWaiting.open();
539                 }
540         };
541 
RequestDispatcher()542         RequestDispatcher() {
543             mWaiting = new ConditionVariable();
544         }
545 
waitForResult(final RequestHelper request, final TetheringManager mgr)546         int waitForResult(final RequestHelper request, final TetheringManager mgr) {
547             mgr.getConnector(c -> request.runRequest(c, mListener));
548             if (!mWaiting.block(DEFAULT_TIMEOUT_MS)) {
549                 throw new IllegalStateException("Callback timeout");
550             }
551 
552             throwIfPermissionFailure(mRemoteResult);
553 
554             return mRemoteResult;
555         }
556     }
557 
throwIfPermissionFailure(final int errorCode)558     private static void throwIfPermissionFailure(final int errorCode) {
559         switch (errorCode) {
560             case TETHER_ERROR_NO_CHANGE_TETHERING_PERMISSION:
561                 throw new SecurityException("No android.permission.TETHER_PRIVILEGED"
562                         + " or android.permission.WRITE_SETTINGS permission");
563             case TETHER_ERROR_NO_ACCESS_TETHERING_PERMISSION:
564                 throw new SecurityException(
565                         "No android.permission.ACCESS_NETWORK_STATE permission");
566         }
567     }
568 
569     /**
570      * A request for a tethered interface.
571      *
572      * There are two reasons why this doesn't implement CLoseable:
573      * 1. To consistency with the existing EthernetManager.TetheredInterfaceRequest, which is
574      * already released.
575      * 2. This is not synchronous, so it's not useful to use try-with-resources.
576      *
577      * {@hide}
578      */
579     @SystemApi(client = MODULE_LIBRARIES)
580     @SuppressLint("NotCloseable")
581     public interface TetheredInterfaceRequest {
582         /**
583          * Release the request to tear down tethered interface.
584          */
release()585         void release();
586     }
587 
588     /**
589      * Callback for requestTetheredInterface.
590      *
591      * {@hide}
592      */
593     @SystemApi(client = MODULE_LIBRARIES)
594     public interface TetheredInterfaceCallback {
595         /**
596          * Called when the tethered interface is available.
597          * @param iface The name of the interface.
598          */
onAvailable(@onNull String iface)599         void onAvailable(@NonNull String iface);
600 
601         /**
602          * Called when the tethered interface is now unavailable.
603          */
onUnavailable()604         void onUnavailable();
605     }
606 
607     private static class TetheringCallbackInternal extends ITetheringEventCallback.Stub {
608         private volatile int mError = TETHER_ERROR_NO_ERROR;
609         private final ConditionVariable mWaitForCallback = new ConditionVariable();
610         // This object is never garbage collected because the Tethering code running in
611         // the system server always maintains a reference to it for as long as
612         // mCallback is registered.
613         //
614         // Don't keep a strong reference to TetheringManager because otherwise
615         // TetheringManager cannot be garbage collected, and because TetheringManager
616         // stores the Context that it was created from, this will prevent the calling
617         // Activity from being garbage collected as well.
618         private final WeakReference<TetheringManager> mTetheringMgrRef;
619 
TetheringCallbackInternal(final TetheringManager tm)620         TetheringCallbackInternal(final TetheringManager tm) {
621             mTetheringMgrRef = new WeakReference<>(tm);
622         }
623 
624         @Override
onCallbackStarted(TetheringCallbackStartedParcel parcel)625         public void onCallbackStarted(TetheringCallbackStartedParcel parcel) {
626             TetheringManager tetheringMgr = mTetheringMgrRef.get();
627             if (tetheringMgr != null) {
628                 tetheringMgr.mTetheringConfiguration = parcel.config;
629                 tetheringMgr.mTetherStatesParcel = parcel.states;
630                 mWaitForCallback.open();
631             }
632         }
633 
634         @Override
onCallbackStopped(int errorCode)635         public void onCallbackStopped(int errorCode) {
636             TetheringManager tetheringMgr = mTetheringMgrRef.get();
637             if (tetheringMgr != null) {
638                 mError = errorCode;
639                 mWaitForCallback.open();
640             }
641         }
642 
643         @Override
onSupportedTetheringTypes(long supportedBitmap)644         public void onSupportedTetheringTypes(long supportedBitmap) { }
645 
646         @Override
onUpstreamChanged(Network network)647         public void onUpstreamChanged(Network network) { }
648 
649         @Override
onConfigurationChanged(TetheringConfigurationParcel config)650         public void onConfigurationChanged(TetheringConfigurationParcel config) {
651             TetheringManager tetheringMgr = mTetheringMgrRef.get();
652             if (tetheringMgr != null) tetheringMgr.mTetheringConfiguration = config;
653         }
654 
655         @Override
onTetherStatesChanged(TetherStatesParcel states)656         public void onTetherStatesChanged(TetherStatesParcel states) {
657             TetheringManager tetheringMgr = mTetheringMgrRef.get();
658             if (tetheringMgr != null) tetheringMgr.mTetherStatesParcel = states;
659         }
660 
661         @Override
onTetherClientsChanged(List<TetheredClient> clients)662         public void onTetherClientsChanged(List<TetheredClient> clients) { }
663 
664         @Override
onOffloadStatusChanged(int status)665         public void onOffloadStatusChanged(int status) { }
666 
waitForStarted()667         public void waitForStarted() {
668             mWaitForCallback.block(DEFAULT_TIMEOUT_MS);
669             throwIfPermissionFailure(mError);
670         }
671     }
672 
unsupportedAfterV()673     private void unsupportedAfterV() {
674         if (SdkLevel.isAtLeastB()) {
675             throw new UnsupportedOperationException("Not supported after SDK version "
676                     + Build.VERSION_CODES.VANILLA_ICE_CREAM);
677         }
678     }
679 
680     /**
681      * Attempt to tether the named interface.  This will setup a dhcp server
682      * on the interface, forward and NAT IP v4 packets and forward DNS requests
683      * to the best active upstream network interface.  Note that if no upstream
684      * IP network interface is available, dhcp will still run and traffic will be
685      * allowed between the tethered devices and this device, though upstream net
686      * access will of course fail until an upstream network interface becomes
687      * active.
688      *
689      * @deprecated Legacy tethering API. Callers should instead use
690      *             {@link #startTethering(int, Executor, StartTetheringCallback)}.
691      *             On SDK versions after {@link Build.VERSION_CODES.VANILLA_ICE_CREAM}, this will
692      *             throw an UnsupportedOperationException.
693      *
694      * @param iface the interface name to tether.
695      * @return error a {@code TETHER_ERROR} value indicating success or failure type
696      *
697      * {@hide}
698      */
699     @Deprecated
700     @SystemApi(client = MODULE_LIBRARIES)
tether(@onNull final String iface)701     public int tether(@NonNull final String iface) {
702         unsupportedAfterV();
703 
704         final String callerPkg = mContext.getOpPackageName();
705         Log.i(TAG, "tether caller:" + callerPkg);
706         final RequestDispatcher dispatcher = new RequestDispatcher();
707 
708         return dispatcher.waitForResult((connector, listener) -> {
709             try {
710                 connector.tether(iface, callerPkg, getAttributionTag(), listener);
711             } catch (RemoteException e) {
712                 throw new IllegalStateException(e);
713             }
714         }, this);
715     }
716 
717     /**
718      * @return the context's attribution tag
719      */
720     private @Nullable String getAttributionTag() {
721         return mContext.getAttributionTag();
722     }
723 
724     /**
725      * Stop tethering the named interface.
726      *
727      * @deprecated Legacy tethering API. Callers should instead use
728      *             {@link #stopTethering(int)}.
729      *             On SDK versions after {@link Build.VERSION_CODES.VANILLA_ICE_CREAM}, this will
730      *             throw an UnsupportedOperationException.
731      *
732      * {@hide}
733      */
734     @Deprecated
735     @SystemApi(client = MODULE_LIBRARIES)
736     public int untether(@NonNull final String iface) {
737         unsupportedAfterV();
738 
739         final String callerPkg = mContext.getOpPackageName();
740         Log.i(TAG, "untether caller:" + callerPkg);
741 
742         final RequestDispatcher dispatcher = new RequestDispatcher();
743 
744         return dispatcher.waitForResult((connector, listener) -> {
745             try {
746                 connector.untether(iface, callerPkg, getAttributionTag(), listener);
747             } catch (RemoteException e) {
748                 throw new IllegalStateException(e);
749             }
750         }, this);
751     }
752 
753     /**
754      * Attempt to both alter the mode of USB and Tethering of USB.
755      *
756      * @deprecated New clients should not use this API anymore. All clients should use
757      * #startTethering or #stopTethering which encapsulate proper entitlement logic. If the API is
758      * used and an entitlement check is needed, downstream USB tethering will be enabled but will
759      * not have any upstream.
760      *
761      * {@hide}
762      */
763     @Deprecated
764     @SystemApi(client = MODULE_LIBRARIES)
765     public int setUsbTethering(final boolean enable) {
766         final String callerPkg = mContext.getOpPackageName();
767         Log.i(TAG, "setUsbTethering caller:" + callerPkg);
768 
769         final RequestDispatcher dispatcher = new RequestDispatcher();
770 
771         return dispatcher.waitForResult((connector, listener) -> {
772             try {
773                 connector.setUsbTethering(enable, callerPkg, getAttributionTag(),
774                         listener);
775             } catch (RemoteException e) {
776                 throw new IllegalStateException(e);
777             }
778         }, this);
779     }
780 
781     /**
782      * Indicates that this tethering connection will provide connectivity beyond this device (e.g.,
783      * global Internet access).
784      */
785     @SuppressLint("UnflaggedApi")
786     public static final int CONNECTIVITY_SCOPE_GLOBAL = 1;
787 
788     /**
789      * Indicates that this tethering connection will only provide local connectivity.
790      * @hide
791      */
792     @SystemApi
793     public static final int CONNECTIVITY_SCOPE_LOCAL = 2;
794 
795     /**
796      * Connectivity scopes for {@link TetheringRequest.Builder#setConnectivityScope}.
797      * @hide
798      */
799     @Retention(RetentionPolicy.SOURCE)
800     @IntDef(prefix = "CONNECTIVITY_SCOPE_", value = {
801             CONNECTIVITY_SCOPE_GLOBAL,
802             CONNECTIVITY_SCOPE_LOCAL,
803     })
804     public @interface ConnectivityScope {}
805 
806     private static String connectivityScopeToString(@ConnectivityScope int scope) {
807         switch (scope) {
808             case CONNECTIVITY_SCOPE_GLOBAL:
809                 return "CONNECTIVITY_SCOPE_GLOBAL";
810             case CONNECTIVITY_SCOPE_LOCAL:
811                 return "CONNECTIVITY_SCOPE_LOCAL";
812             default:
813                 return "CONNECTIVITY_SCOPE_UNKNOWN(" + scope + ")";
814         }
815     }
816 
817     /**
818      *  Use with {@link #startTethering} to specify additional parameters when starting tethering.
819      */
820     @SuppressLint("UnflaggedApi")
821     public static final class TetheringRequest implements Parcelable {
822         /**
823          * Tethering started by an explicit call to startTethering.
824          * @hide
825          */
826         public static final int REQUEST_TYPE_EXPLICIT = 0;
827 
828         /**
829          * Tethering implicitly started by broadcasts (LOHS and P2P). Can never be pending.
830          * @hide
831          */
832         public static final int REQUEST_TYPE_IMPLICIT = 1;
833 
834         /**
835          * Tethering started by the legacy tether() call. Can only happen on V-.
836          * @hide
837          */
838         public static final int REQUEST_TYPE_LEGACY = 2;
839 
840         /**
841          * Tethering started but there was no pending request found. This may happen if Tethering is
842          * started and immediately stopped before the link layer goes up, or if we get a link layer
843          * event without a prior call to startTethering (e.g. adb shell cmd wifi start-softap).
844          * @hide
845          */
846         public static final int REQUEST_TYPE_PLACEHOLDER = 3;
847 
848         /**
849          * Type of request, used to keep track of whether the request was explicitly sent by
850          * startTethering, implicitly created by broadcasts, or via legacy tether().
851          * @hide
852          */
853         @Retention(RetentionPolicy.SOURCE)
854         @IntDef(prefix = "TYPE_", value = {
855                 REQUEST_TYPE_EXPLICIT,
856                 REQUEST_TYPE_IMPLICIT,
857                 REQUEST_TYPE_LEGACY,
858                 REQUEST_TYPE_PLACEHOLDER,
859         })
860         public @interface RequestType {}
861 
862         /** A configuration set for TetheringRequest. */
863         private final TetheringRequestParcel mRequestParcel;
864 
865         /**
866          * @hide
867          */
868         @FlaggedApi(Flags.FLAG_TETHERING_WITH_SOFT_AP_CONFIG)
869         public TetheringRequest(@NonNull final TetheringRequestParcel request) {
870             mRequestParcel = request;
871         }
872 
873         private TetheringRequest(@NonNull Parcel in) {
874             mRequestParcel = in.readParcelable(TetheringRequestParcel.class.getClassLoader());
875         }
876 
877         @FlaggedApi(Flags.FLAG_TETHERING_WITH_SOFT_AP_CONFIG)
878         @NonNull
879         public static final Creator<TetheringRequest> CREATOR = new Creator<>() {
880             @Override
881             public TetheringRequest createFromParcel(@NonNull Parcel in) {
882                 return new TetheringRequest(in);
883             }
884 
885             @Override
886             public TetheringRequest[] newArray(int size) {
887                 return new TetheringRequest[size];
888             }
889         };
890 
891         @FlaggedApi(Flags.FLAG_TETHERING_WITH_SOFT_AP_CONFIG)
892         @Override
893         public int describeContents() {
894             return 0;
895         }
896 
897         @FlaggedApi(Flags.FLAG_TETHERING_WITH_SOFT_AP_CONFIG)
898         @Override
899         public void writeToParcel(@NonNull Parcel dest, int flags) {
900             dest.writeParcelable(mRequestParcel, flags);
901         }
902 
903         /** Builder used to create TetheringRequest. */
904         @SuppressLint({"UnflaggedApi", "StaticFinalBuilder"})
905         public static class Builder {
906             private final TetheringRequestParcel mBuilderParcel;
907 
908             /** Default constructor of Builder. */
909             @SuppressLint("UnflaggedApi")
910             public Builder(@TetheringType final int type) {
911                 mBuilderParcel = new TetheringRequestParcel();
912                 mBuilderParcel.tetheringType = type;
913                 mBuilderParcel.localIPv4Address = null;
914                 mBuilderParcel.staticClientAddress = null;
915                 mBuilderParcel.exemptFromEntitlementCheck = false;
916                 mBuilderParcel.showProvisioningUi = true;
917                 mBuilderParcel.connectivityScope = getDefaultConnectivityScope(type);
918                 mBuilderParcel.uid = Process.INVALID_UID;
919                 mBuilderParcel.softApConfig = null;
920                 mBuilderParcel.interfaceName = null;
921                 mBuilderParcel.requestType = REQUEST_TYPE_EXPLICIT;
922             }
923 
924             /**
925              * Configure tethering with static IPv4 assignment.
926              *
927              * A DHCP server will be started, but will only be able to offer the client address.
928              * The two addresses must be in the same prefix.
929              *
930              * @param localIPv4Address The preferred local IPv4 link address to use.
931              * @param clientAddress The static client address.
932              * @hide
933              */
934             @SystemApi
935             @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
936             @NonNull
937             public Builder setStaticIpv4Addresses(@NonNull final LinkAddress localIPv4Address,
938                     @NonNull final LinkAddress clientAddress) {
939                 Objects.requireNonNull(localIPv4Address);
940                 Objects.requireNonNull(clientAddress);
941                 if (!checkStaticAddressConfiguration(localIPv4Address, clientAddress)) {
942                     throw new IllegalArgumentException("Invalid server or client addresses");
943                 }
944 
945                 mBuilderParcel.localIPv4Address = localIPv4Address;
946                 mBuilderParcel.staticClientAddress = clientAddress;
947                 return this;
948             }
949 
950             /**
951              * Start tethering without entitlement checks.
952              * @hide
953              */
954             @SystemApi
955             @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
956             @NonNull
957             public Builder setExemptFromEntitlementCheck(boolean exempt) {
958                 mBuilderParcel.exemptFromEntitlementCheck = exempt;
959                 return this;
960             }
961 
962             /**
963              * If an entitlement check is needed, sets whether to show the entitlement UI or to
964              * perform a silent entitlement check. By default, the entitlement UI is shown.
965              * @hide
966              */
967             @SystemApi
968             @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
969             @NonNull
970             public Builder setShouldShowEntitlementUi(boolean showUi) {
971                 mBuilderParcel.showProvisioningUi = showUi;
972                 return this;
973             }
974 
975             /**
976              * Sets the name of the interface. Currently supported only for
977              * - {@link #TETHERING_VIRTUAL}.
978              * - {@link #TETHERING_WIFI} (for Local-only Hotspot)
979              * - {@link #TETHERING_WIFI_P2P}
980              * @hide
981              */
982             @FlaggedApi(Flags.FLAG_TETHERING_WITH_SOFT_AP_CONFIG)
983             @RequiresPermission(anyOf = {
984                     android.Manifest.permission.NETWORK_SETTINGS,
985                     android.Manifest.permission.NETWORK_STACK,
986                     NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
987             })
988             @NonNull
989             @SystemApi(client = MODULE_LIBRARIES)
990             public Builder setInterfaceName(@Nullable final String interfaceName) {
991                 switch (mBuilderParcel.tetheringType) {
992                     case TETHERING_VIRTUAL:
993                     case TETHERING_WIFI_P2P:
994                     case TETHERING_WIFI:
995                         break;
996                     default:
997                         throw new IllegalArgumentException("Interface name cannot be set for"
998                                 + " tethering type " + interfaceName);
999                 }
1000                 mBuilderParcel.interfaceName = interfaceName;
1001                 return this;
1002             }
1003 
1004             /**
1005              * Sets the connectivity scope to be provided by this tethering downstream.
1006              * @hide
1007              */
1008             @SystemApi
1009             @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
1010             @NonNull
1011             public Builder setConnectivityScope(@ConnectivityScope int scope) {
1012                 if (!checkConnectivityScope(mBuilderParcel.tetheringType, scope)) {
1013                     throw new IllegalArgumentException("Invalid connectivity scope " + scope);
1014                 }
1015 
1016                 mBuilderParcel.connectivityScope = scope;
1017                 return this;
1018             }
1019 
1020             /**
1021              * Set the desired SoftApConfiguration for {@link #TETHERING_WIFI}. If this is null or
1022              * not set, then the persistent tethering SoftApConfiguration from
1023              * {@link WifiManager#getSoftApConfiguration()} will be used.
1024              * </p>
1025              * If TETHERING_WIFI is already enabled and a new request is made with a different
1026              * SoftApConfiguration, the request will be accepted if the device can support an
1027              * additional tethering Wi-Fi AP interface. Otherwise, the request will be rejected.
1028              * </p>
1029              * Non-system callers using TETHERING_WIFI must specify a SoftApConfiguration.
1030              *
1031              * @param softApConfig SoftApConfiguration to use.
1032              * @throws IllegalArgumentException if the tethering type isn't TETHERING_WIFI.
1033              */
1034             @FlaggedApi(Flags.FLAG_TETHERING_WITH_SOFT_AP_CONFIG)
1035             @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
1036             @NonNull
1037             public Builder setSoftApConfiguration(@Nullable SoftApConfiguration softApConfig) {
1038                 if (mBuilderParcel.tetheringType != TETHERING_WIFI) {
1039                     throw new IllegalArgumentException(
1040                             "SoftApConfiguration can only be set for TETHERING_WIFI");
1041                 }
1042                 mBuilderParcel.softApConfig = softApConfig;
1043                 return this;
1044             }
1045 
1046             /** Build {@link TetheringRequest} with the currently set configuration. */
1047             @NonNull
1048             @SuppressLint("UnflaggedApi")
1049             public TetheringRequest build() {
1050                 return new TetheringRequest(mBuilderParcel);
1051             }
1052         }
1053 
1054         /**
1055          * Get the local IPv4 address, if one was configured with
1056          * {@link Builder#setStaticIpv4Addresses}.
1057          * @hide
1058          */
1059         @SystemApi
1060         @Nullable
1061         public LinkAddress getLocalIpv4Address() {
1062             return mRequestParcel.localIPv4Address;
1063         }
1064 
1065         /**
1066          * Get the static IPv4 address of the client, if one was configured with
1067          * {@link Builder#setStaticIpv4Addresses}.
1068          * @hide
1069          */
1070         @SystemApi
1071         @Nullable
1072         public LinkAddress getClientStaticIpv4Address() {
1073             return mRequestParcel.staticClientAddress;
1074         }
1075 
1076         /**
1077          * Get tethering type.
1078          * @hide
1079          */
1080         @SystemApi
1081         @TetheringType
1082         public int getTetheringType() {
1083             return mRequestParcel.tetheringType;
1084         }
1085 
1086         /**
1087          * Get connectivity type
1088          * @hide
1089          */
1090         @SystemApi
1091         @ConnectivityScope
1092         public int getConnectivityScope() {
1093             return mRequestParcel.connectivityScope;
1094         }
1095 
1096         /**
1097          * Check if exempt from entitlement check.
1098          * @hide
1099          */
1100         @SystemApi
1101         public boolean isExemptFromEntitlementCheck() {
1102             return mRequestParcel.exemptFromEntitlementCheck;
1103         }
1104 
1105         /**
1106          * Check if show entitlement ui.
1107          * @hide
1108          */
1109         @SystemApi
1110         public boolean getShouldShowEntitlementUi() {
1111             return mRequestParcel.showProvisioningUi;
1112         }
1113 
1114         /**
1115          * Get interface name.
1116          * @hide
1117          */
1118         @FlaggedApi(Flags.FLAG_TETHERING_WITH_SOFT_AP_CONFIG)
1119         @Nullable
1120         @SystemApi(client = MODULE_LIBRARIES)
1121         public String getInterfaceName() {
1122             return mRequestParcel.interfaceName;
1123         }
1124 
1125         /**
1126          * Check whether the two addresses are ipv4 and in the same prefix.
1127          * @hide
1128          */
1129         public static boolean checkStaticAddressConfiguration(
1130                 @NonNull final LinkAddress localIPv4Address,
1131                 @NonNull final LinkAddress clientAddress) {
1132             return localIPv4Address.getPrefixLength() == clientAddress.getPrefixLength()
1133                     && localIPv4Address.isIpv4() && clientAddress.isIpv4()
1134                     && new IpPrefix(localIPv4Address.toString()).equals(
1135                     new IpPrefix(clientAddress.toString()));
1136         }
1137 
1138         /**
1139          * Returns the default connectivity scope for the given tethering type. Usually this is
1140          * CONNECTIVITY_SCOPE_GLOBAL, except for NCM which for historical reasons defaults to local.
1141          * @hide
1142          */
1143         public static @ConnectivityScope int getDefaultConnectivityScope(int tetheringType) {
1144             return tetheringType != TETHERING_NCM
1145                     ? CONNECTIVITY_SCOPE_GLOBAL
1146                     : CONNECTIVITY_SCOPE_LOCAL;
1147         }
1148 
1149         /**
1150          * Checks whether the requested connectivity scope is allowed.
1151          * @hide
1152          */
1153         private static boolean checkConnectivityScope(int type, int scope) {
1154             if (scope == CONNECTIVITY_SCOPE_GLOBAL) return true;
1155             return type == TETHERING_USB || type == TETHERING_ETHERNET || type == TETHERING_NCM;
1156         }
1157 
1158         /**
1159          * Get the desired SoftApConfiguration of the request, if one was specified.
1160          */
1161         @FlaggedApi(Flags.FLAG_TETHERING_WITH_SOFT_AP_CONFIG)
1162         @Nullable
1163         public SoftApConfiguration getSoftApConfiguration() {
1164             return mRequestParcel.softApConfig;
1165         }
1166 
1167         /**
1168          * Sets the UID of the app that sent this request. This should always be overridden when
1169          * receiving TetheringRequest from an external source.
1170          * @hide
1171          */
1172         public void setUid(int uid) {
1173             mRequestParcel.uid = uid;
1174         }
1175 
1176         /**
1177          * Sets the package name of the app that sent this request. This should always be overridden
1178          * when receiving a TetheringRequest from an external source.
1179          * @hide
1180          */
1181         public void setPackageName(String packageName) {
1182             mRequestParcel.packageName = packageName;
1183         }
1184 
1185         /**
1186          * Gets the UID of the app that sent this request. This defaults to
1187          * {@link Process#INVALID_UID} if unset.
1188          * @hide
1189          */
1190         @FlaggedApi(Flags.FLAG_TETHERING_WITH_SOFT_AP_CONFIG)
1191         @SystemApi(client = MODULE_LIBRARIES)
1192         public int getUid() {
1193             return mRequestParcel.uid;
1194         }
1195 
1196         /**
1197          * Gets the package name of the app that sent this request. This defaults to {@code null} if
1198          * unset.
1199          * @hide
1200          */
1201         @FlaggedApi(Flags.FLAG_TETHERING_WITH_SOFT_AP_CONFIG)
1202         @SystemApi(client = MODULE_LIBRARIES)
1203         @Nullable
1204         public String getPackageName() {
1205             return mRequestParcel.packageName;
1206         }
1207 
1208         /**
1209          * Get a TetheringRequestParcel from the configuration
1210          * @hide
1211          */
1212         public TetheringRequestParcel getParcel() {
1213             return mRequestParcel;
1214         }
1215 
1216         /**
1217          * Get the type of the request.
1218          * @hide
1219          */
1220         public @RequestType int getRequestType() {
1221             return mRequestParcel.requestType;
1222         }
1223 
1224         /**
1225          * String of TetheringRequest detail.
1226          * @hide
1227          */
1228         @SystemApi
1229         public String toString() {
1230             StringJoiner sj = new StringJoiner(", ", "TetheringRequest[ ", " ]");
1231             sj.add(typeToString(mRequestParcel.tetheringType));
1232             if (mRequestParcel.requestType == REQUEST_TYPE_IMPLICIT) {
1233                 sj.add("IMPLICIT");
1234             } else if (mRequestParcel.requestType == REQUEST_TYPE_LEGACY) {
1235                 sj.add("LEGACY");
1236             } else if (mRequestParcel.requestType == REQUEST_TYPE_PLACEHOLDER) {
1237                 sj.add("PLACEHOLDER");
1238             }
1239             if (mRequestParcel.localIPv4Address != null) {
1240                 sj.add("localIpv4Address=" + mRequestParcel.localIPv4Address);
1241             }
1242             if (mRequestParcel.staticClientAddress != null) {
1243                 sj.add("staticClientAddress=" + mRequestParcel.staticClientAddress);
1244             }
1245             if (mRequestParcel.exemptFromEntitlementCheck) {
1246                 sj.add("exemptFromEntitlementCheck");
1247             }
1248             if (mRequestParcel.showProvisioningUi) {
1249                 sj.add("showProvisioningUi");
1250             }
1251             sj.add(connectivityScopeToString(mRequestParcel.connectivityScope));
1252             if (mRequestParcel.softApConfig != null) {
1253                 sj.add("softApConfig=" + mRequestParcel.softApConfig);
1254             }
1255             if (mRequestParcel.uid != Process.INVALID_UID) {
1256                 sj.add("uid=" + mRequestParcel.uid);
1257             }
1258             if (mRequestParcel.packageName != null) {
1259                 sj.add("packageName=" + mRequestParcel.packageName);
1260             }
1261             if (mRequestParcel.interfaceName != null) {
1262                 sj.add("interfaceName=" + mRequestParcel.interfaceName);
1263             }
1264             return sj.toString();
1265         }
1266 
1267         @SuppressLint("UnflaggedApi")
1268         private static boolean supportsInterfaceName(int tetheringType) {
1269             // TODO: Check the interface name for TETHERING_WIFI and TETHERING_WIFI_P2P once
1270             //       they're actually used.
1271             // Suppress lint for TETHERING_VIRTUAL since this method is only used internally.
1272             return tetheringType == TETHERING_VIRTUAL;
1273         }
1274 
1275         private static boolean supportsConcurrentConnectivityScopes(int tetheringType) {
1276             // Currently, only WIFI supports simultaneous local and global connectivity.
1277             // This can't happen for REQUEST_TYPE_EXPLICIT requests, because
1278             // TetheringRequest.Builder will not allow building an explicit TetheringRequest
1279             // with TETHERING_WIFI and CONNECTIVITY_SCOPE_LOCAL, but when local-only hotspot
1280             // is running, there is a REQUEST_TYPE_IMPLICIT request in the serving request list.
1281             return tetheringType == TETHERING_WIFI;
1282         }
1283 
1284         /**
1285          * Returns true if the other TetheringRequest "fuzzy" matches this one. This is used
1286          * internally to match tracked requests with external requests from API calls, and to reject
1287          * additional requests that the link layer has no capacity for.
1288          * @hide
1289          */
1290         public boolean fuzzyMatches(final TetheringRequest other) {
1291             if (other == null) return false;
1292             final int type = getTetheringType();
1293             if (type != other.getTetheringType()) return false;
1294             if (supportsInterfaceName(type)
1295                     && !TextUtils.equals(getInterfaceName(), other.getInterfaceName())) {
1296                 return false;
1297             }
1298             if (supportsConcurrentConnectivityScopes(type)
1299                     && getConnectivityScope() != other.getConnectivityScope()) {
1300                 return false;
1301             }
1302             return true;
1303         }
1304 
1305         /**
1306          * @hide
1307          */
1308         @SystemApi
1309         @Override
1310         public boolean equals(Object obj) {
1311             if (this == obj) return true;
1312             if (!(obj instanceof TetheringRequest otherRequest)) return false;
1313             if (!equalsIgnoreUidPackage(otherRequest)) return false;
1314             TetheringRequestParcel parcel = getParcel();
1315             TetheringRequestParcel otherParcel = otherRequest.getParcel();
1316             return parcel.uid == otherParcel.uid
1317                     && Objects.equals(parcel.packageName, otherParcel.packageName);
1318         }
1319 
1320         /**
1321          * @hide
1322          */
1323         public boolean equalsIgnoreUidPackage(TetheringRequest otherRequest) {
1324             TetheringRequestParcel parcel = getParcel();
1325             TetheringRequestParcel otherParcel = otherRequest.getParcel();
1326             // Note: Changes here should also be reflected in fuzzyMatches(TetheringRequest) when
1327             //       appropriate.
1328             return parcel.requestType == otherParcel.requestType
1329                     && parcel.tetheringType == otherParcel.tetheringType
1330                     && Objects.equals(parcel.localIPv4Address, otherParcel.localIPv4Address)
1331                     && Objects.equals(parcel.staticClientAddress, otherParcel.staticClientAddress)
1332                     && parcel.exemptFromEntitlementCheck == otherParcel.exemptFromEntitlementCheck
1333                     && parcel.showProvisioningUi == otherParcel.showProvisioningUi
1334                     && parcel.connectivityScope == otherParcel.connectivityScope
1335                     && Objects.equals(parcel.softApConfig, otherParcel.softApConfig)
1336                     && Objects.equals(parcel.interfaceName, otherParcel.interfaceName);
1337         }
1338 
1339         /**
1340          * @hide
1341          */
1342         @SystemApi
1343         @Override
1344         public int hashCode() {
1345             TetheringRequestParcel parcel = getParcel();
1346             return Objects.hash(parcel.tetheringType, parcel.localIPv4Address,
1347                     parcel.staticClientAddress, parcel.exemptFromEntitlementCheck,
1348                     parcel.showProvisioningUi, parcel.connectivityScope, parcel.softApConfig,
1349                     parcel.uid, parcel.packageName, parcel.interfaceName);
1350         }
1351     }
1352 
1353     /**
1354      * Callback for use with {@link #startTethering} to find out whether tethering succeeded.
1355      */
1356     @SuppressLint("UnflaggedApi")
1357     public interface StartTetheringCallback {
1358         /**
1359          * Called when tethering has been successfully started.
1360          */
1361         @SuppressLint("UnflaggedApi")
1362         default void onTetheringStarted() {}
1363 
1364         /**
1365          * Called when starting tethering failed.
1366          *
1367          * @param error The error that caused the failure.
1368          */
1369         @SuppressLint("UnflaggedApi")
1370         default void onTetheringFailed(@StartTetheringError final int error) {}
1371     }
1372 
1373     /**
1374      * Callback for use with {@link #stopTethering} to find out whether stop tethering succeeded.
1375      */
1376     @FlaggedApi(Flags.FLAG_TETHERING_WITH_SOFT_AP_CONFIG)
1377     public interface StopTetheringCallback {
1378         /**
1379          * Called when tethering has been successfully stopped.
1380          */
1381         default void onStopTetheringSucceeded() {}
1382 
1383         /**
1384          * Called when starting tethering failed.
1385          *
1386          * @param error The error that caused the failure.
1387          */
1388         default void onStopTetheringFailed(@StopTetheringError final int error) {}
1389     }
1390 
1391     /**
1392      * Starts tethering and runs tether provisioning for the given type if needed. If provisioning
1393      * fails, stopTethering will be called automatically.
1394      *
1395      * @param request a {@link TetheringRequest} which can specify the preferred configuration.
1396      * @param executor {@link Executor} to specify the thread upon which the callback of
1397      *         TetheringRequest will be invoked.
1398      * @param callback A callback that will be called to indicate the success status of the
1399      *                 tethering start request.
1400      */
1401     @RequiresPermission(value = android.Manifest.permission.TETHER_PRIVILEGED, conditional = true)
1402     @SuppressLint("UnflaggedApi")
1403     public void startTethering(@NonNull final TetheringRequest request,
1404             @NonNull final Executor executor, @NonNull final StartTetheringCallback callback) {
1405         final String callerPkg = mContext.getOpPackageName();
1406         Log.i(TAG, "startTethering caller:" + callerPkg);
1407 
1408         final IIntResultListener listener = new IIntResultListener.Stub() {
1409             @Override
1410             public void onResult(final int resultCode) {
1411                 executor.execute(() -> {
1412                     if (resultCode == TETHER_ERROR_NO_ERROR) {
1413                         callback.onTetheringStarted();
1414                     } else {
1415                         callback.onTetheringFailed(resultCode);
1416                     }
1417                 });
1418             }
1419         };
1420         getConnector(c -> c.startTethering(request.getParcel(), callerPkg,
1421                 getAttributionTag(), listener));
1422     }
1423 
1424     /**
1425      * Starts tethering and runs tether provisioning for the given type if needed. If provisioning
1426      * fails, stopTethering will be called automatically.
1427      *
1428      * @param type The tethering type, on of the {@code TetheringManager#TETHERING_*} constants.
1429      * @param executor {@link Executor} to specify the thread upon which the callback of
1430      *         TetheringRequest will be invoked.
1431      * @hide
1432      */
1433     @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
1434     @SystemApi(client = MODULE_LIBRARIES)
1435     public void startTethering(int type, @NonNull final Executor executor,
1436             @NonNull final StartTetheringCallback callback) {
1437         startTethering(new TetheringRequest.Builder(type).build(), executor, callback);
1438     }
1439 
1440     /**
1441      * Stops tethering for the given type. Also cancels any provisioning rechecks for that type if
1442      * applicable.
1443      *
1444      * @hide
1445      */
1446     @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
1447     @SystemApi
1448     public void stopTethering(@TetheringType final int type) {
1449         final String callerPkg = mContext.getOpPackageName();
1450         Log.i(TAG, "stopTethering caller:" + callerPkg);
1451 
1452         getConnector(c -> c.stopTethering(type, callerPkg, getAttributionTag(),
1453                 new IIntResultListener.Stub() {
1454             @Override
1455             public void onResult(int resultCode) {
1456                 // TODO: provide an API to obtain result
1457                 // This has never been possible as stopTethering has always been void and never
1458                 // taken a callback object. The only indication that callers have is if the call
1459                 // results in a TETHER_STATE_CHANGE broadcast.
1460             }
1461         }));
1462     }
1463 
1464     /**
1465      * Stops tethering for the given request. Operation will fail with
1466      * {@link #TETHER_ERROR_UNKNOWN_REQUEST} if there is no request that matches it.
1467      */
1468     @RequiresPermission(value = android.Manifest.permission.TETHER_PRIVILEGED, conditional = true)
1469     @FlaggedApi(Flags.FLAG_TETHERING_WITH_SOFT_AP_CONFIG)
1470     public void stopTethering(@NonNull TetheringRequest request,
1471             @NonNull final Executor executor, @NonNull final StopTetheringCallback callback) {
1472         Objects.requireNonNull(request);
1473         Objects.requireNonNull(executor);
1474         Objects.requireNonNull(callback);
1475 
1476         final String callerPkg = mContext.getOpPackageName();
1477         Log.i(TAG, "stopTethering: request=" + request + ", caller=" + callerPkg);
1478         getConnector(c -> c.stopTetheringRequest(request, callerPkg, getAttributionTag(),
1479                 new IIntResultListener.Stub() {
1480                     @Override
1481                     public void onResult(final int resultCode) {
1482                         executor.execute(() -> {
1483                             if (resultCode == TETHER_ERROR_NO_ERROR) {
1484                                 callback.onStopTetheringSucceeded();
1485                             } else {
1486                                 callback.onStopTetheringFailed(resultCode);
1487                             }
1488                         });
1489                     }
1490                 }));
1491     }
1492 
1493     /**
1494      * Callback for use with {@link #getLatestTetheringEntitlementResult} to find out whether
1495      * entitlement succeeded.
1496      * @hide
1497      */
1498     @SystemApi
1499     public interface OnTetheringEntitlementResultListener  {
1500         /**
1501          * Called to notify entitlement result.
1502          *
1503          * @param resultCode an int value of entitlement result. It may be one of
1504          *         {@link #TETHER_ERROR_NO_ERROR},
1505          *         {@link #TETHER_ERROR_PROVISIONING_FAILED}, or
1506          *         {@link #TETHER_ERROR_ENTITLEMENT_UNKNOWN}.
1507          */
1508         void onTetheringEntitlementResult(@EntitlementResult int result);
1509     }
1510 
1511     /**
1512      * Request the latest value of the tethering entitlement check.
1513      *
1514      * <p>This method will only return the latest entitlement result if it is available. If no
1515      * cached entitlement result is available, and {@code showEntitlementUi} is false,
1516      * {@link #TETHER_ERROR_ENTITLEMENT_UNKNOWN} will be returned. If {@code showEntitlementUi} is
1517      * true, entitlement will be run.
1518      *
1519      * @param type the downstream type of tethering. Must be one of {@code #TETHERING_*} constants.
1520      * @param showEntitlementUi a boolean indicating whether to check result for the UI-based
1521      *         entitlement check or the silent entitlement check.
1522      * @param executor the executor on which callback will be invoked.
1523      * @param listener an {@link OnTetheringEntitlementResultListener} which will be called to
1524      *         notify the caller of the result of entitlement check. The listener may be called zero
1525      *         or one time.
1526      * @hide
1527      */
1528     @SystemApi
1529     @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
1530     public void requestLatestTetheringEntitlementResult(@TetheringType int type,
1531             boolean showEntitlementUi,
1532             @NonNull Executor executor,
1533             @NonNull final OnTetheringEntitlementResultListener listener) {
1534         if (listener == null) {
1535             throw new IllegalArgumentException(
1536                     "OnTetheringEntitlementResultListener cannot be null.");
1537         }
1538 
1539         ResultReceiver wrappedListener = new ResultReceiver(null /* handler */) {
1540             @Override
1541             protected void onReceiveResult(int resultCode, Bundle resultData) {
1542                 executor.execute(() -> {
1543                     listener.onTetheringEntitlementResult(resultCode);
1544                 });
1545             }
1546         };
1547 
1548         requestLatestTetheringEntitlementResult(type, wrappedListener,
1549                     showEntitlementUi);
1550     }
1551 
1552     /**
1553      * Helper function of #requestLatestTetheringEntitlementResult to remain backwards compatible
1554      * with ConnectivityManager#getLatestTetheringEntitlementResult
1555      *
1556      * {@hide}
1557      */
1558     // TODO: improve the usage of ResultReceiver, b/145096122
1559     @SystemApi(client = MODULE_LIBRARIES)
1560     public void requestLatestTetheringEntitlementResult(@TetheringType final int type,
1561             @NonNull final ResultReceiver receiver, final boolean showEntitlementUi) {
1562         final String callerPkg = mContext.getOpPackageName();
1563         Log.i(TAG, "getLatestTetheringEntitlementResult caller:" + callerPkg);
1564 
1565         getConnector(c -> c.requestLatestTetheringEntitlementResult(
1566                 type, receiver, showEntitlementUi, callerPkg, getAttributionTag()));
1567     }
1568 
1569     /**
1570      * Callback for use with {@link registerTetheringEventCallback} to find out tethering
1571      * upstream status.
1572      */
1573     @SuppressLint("UnflaggedApi")
1574     public interface TetheringEventCallback {
1575         /**
1576          * Called when tethering supported status changed.
1577          *
1578          * <p>This callback will be called immediately after the callback is
1579          * registered, and never be called if there is changes afterward.
1580          *
1581          * <p>Tethering may be disabled via system properties, device configuration, or device
1582          * policy restrictions.
1583          *
1584          * @param supported whether any tethering type is supported.
1585          * @hide
1586          */
1587         @SystemApi
1588         default void onTetheringSupported(boolean supported) {}
1589 
1590         /**
1591          * Called when tethering supported status changed.
1592          *
1593          * <p>This will be called immediately after the callback is registered, and may be called
1594          * multiple times later upon changes.
1595          *
1596          * <p>Tethering may be disabled via system properties, device configuration, or device
1597          * policy restrictions.
1598          *
1599          * @param supportedTypes a set of @TetheringType which is supported.
1600          * @hide
1601          */
1602         default void onSupportedTetheringTypes(@NonNull Set<Integer> supportedTypes) {}
1603 
1604         /**
1605          * Called when tethering upstream changed.
1606          *
1607          * <p>This will be called immediately after the callback is registered, and may be called
1608          * multiple times later upon changes.
1609          *
1610          * @param network the {@link Network} of tethering upstream. Null means tethering doesn't
1611          * have any upstream.
1612          * @hide
1613          */
1614         @SystemApi
1615         default void onUpstreamChanged(@Nullable Network network) {}
1616 
1617         /**
1618          * Called when there was a change in tethering interface regular expressions.
1619          *
1620          * <p>This will be called immediately after the callback is registered, and may be called
1621          * multiple times later upon changes.
1622          * @param reg The new regular expressions.
1623          *
1624          * @deprecated New clients should use the callbacks with {@link TetheringInterface} which
1625          * has the mapping between tethering type and interface. InterfaceRegex is no longer needed
1626          * to determine the mapping of tethering type and interface.
1627          *
1628          * @hide
1629          */
1630         @Deprecated
1631         @SystemApi(client = MODULE_LIBRARIES)
1632         default void onTetherableInterfaceRegexpsChanged(@NonNull TetheringInterfaceRegexps reg) {}
1633 
1634         /**
1635          * Called when there was a change in the list of tetherable interfaces. Tetherable
1636          * interface means this interface is available and can be used for tethering.
1637          *
1638          * <p>This will be called immediately after the callback is registered, and may be called
1639          * multiple times later upon changes.
1640          * @param interfaces The list of tetherable interface names.
1641          * @hide
1642          */
1643         @SystemApi
1644         default void onTetherableInterfacesChanged(@NonNull List<String> interfaces) {}
1645 
1646         /**
1647          * Called when there was a change in the list of tetherable interfaces. Tetherable
1648          * interface means this interface is available and can be used for tethering.
1649          *
1650          * <p>This will be called immediately after the callback is registered, and may be called
1651          * multiple times later upon changes.
1652          * @param interfaces The set of TetheringInterface of currently tetherable interface.
1653          * @hide
1654          */
1655         @SystemApi
1656         default void onTetherableInterfacesChanged(@NonNull Set<TetheringInterface> interfaces) {
1657             // By default, the new callback calls the old callback, so apps
1658             // implementing the old callback just work.
1659             onTetherableInterfacesChanged(toIfaces(interfaces));
1660         }
1661 
1662         /**
1663          * Called when there was a change in the list of tethered interfaces.
1664          *
1665          * <p>This will be called immediately after the callback is registered, and may be called
1666          * multiple times later upon changes.
1667          * @param interfaces The lit of 0 or more String of currently tethered interface names.
1668          * @hide
1669          */
1670         @SystemApi
1671         default void onTetheredInterfacesChanged(@NonNull List<String> interfaces) {}
1672 
1673         /**
1674          * Called when there was a change in the list of tethered interfaces.
1675          *
1676          * <p>This will be called immediately after the callback is registered, and may be called
1677          * multiple times later upon changes.
1678          * @param interfaces The set of 0 or more TetheringInterface of currently tethered
1679          * interface.
1680          */
1681         @SuppressLint("UnflaggedApi")
1682         default void onTetheredInterfacesChanged(@NonNull Set<TetheringInterface> interfaces) {
1683             // By default, the new callback calls the old callback, so apps
1684             // implementing the old callback just work.
1685             onTetheredInterfacesChanged(toIfaces(interfaces));
1686         }
1687 
1688         /**
1689          * Called when there was a change in the list of local-only interfaces.
1690          *
1691          * <p>This will be called immediately after the callback is registered, and may be called
1692          * multiple times later upon changes.
1693          * @param interfaces The list of 0 or more String of active local-only interface names.
1694          * @hide
1695          */
1696         @SystemApi
1697         default void onLocalOnlyInterfacesChanged(@NonNull List<String> interfaces) {}
1698 
1699         /**
1700          * Called when there was a change in the list of local-only interfaces.
1701          *
1702          * <p>This will be called immediately after the callback is registered, and may be called
1703          * multiple times later upon changes.
1704          * @param interfaces The set of 0 or more TetheringInterface of active local-only
1705          * interface.
1706          * @hide
1707          */
1708         @SystemApi
1709         default void onLocalOnlyInterfacesChanged(@NonNull Set<TetheringInterface> interfaces) {
1710             // By default, the new callback calls the old callback, so apps
1711             // implementing the old callback just work.
1712             onLocalOnlyInterfacesChanged(toIfaces(interfaces));
1713         }
1714 
1715         /**
1716          * Called when an error occurred configuring tethering.
1717          *
1718          * <p>This will be called immediately after the callback is registered if the latest status
1719          * on the interface is an error, and may be called multiple times later upon changes.
1720          * @param ifName Name of the interface.
1721          * @param error One of {@code TetheringManager#TETHER_ERROR_*}.
1722          * @hide
1723          */
1724         @SystemApi
1725         default void onError(@NonNull String ifName, @TetheringIfaceError int error) {}
1726 
1727         /**
1728          * Called when an error occurred configuring tethering.
1729          *
1730          * <p>This will be called immediately after the callback is registered if the latest status
1731          * on the interface is an error, and may be called multiple times later upon changes.
1732          * @param iface The interface that experienced the error.
1733          * @param error One of {@code TetheringManager#TETHER_ERROR_*}.
1734          * @hide
1735          */
1736         @SystemApi
1737         default void onError(@NonNull TetheringInterface iface, @TetheringIfaceError int error) {
1738             // By default, the new callback calls the old callback, so apps
1739             // implementing the old callback just work.
1740             onError(iface.getInterface(), error);
1741         }
1742 
1743         /**
1744          * Called when the list of tethered clients changes.
1745          *
1746          * <p>This callback provides best-effort information on connected clients based on state
1747          * known to the system, however the list cannot be completely accurate (and should not be
1748          * used for security purposes). For example, clients behind a bridge and using static IP
1749          * assignments are not visible to the tethering device; or even when using DHCP, such
1750          * clients may still be reported by this callback after disconnection as the system cannot
1751          * determine if they are still connected.
1752          * @param clients The new set of tethered clients; the collection is not ordered.
1753          * @hide
1754          */
1755         @SystemApi
1756         default void onClientsChanged(@NonNull Collection<TetheredClient> clients) {}
1757 
1758         /**
1759          * Called when tethering offload status changes.
1760          *
1761          * <p>This will be called immediately after the callback is registered.
1762          * @param status The offload status.
1763          * @hide
1764          */
1765         @SystemApi
1766         default void onOffloadStatusChanged(@TetherOffloadStatus int status) {}
1767     }
1768 
1769     /**
1770      * Covert DownStreamInterface collection to interface String array list. Internal use only.
1771      *
1772      * @hide
1773      */
1774     public static ArrayList<String> toIfaces(Collection<TetheringInterface> tetherIfaces) {
1775         final ArrayList<String> ifaces = new ArrayList<>();
1776         for (TetheringInterface tether : tetherIfaces) {
1777             ifaces.add(tether.getInterface());
1778         }
1779 
1780         return ifaces;
1781     }
1782 
1783     private static String[] toIfaces(TetheringInterface[] tetherIfaces) {
1784         final String[] ifaces = new String[tetherIfaces.length];
1785         for (int i = 0; i < tetherIfaces.length; i++) {
1786             ifaces[i] = tetherIfaces[i].getInterface();
1787         }
1788 
1789         return ifaces;
1790     }
1791 
1792 
1793     /**
1794      * Regular expressions used to identify tethering interfaces.
1795      *
1796      * @deprecated Instead of using regex to determine tethering type. New client could use the
1797      * callbacks with {@link TetheringInterface} which has the mapping of type and interface.
1798      * @hide
1799      */
1800     @Deprecated
1801     @SystemApi(client = MODULE_LIBRARIES)
1802     public static class TetheringInterfaceRegexps {
1803         private final String[] mTetherableBluetoothRegexs;
1804         private final String[] mTetherableUsbRegexs;
1805         private final String[] mTetherableWifiRegexs;
1806 
1807         /** @hide */
1808         public TetheringInterfaceRegexps(@NonNull String[] tetherableBluetoothRegexs,
1809                 @NonNull String[] tetherableUsbRegexs, @NonNull String[] tetherableWifiRegexs) {
1810             mTetherableBluetoothRegexs = tetherableBluetoothRegexs.clone();
1811             mTetherableUsbRegexs = tetherableUsbRegexs.clone();
1812             mTetherableWifiRegexs = tetherableWifiRegexs.clone();
1813         }
1814 
1815         @NonNull
1816         public List<String> getTetherableBluetoothRegexs() {
1817             return Collections.unmodifiableList(Arrays.asList(mTetherableBluetoothRegexs));
1818         }
1819 
1820         @NonNull
1821         public List<String> getTetherableUsbRegexs() {
1822             return Collections.unmodifiableList(Arrays.asList(mTetherableUsbRegexs));
1823         }
1824 
1825         @NonNull
1826         public List<String> getTetherableWifiRegexs() {
1827             return Collections.unmodifiableList(Arrays.asList(mTetherableWifiRegexs));
1828         }
1829 
1830         @Override
1831         public int hashCode() {
1832             return Objects.hash(
1833                     Arrays.hashCode(mTetherableBluetoothRegexs),
1834                     Arrays.hashCode(mTetherableUsbRegexs),
1835                     Arrays.hashCode(mTetherableWifiRegexs));
1836         }
1837 
1838         @Override
1839         public boolean equals(@Nullable Object obj) {
1840             if (!(obj instanceof TetheringInterfaceRegexps)) return false;
1841             final TetheringInterfaceRegexps other = (TetheringInterfaceRegexps) obj;
1842             return Arrays.equals(mTetherableBluetoothRegexs, other.mTetherableBluetoothRegexs)
1843                     && Arrays.equals(mTetherableUsbRegexs, other.mTetherableUsbRegexs)
1844                     && Arrays.equals(mTetherableWifiRegexs, other.mTetherableWifiRegexs);
1845         }
1846     }
1847 
1848     /**
1849      * Start listening to tethering change events. Any new added callback will receive the last
1850      * tethering status right away. If callback is registered,
1851      * {@link TetheringEventCallback#onUpstreamChanged} will immediately be called. If tethering
1852      * has no upstream or disabled, the argument of callback will be null. The same callback object
1853      * cannot be registered twice.
1854      *
1855      * @param executor the executor on which callback will be invoked.
1856      * @param callback the callback to be called when tethering has change events.
1857      */
1858     @RequiresPermission(Manifest.permission.ACCESS_NETWORK_STATE)
1859     @SuppressLint("UnflaggedApi")
1860     public void registerTetheringEventCallback(@NonNull Executor executor,
1861             @NonNull TetheringEventCallback callback) {
1862         Objects.requireNonNull(executor);
1863         Objects.requireNonNull(callback);
1864 
1865         final String callerPkg = mContext.getOpPackageName();
1866         Log.i(TAG, "registerTetheringEventCallback caller:" + callerPkg);
1867 
1868         synchronized (mTetheringEventCallbacks) {
1869             if (mTetheringEventCallbacks.containsKey(callback)) {
1870                 throw new IllegalArgumentException("callback was already registered.");
1871             }
1872             final ITetheringEventCallback remoteCallback = new ITetheringEventCallback.Stub() {
1873                 // Only accessed with a lock on this object
1874                 private final HashMap<TetheringInterface, Integer> mErrorStates = new HashMap<>();
1875                 private TetheringInterface[] mLastTetherableInterfaces = null;
1876                 private TetheringInterface[] mLastTetheredInterfaces = null;
1877                 private TetheringInterface[] mLastLocalOnlyInterfaces = null;
1878 
1879                 @Override
1880                 public void onUpstreamChanged(Network network) throws RemoteException {
1881                     executor.execute(() -> {
1882                         callback.onUpstreamChanged(network);
1883                     });
1884                 }
1885 
1886                 private synchronized void sendErrorCallbacks(final TetherStatesParcel newStates) {
1887                     for (int i = 0; i < newStates.erroredIfaceList.length; i++) {
1888                         final TetheringInterface tetherIface = newStates.erroredIfaceList[i];
1889                         final Integer lastError = mErrorStates.get(tetherIface);
1890                         final int newError = newStates.lastErrorList[i];
1891                         if (newError != TETHER_ERROR_NO_ERROR
1892                                 && !Objects.equals(lastError, newError)) {
1893                             callback.onError(tetherIface, newError);
1894                         }
1895                         mErrorStates.put(tetherIface, newError);
1896                     }
1897                 }
1898 
1899                 private synchronized void maybeSendTetherableIfacesChangedCallback(
1900                         final TetherStatesParcel newStates) {
1901                     if (Arrays.equals(mLastTetherableInterfaces, newStates.availableList)) return;
1902                     mLastTetherableInterfaces = newStates.availableList.clone();
1903                     callback.onTetherableInterfacesChanged(
1904                             Collections.unmodifiableSet((new ArraySet(mLastTetherableInterfaces))));
1905                 }
1906 
1907                 private synchronized void maybeSendTetheredIfacesChangedCallback(
1908                         final TetherStatesParcel newStates) {
1909                     if (Arrays.equals(mLastTetheredInterfaces, newStates.tetheredList)) return;
1910                     mLastTetheredInterfaces = newStates.tetheredList.clone();
1911                     callback.onTetheredInterfacesChanged(
1912                             Collections.unmodifiableSet((new ArraySet(mLastTetheredInterfaces))));
1913                 }
1914 
1915                 private synchronized void maybeSendLocalOnlyIfacesChangedCallback(
1916                         final TetherStatesParcel newStates) {
1917                     if (Arrays.equals(mLastLocalOnlyInterfaces, newStates.localOnlyList)) return;
1918                     mLastLocalOnlyInterfaces = newStates.localOnlyList.clone();
1919                     callback.onLocalOnlyInterfacesChanged(
1920                             Collections.unmodifiableSet((new ArraySet(mLastLocalOnlyInterfaces))));
1921                 }
1922 
1923                 // Called immediately after the callbacks are registered.
1924                 @Override
1925                 public void onCallbackStarted(TetheringCallbackStartedParcel parcel) {
1926                     executor.execute(() -> {
1927                         callback.onSupportedTetheringTypes(unpackBits(parcel.supportedTypes));
1928                         callback.onTetheringSupported(parcel.supportedTypes != 0);
1929                         callback.onUpstreamChanged(parcel.upstreamNetwork);
1930                         sendErrorCallbacks(parcel.states);
1931                         sendRegexpsChanged(parcel.config);
1932                         maybeSendTetherableIfacesChangedCallback(parcel.states);
1933                         maybeSendTetheredIfacesChangedCallback(parcel.states);
1934                         maybeSendLocalOnlyIfacesChangedCallback(parcel.states);
1935                         callback.onClientsChanged(parcel.tetheredClients);
1936                         callback.onOffloadStatusChanged(parcel.offloadStatus);
1937                     });
1938                 }
1939 
1940                 @Override
1941                 public void onCallbackStopped(int errorCode) {
1942                     executor.execute(() -> {
1943                         throwIfPermissionFailure(errorCode);
1944                     });
1945                 }
1946 
1947                 @Override
1948                 public void onSupportedTetheringTypes(long supportedBitmap) {
1949                     executor.execute(() -> {
1950                         callback.onSupportedTetheringTypes(unpackBits(supportedBitmap));
1951                     });
1952                 }
1953 
1954                 private void sendRegexpsChanged(TetheringConfigurationParcel parcel) {
1955                     callback.onTetherableInterfaceRegexpsChanged(new TetheringInterfaceRegexps(
1956                             parcel.tetherableBluetoothRegexs,
1957                             parcel.tetherableUsbRegexs,
1958                             parcel.tetherableWifiRegexs));
1959                 }
1960 
1961                 @Override
1962                 public void onConfigurationChanged(TetheringConfigurationParcel config) {
1963                     executor.execute(() -> sendRegexpsChanged(config));
1964                 }
1965 
1966                 @Override
1967                 public void onTetherStatesChanged(TetherStatesParcel states) {
1968                     executor.execute(() -> {
1969                         sendErrorCallbacks(states);
1970                         maybeSendTetherableIfacesChangedCallback(states);
1971                         maybeSendTetheredIfacesChangedCallback(states);
1972                         maybeSendLocalOnlyIfacesChangedCallback(states);
1973                     });
1974                 }
1975 
1976                 @Override
1977                 public void onTetherClientsChanged(final List<TetheredClient> clients) {
1978                     executor.execute(() -> callback.onClientsChanged(clients));
1979                 }
1980 
1981                 @Override
1982                 public void onOffloadStatusChanged(final int status) {
1983                     executor.execute(() -> callback.onOffloadStatusChanged(status));
1984                 }
1985             };
1986             getConnector(c -> c.registerTetheringEventCallback(remoteCallback, callerPkg));
1987             mTetheringEventCallbacks.put(callback, remoteCallback);
1988         }
1989     }
1990 
1991     /**
1992      * Unpack bitmap to a set of bit position intergers.
1993      * @hide
1994      */
1995     public static ArraySet<Integer> unpackBits(long val) {
1996         final ArraySet<Integer> result = new ArraySet<>(Long.bitCount(val));
1997         int bitPos = 0;
1998         while (val != 0) {
1999             if ((val & 1) == 1) result.add(bitPos);
2000 
2001             val = val >>> 1;
2002             bitPos++;
2003         }
2004 
2005         return result;
2006     }
2007 
2008     /**
2009      * Remove tethering event callback previously registered with
2010      * {@link #registerTetheringEventCallback}.
2011      *
2012      * @param callback previously registered callback.
2013      */
2014     @RequiresPermission(anyOf = {
2015             Manifest.permission.TETHER_PRIVILEGED,
2016             Manifest.permission.ACCESS_NETWORK_STATE
2017     })
2018     @SuppressLint("UnflaggedApi")
2019     public void unregisterTetheringEventCallback(@NonNull final TetheringEventCallback callback) {
2020         Objects.requireNonNull(callback);
2021 
2022         final String callerPkg = mContext.getOpPackageName();
2023         Log.i(TAG, "unregisterTetheringEventCallback caller:" + callerPkg);
2024 
2025         synchronized (mTetheringEventCallbacks) {
2026             ITetheringEventCallback remoteCallback = mTetheringEventCallbacks.remove(callback);
2027             if (remoteCallback == null) {
2028                 throw new IllegalArgumentException("callback was not registered.");
2029             }
2030 
2031             getConnector(c -> c.unregisterTetheringEventCallback(remoteCallback, callerPkg));
2032         }
2033     }
2034 
2035     /**
2036      * Get a more detailed error code after a Tethering or Untethering
2037      * request asynchronously failed.
2038      *
2039      * @param iface The name of the interface of interest
2040      * @return error The error code of the last error tethering or untethering the named
2041      *               interface
2042      * @hide
2043      */
2044     @SystemApi(client = MODULE_LIBRARIES)
2045     public int getLastTetherError(@NonNull final String iface) {
2046         mCallback.waitForStarted();
2047         if (mTetherStatesParcel == null) return TETHER_ERROR_NO_ERROR;
2048 
2049         int i = 0;
2050         for (TetheringInterface errored : mTetherStatesParcel.erroredIfaceList) {
2051             if (iface.equals(errored.getInterface())) return mTetherStatesParcel.lastErrorList[i];
2052 
2053             i++;
2054         }
2055         return TETHER_ERROR_NO_ERROR;
2056     }
2057 
2058     /**
2059      * Get the list of regular expressions that define any tetherable
2060      * USB network interfaces.  If USB tethering is not supported by the
2061      * device, this list should be empty.
2062      *
2063      * @return an array of 0 or more regular expression Strings defining
2064      *        what interfaces are considered tetherable usb interfaces.
2065      * @hide
2066      */
2067     @SystemApi(client = MODULE_LIBRARIES)
2068     public @NonNull String[] getTetherableUsbRegexs() {
2069         mCallback.waitForStarted();
2070         return mTetheringConfiguration.tetherableUsbRegexs;
2071     }
2072 
2073     /**
2074      * Get the list of regular expressions that define any tetherable
2075      * Wifi network interfaces.  If Wifi tethering is not supported by the
2076      * device, this list should be empty.
2077      *
2078      * @return an array of 0 or more regular expression Strings defining
2079      *        what interfaces are considered tetherable wifi interfaces.
2080      * @hide
2081      */
2082     @SystemApi(client = MODULE_LIBRARIES)
2083     public @NonNull String[] getTetherableWifiRegexs() {
2084         mCallback.waitForStarted();
2085         return mTetheringConfiguration.tetherableWifiRegexs;
2086     }
2087 
2088     /**
2089      * Get the list of regular expressions that define any tetherable
2090      * Bluetooth network interfaces.  If Bluetooth tethering is not supported by the
2091      * device, this list should be empty.
2092      *
2093      * @return an array of 0 or more regular expression Strings defining
2094      *        what interfaces are considered tetherable bluetooth interfaces.
2095      * @hide
2096      */
2097     @SystemApi(client = MODULE_LIBRARIES)
2098     public @NonNull String[] getTetherableBluetoothRegexs() {
2099         mCallback.waitForStarted();
2100         return mTetheringConfiguration.tetherableBluetoothRegexs;
2101     }
2102 
2103     /**
2104      * Get the set of tetherable, available interfaces.  This list is limited by
2105      * device configuration and current interface existence.
2106      *
2107      * @return an array of 0 or more Strings of tetherable interface names.
2108      * @hide
2109      */
2110     @SystemApi(client = MODULE_LIBRARIES)
2111     public @NonNull String[] getTetherableIfaces() {
2112         mCallback.waitForStarted();
2113         if (mTetherStatesParcel == null) return new String[0];
2114 
2115         return toIfaces(mTetherStatesParcel.availableList);
2116     }
2117 
2118     /**
2119      * Get the set of tethered interfaces.
2120      *
2121      * @return an array of 0 or more String of currently tethered interface names.
2122      * @hide
2123      */
2124     @SystemApi(client = MODULE_LIBRARIES)
2125     public @NonNull String[] getTetheredIfaces() {
2126         mCallback.waitForStarted();
2127         if (mTetherStatesParcel == null) return new String[0];
2128 
2129         return toIfaces(mTetherStatesParcel.tetheredList);
2130     }
2131 
2132     /**
2133      * Get the set of interface names which attempted to tether but
2134      * failed.  Re-attempting to tether may cause them to reset to the Tethered
2135      * state.  Alternatively, causing the interface to be destroyed and recreated
2136      * may cause them to reset to the available state.
2137      * {@link TetheringManager#getLastTetherError} can be used to get more
2138      * information on the cause of the errors.
2139      *
2140      * @return an array of 0 or more String indicating the interface names
2141      *        which failed to tether.
2142      * @hide
2143      */
2144     @SystemApi(client = MODULE_LIBRARIES)
2145     public @NonNull String[] getTetheringErroredIfaces() {
2146         mCallback.waitForStarted();
2147         if (mTetherStatesParcel == null) return new String[0];
2148 
2149         return toIfaces(mTetherStatesParcel.erroredIfaceList);
2150     }
2151 
2152     /**
2153      * Get the set of tethered dhcp ranges.
2154      *
2155      * @deprecated This API just return the default value which is not used in DhcpServer.
2156      * @hide
2157      */
2158     @Deprecated
2159     public @NonNull String[] getTetheredDhcpRanges() {
2160         mCallback.waitForStarted();
2161         return mTetheringConfiguration.legacyDhcpRanges;
2162     }
2163 
2164     /**
2165      * Check if the device allows for tethering.  It may be disabled via
2166      * {@code ro.tether.denied} system property, Settings.TETHER_SUPPORTED or
2167      * due to device configuration.
2168      *
2169      * @return a boolean - {@code true} indicating Tethering is supported.
2170      * @hide
2171      */
2172     @SystemApi(client = MODULE_LIBRARIES)
2173     public boolean isTetheringSupported() {
2174         final String callerPkg = mContext.getOpPackageName();
2175 
2176         return isTetheringSupported(callerPkg);
2177     }
2178 
2179     /**
2180      * Check if the device allows for tethering. It may be disabled via {@code ro.tether.denied}
2181      * system property, Settings.TETHER_SUPPORTED or due to device configuration. This is useful
2182      * for system components that query this API on behalf of an app. In particular, Bluetooth
2183      * has @UnsupportedAppUsage calls that will let apps turn on bluetooth tethering if they have
2184      * the right permissions, but such an app needs to know whether it can (permissions as well
2185      * as support from the device) turn on tethering in the first place to show the appropriate UI.
2186      *
2187      * @param callerPkg The caller package name, if it is not matching the calling uid,
2188      *       SecurityException would be thrown.
2189      * @return a boolean - {@code true} indicating Tethering is supported.
2190      * @hide
2191      */
2192     @SystemApi(client = MODULE_LIBRARIES)
2193     public boolean isTetheringSupported(@NonNull final String callerPkg) {
2194 
2195         final RequestDispatcher dispatcher = new RequestDispatcher();
2196         final int ret = dispatcher.waitForResult((connector, listener) -> {
2197             try {
2198                 connector.isTetheringSupported(callerPkg, getAttributionTag(), listener);
2199             } catch (RemoteException e) {
2200                 throw new IllegalStateException(e);
2201             }
2202         }, this);
2203 
2204         return ret == TETHER_ERROR_NO_ERROR;
2205     }
2206 
2207     /**
2208      * Stop all active tethering.
2209      * @hide
2210      */
2211     @SystemApi
2212     @RequiresPermission(android.Manifest.permission.TETHER_PRIVILEGED)
2213     public void stopAllTethering() {
2214         final String callerPkg = mContext.getOpPackageName();
2215         Log.i(TAG, "stopAllTethering caller:" + callerPkg);
2216 
2217         getConnector(c -> c.stopAllTethering(callerPkg, getAttributionTag(),
2218                 new IIntResultListener.Stub() {
2219                     @Override
2220                     public void onResult(int resultCode) {
2221                         // TODO: add an API parameter to send result to caller.
2222                         // This has never been possible as stopAllTethering has always been void
2223                         // and never taken a callback object. The only indication that callers have
2224                         // is if the call results in a TETHER_STATE_CHANGE broadcast.
2225                     }
2226                 }));
2227     }
2228 
2229     /**
2230      * Whether to treat networks that have TRANSPORT_TEST as Tethering upstreams. The effects of
2231      * this method apply to any test networks that are already present on the system.
2232      *
2233      * @throws SecurityException If the caller doesn't have the NETWORK_SETTINGS permission.
2234      * @hide
2235      */
2236     @RequiresPermission(android.Manifest.permission.NETWORK_SETTINGS)
2237     public void setPreferTestNetworks(final boolean prefer) {
2238         Log.i(TAG, "setPreferTestNetworks caller: " + mContext.getOpPackageName());
2239 
2240         final RequestDispatcher dispatcher = new RequestDispatcher();
2241         final int ret = dispatcher.waitForResult((connector, listener) -> {
2242             try {
2243                 connector.setPreferTestNetworks(prefer, listener);
2244             } catch (RemoteException e) {
2245                 throw new IllegalStateException(e);
2246             }
2247         }, this);
2248     }
2249 }
2250