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