1 /*
2  * Copyright (C) 2014 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.net;
18 
19 import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
20 
21 import android.annotation.CallbackExecutor;
22 import android.annotation.IntDef;
23 import android.annotation.NonNull;
24 import android.annotation.Nullable;
25 import android.annotation.RequiresPermission;
26 import android.annotation.SystemApi;
27 import android.annotation.SystemService;
28 import android.compat.annotation.UnsupportedAppUsage;
29 import android.content.Context;
30 import android.os.Build;
31 import android.os.OutcomeReceiver;
32 import android.os.RemoteException;
33 import android.util.ArrayMap;
34 
35 import com.android.internal.annotations.GuardedBy;
36 import com.android.modules.utils.BackgroundThread;
37 
38 import java.lang.annotation.Retention;
39 import java.lang.annotation.RetentionPolicy;
40 import java.util.List;
41 import java.util.Objects;
42 import java.util.concurrent.Executor;
43 import java.util.function.IntConsumer;
44 
45 /**
46  * A class that manages and configures Ethernet interfaces.
47  *
48  * @hide
49  */
50 @SystemApi
51 @SystemService(Context.ETHERNET_SERVICE)
52 public class EthernetManager {
53     private static final String TAG = "EthernetManager";
54 
55     private final IEthernetManager mService;
56     @GuardedBy("mListenerLock")
57     private final ArrayMap<InterfaceStateListener, IEthernetServiceListener>
58             mIfaceServiceListeners = new ArrayMap<>();
59     @GuardedBy("mListenerLock")
60     private final ArrayMap<IntConsumer, IEthernetServiceListener> mStateServiceListeners =
61             new ArrayMap<>();
62     final Object mListenerLock = new Object();
63 
64     /**
65      * Indicates that Ethernet is disabled.
66      *
67      * @hide
68      */
69     @SystemApi(client = MODULE_LIBRARIES)
70     public static final int ETHERNET_STATE_DISABLED = 0;
71 
72     /**
73      * Indicates that Ethernet is enabled.
74      *
75      * @hide
76      */
77     @SystemApi(client = MODULE_LIBRARIES)
78     public static final int ETHERNET_STATE_ENABLED  = 1;
79 
80     /**
81      * The interface is absent.
82      * @hide
83      */
84     @SystemApi(client = MODULE_LIBRARIES)
85     public static final int STATE_ABSENT = 0;
86 
87     /**
88      * The interface is present but link is down.
89      * @hide
90      */
91     @SystemApi(client = MODULE_LIBRARIES)
92     public static final int STATE_LINK_DOWN = 1;
93 
94     /**
95      * The interface is present and link is up.
96      * @hide
97      */
98     @SystemApi(client = MODULE_LIBRARIES)
99     public static final int STATE_LINK_UP = 2;
100 
101     /** @hide */
102     @IntDef(prefix = "STATE_", value = {STATE_ABSENT, STATE_LINK_DOWN, STATE_LINK_UP})
103     @Retention(RetentionPolicy.SOURCE)
104     public @interface InterfaceState {}
105 
106     /**
107      * The interface currently does not have any specific role.
108      * @hide
109      */
110     @SystemApi(client = MODULE_LIBRARIES)
111     public static final int ROLE_NONE = 0;
112 
113     /**
114      * The interface is in client mode (e.g., connected to the Internet).
115      * @hide
116      */
117     @SystemApi(client = MODULE_LIBRARIES)
118     public static final int ROLE_CLIENT = 1;
119 
120     /**
121      * Ethernet interface is in server mode (e.g., providing Internet access to tethered devices).
122      * @hide
123      */
124     @SystemApi(client = MODULE_LIBRARIES)
125     public static final int ROLE_SERVER = 2;
126 
127     /** @hide */
128     @IntDef(prefix = "ROLE_", value = {ROLE_NONE, ROLE_CLIENT, ROLE_SERVER})
129     @Retention(RetentionPolicy.SOURCE)
130     public @interface Role {}
131 
132     /**
133      * A listener that receives notifications about the state of Ethernet interfaces on the system.
134      * @hide
135      */
136     @SystemApi(client = MODULE_LIBRARIES)
137     public interface InterfaceStateListener {
138         /**
139          * Called when an Ethernet interface changes state.
140          *
141          * @param iface the name of the interface.
142          * @param state the current state of the interface, or {@link #STATE_ABSENT} if the
143          *              interface was removed.
144          * @param role whether the interface is in client mode or server mode.
145          * @param configuration the current IP configuration of the interface.
146          * @hide
147          */
148         @SystemApi(client = MODULE_LIBRARIES)
onInterfaceStateChanged(@onNull String iface, @InterfaceState int state, @Role int role, @Nullable IpConfiguration configuration)149         void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
150                 @Role int role, @Nullable IpConfiguration configuration);
151     }
152 
153     /**
154      * A listener interface to receive notification on changes in Ethernet.
155      * This has never been a supported API. Use {@link InterfaceStateListener} instead.
156      * @hide
157      */
158     public interface Listener extends InterfaceStateListener {
159         /**
160          * Called when Ethernet port's availability is changed.
161          * @param iface Ethernet interface name
162          * @param isAvailable {@code true} if Ethernet port exists.
163          * @hide
164          */
165         @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
onAvailabilityChanged(String iface, boolean isAvailable)166         void onAvailabilityChanged(String iface, boolean isAvailable);
167 
168         /** Default implementation for backwards compatibility. Only calls the legacy listener. */
onInterfaceStateChanged(@onNull String iface, @InterfaceState int state, @Role int role, @Nullable IpConfiguration configuration)169         default void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
170                 @Role int role, @Nullable IpConfiguration configuration) {
171             onAvailabilityChanged(iface, (state >= STATE_LINK_UP));
172         }
173 
174     }
175 
176     /**
177      * Create a new EthernetManager instance.
178      * Applications will almost always want to use
179      * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
180      * the standard {@link android.content.Context#ETHERNET_SERVICE Context.ETHERNET_SERVICE}.
181      * @hide
182      */
EthernetManager(Context context, IEthernetManager service)183     public EthernetManager(Context context, IEthernetManager service) {
184         mService = service;
185     }
186 
187     /**
188      * Get Ethernet configuration.
189      * @return the Ethernet Configuration, contained in {@link IpConfiguration}.
190      * @hide
191      */
192     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getConfiguration(String iface)193     public IpConfiguration getConfiguration(String iface) {
194         try {
195             return mService.getConfiguration(iface);
196         } catch (RemoteException e) {
197             throw e.rethrowFromSystemServer();
198         }
199     }
200 
201     /**
202      * Set Ethernet configuration.
203      * @hide
204      */
205     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
setConfiguration(@onNull String iface, @NonNull IpConfiguration config)206     public void setConfiguration(@NonNull String iface, @NonNull IpConfiguration config) {
207         try {
208             mService.setConfiguration(iface, config);
209         } catch (RemoteException e) {
210             throw e.rethrowFromSystemServer();
211         }
212     }
213 
214     /**
215      * Indicates whether the system currently has one or more Ethernet interfaces.
216      * @hide
217      */
218     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isAvailable()219     public boolean isAvailable() {
220         return getAvailableInterfaces().length > 0;
221     }
222 
223     /**
224      * Indicates whether the system has given interface.
225      *
226      * @param iface Ethernet interface name
227      * @hide
228      */
229     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
isAvailable(String iface)230     public boolean isAvailable(String iface) {
231         try {
232             return mService.isAvailable(iface);
233         } catch (RemoteException e) {
234             throw e.rethrowFromSystemServer();
235         }
236     }
237 
238     /**
239      * Adds a listener.
240      * This has never been a supported API. Use {@link #addInterfaceStateListener} instead.
241      *
242      * @param listener A {@link Listener} to add.
243      * @throws IllegalArgumentException If the listener is null.
244      * @hide
245      */
246     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
addListener(@onNull Listener listener)247     public void addListener(@NonNull Listener listener) {
248         addListener(listener, BackgroundThread.getExecutor());
249     }
250 
251     /**
252      * Adds a listener.
253      * This has never been a supported API. Use {@link #addInterfaceStateListener} instead.
254      *
255      * @param listener A {@link Listener} to add.
256      * @param executor Executor to run callbacks on.
257      * @throws IllegalArgumentException If the listener or executor is null.
258      * @hide
259      */
260     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
addListener(@onNull Listener listener, @NonNull Executor executor)261     public void addListener(@NonNull Listener listener, @NonNull Executor executor) {
262         addInterfaceStateListener(executor, listener);
263     }
264 
265     /**
266      * Listen to changes in the state of Ethernet interfaces.
267      *
268      * Adds a listener to receive notification for any state change of all existing Ethernet
269      * interfaces.
270      * <p>{@link Listener#onInterfaceStateChanged} will be triggered immediately for all
271      * existing interfaces upon adding a listener. The same method will be called on the
272      * listener every time any of the interface changes state. In particular, if an
273      * interface is removed, it will be called with state {@link #STATE_ABSENT}.
274      * <p>Use {@link #removeInterfaceStateListener} with the same object to stop listening.
275      *
276      * @param executor Executor to run callbacks on.
277      * @param listener A {@link Listener} to add.
278      * @hide
279      */
280     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
281     @SystemApi(client = MODULE_LIBRARIES)
addInterfaceStateListener(@onNull Executor executor, @NonNull InterfaceStateListener listener)282     public void addInterfaceStateListener(@NonNull Executor executor,
283             @NonNull InterfaceStateListener listener) {
284         if (listener == null || executor == null) {
285             throw new NullPointerException("listener and executor must not be null");
286         }
287 
288         final IEthernetServiceListener.Stub serviceListener = new IEthernetServiceListener.Stub() {
289             @Override
290             public void onEthernetStateChanged(int state) {}
291 
292             @Override
293             public void onInterfaceStateChanged(String iface, int state, int role,
294                     IpConfiguration configuration) {
295                 executor.execute(() ->
296                         listener.onInterfaceStateChanged(iface, state, role, configuration));
297             }
298         };
299         synchronized (mListenerLock) {
300             addServiceListener(serviceListener);
301             mIfaceServiceListeners.put(listener, serviceListener);
302         }
303     }
304 
305     @GuardedBy("mListenerLock")
addServiceListener(@onNull final IEthernetServiceListener listener)306     private void addServiceListener(@NonNull final IEthernetServiceListener listener) {
307         try {
308             mService.addListener(listener);
309         } catch (RemoteException e) {
310             throw e.rethrowFromSystemServer();
311         }
312 
313     }
314 
315     /**
316      * Returns an array of available Ethernet interface names.
317      * @hide
318      */
319     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
getAvailableInterfaces()320     public String[] getAvailableInterfaces() {
321         try {
322             return mService.getAvailableInterfaces();
323         } catch (RemoteException e) {
324             throw e.rethrowAsRuntimeException();
325         }
326     }
327 
328     /**
329      * Removes a listener.
330      *
331      * @param listener A {@link Listener} to remove.
332      * @hide
333      */
334     @SystemApi(client = MODULE_LIBRARIES)
removeInterfaceStateListener(@onNull InterfaceStateListener listener)335     public void removeInterfaceStateListener(@NonNull InterfaceStateListener listener) {
336         Objects.requireNonNull(listener);
337         synchronized (mListenerLock) {
338             maybeRemoveServiceListener(mIfaceServiceListeners.remove(listener));
339         }
340     }
341 
342     @GuardedBy("mListenerLock")
maybeRemoveServiceListener(@ullable final IEthernetServiceListener listener)343     private void maybeRemoveServiceListener(@Nullable final IEthernetServiceListener listener) {
344         if (listener == null) return;
345 
346         try {
347             mService.removeListener(listener);
348         } catch (RemoteException e) {
349             throw e.rethrowFromSystemServer();
350         }
351     }
352 
353     /**
354      * Removes a listener.
355      * This has never been a supported API. Use {@link #removeInterfaceStateListener} instead.
356      * @param listener A {@link Listener} to remove.
357      * @hide
358      */
359     @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
removeListener(@onNull Listener listener)360     public void removeListener(@NonNull Listener listener) {
361         if (listener == null) {
362             throw new IllegalArgumentException("listener must not be null");
363         }
364         removeInterfaceStateListener(listener);
365     }
366 
367     /**
368      * Whether to treat interfaces created by {@link TestNetworkManager#createTapInterface}
369      * as Ethernet interfaces. The effects of this method apply to any test interfaces that are
370      * already present on the system.
371      * @hide
372      */
373     @SystemApi(client = MODULE_LIBRARIES)
setIncludeTestInterfaces(boolean include)374     public void setIncludeTestInterfaces(boolean include) {
375         try {
376             mService.setIncludeTestInterfaces(include);
377         } catch (RemoteException e) {
378             throw e.rethrowFromSystemServer();
379         }
380     }
381 
382     /**
383      * A request for a tethered interface.
384      */
385     public static class TetheredInterfaceRequest {
386         private final IEthernetManager mService;
387         private final ITetheredInterfaceCallback mCb;
388 
TetheredInterfaceRequest(@onNull IEthernetManager service, @NonNull ITetheredInterfaceCallback cb)389         private TetheredInterfaceRequest(@NonNull IEthernetManager service,
390                 @NonNull ITetheredInterfaceCallback cb) {
391             this.mService = service;
392             this.mCb = cb;
393         }
394 
395         /**
396          * Release the request, causing the interface to revert back from tethering mode if there
397          * is no other requestor.
398          */
release()399         public void release() {
400             try {
401                 mService.releaseTetheredInterface(mCb);
402             } catch (RemoteException e) {
403                 e.rethrowFromSystemServer();
404             }
405         }
406     }
407 
408     /**
409      * Callback for {@link #requestTetheredInterface(TetheredInterfaceCallback)}.
410      */
411     public interface TetheredInterfaceCallback {
412         /**
413          * Called when the tethered interface is available.
414          * @param iface The name of the interface.
415          */
onAvailable(@onNull String iface)416         void onAvailable(@NonNull String iface);
417 
418         /**
419          * Called when the tethered interface is now unavailable.
420          */
onUnavailable()421         void onUnavailable();
422     }
423 
424     /**
425      * Request a tethered interface in tethering mode.
426      *
427      * <p>When this method is called and there is at least one ethernet interface available, the
428      * system will designate one to act as a tethered interface. If there is already a tethered
429      * interface, the existing interface will be used.
430      * @param callback A callback to be called once the request has been fulfilled.
431      */
432     @RequiresPermission(anyOf = {
433             android.Manifest.permission.NETWORK_STACK,
434             android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
435     })
436     @NonNull
requestTetheredInterface(@onNull final Executor executor, @NonNull final TetheredInterfaceCallback callback)437     public TetheredInterfaceRequest requestTetheredInterface(@NonNull final Executor executor,
438             @NonNull final TetheredInterfaceCallback callback) {
439         Objects.requireNonNull(callback, "Callback must be non-null");
440         Objects.requireNonNull(executor, "Executor must be non-null");
441         final ITetheredInterfaceCallback cbInternal = new ITetheredInterfaceCallback.Stub() {
442             @Override
443             public void onAvailable(String iface) {
444                 executor.execute(() -> callback.onAvailable(iface));
445             }
446 
447             @Override
448             public void onUnavailable() {
449                 executor.execute(() -> callback.onUnavailable());
450             }
451         };
452 
453         try {
454             mService.requestTetheredInterface(cbInternal);
455         } catch (RemoteException e) {
456             throw e.rethrowFromSystemServer();
457         }
458         return new TetheredInterfaceRequest(mService, cbInternal);
459     }
460 
461     private static final class NetworkInterfaceOutcomeReceiver
462             extends INetworkInterfaceOutcomeReceiver.Stub {
463         @NonNull
464         private final Executor mExecutor;
465         @NonNull
466         private final OutcomeReceiver<String, EthernetNetworkManagementException> mCallback;
467 
NetworkInterfaceOutcomeReceiver( @onNull final Executor executor, @NonNull final OutcomeReceiver<String, EthernetNetworkManagementException> callback)468         NetworkInterfaceOutcomeReceiver(
469                 @NonNull final Executor executor,
470                 @NonNull final OutcomeReceiver<String, EthernetNetworkManagementException>
471                         callback) {
472             Objects.requireNonNull(executor, "Pass a non-null executor");
473             Objects.requireNonNull(callback, "Pass a non-null callback");
474             mExecutor = executor;
475             mCallback = callback;
476         }
477 
478         @Override
onResult(@onNull String iface)479         public void onResult(@NonNull String iface) {
480             mExecutor.execute(() -> mCallback.onResult(iface));
481         }
482 
483         @Override
onError(@onNull EthernetNetworkManagementException e)484         public void onError(@NonNull EthernetNetworkManagementException e) {
485             mExecutor.execute(() -> mCallback.onError(e));
486         }
487     }
488 
makeNetworkInterfaceOutcomeReceiver( @ullable final Executor executor, @Nullable final OutcomeReceiver<String, EthernetNetworkManagementException> callback)489     private NetworkInterfaceOutcomeReceiver makeNetworkInterfaceOutcomeReceiver(
490             @Nullable final Executor executor,
491             @Nullable final OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
492         if (null != callback) {
493             Objects.requireNonNull(executor, "Pass a non-null executor, or a null callback");
494         }
495         final NetworkInterfaceOutcomeReceiver proxy;
496         if (null == callback) {
497             proxy = null;
498         } else {
499             proxy = new NetworkInterfaceOutcomeReceiver(executor, callback);
500         }
501         return proxy;
502     }
503 
504     /**
505      * Updates the configuration of an automotive device's ethernet network.
506      *
507      * The {@link EthernetNetworkUpdateRequest} {@code request} argument describes how to update the
508      * configuration for this network.
509      * Use {@link StaticIpConfiguration.Builder} to build a {@code StaticIpConfiguration} object for
510      * this network to put inside the {@code request}.
511      * Similarly, use {@link NetworkCapabilities.Builder} to build a {@code NetworkCapabilities}
512      * object for this network to put inside the {@code request}.
513      *
514      * The provided {@link OutcomeReceiver} is called once the operation has finished execution.
515      *
516      * @param iface the name of the interface to act upon.
517      * @param request the {@link EthernetNetworkUpdateRequest} used to set an ethernet network's
518      *                {@link StaticIpConfiguration} and {@link NetworkCapabilities} values.
519      * @param executor an {@link Executor} to execute the callback on. Optional if callback is null.
520      * @param callback an optional {@link OutcomeReceiver} to listen for completion of the
521      *                 operation. On success, {@link OutcomeReceiver#onResult} is called with the
522      *                 interface name. On error, {@link OutcomeReceiver#onError} is called with more
523      *                 information about the error.
524      * @throws SecurityException if the process doesn't hold
525      *                          {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
526      * @throws UnsupportedOperationException if the {@link NetworkCapabilities} are updated on a
527      *                                       non-automotive device or this function is called on an
528      *                                       unsupported interface.
529      * @hide
530      */
531     @SystemApi
532     @RequiresPermission(anyOf = {
533             NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
534             android.Manifest.permission.NETWORK_STACK,
535             android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
updateConfiguration( @onNull String iface, @NonNull EthernetNetworkUpdateRequest request, @Nullable @CallbackExecutor Executor executor, @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback)536     public void updateConfiguration(
537             @NonNull String iface,
538             @NonNull EthernetNetworkUpdateRequest request,
539             @Nullable @CallbackExecutor Executor executor,
540             @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
541         Objects.requireNonNull(iface, "iface must be non-null");
542         Objects.requireNonNull(request, "request must be non-null");
543         final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
544                 executor, callback);
545         try {
546             mService.updateConfiguration(iface, request, proxy);
547         } catch (RemoteException e) {
548             throw e.rethrowFromSystemServer();
549         }
550     }
551 
552     /**
553      * Enable a network interface.
554      *
555      * Enables a previously disabled network interface. An attempt to enable an already-enabled
556      * interface is ignored.
557      * The provided {@link OutcomeReceiver} is called once the operation has finished execution.
558      *
559      * @param iface the name of the interface to enable.
560      * @param executor an {@link Executor} to execute the callback on. Optional if callback is null.
561      * @param callback an optional {@link OutcomeReceiver} to listen for completion of the
562      *                 operation. On success, {@link OutcomeReceiver#onResult} is called with the
563      *                 interface name. On error, {@link OutcomeReceiver#onError} is called with more
564      *                 information about the error.
565      * @throws SecurityException if the process doesn't hold
566      *                          {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
567      * @hide
568      */
569     @SystemApi
570     @RequiresPermission(anyOf = {
571             NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
572             android.Manifest.permission.NETWORK_STACK,
573             android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
enableInterface( @onNull String iface, @Nullable @CallbackExecutor Executor executor, @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback)574     public void enableInterface(
575             @NonNull String iface,
576             @Nullable @CallbackExecutor Executor executor,
577             @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
578         Objects.requireNonNull(iface, "iface must be non-null");
579         final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
580                 executor, callback);
581         try {
582             mService.enableInterface(iface, proxy);
583         } catch (RemoteException e) {
584             throw e.rethrowFromSystemServer();
585         }
586     }
587 
588     /**
589      * Disable a network interface.
590      *
591      * Disables the specified interface. If this interface is in use in a connected
592      * {@link android.net.Network}, then that {@code Network} will be torn down.
593      * The provided {@link OutcomeReceiver} is called once the operation has finished execution.
594      *
595      * @param iface the name of the interface to disable.
596      * @param executor an {@link Executor} to execute the callback on. Optional if callback is null.
597      * @param callback an optional {@link OutcomeReceiver} to listen for completion of the
598      *                 operation. On success, {@link OutcomeReceiver#onResult} is called with the
599      *                 interface name. On error, {@link OutcomeReceiver#onError} is called with more
600      *                 information about the error.
601      * @throws SecurityException if the process doesn't hold
602      *                          {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
603      * @hide
604      */
605     @SystemApi
606     @RequiresPermission(anyOf = {
607             NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
608             android.Manifest.permission.NETWORK_STACK,
609             android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
disableInterface( @onNull String iface, @Nullable @CallbackExecutor Executor executor, @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback)610     public void disableInterface(
611             @NonNull String iface,
612             @Nullable @CallbackExecutor Executor executor,
613             @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
614         Objects.requireNonNull(iface, "iface must be non-null");
615         final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
616                 executor, callback);
617         try {
618             mService.disableInterface(iface, proxy);
619         } catch (RemoteException e) {
620             throw e.rethrowFromSystemServer();
621         }
622     }
623 
624     /**
625      * Change ethernet setting.
626      *
627      * @param enabled enable or disable ethernet settings.
628      *
629      * @hide
630      */
631     @RequiresPermission(anyOf = {
632             NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
633             android.Manifest.permission.NETWORK_STACK,
634             android.Manifest.permission.NETWORK_SETTINGS})
635     @SystemApi(client = MODULE_LIBRARIES)
setEthernetEnabled(boolean enabled)636     public void setEthernetEnabled(boolean enabled) {
637         try {
638             mService.setEthernetEnabled(enabled);
639         } catch (RemoteException e) {
640             throw e.rethrowFromSystemServer();
641         }
642     }
643 
644     /**
645      * Register a IntConsumer to be called back on ethernet state changes.
646      *
647      * <p>{@link IntConsumer#accept} with the current ethernet state will be triggered immediately
648      * upon adding a listener. The same callback is invoked on Ethernet state change, i.e. when
649      * calling {@link #setEthernetEnabled}.
650      * <p>The reported state is represented by:
651      * {@link #ETHERNET_STATE_DISABLED}: ethernet is now disabled.
652      * {@link #ETHERNET_STATE_ENABLED}: ethernet is now enabled.
653      *
654      * @param executor to run callbacks on.
655      * @param listener to listen ethernet state changed.
656      *
657      * @hide
658      */
659     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
660     @SystemApi(client = MODULE_LIBRARIES)
addEthernetStateListener(@onNull Executor executor, @NonNull IntConsumer listener)661     public void addEthernetStateListener(@NonNull Executor executor,
662             @NonNull IntConsumer listener) {
663         Objects.requireNonNull(executor);
664         Objects.requireNonNull(listener);
665         final IEthernetServiceListener.Stub serviceListener = new IEthernetServiceListener.Stub() {
666             @Override
667             public void onEthernetStateChanged(int state) {
668                 executor.execute(() -> listener.accept(state));
669             }
670 
671             @Override
672             public void onInterfaceStateChanged(String iface, int state, int role,
673                     IpConfiguration configuration) {}
674         };
675         synchronized (mListenerLock) {
676             addServiceListener(serviceListener);
677             mStateServiceListeners.put(listener, serviceListener);
678         }
679     }
680 
681     /**
682      * Removes a listener.
683      *
684      * @param listener to listen ethernet state changed.
685      *
686      * @hide
687      */
688     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
689     @SystemApi(client = MODULE_LIBRARIES)
removeEthernetStateListener(@onNull IntConsumer listener)690     public void removeEthernetStateListener(@NonNull IntConsumer listener) {
691         Objects.requireNonNull(listener);
692         synchronized (mListenerLock) {
693             maybeRemoveServiceListener(mStateServiceListeners.remove(listener));
694         }
695     }
696 
697     /**
698      * Returns an array of existing Ethernet interface names regardless whether the interface
699      * is available or not currently.
700      * @hide
701      */
702     @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
703     @SystemApi(client = MODULE_LIBRARIES)
704     @NonNull
getInterfaceList()705     public List<String> getInterfaceList() {
706         try {
707             return mService.getInterfaceList();
708         } catch (RemoteException e) {
709             throw e.rethrowAsRuntimeException();
710         }
711     }
712 }
713