blob: 2b76dd935f445770c517ff67d59c0ae3cc199720 [file] [log] [blame]
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -07001/*
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
17package android.net;
18
Xiao Ma7f9ac502022-01-30 11:27:16 +000019import static android.annotation.SystemApi.Client.MODULE_LIBRARIES;
20
James Mattis407ea1d2021-12-14 18:23:30 -080021import android.annotation.CallbackExecutor;
Xiao Ma7f9ac502022-01-30 11:27:16 +000022import android.annotation.IntDef;
Lorenzo Colitti19b8b882020-01-24 19:29:17 +090023import android.annotation.NonNull;
James Mattis407ea1d2021-12-14 18:23:30 -080024import android.annotation.Nullable;
James Mattis28547372022-02-02 14:32:40 -080025import android.annotation.RequiresFeature;
Remi NGUYEN VAN11f39242020-03-09 13:56:18 +090026import android.annotation.RequiresPermission;
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +090027import android.annotation.SystemApi;
Jeff Sharkeyad1cebe2017-06-02 17:36:26 -060028import android.annotation.SystemService;
Artur Satayev164c7562019-12-10 17:47:52 +000029import android.compat.annotation.UnsupportedAppUsage;
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070030import android.content.Context;
James Mattis28547372022-02-02 14:32:40 -080031import android.content.pm.PackageManager;
Mathew Inwoodfe2fed72020-11-04 09:29:36 +000032import android.os.Build;
Patrick Rohrd6156a92022-03-17 19:19:21 +000033import android.os.OutcomeReceiver;
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070034import android.os.RemoteException;
35
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090036import com.android.internal.annotations.GuardedBy;
Xiao Madbc8e0f2021-12-28 09:16:09 +000037import com.android.modules.utils.BackgroundThread;
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090038
Xiao Ma7f9ac502022-01-30 11:27:16 +000039import java.lang.annotation.Retention;
40import java.lang.annotation.RetentionPolicy;
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090041import java.util.ArrayList;
Xiao Ma1edd4552022-03-17 05:56:09 +000042import java.util.List;
Lorenzo Colitti19b8b882020-01-24 19:29:17 +090043import java.util.Objects;
markchienc8e7d752020-02-26 20:54:55 +080044import java.util.concurrent.Executor;
markchien5912ab62022-03-17 18:19:39 +080045import java.util.function.IntConsumer;
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090046
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070047/**
Xiao Ma7f9ac502022-01-30 11:27:16 +000048 * A class that manages and configures Ethernet interfaces.
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070049 *
50 * @hide
51 */
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +090052@SystemApi
Jeff Sharkeyad1cebe2017-06-02 17:36:26 -060053@SystemService(Context.ETHERNET_SERVICE)
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070054public class EthernetManager {
55 private static final String TAG = "EthernetManager";
56
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070057 private final IEthernetManager mService;
markchien5912ab62022-03-17 18:19:39 +080058 @GuardedBy("mListenerLock")
59 private final ArrayList<ListenerInfo<InterfaceStateListener>> mIfaceListeners =
60 new ArrayList<>();
61 @GuardedBy("mListenerLock")
62 private final ArrayList<ListenerInfo<IntConsumer>> mEthernetStateListeners =
63 new ArrayList<>();
64 final Object mListenerLock = new Object();
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090065 private final IEthernetServiceListener.Stub mServiceListener =
66 new IEthernetServiceListener.Stub() {
67 @Override
markchien5912ab62022-03-17 18:19:39 +080068 public void onEthernetStateChanged(int state) {
69 synchronized (mListenerLock) {
70 for (ListenerInfo<IntConsumer> li : mEthernetStateListeners) {
71 li.executor.execute(() -> {
72 li.listener.accept(state);
73 });
74 }
75 }
76 }
77
78 @Override
Xiao Ma7f9ac502022-01-30 11:27:16 +000079 public void onInterfaceStateChanged(String iface, int state, int role,
80 IpConfiguration configuration) {
markchien5912ab62022-03-17 18:19:39 +080081 synchronized (mListenerLock) {
82 for (ListenerInfo<InterfaceStateListener> li : mIfaceListeners) {
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090083 li.executor.execute(() ->
Xiao Ma7f9ac502022-01-30 11:27:16 +000084 li.listener.onInterfaceStateChanged(iface, state, role,
85 configuration));
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090086 }
87 }
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090088 }
89 };
90
markchien5912ab62022-03-17 18:19:39 +080091 /**
92 * Indicates that Ethernet is disabled.
93 *
94 * @hide
95 */
96 @SystemApi(client = MODULE_LIBRARIES)
97 public static final int ETHERNET_STATE_DISABLED = 0;
98
99 /**
100 * Indicates that Ethernet is enabled.
101 *
102 * @hide
103 */
104 @SystemApi(client = MODULE_LIBRARIES)
105 public static final int ETHERNET_STATE_ENABLED = 1;
106
107 private static class ListenerInfo<T> {
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900108 @NonNull
109 public final Executor executor;
110 @NonNull
markchien5912ab62022-03-17 18:19:39 +0800111 public final T listener;
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900112
markchien5912ab62022-03-17 18:19:39 +0800113 private ListenerInfo(@NonNull Executor executor, @NonNull T listener) {
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900114 this.executor = executor;
115 this.listener = listener;
116 }
117 }
118
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900119 /**
Xiao Ma7f9ac502022-01-30 11:27:16 +0000120 * The interface is absent.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900121 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900122 */
Xiao Ma7f9ac502022-01-30 11:27:16 +0000123 @SystemApi(client = MODULE_LIBRARIES)
124 public static final int STATE_ABSENT = 0;
125
126 /**
127 * The interface is present but link is down.
128 * @hide
129 */
130 @SystemApi(client = MODULE_LIBRARIES)
131 public static final int STATE_LINK_DOWN = 1;
132
133 /**
134 * The interface is present and link is up.
135 * @hide
136 */
137 @SystemApi(client = MODULE_LIBRARIES)
138 public static final int STATE_LINK_UP = 2;
139
140 /** @hide */
141 @IntDef(prefix = "STATE_", value = {STATE_ABSENT, STATE_LINK_DOWN, STATE_LINK_UP})
142 @Retention(RetentionPolicy.SOURCE)
143 public @interface InterfaceState {}
144
145 /**
146 * The interface currently does not have any specific role.
147 * @hide
148 */
149 @SystemApi(client = MODULE_LIBRARIES)
150 public static final int ROLE_NONE = 0;
151
152 /**
153 * The interface is in client mode (e.g., connected to the Internet).
154 * @hide
155 */
156 @SystemApi(client = MODULE_LIBRARIES)
157 public static final int ROLE_CLIENT = 1;
158
159 /**
160 * Ethernet interface is in server mode (e.g., providing Internet access to tethered devices).
161 * @hide
162 */
163 @SystemApi(client = MODULE_LIBRARIES)
164 public static final int ROLE_SERVER = 2;
165
166 /** @hide */
167 @IntDef(prefix = "ROLE_", value = {ROLE_NONE, ROLE_CLIENT, ROLE_SERVER})
168 @Retention(RetentionPolicy.SOURCE)
169 public @interface Role {}
170
171 /**
172 * A listener that receives notifications about the state of Ethernet interfaces on the system.
173 * @hide
174 */
175 @SystemApi(client = MODULE_LIBRARIES)
176 public interface InterfaceStateListener {
177 /**
178 * Called when an Ethernet interface changes state.
179 *
180 * @param iface the name of the interface.
181 * @param state the current state of the interface, or {@link #STATE_ABSENT} if the
182 * interface was removed.
Lorenzo Colitti6c032e52022-02-11 12:18:59 +0900183 * @param role whether the interface is in client mode or server mode.
Xiao Ma7f9ac502022-01-30 11:27:16 +0000184 * @param configuration the current IP configuration of the interface.
185 * @hide
186 */
187 @SystemApi(client = MODULE_LIBRARIES)
188 void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
189 @Role int role, @Nullable IpConfiguration configuration);
190 }
191
192 /**
193 * A listener interface to receive notification on changes in Ethernet.
194 * This has never been a supported API. Use {@link InterfaceStateListener} instead.
195 * @hide
196 */
197 public interface Listener extends InterfaceStateListener {
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900198 /**
199 * Called when Ethernet port's availability is changed.
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700200 * @param iface Ethernet interface name
201 * @param isAvailable {@code true} if Ethernet port exists.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900202 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900203 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000204 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700205 void onAvailabilityChanged(String iface, boolean isAvailable);
Xiao Ma7f9ac502022-01-30 11:27:16 +0000206
207 /** Default implementation for backwards compatibility. Only calls the legacy listener. */
208 default void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
209 @Role int role, @Nullable IpConfiguration configuration) {
210 onAvailabilityChanged(iface, (state >= STATE_LINK_UP));
211 }
212
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900213 }
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700214
215 /**
216 * Create a new EthernetManager instance.
217 * Applications will almost always want to use
218 * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
219 * the standard {@link android.content.Context#ETHERNET_SERVICE Context.ETHERNET_SERVICE}.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900220 * @hide
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700221 */
222 public EthernetManager(Context context, IEthernetManager service) {
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700223 mService = service;
224 }
225
226 /**
Lorenzo Colitti56e4e582014-05-22 11:51:27 -0700227 * Get Ethernet configuration.
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700228 * @return the Ethernet Configuration, contained in {@link IpConfiguration}.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900229 * @hide
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700230 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000231 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700232 public IpConfiguration getConfiguration(String iface) {
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700233 try {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700234 return mService.getConfiguration(iface);
Jeff Sharkeyf7138282016-03-01 19:27:23 -0700235 } catch (RemoteException e) {
236 throw e.rethrowFromSystemServer();
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700237 }
238 }
239
240 /**
Lorenzo Colitti56e4e582014-05-22 11:51:27 -0700241 * Set Ethernet configuration.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900242 * @hide
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700243 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000244 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Xiao Ma7f9ac502022-01-30 11:27:16 +0000245 public void setConfiguration(@NonNull String iface, @NonNull IpConfiguration config) {
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700246 try {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700247 mService.setConfiguration(iface, config);
Jeff Sharkeyf7138282016-03-01 19:27:23 -0700248 } catch (RemoteException e) {
249 throw e.rethrowFromSystemServer();
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900250 }
251 }
252
253 /**
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700254 * Indicates whether the system currently has one or more Ethernet interfaces.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900255 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900256 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000257 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900258 public boolean isAvailable() {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700259 return getAvailableInterfaces().length > 0;
260 }
261
262 /**
263 * Indicates whether the system has given interface.
264 *
265 * @param iface Ethernet interface name
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900266 * @hide
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700267 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000268 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700269 public boolean isAvailable(String iface) {
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900270 try {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700271 return mService.isAvailable(iface);
Jeff Sharkeyf7138282016-03-01 19:27:23 -0700272 } catch (RemoteException e) {
273 throw e.rethrowFromSystemServer();
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900274 }
275 }
276
277 /**
278 * Adds a listener.
Xiao Ma7f9ac502022-01-30 11:27:16 +0000279 * This has never been a supported API. Use {@link #addInterfaceStateListener} instead.
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900280 *
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900281 * @param listener A {@link Listener} to add.
282 * @throws IllegalArgumentException If the listener is null.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900283 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900284 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000285 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900286 public void addListener(@NonNull Listener listener) {
287 addListener(listener, BackgroundThread.getExecutor());
288 }
289
290 /**
291 * Adds a listener.
Xiao Ma7f9ac502022-01-30 11:27:16 +0000292 * This has never been a supported API. Use {@link #addInterfaceStateListener} instead.
293 *
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900294 * @param listener A {@link Listener} to add.
295 * @param executor Executor to run callbacks on.
296 * @throws IllegalArgumentException If the listener or executor is null.
297 * @hide
298 */
299 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
300 public void addListener(@NonNull Listener listener, @NonNull Executor executor) {
Xiao Ma7f9ac502022-01-30 11:27:16 +0000301 addInterfaceStateListener(executor, listener);
302 }
303
304 /**
305 * Listen to changes in the state of Ethernet interfaces.
306 *
307 * Adds a listener to receive notification for any state change of all existing Ethernet
308 * interfaces.
309 * <p>{@link Listener#onInterfaceStateChanged} will be triggered immediately for all
310 * existing interfaces upon adding a listener. The same method will be called on the
311 * listener every time any of the interface changes state. In particular, if an
312 * interface is removed, it will be called with state {@link #STATE_ABSENT}.
313 * <p>Use {@link #removeInterfaceStateListener} with the same object to stop listening.
314 *
315 * @param executor Executor to run callbacks on.
316 * @param listener A {@link Listener} to add.
317 * @hide
318 */
319 @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
320 @SystemApi(client = MODULE_LIBRARIES)
321 public void addInterfaceStateListener(@NonNull Executor executor,
322 @NonNull InterfaceStateListener listener) {
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900323 if (listener == null || executor == null) {
324 throw new NullPointerException("listener and executor must not be null");
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900325 }
markchien5912ab62022-03-17 18:19:39 +0800326 synchronized (mListenerLock) {
327 maybeAddServiceListener();
328 mIfaceListeners.add(new ListenerInfo<InterfaceStateListener>(executor, listener));
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900329 }
330 }
331
markchien5912ab62022-03-17 18:19:39 +0800332 @GuardedBy("mListenerLock")
333 private void maybeAddServiceListener() {
334 if (!mIfaceListeners.isEmpty() || !mEthernetStateListeners.isEmpty()) return;
335
336 try {
337 mService.addListener(mServiceListener);
338 } catch (RemoteException e) {
339 throw e.rethrowFromSystemServer();
340 }
341
342 }
343
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900344 /**
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700345 * Returns an array of available Ethernet interface names.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900346 * @hide
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700347 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000348 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700349 public String[] getAvailableInterfaces() {
350 try {
351 return mService.getAvailableInterfaces();
352 } catch (RemoteException e) {
353 throw e.rethrowAsRuntimeException();
354 }
355 }
356
357 /**
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900358 * Removes a listener.
Xiao Ma7f9ac502022-01-30 11:27:16 +0000359 *
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900360 * @param listener A {@link Listener} to remove.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900361 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900362 */
Xiao Ma7f9ac502022-01-30 11:27:16 +0000363 @SystemApi(client = MODULE_LIBRARIES)
364 public void removeInterfaceStateListener(@NonNull InterfaceStateListener listener) {
365 Objects.requireNonNull(listener);
markchien5912ab62022-03-17 18:19:39 +0800366 synchronized (mListenerLock) {
367 mIfaceListeners.removeIf(l -> l.listener == listener);
368 maybeRemoveServiceListener();
369 }
370 }
371
372 @GuardedBy("mListenerLock")
373 private void maybeRemoveServiceListener() {
374 if (!mIfaceListeners.isEmpty() || !mEthernetStateListeners.isEmpty()) return;
375
376 try {
377 mService.removeListener(mServiceListener);
378 } catch (RemoteException e) {
379 throw e.rethrowFromSystemServer();
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700380 }
381 }
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900382
383 /**
Xiao Ma7f9ac502022-01-30 11:27:16 +0000384 * Removes a listener.
385 * This has never been a supported API. Use {@link #removeInterfaceStateListener} instead.
386 * @param listener A {@link Listener} to remove.
387 * @hide
388 */
389 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
390 public void removeListener(@NonNull Listener listener) {
391 if (listener == null) {
392 throw new IllegalArgumentException("listener must not be null");
393 }
394 removeInterfaceStateListener(listener);
395 }
396
397 /**
Lorenzo Colitti013187d2020-03-17 00:16:13 +0900398 * Whether to treat interfaces created by {@link TestNetworkManager#createTapInterface}
399 * as Ethernet interfaces. The effects of this method apply to any test interfaces that are
400 * already present on the system.
401 * @hide
402 */
Xiao Ma7f9ac502022-01-30 11:27:16 +0000403 @SystemApi(client = MODULE_LIBRARIES)
Lorenzo Colitti013187d2020-03-17 00:16:13 +0900404 public void setIncludeTestInterfaces(boolean include) {
405 try {
406 mService.setIncludeTestInterfaces(include);
407 } catch (RemoteException e) {
408 throw e.rethrowFromSystemServer();
409 }
410 }
411
412 /**
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900413 * A request for a tethered interface.
414 */
415 public static class TetheredInterfaceRequest {
416 private final IEthernetManager mService;
417 private final ITetheredInterfaceCallback mCb;
418
419 private TetheredInterfaceRequest(@NonNull IEthernetManager service,
420 @NonNull ITetheredInterfaceCallback cb) {
421 this.mService = service;
422 this.mCb = cb;
423 }
424
425 /**
426 * Release the request, causing the interface to revert back from tethering mode if there
427 * is no other requestor.
428 */
429 public void release() {
430 try {
431 mService.releaseTetheredInterface(mCb);
432 } catch (RemoteException e) {
433 e.rethrowFromSystemServer();
434 }
435 }
436 }
437
438 /**
439 * Callback for {@link #requestTetheredInterface(TetheredInterfaceCallback)}.
440 */
441 public interface TetheredInterfaceCallback {
442 /**
443 * Called when the tethered interface is available.
444 * @param iface The name of the interface.
445 */
446 void onAvailable(@NonNull String iface);
447
448 /**
449 * Called when the tethered interface is now unavailable.
450 */
451 void onUnavailable();
452 }
453
454 /**
455 * Request a tethered interface in tethering mode.
456 *
457 * <p>When this method is called and there is at least one ethernet interface available, the
458 * system will designate one to act as a tethered interface. If there is already a tethered
459 * interface, the existing interface will be used.
460 * @param callback A callback to be called once the request has been fulfilled.
461 */
Remi NGUYEN VAN11f39242020-03-09 13:56:18 +0900462 @RequiresPermission(anyOf = {
463 android.Manifest.permission.NETWORK_STACK,
464 android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
465 })
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900466 @NonNull
markchienc8e7d752020-02-26 20:54:55 +0800467 public TetheredInterfaceRequest requestTetheredInterface(@NonNull final Executor executor,
468 @NonNull final TetheredInterfaceCallback callback) {
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900469 Objects.requireNonNull(callback, "Callback must be non-null");
markchienc8e7d752020-02-26 20:54:55 +0800470 Objects.requireNonNull(executor, "Executor must be non-null");
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900471 final ITetheredInterfaceCallback cbInternal = new ITetheredInterfaceCallback.Stub() {
472 @Override
473 public void onAvailable(String iface) {
markchienc8e7d752020-02-26 20:54:55 +0800474 executor.execute(() -> callback.onAvailable(iface));
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900475 }
476
477 @Override
478 public void onUnavailable() {
markchienc8e7d752020-02-26 20:54:55 +0800479 executor.execute(() -> callback.onUnavailable());
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900480 }
481 };
482
483 try {
484 mService.requestTetheredInterface(cbInternal);
485 } catch (RemoteException e) {
486 throw e.rethrowFromSystemServer();
487 }
488 return new TetheredInterfaceRequest(mService, cbInternal);
489 }
James Mattis407ea1d2021-12-14 18:23:30 -0800490
Patrick Rohrd6156a92022-03-17 19:19:21 +0000491 private static final class NetworkInterfaceOutcomeReceiver
492 extends INetworkInterfaceOutcomeReceiver.Stub {
James Mattis407ea1d2021-12-14 18:23:30 -0800493 @NonNull
494 private final Executor mExecutor;
495 @NonNull
Patrick Rohrd6156a92022-03-17 19:19:21 +0000496 private final OutcomeReceiver<String, EthernetNetworkManagementException> mCallback;
James Mattis407ea1d2021-12-14 18:23:30 -0800497
Patrick Rohrd6156a92022-03-17 19:19:21 +0000498 NetworkInterfaceOutcomeReceiver(
James Mattis407ea1d2021-12-14 18:23:30 -0800499 @NonNull final Executor executor,
Patrick Rohrd6156a92022-03-17 19:19:21 +0000500 @NonNull final OutcomeReceiver<String, EthernetNetworkManagementException>
501 callback) {
James Mattis407ea1d2021-12-14 18:23:30 -0800502 Objects.requireNonNull(executor, "Pass a non-null executor");
Patrick Rohrd6156a92022-03-17 19:19:21 +0000503 Objects.requireNonNull(callback, "Pass a non-null callback");
James Mattis407ea1d2021-12-14 18:23:30 -0800504 mExecutor = executor;
Patrick Rohrd6156a92022-03-17 19:19:21 +0000505 mCallback = callback;
James Mattis407ea1d2021-12-14 18:23:30 -0800506 }
507
508 @Override
Patrick Rohrd6156a92022-03-17 19:19:21 +0000509 public void onResult(@NonNull String iface) {
510 mExecutor.execute(() -> mCallback.onResult(iface));
511 }
512
513 @Override
514 public void onError(@NonNull EthernetNetworkManagementException e) {
515 mExecutor.execute(() -> mCallback.onError(e));
James Mattis407ea1d2021-12-14 18:23:30 -0800516 }
517 }
518
Patrick Rohrd6156a92022-03-17 19:19:21 +0000519 private NetworkInterfaceOutcomeReceiver makeNetworkInterfaceOutcomeReceiver(
James Mattis407ea1d2021-12-14 18:23:30 -0800520 @Nullable final Executor executor,
Patrick Rohrd6156a92022-03-17 19:19:21 +0000521 @Nullable final OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
522 if (null != callback) {
523 Objects.requireNonNull(executor, "Pass a non-null executor, or a null callback");
James Mattis407ea1d2021-12-14 18:23:30 -0800524 }
Patrick Rohrd6156a92022-03-17 19:19:21 +0000525 final NetworkInterfaceOutcomeReceiver proxy;
526 if (null == callback) {
James Mattis407ea1d2021-12-14 18:23:30 -0800527 proxy = null;
528 } else {
Patrick Rohrd6156a92022-03-17 19:19:21 +0000529 proxy = new NetworkInterfaceOutcomeReceiver(executor, callback);
James Mattis407ea1d2021-12-14 18:23:30 -0800530 }
531 return proxy;
532 }
533
James Mattis28547372022-02-02 14:32:40 -0800534 /**
535 * Updates the configuration of an automotive device's ethernet network.
536 *
537 * The {@link EthernetNetworkUpdateRequest} {@code request} argument describes how to update the
538 * configuration for this network.
539 * Use {@link StaticIpConfiguration.Builder} to build a {@code StaticIpConfiguration} object for
540 * this network to put inside the {@code request}.
541 * Similarly, use {@link NetworkCapabilities.Builder} to build a {@code NetworkCapabilities}
542 * object for this network to put inside the {@code request}.
543 *
Patrick Rohr50c470e2022-03-28 13:03:08 +0200544 * The provided {@link OutcomeReceiver} is called once the operation has finished execution.
James Mattis28547372022-02-02 14:32:40 -0800545 *
546 * @param iface the name of the interface to act upon.
547 * @param request the {@link EthernetNetworkUpdateRequest} used to set an ethernet network's
548 * {@link StaticIpConfiguration} and {@link NetworkCapabilities} values.
Patrick Rohrd6156a92022-03-17 19:19:21 +0000549 * @param executor an {@link Executor} to execute the callback on. Optional if callback is null.
550 * @param callback an optional {@link OutcomeReceiver} to listen for completion of the
551 * operation. On success, {@link OutcomeReceiver#onResult} is called with the
552 * interface name. On error, {@link OutcomeReceiver#onError} is called with more
553 * information about the error.
James Mattis28547372022-02-02 14:32:40 -0800554 * @throws SecurityException if the process doesn't hold
555 * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
Patrick Rohr0f2cbe92022-03-28 11:47:20 +0200556 * @throws UnsupportedOperationException if the {@link NetworkCapabilities} are updated on a
557 * non-automotive device or this function is called on an
James Mattis28547372022-02-02 14:32:40 -0800558 * unsupported interface.
559 * @hide
560 */
561 @SystemApi
562 @RequiresPermission(anyOf = {
563 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
564 android.Manifest.permission.NETWORK_STACK,
565 android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
James Mattis28547372022-02-02 14:32:40 -0800566 public void updateConfiguration(
James Mattis407ea1d2021-12-14 18:23:30 -0800567 @NonNull String iface,
James Mattis1ecadfa2022-01-28 13:42:38 -0800568 @NonNull EthernetNetworkUpdateRequest request,
James Mattis407ea1d2021-12-14 18:23:30 -0800569 @Nullable @CallbackExecutor Executor executor,
Patrick Rohrd6156a92022-03-17 19:19:21 +0000570 @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
James Mattis28547372022-02-02 14:32:40 -0800571 Objects.requireNonNull(iface, "iface must be non-null");
572 Objects.requireNonNull(request, "request must be non-null");
Patrick Rohrd6156a92022-03-17 19:19:21 +0000573 final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
574 executor, callback);
James Mattis407ea1d2021-12-14 18:23:30 -0800575 try {
576 mService.updateConfiguration(iface, request, proxy);
577 } catch (RemoteException e) {
578 throw e.rethrowFromSystemServer();
579 }
580 }
581
James Mattis28547372022-02-02 14:32:40 -0800582 /**
Patrick Rohr3879cf12022-03-16 12:34:41 +0100583 * Enable a network interface.
James Mattis28547372022-02-02 14:32:40 -0800584 *
Patrick Rohr50c470e2022-03-28 13:03:08 +0200585 * Enables a previously disabled network interface. An attempt to enable an already-enabled
586 * interface is ignored.
587 * The provided {@link OutcomeReceiver} is called once the operation has finished execution.
James Mattis28547372022-02-02 14:32:40 -0800588 *
Patrick Rohr3879cf12022-03-16 12:34:41 +0100589 * @param iface the name of the interface to enable.
Patrick Rohrd6156a92022-03-17 19:19:21 +0000590 * @param executor an {@link Executor} to execute the callback on. Optional if callback is null.
591 * @param callback an optional {@link OutcomeReceiver} to listen for completion of the
592 * operation. On success, {@link OutcomeReceiver#onResult} is called with the
593 * interface name. On error, {@link OutcomeReceiver#onError} is called with more
594 * information about the error.
James Mattis28547372022-02-02 14:32:40 -0800595 * @throws SecurityException if the process doesn't hold
596 * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
James Mattis28547372022-02-02 14:32:40 -0800597 * @hide
598 */
599 @SystemApi
600 @RequiresPermission(anyOf = {
601 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
602 android.Manifest.permission.NETWORK_STACK,
603 android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
604 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
Patrick Rohr3879cf12022-03-16 12:34:41 +0100605 public void enableInterface(
James Mattis407ea1d2021-12-14 18:23:30 -0800606 @NonNull String iface,
607 @Nullable @CallbackExecutor Executor executor,
Patrick Rohrd6156a92022-03-17 19:19:21 +0000608 @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
James Mattis28547372022-02-02 14:32:40 -0800609 Objects.requireNonNull(iface, "iface must be non-null");
Patrick Rohrd6156a92022-03-17 19:19:21 +0000610 final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
611 executor, callback);
James Mattis407ea1d2021-12-14 18:23:30 -0800612 try {
613 mService.connectNetwork(iface, proxy);
614 } catch (RemoteException e) {
615 throw e.rethrowFromSystemServer();
616 }
617 }
618
James Mattis28547372022-02-02 14:32:40 -0800619 /**
Patrick Rohr3879cf12022-03-16 12:34:41 +0100620 * Disable a network interface.
James Mattis28547372022-02-02 14:32:40 -0800621 *
Patrick Rohr50c470e2022-03-28 13:03:08 +0200622 * Disables the specified interface. If this interface is in use in a connected
623 * {@link android.net.Network}, then that {@code Network} will be torn down.
624 * The provided {@link OutcomeReceiver} is called once the operation has finished execution.
James Mattis28547372022-02-02 14:32:40 -0800625 *
Patrick Rohr3879cf12022-03-16 12:34:41 +0100626 * @param iface the name of the interface to disable.
Patrick Rohrd6156a92022-03-17 19:19:21 +0000627 * @param executor an {@link Executor} to execute the callback on. Optional if callback is null.
628 * @param callback an optional {@link OutcomeReceiver} to listen for completion of the
629 * operation. On success, {@link OutcomeReceiver#onResult} is called with the
630 * interface name. On error, {@link OutcomeReceiver#onError} is called with more
631 * information about the error.
James Mattis28547372022-02-02 14:32:40 -0800632 * @throws SecurityException if the process doesn't hold
633 * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
James Mattis28547372022-02-02 14:32:40 -0800634 * @hide
635 */
636 @SystemApi
637 @RequiresPermission(anyOf = {
638 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
639 android.Manifest.permission.NETWORK_STACK,
640 android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
641 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
Patrick Rohr3879cf12022-03-16 12:34:41 +0100642 public void disableInterface(
James Mattis407ea1d2021-12-14 18:23:30 -0800643 @NonNull String iface,
644 @Nullable @CallbackExecutor Executor executor,
Patrick Rohrd6156a92022-03-17 19:19:21 +0000645 @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
James Mattis28547372022-02-02 14:32:40 -0800646 Objects.requireNonNull(iface, "iface must be non-null");
Patrick Rohrd6156a92022-03-17 19:19:21 +0000647 final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
648 executor, callback);
James Mattis407ea1d2021-12-14 18:23:30 -0800649 try {
650 mService.disconnectNetwork(iface, proxy);
651 } catch (RemoteException e) {
652 throw e.rethrowFromSystemServer();
653 }
654 }
markchien5912ab62022-03-17 18:19:39 +0800655
656 /**
657 * Change ethernet setting.
658 *
659 * @param enabled enable or disable ethernet settings.
660 *
661 * @hide
662 */
663 @RequiresPermission(anyOf = {
664 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
665 android.Manifest.permission.NETWORK_STACK,
666 android.Manifest.permission.NETWORK_SETTINGS})
667 @SystemApi(client = MODULE_LIBRARIES)
668 public void setEthernetEnabled(boolean enabled) {
669 try {
670 mService.setEthernetEnabled(enabled);
671 } catch (RemoteException e) {
672 throw e.rethrowFromSystemServer();
673 }
674 }
675
676 /**
677 * Listen to changes in the state of ethernet.
678 *
679 * @param executor to run callbacks on.
680 * @param listener to listen ethernet state changed.
681 *
682 * @hide
683 */
684 @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
685 @SystemApi(client = MODULE_LIBRARIES)
686 public void addEthernetStateListener(@NonNull Executor executor,
687 @NonNull IntConsumer listener) {
688 Objects.requireNonNull(executor);
689 Objects.requireNonNull(listener);
690 synchronized (mListenerLock) {
691 maybeAddServiceListener();
692 mEthernetStateListeners.add(new ListenerInfo<IntConsumer>(executor, listener));
693 }
694 }
695
696 /**
697 * Removes a listener.
698 *
699 * @param listener to listen ethernet state changed.
700 *
701 * @hide
702 */
703 @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
704 @SystemApi(client = MODULE_LIBRARIES)
705 public void removeEthernetStateListener(@NonNull IntConsumer listener) {
706 Objects.requireNonNull(listener);
707 synchronized (mListenerLock) {
708 mEthernetStateListeners.removeIf(l -> l.listener == listener);
709 maybeRemoveServiceListener();
710 }
711 }
Xiao Ma1edd4552022-03-17 05:56:09 +0000712
713 /**
714 * Returns an array of existing Ethernet interface names regardless whether the interface
715 * is available or not currently.
716 * @hide
717 */
718 @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
719 @SystemApi(client = MODULE_LIBRARIES)
720 @NonNull
721 public List<String> getInterfaceList() {
722 try {
723 return mService.getInterfaceList();
724 } catch (RemoteException e) {
725 throw e.rethrowAsRuntimeException();
726 }
727 }
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700728}