blob: 217d670743d7f5282b3061a64849287ac2202873 [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;
Lorenzo Colitti19b8b882020-01-24 19:29:17 +090042import java.util.Objects;
markchienc8e7d752020-02-26 20:54:55 +080043import java.util.concurrent.Executor;
markchien5912ab62022-03-17 18:19:39 +080044import java.util.function.IntConsumer;
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090045
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070046/**
Xiao Ma7f9ac502022-01-30 11:27:16 +000047 * A class that manages and configures Ethernet interfaces.
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070048 *
49 * @hide
50 */
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +090051@SystemApi
Jeff Sharkeyad1cebe2017-06-02 17:36:26 -060052@SystemService(Context.ETHERNET_SERVICE)
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070053public class EthernetManager {
54 private static final String TAG = "EthernetManager";
55
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070056 private final IEthernetManager mService;
markchien5912ab62022-03-17 18:19:39 +080057 @GuardedBy("mListenerLock")
58 private final ArrayList<ListenerInfo<InterfaceStateListener>> mIfaceListeners =
59 new ArrayList<>();
60 @GuardedBy("mListenerLock")
61 private final ArrayList<ListenerInfo<IntConsumer>> mEthernetStateListeners =
62 new ArrayList<>();
63 final Object mListenerLock = new Object();
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090064 private final IEthernetServiceListener.Stub mServiceListener =
65 new IEthernetServiceListener.Stub() {
66 @Override
markchien5912ab62022-03-17 18:19:39 +080067 public void onEthernetStateChanged(int state) {
68 synchronized (mListenerLock) {
69 for (ListenerInfo<IntConsumer> li : mEthernetStateListeners) {
70 li.executor.execute(() -> {
71 li.listener.accept(state);
72 });
73 }
74 }
75 }
76
77 @Override
Xiao Ma7f9ac502022-01-30 11:27:16 +000078 public void onInterfaceStateChanged(String iface, int state, int role,
79 IpConfiguration configuration) {
markchien5912ab62022-03-17 18:19:39 +080080 synchronized (mListenerLock) {
81 for (ListenerInfo<InterfaceStateListener> li : mIfaceListeners) {
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090082 li.executor.execute(() ->
Xiao Ma7f9ac502022-01-30 11:27:16 +000083 li.listener.onInterfaceStateChanged(iface, state, role,
84 configuration));
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090085 }
86 }
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090087 }
88 };
89
markchien5912ab62022-03-17 18:19:39 +080090 /**
91 * Indicates that Ethernet is disabled.
92 *
93 * @hide
94 */
95 @SystemApi(client = MODULE_LIBRARIES)
96 public static final int ETHERNET_STATE_DISABLED = 0;
97
98 /**
99 * Indicates that Ethernet is enabled.
100 *
101 * @hide
102 */
103 @SystemApi(client = MODULE_LIBRARIES)
104 public static final int ETHERNET_STATE_ENABLED = 1;
105
106 private static class ListenerInfo<T> {
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900107 @NonNull
108 public final Executor executor;
109 @NonNull
markchien5912ab62022-03-17 18:19:39 +0800110 public final T listener;
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900111
markchien5912ab62022-03-17 18:19:39 +0800112 private ListenerInfo(@NonNull Executor executor, @NonNull T listener) {
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900113 this.executor = executor;
114 this.listener = listener;
115 }
116 }
117
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900118 /**
Xiao Ma7f9ac502022-01-30 11:27:16 +0000119 * The interface is absent.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900120 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900121 */
Xiao Ma7f9ac502022-01-30 11:27:16 +0000122 @SystemApi(client = MODULE_LIBRARIES)
123 public static final int STATE_ABSENT = 0;
124
125 /**
126 * The interface is present but link is down.
127 * @hide
128 */
129 @SystemApi(client = MODULE_LIBRARIES)
130 public static final int STATE_LINK_DOWN = 1;
131
132 /**
133 * The interface is present and link is up.
134 * @hide
135 */
136 @SystemApi(client = MODULE_LIBRARIES)
137 public static final int STATE_LINK_UP = 2;
138
139 /** @hide */
140 @IntDef(prefix = "STATE_", value = {STATE_ABSENT, STATE_LINK_DOWN, STATE_LINK_UP})
141 @Retention(RetentionPolicy.SOURCE)
142 public @interface InterfaceState {}
143
144 /**
145 * The interface currently does not have any specific role.
146 * @hide
147 */
148 @SystemApi(client = MODULE_LIBRARIES)
149 public static final int ROLE_NONE = 0;
150
151 /**
152 * The interface is in client mode (e.g., connected to the Internet).
153 * @hide
154 */
155 @SystemApi(client = MODULE_LIBRARIES)
156 public static final int ROLE_CLIENT = 1;
157
158 /**
159 * Ethernet interface is in server mode (e.g., providing Internet access to tethered devices).
160 * @hide
161 */
162 @SystemApi(client = MODULE_LIBRARIES)
163 public static final int ROLE_SERVER = 2;
164
165 /** @hide */
166 @IntDef(prefix = "ROLE_", value = {ROLE_NONE, ROLE_CLIENT, ROLE_SERVER})
167 @Retention(RetentionPolicy.SOURCE)
168 public @interface Role {}
169
170 /**
171 * A listener that receives notifications about the state of Ethernet interfaces on the system.
172 * @hide
173 */
174 @SystemApi(client = MODULE_LIBRARIES)
175 public interface InterfaceStateListener {
176 /**
177 * Called when an Ethernet interface changes state.
178 *
179 * @param iface the name of the interface.
180 * @param state the current state of the interface, or {@link #STATE_ABSENT} if the
181 * interface was removed.
Lorenzo Colitti6c032e52022-02-11 12:18:59 +0900182 * @param role whether the interface is in client mode or server mode.
Xiao Ma7f9ac502022-01-30 11:27:16 +0000183 * @param configuration the current IP configuration of the interface.
184 * @hide
185 */
186 @SystemApi(client = MODULE_LIBRARIES)
187 void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
188 @Role int role, @Nullable IpConfiguration configuration);
189 }
190
191 /**
192 * A listener interface to receive notification on changes in Ethernet.
193 * This has never been a supported API. Use {@link InterfaceStateListener} instead.
194 * @hide
195 */
196 public interface Listener extends InterfaceStateListener {
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900197 /**
198 * Called when Ethernet port's availability is changed.
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700199 * @param iface Ethernet interface name
200 * @param isAvailable {@code true} if Ethernet port exists.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900201 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900202 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000203 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700204 void onAvailabilityChanged(String iface, boolean isAvailable);
Xiao Ma7f9ac502022-01-30 11:27:16 +0000205
206 /** Default implementation for backwards compatibility. Only calls the legacy listener. */
207 default void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
208 @Role int role, @Nullable IpConfiguration configuration) {
209 onAvailabilityChanged(iface, (state >= STATE_LINK_UP));
210 }
211
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900212 }
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700213
214 /**
215 * Create a new EthernetManager instance.
216 * Applications will almost always want to use
217 * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
218 * the standard {@link android.content.Context#ETHERNET_SERVICE Context.ETHERNET_SERVICE}.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900219 * @hide
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700220 */
221 public EthernetManager(Context context, IEthernetManager service) {
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700222 mService = service;
223 }
224
225 /**
Lorenzo Colitti56e4e582014-05-22 11:51:27 -0700226 * Get Ethernet configuration.
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700227 * @return the Ethernet Configuration, contained in {@link IpConfiguration}.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900228 * @hide
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700229 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000230 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700231 public IpConfiguration getConfiguration(String iface) {
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700232 try {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700233 return mService.getConfiguration(iface);
Jeff Sharkeyf7138282016-03-01 19:27:23 -0700234 } catch (RemoteException e) {
235 throw e.rethrowFromSystemServer();
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700236 }
237 }
238
239 /**
Lorenzo Colitti56e4e582014-05-22 11:51:27 -0700240 * Set Ethernet configuration.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900241 * @hide
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700242 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000243 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Xiao Ma7f9ac502022-01-30 11:27:16 +0000244 public void setConfiguration(@NonNull String iface, @NonNull IpConfiguration config) {
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700245 try {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700246 mService.setConfiguration(iface, config);
Jeff Sharkeyf7138282016-03-01 19:27:23 -0700247 } catch (RemoteException e) {
248 throw e.rethrowFromSystemServer();
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900249 }
250 }
251
252 /**
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700253 * Indicates whether the system currently has one or more Ethernet interfaces.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900254 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900255 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000256 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900257 public boolean isAvailable() {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700258 return getAvailableInterfaces().length > 0;
259 }
260
261 /**
262 * Indicates whether the system has given interface.
263 *
264 * @param iface Ethernet interface name
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900265 * @hide
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700266 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000267 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700268 public boolean isAvailable(String iface) {
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900269 try {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700270 return mService.isAvailable(iface);
Jeff Sharkeyf7138282016-03-01 19:27:23 -0700271 } catch (RemoteException e) {
272 throw e.rethrowFromSystemServer();
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900273 }
274 }
275
276 /**
277 * Adds a listener.
Xiao Ma7f9ac502022-01-30 11:27:16 +0000278 * This has never been a supported API. Use {@link #addInterfaceStateListener} instead.
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900279 *
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900280 * @param listener A {@link Listener} to add.
281 * @throws IllegalArgumentException If the listener is null.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900282 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900283 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000284 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900285 public void addListener(@NonNull Listener listener) {
286 addListener(listener, BackgroundThread.getExecutor());
287 }
288
289 /**
290 * Adds a listener.
Xiao Ma7f9ac502022-01-30 11:27:16 +0000291 * This has never been a supported API. Use {@link #addInterfaceStateListener} instead.
292 *
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900293 * @param listener A {@link Listener} to add.
294 * @param executor Executor to run callbacks on.
295 * @throws IllegalArgumentException If the listener or executor is null.
296 * @hide
297 */
298 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
299 public void addListener(@NonNull Listener listener, @NonNull Executor executor) {
Xiao Ma7f9ac502022-01-30 11:27:16 +0000300 addInterfaceStateListener(executor, listener);
301 }
302
303 /**
304 * Listen to changes in the state of Ethernet interfaces.
305 *
306 * Adds a listener to receive notification for any state change of all existing Ethernet
307 * interfaces.
308 * <p>{@link Listener#onInterfaceStateChanged} will be triggered immediately for all
309 * existing interfaces upon adding a listener. The same method will be called on the
310 * listener every time any of the interface changes state. In particular, if an
311 * interface is removed, it will be called with state {@link #STATE_ABSENT}.
312 * <p>Use {@link #removeInterfaceStateListener} with the same object to stop listening.
313 *
314 * @param executor Executor to run callbacks on.
315 * @param listener A {@link Listener} to add.
316 * @hide
317 */
318 @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
319 @SystemApi(client = MODULE_LIBRARIES)
320 public void addInterfaceStateListener(@NonNull Executor executor,
321 @NonNull InterfaceStateListener listener) {
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900322 if (listener == null || executor == null) {
323 throw new NullPointerException("listener and executor must not be null");
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900324 }
markchien5912ab62022-03-17 18:19:39 +0800325 synchronized (mListenerLock) {
326 maybeAddServiceListener();
327 mIfaceListeners.add(new ListenerInfo<InterfaceStateListener>(executor, listener));
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900328 }
329 }
330
markchien5912ab62022-03-17 18:19:39 +0800331 @GuardedBy("mListenerLock")
332 private void maybeAddServiceListener() {
333 if (!mIfaceListeners.isEmpty() || !mEthernetStateListeners.isEmpty()) return;
334
335 try {
336 mService.addListener(mServiceListener);
337 } catch (RemoteException e) {
338 throw e.rethrowFromSystemServer();
339 }
340
341 }
342
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900343 /**
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700344 * Returns an array of available Ethernet interface names.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900345 * @hide
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700346 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000347 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700348 public String[] getAvailableInterfaces() {
349 try {
350 return mService.getAvailableInterfaces();
351 } catch (RemoteException e) {
352 throw e.rethrowAsRuntimeException();
353 }
354 }
355
356 /**
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900357 * Removes a listener.
Xiao Ma7f9ac502022-01-30 11:27:16 +0000358 *
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900359 * @param listener A {@link Listener} to remove.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900360 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900361 */
Xiao Ma7f9ac502022-01-30 11:27:16 +0000362 @SystemApi(client = MODULE_LIBRARIES)
363 public void removeInterfaceStateListener(@NonNull InterfaceStateListener listener) {
364 Objects.requireNonNull(listener);
markchien5912ab62022-03-17 18:19:39 +0800365 synchronized (mListenerLock) {
366 mIfaceListeners.removeIf(l -> l.listener == listener);
367 maybeRemoveServiceListener();
368 }
369 }
370
371 @GuardedBy("mListenerLock")
372 private void maybeRemoveServiceListener() {
373 if (!mIfaceListeners.isEmpty() || !mEthernetStateListeners.isEmpty()) return;
374
375 try {
376 mService.removeListener(mServiceListener);
377 } catch (RemoteException e) {
378 throw e.rethrowFromSystemServer();
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700379 }
380 }
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900381
382 /**
Xiao Ma7f9ac502022-01-30 11:27:16 +0000383 * Removes a listener.
384 * This has never been a supported API. Use {@link #removeInterfaceStateListener} instead.
385 * @param listener A {@link Listener} to remove.
386 * @hide
387 */
388 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
389 public void removeListener(@NonNull Listener listener) {
390 if (listener == null) {
391 throw new IllegalArgumentException("listener must not be null");
392 }
393 removeInterfaceStateListener(listener);
394 }
395
396 /**
Lorenzo Colitti013187d2020-03-17 00:16:13 +0900397 * Whether to treat interfaces created by {@link TestNetworkManager#createTapInterface}
398 * as Ethernet interfaces. The effects of this method apply to any test interfaces that are
399 * already present on the system.
400 * @hide
401 */
Xiao Ma7f9ac502022-01-30 11:27:16 +0000402 @SystemApi(client = MODULE_LIBRARIES)
Lorenzo Colitti013187d2020-03-17 00:16:13 +0900403 public void setIncludeTestInterfaces(boolean include) {
404 try {
405 mService.setIncludeTestInterfaces(include);
406 } catch (RemoteException e) {
407 throw e.rethrowFromSystemServer();
408 }
409 }
410
411 /**
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900412 * A request for a tethered interface.
413 */
414 public static class TetheredInterfaceRequest {
415 private final IEthernetManager mService;
416 private final ITetheredInterfaceCallback mCb;
417
418 private TetheredInterfaceRequest(@NonNull IEthernetManager service,
419 @NonNull ITetheredInterfaceCallback cb) {
420 this.mService = service;
421 this.mCb = cb;
422 }
423
424 /**
425 * Release the request, causing the interface to revert back from tethering mode if there
426 * is no other requestor.
427 */
428 public void release() {
429 try {
430 mService.releaseTetheredInterface(mCb);
431 } catch (RemoteException e) {
432 e.rethrowFromSystemServer();
433 }
434 }
435 }
436
437 /**
438 * Callback for {@link #requestTetheredInterface(TetheredInterfaceCallback)}.
439 */
440 public interface TetheredInterfaceCallback {
441 /**
442 * Called when the tethered interface is available.
443 * @param iface The name of the interface.
444 */
445 void onAvailable(@NonNull String iface);
446
447 /**
448 * Called when the tethered interface is now unavailable.
449 */
450 void onUnavailable();
451 }
452
453 /**
454 * Request a tethered interface in tethering mode.
455 *
456 * <p>When this method is called and there is at least one ethernet interface available, the
457 * system will designate one to act as a tethered interface. If there is already a tethered
458 * interface, the existing interface will be used.
459 * @param callback A callback to be called once the request has been fulfilled.
460 */
Remi NGUYEN VAN11f39242020-03-09 13:56:18 +0900461 @RequiresPermission(anyOf = {
462 android.Manifest.permission.NETWORK_STACK,
463 android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
464 })
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900465 @NonNull
markchienc8e7d752020-02-26 20:54:55 +0800466 public TetheredInterfaceRequest requestTetheredInterface(@NonNull final Executor executor,
467 @NonNull final TetheredInterfaceCallback callback) {
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900468 Objects.requireNonNull(callback, "Callback must be non-null");
markchienc8e7d752020-02-26 20:54:55 +0800469 Objects.requireNonNull(executor, "Executor must be non-null");
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900470 final ITetheredInterfaceCallback cbInternal = new ITetheredInterfaceCallback.Stub() {
471 @Override
472 public void onAvailable(String iface) {
markchienc8e7d752020-02-26 20:54:55 +0800473 executor.execute(() -> callback.onAvailable(iface));
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900474 }
475
476 @Override
477 public void onUnavailable() {
markchienc8e7d752020-02-26 20:54:55 +0800478 executor.execute(() -> callback.onUnavailable());
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900479 }
480 };
481
482 try {
483 mService.requestTetheredInterface(cbInternal);
484 } catch (RemoteException e) {
485 throw e.rethrowFromSystemServer();
486 }
487 return new TetheredInterfaceRequest(mService, cbInternal);
488 }
James Mattis407ea1d2021-12-14 18:23:30 -0800489
Patrick Rohrd6156a92022-03-17 19:19:21 +0000490 private static final class NetworkInterfaceOutcomeReceiver
491 extends INetworkInterfaceOutcomeReceiver.Stub {
James Mattis407ea1d2021-12-14 18:23:30 -0800492 @NonNull
493 private final Executor mExecutor;
494 @NonNull
Patrick Rohrd6156a92022-03-17 19:19:21 +0000495 private final OutcomeReceiver<String, EthernetNetworkManagementException> mCallback;
James Mattis407ea1d2021-12-14 18:23:30 -0800496
Patrick Rohrd6156a92022-03-17 19:19:21 +0000497 NetworkInterfaceOutcomeReceiver(
James Mattis407ea1d2021-12-14 18:23:30 -0800498 @NonNull final Executor executor,
Patrick Rohrd6156a92022-03-17 19:19:21 +0000499 @NonNull final OutcomeReceiver<String, EthernetNetworkManagementException>
500 callback) {
James Mattis407ea1d2021-12-14 18:23:30 -0800501 Objects.requireNonNull(executor, "Pass a non-null executor");
Patrick Rohrd6156a92022-03-17 19:19:21 +0000502 Objects.requireNonNull(callback, "Pass a non-null callback");
James Mattis407ea1d2021-12-14 18:23:30 -0800503 mExecutor = executor;
Patrick Rohrd6156a92022-03-17 19:19:21 +0000504 mCallback = callback;
James Mattis407ea1d2021-12-14 18:23:30 -0800505 }
506
507 @Override
Patrick Rohrd6156a92022-03-17 19:19:21 +0000508 public void onResult(@NonNull String iface) {
509 mExecutor.execute(() -> mCallback.onResult(iface));
510 }
511
512 @Override
513 public void onError(@NonNull EthernetNetworkManagementException e) {
514 mExecutor.execute(() -> mCallback.onError(e));
James Mattis407ea1d2021-12-14 18:23:30 -0800515 }
516 }
517
Patrick Rohrd6156a92022-03-17 19:19:21 +0000518 private NetworkInterfaceOutcomeReceiver makeNetworkInterfaceOutcomeReceiver(
James Mattis407ea1d2021-12-14 18:23:30 -0800519 @Nullable final Executor executor,
Patrick Rohrd6156a92022-03-17 19:19:21 +0000520 @Nullable final OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
521 if (null != callback) {
522 Objects.requireNonNull(executor, "Pass a non-null executor, or a null callback");
James Mattis407ea1d2021-12-14 18:23:30 -0800523 }
Patrick Rohrd6156a92022-03-17 19:19:21 +0000524 final NetworkInterfaceOutcomeReceiver proxy;
525 if (null == callback) {
James Mattis407ea1d2021-12-14 18:23:30 -0800526 proxy = null;
527 } else {
Patrick Rohrd6156a92022-03-17 19:19:21 +0000528 proxy = new NetworkInterfaceOutcomeReceiver(executor, callback);
James Mattis407ea1d2021-12-14 18:23:30 -0800529 }
530 return proxy;
531 }
532
James Mattis28547372022-02-02 14:32:40 -0800533 /**
534 * Updates the configuration of an automotive device's ethernet network.
535 *
536 * The {@link EthernetNetworkUpdateRequest} {@code request} argument describes how to update the
537 * configuration for this network.
538 * Use {@link StaticIpConfiguration.Builder} to build a {@code StaticIpConfiguration} object for
539 * this network to put inside the {@code request}.
540 * Similarly, use {@link NetworkCapabilities.Builder} to build a {@code NetworkCapabilities}
541 * object for this network to put inside the {@code request}.
542 *
Patrick Rohrd6156a92022-03-17 19:19:21 +0000543 * This function accepts an {@link OutcomeReceiver} that is called once the operation has
544 * 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}.
556 * @throws UnsupportedOperationException if called on a non-automotive device or on an
557 * unsupported interface.
558 * @hide
559 */
560 @SystemApi
561 @RequiresPermission(anyOf = {
562 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
563 android.Manifest.permission.NETWORK_STACK,
564 android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
James Mattis28547372022-02-02 14:32:40 -0800565 public void updateConfiguration(
James Mattis407ea1d2021-12-14 18:23:30 -0800566 @NonNull String iface,
James Mattis1ecadfa2022-01-28 13:42:38 -0800567 @NonNull EthernetNetworkUpdateRequest request,
James Mattis407ea1d2021-12-14 18:23:30 -0800568 @Nullable @CallbackExecutor Executor executor,
Patrick Rohrd6156a92022-03-17 19:19:21 +0000569 @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
James Mattis28547372022-02-02 14:32:40 -0800570 Objects.requireNonNull(iface, "iface must be non-null");
571 Objects.requireNonNull(request, "request must be non-null");
Patrick Rohrd6156a92022-03-17 19:19:21 +0000572 final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
573 executor, callback);
James Mattis407ea1d2021-12-14 18:23:30 -0800574 try {
575 mService.updateConfiguration(iface, request, proxy);
576 } catch (RemoteException e) {
577 throw e.rethrowFromSystemServer();
578 }
579 }
580
James Mattis28547372022-02-02 14:32:40 -0800581 /**
582 * Set an ethernet network's link state up.
583 *
Patrick Rohrd6156a92022-03-17 19:19:21 +0000584 * When the link is successfully turned up, the callback will be called with the network
585 * interface was torn down, if any. If any error or unexpected condition happens while the
586 * system tries to turn the interface down, the callback will be called with an appropriate
587 * exception. The callback is guaranteed to be called exactly once for each call to this method.
James Mattis28547372022-02-02 14:32:40 -0800588 *
589 * @param iface the name of the interface to act upon.
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}.
597 * @throws UnsupportedOperationException if called on a non-automotive device.
598 * @hide
599 */
600 @SystemApi
601 @RequiresPermission(anyOf = {
602 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
603 android.Manifest.permission.NETWORK_STACK,
604 android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
605 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
606 public void connectNetwork(
James Mattis407ea1d2021-12-14 18:23:30 -0800607 @NonNull String iface,
608 @Nullable @CallbackExecutor Executor executor,
Patrick Rohrd6156a92022-03-17 19:19:21 +0000609 @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
James Mattis28547372022-02-02 14:32:40 -0800610 Objects.requireNonNull(iface, "iface must be non-null");
Patrick Rohrd6156a92022-03-17 19:19:21 +0000611 final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
612 executor, callback);
James Mattis407ea1d2021-12-14 18:23:30 -0800613 try {
614 mService.connectNetwork(iface, proxy);
615 } catch (RemoteException e) {
616 throw e.rethrowFromSystemServer();
617 }
618 }
619
James Mattis28547372022-02-02 14:32:40 -0800620 /**
621 * Set an ethernet network's link state down.
622 *
Patrick Rohrd6156a92022-03-17 19:19:21 +0000623 * When the link is successfully turned down, the callback will be called with the network
624 * interface was torn down, if any. If any error or unexpected condition happens while the
625 * system tries to turn the interface down, the callback will be called with an appropriate
626 * exception. The callback is guaranteed to be called exactly once for each call to this method.
James Mattis28547372022-02-02 14:32:40 -0800627 *
628 * @param iface the name of the interface to act upon.
Patrick Rohrd6156a92022-03-17 19:19:21 +0000629 * @param executor an {@link Executor} to execute the callback on. Optional if callback is null.
630 * @param callback an optional {@link OutcomeReceiver} to listen for completion of the
631 * operation. On success, {@link OutcomeReceiver#onResult} is called with the
632 * interface name. On error, {@link OutcomeReceiver#onError} is called with more
633 * information about the error.
James Mattis28547372022-02-02 14:32:40 -0800634 * @throws SecurityException if the process doesn't hold
635 * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
636 * @throws UnsupportedOperationException if called on a non-automotive device.
637 * @hide
638 */
639 @SystemApi
640 @RequiresPermission(anyOf = {
641 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
642 android.Manifest.permission.NETWORK_STACK,
643 android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
644 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
645 public void disconnectNetwork(
James Mattis407ea1d2021-12-14 18:23:30 -0800646 @NonNull String iface,
647 @Nullable @CallbackExecutor Executor executor,
Patrick Rohrd6156a92022-03-17 19:19:21 +0000648 @Nullable OutcomeReceiver<String, EthernetNetworkManagementException> callback) {
James Mattis28547372022-02-02 14:32:40 -0800649 Objects.requireNonNull(iface, "iface must be non-null");
Patrick Rohrd6156a92022-03-17 19:19:21 +0000650 final NetworkInterfaceOutcomeReceiver proxy = makeNetworkInterfaceOutcomeReceiver(
651 executor, callback);
James Mattis407ea1d2021-12-14 18:23:30 -0800652 try {
653 mService.disconnectNetwork(iface, proxy);
654 } catch (RemoteException e) {
655 throw e.rethrowFromSystemServer();
656 }
657 }
markchien5912ab62022-03-17 18:19:39 +0800658
659 /**
660 * Change ethernet setting.
661 *
662 * @param enabled enable or disable ethernet settings.
663 *
664 * @hide
665 */
666 @RequiresPermission(anyOf = {
667 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
668 android.Manifest.permission.NETWORK_STACK,
669 android.Manifest.permission.NETWORK_SETTINGS})
670 @SystemApi(client = MODULE_LIBRARIES)
671 public void setEthernetEnabled(boolean enabled) {
672 try {
673 mService.setEthernetEnabled(enabled);
674 } catch (RemoteException e) {
675 throw e.rethrowFromSystemServer();
676 }
677 }
678
679 /**
680 * Listen to changes in the state of ethernet.
681 *
682 * @param executor to run callbacks on.
683 * @param listener to listen ethernet state changed.
684 *
685 * @hide
686 */
687 @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
688 @SystemApi(client = MODULE_LIBRARIES)
689 public void addEthernetStateListener(@NonNull Executor executor,
690 @NonNull IntConsumer listener) {
691 Objects.requireNonNull(executor);
692 Objects.requireNonNull(listener);
693 synchronized (mListenerLock) {
694 maybeAddServiceListener();
695 mEthernetStateListeners.add(new ListenerInfo<IntConsumer>(executor, listener));
696 }
697 }
698
699 /**
700 * Removes a listener.
701 *
702 * @param listener to listen ethernet state changed.
703 *
704 * @hide
705 */
706 @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
707 @SystemApi(client = MODULE_LIBRARIES)
708 public void removeEthernetStateListener(@NonNull IntConsumer listener) {
709 Objects.requireNonNull(listener);
710 synchronized (mListenerLock) {
711 mEthernetStateListeners.removeIf(l -> l.listener == listener);
712 maybeRemoveServiceListener();
713 }
714 }
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700715}