blob: eba51c11487ec0fd991092d5d453ee218f9c7f8f [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;
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070033import android.os.RemoteException;
34
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090035import com.android.internal.annotations.GuardedBy;
36import com.android.internal.os.BackgroundThread;
37
Xiao Ma7f9ac502022-01-30 11:27:16 +000038import java.lang.annotation.Retention;
39import java.lang.annotation.RetentionPolicy;
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090040import java.util.ArrayList;
Lorenzo Colitti19b8b882020-01-24 19:29:17 +090041import java.util.Objects;
markchienc8e7d752020-02-26 20:54:55 +080042import java.util.concurrent.Executor;
James Mattis407ea1d2021-12-14 18:23:30 -080043import java.util.function.BiConsumer;
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090044
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070045/**
Xiao Ma7f9ac502022-01-30 11:27:16 +000046 * A class that manages and configures Ethernet interfaces.
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070047 *
48 * @hide
49 */
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +090050@SystemApi
Jeff Sharkeyad1cebe2017-06-02 17:36:26 -060051@SystemService(Context.ETHERNET_SERVICE)
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070052public class EthernetManager {
53 private static final String TAG = "EthernetManager";
54
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -070055 private final IEthernetManager mService;
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090056 @GuardedBy("mListeners")
57 private final ArrayList<ListenerInfo> mListeners = new ArrayList<>();
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090058 private final IEthernetServiceListener.Stub mServiceListener =
59 new IEthernetServiceListener.Stub() {
60 @Override
Xiao Ma7f9ac502022-01-30 11:27:16 +000061 public void onInterfaceStateChanged(String iface, int state, int role,
62 IpConfiguration configuration) {
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090063 synchronized (mListeners) {
64 for (ListenerInfo li : mListeners) {
65 li.executor.execute(() ->
Xiao Ma7f9ac502022-01-30 11:27:16 +000066 li.listener.onInterfaceStateChanged(iface, state, role,
67 configuration));
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090068 }
69 }
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090070 }
71 };
72
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090073 private static class ListenerInfo {
74 @NonNull
75 public final Executor executor;
76 @NonNull
Xiao Ma7f9ac502022-01-30 11:27:16 +000077 public final InterfaceStateListener listener;
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090078
Xiao Ma7f9ac502022-01-30 11:27:16 +000079 private ListenerInfo(@NonNull Executor executor, @NonNull InterfaceStateListener listener) {
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +090080 this.executor = executor;
81 this.listener = listener;
82 }
83 }
84
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090085 /**
Xiao Ma7f9ac502022-01-30 11:27:16 +000086 * The interface is absent.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +090087 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +090088 */
Xiao Ma7f9ac502022-01-30 11:27:16 +000089 @SystemApi(client = MODULE_LIBRARIES)
90 public static final int STATE_ABSENT = 0;
91
92 /**
93 * The interface is present but link is down.
94 * @hide
95 */
96 @SystemApi(client = MODULE_LIBRARIES)
97 public static final int STATE_LINK_DOWN = 1;
98
99 /**
100 * The interface is present and link is up.
101 * @hide
102 */
103 @SystemApi(client = MODULE_LIBRARIES)
104 public static final int STATE_LINK_UP = 2;
105
106 /** @hide */
107 @IntDef(prefix = "STATE_", value = {STATE_ABSENT, STATE_LINK_DOWN, STATE_LINK_UP})
108 @Retention(RetentionPolicy.SOURCE)
109 public @interface InterfaceState {}
110
111 /**
112 * The interface currently does not have any specific role.
113 * @hide
114 */
115 @SystemApi(client = MODULE_LIBRARIES)
116 public static final int ROLE_NONE = 0;
117
118 /**
119 * The interface is in client mode (e.g., connected to the Internet).
120 * @hide
121 */
122 @SystemApi(client = MODULE_LIBRARIES)
123 public static final int ROLE_CLIENT = 1;
124
125 /**
126 * Ethernet interface is in server mode (e.g., providing Internet access to tethered devices).
127 * @hide
128 */
129 @SystemApi(client = MODULE_LIBRARIES)
130 public static final int ROLE_SERVER = 2;
131
132 /** @hide */
133 @IntDef(prefix = "ROLE_", value = {ROLE_NONE, ROLE_CLIENT, ROLE_SERVER})
134 @Retention(RetentionPolicy.SOURCE)
135 public @interface Role {}
136
137 /**
138 * A listener that receives notifications about the state of Ethernet interfaces on the system.
139 * @hide
140 */
141 @SystemApi(client = MODULE_LIBRARIES)
142 public interface InterfaceStateListener {
143 /**
144 * Called when an Ethernet interface changes state.
145 *
146 * @param iface the name of the interface.
147 * @param state the current state of the interface, or {@link #STATE_ABSENT} if the
148 * interface was removed.
Lorenzo Colitti6c032e52022-02-11 12:18:59 +0900149 * @param role whether the interface is in client mode or server mode.
Xiao Ma7f9ac502022-01-30 11:27:16 +0000150 * @param configuration the current IP configuration of the interface.
151 * @hide
152 */
153 @SystemApi(client = MODULE_LIBRARIES)
154 void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
155 @Role int role, @Nullable IpConfiguration configuration);
156 }
157
158 /**
159 * A listener interface to receive notification on changes in Ethernet.
160 * This has never been a supported API. Use {@link InterfaceStateListener} instead.
161 * @hide
162 */
163 public interface Listener extends InterfaceStateListener {
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900164 /**
165 * Called when Ethernet port's availability is changed.
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700166 * @param iface Ethernet interface name
167 * @param isAvailable {@code true} if Ethernet port exists.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900168 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900169 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000170 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700171 void onAvailabilityChanged(String iface, boolean isAvailable);
Xiao Ma7f9ac502022-01-30 11:27:16 +0000172
173 /** Default implementation for backwards compatibility. Only calls the legacy listener. */
174 default void onInterfaceStateChanged(@NonNull String iface, @InterfaceState int state,
175 @Role int role, @Nullable IpConfiguration configuration) {
176 onAvailabilityChanged(iface, (state >= STATE_LINK_UP));
177 }
178
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900179 }
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700180
181 /**
182 * Create a new EthernetManager instance.
183 * Applications will almost always want to use
184 * {@link android.content.Context#getSystemService Context.getSystemService()} to retrieve
185 * the standard {@link android.content.Context#ETHERNET_SERVICE Context.ETHERNET_SERVICE}.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900186 * @hide
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700187 */
188 public EthernetManager(Context context, IEthernetManager service) {
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700189 mService = service;
190 }
191
192 /**
Lorenzo Colitti56e4e582014-05-22 11:51:27 -0700193 * Get Ethernet configuration.
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700194 * @return the Ethernet Configuration, contained in {@link IpConfiguration}.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900195 * @hide
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700196 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000197 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700198 public IpConfiguration getConfiguration(String iface) {
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700199 try {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700200 return mService.getConfiguration(iface);
Jeff Sharkeyf7138282016-03-01 19:27:23 -0700201 } catch (RemoteException e) {
202 throw e.rethrowFromSystemServer();
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700203 }
204 }
205
206 /**
Lorenzo Colitti56e4e582014-05-22 11:51:27 -0700207 * Set Ethernet configuration.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900208 * @hide
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700209 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000210 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Xiao Ma7f9ac502022-01-30 11:27:16 +0000211 public void setConfiguration(@NonNull String iface, @NonNull IpConfiguration config) {
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700212 try {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700213 mService.setConfiguration(iface, config);
Jeff Sharkeyf7138282016-03-01 19:27:23 -0700214 } catch (RemoteException e) {
215 throw e.rethrowFromSystemServer();
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900216 }
217 }
218
219 /**
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700220 * Indicates whether the system currently has one or more Ethernet interfaces.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900221 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900222 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000223 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900224 public boolean isAvailable() {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700225 return getAvailableInterfaces().length > 0;
226 }
227
228 /**
229 * Indicates whether the system has given interface.
230 *
231 * @param iface Ethernet interface name
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900232 * @hide
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700233 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000234 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700235 public boolean isAvailable(String iface) {
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900236 try {
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700237 return mService.isAvailable(iface);
Jeff Sharkeyf7138282016-03-01 19:27:23 -0700238 } catch (RemoteException e) {
239 throw e.rethrowFromSystemServer();
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900240 }
241 }
242
243 /**
244 * Adds a listener.
Xiao Ma7f9ac502022-01-30 11:27:16 +0000245 * This has never been a supported API. Use {@link #addInterfaceStateListener} instead.
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900246 *
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900247 * @param listener A {@link Listener} to add.
248 * @throws IllegalArgumentException If the listener is null.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900249 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900250 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000251 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900252 public void addListener(@NonNull Listener listener) {
253 addListener(listener, BackgroundThread.getExecutor());
254 }
255
256 /**
257 * Adds a listener.
Xiao Ma7f9ac502022-01-30 11:27:16 +0000258 * This has never been a supported API. Use {@link #addInterfaceStateListener} instead.
259 *
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900260 * @param listener A {@link Listener} to add.
261 * @param executor Executor to run callbacks on.
262 * @throws IllegalArgumentException If the listener or executor is null.
263 * @hide
264 */
265 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
266 public void addListener(@NonNull Listener listener, @NonNull Executor executor) {
Xiao Ma7f9ac502022-01-30 11:27:16 +0000267 addInterfaceStateListener(executor, listener);
268 }
269
270 /**
271 * Listen to changes in the state of Ethernet interfaces.
272 *
273 * Adds a listener to receive notification for any state change of all existing Ethernet
274 * interfaces.
275 * <p>{@link Listener#onInterfaceStateChanged} will be triggered immediately for all
276 * existing interfaces upon adding a listener. The same method will be called on the
277 * listener every time any of the interface changes state. In particular, if an
278 * interface is removed, it will be called with state {@link #STATE_ABSENT}.
279 * <p>Use {@link #removeInterfaceStateListener} with the same object to stop listening.
280 *
281 * @param executor Executor to run callbacks on.
282 * @param listener A {@link Listener} to add.
283 * @hide
284 */
285 @RequiresPermission(android.Manifest.permission.ACCESS_NETWORK_STATE)
286 @SystemApi(client = MODULE_LIBRARIES)
287 public void addInterfaceStateListener(@NonNull Executor executor,
288 @NonNull InterfaceStateListener listener) {
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900289 if (listener == null || executor == null) {
290 throw new NullPointerException("listener and executor must not be null");
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900291 }
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900292 synchronized (mListeners) {
293 mListeners.add(new ListenerInfo(executor, listener));
294 if (mListeners.size() == 1) {
295 try {
296 mService.addListener(mServiceListener);
297 } catch (RemoteException e) {
298 throw e.rethrowFromSystemServer();
299 }
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900300 }
301 }
302 }
303
304 /**
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700305 * Returns an array of available Ethernet interface names.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900306 * @hide
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700307 */
Mathew Inwoodfe2fed72020-11-04 09:29:36 +0000308 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
Pavel Maltsev50ec1f32017-10-31 15:34:16 -0700309 public String[] getAvailableInterfaces() {
310 try {
311 return mService.getAvailableInterfaces();
312 } catch (RemoteException e) {
313 throw e.rethrowAsRuntimeException();
314 }
315 }
316
317 /**
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900318 * Removes a listener.
Xiao Ma7f9ac502022-01-30 11:27:16 +0000319 *
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900320 * @param listener A {@link Listener} to remove.
Remi NGUYEN VAN199d6852020-01-24 22:57:09 +0900321 * @hide
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900322 */
Xiao Ma7f9ac502022-01-30 11:27:16 +0000323 @SystemApi(client = MODULE_LIBRARIES)
324 public void removeInterfaceStateListener(@NonNull InterfaceStateListener listener) {
325 Objects.requireNonNull(listener);
Remi NGUYEN VAN55838a82020-12-03 17:58:49 +0900326 synchronized (mListeners) {
327 mListeners.removeIf(l -> l.listener == listener);
328 if (mListeners.isEmpty()) {
329 try {
330 mService.removeListener(mServiceListener);
331 } catch (RemoteException e) {
332 throw e.rethrowFromSystemServer();
333 }
Jaewan Kim32b3f2c2014-10-20 12:04:13 +0900334 }
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700335 }
336 }
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900337
338 /**
Xiao Ma7f9ac502022-01-30 11:27:16 +0000339 * Removes a listener.
340 * This has never been a supported API. Use {@link #removeInterfaceStateListener} instead.
341 * @param listener A {@link Listener} to remove.
342 * @hide
343 */
344 @UnsupportedAppUsage(maxTargetSdk = Build.VERSION_CODES.R, trackingBug = 170729553)
345 public void removeListener(@NonNull Listener listener) {
346 if (listener == null) {
347 throw new IllegalArgumentException("listener must not be null");
348 }
349 removeInterfaceStateListener(listener);
350 }
351
352 /**
Lorenzo Colitti013187d2020-03-17 00:16:13 +0900353 * Whether to treat interfaces created by {@link TestNetworkManager#createTapInterface}
354 * as Ethernet interfaces. The effects of this method apply to any test interfaces that are
355 * already present on the system.
356 * @hide
357 */
Xiao Ma7f9ac502022-01-30 11:27:16 +0000358 @SystemApi(client = MODULE_LIBRARIES)
Lorenzo Colitti013187d2020-03-17 00:16:13 +0900359 public void setIncludeTestInterfaces(boolean include) {
360 try {
361 mService.setIncludeTestInterfaces(include);
362 } catch (RemoteException e) {
363 throw e.rethrowFromSystemServer();
364 }
365 }
366
367 /**
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900368 * A request for a tethered interface.
369 */
370 public static class TetheredInterfaceRequest {
371 private final IEthernetManager mService;
372 private final ITetheredInterfaceCallback mCb;
373
374 private TetheredInterfaceRequest(@NonNull IEthernetManager service,
375 @NonNull ITetheredInterfaceCallback cb) {
376 this.mService = service;
377 this.mCb = cb;
378 }
379
380 /**
381 * Release the request, causing the interface to revert back from tethering mode if there
382 * is no other requestor.
383 */
384 public void release() {
385 try {
386 mService.releaseTetheredInterface(mCb);
387 } catch (RemoteException e) {
388 e.rethrowFromSystemServer();
389 }
390 }
391 }
392
393 /**
394 * Callback for {@link #requestTetheredInterface(TetheredInterfaceCallback)}.
395 */
396 public interface TetheredInterfaceCallback {
397 /**
398 * Called when the tethered interface is available.
399 * @param iface The name of the interface.
400 */
401 void onAvailable(@NonNull String iface);
402
403 /**
404 * Called when the tethered interface is now unavailable.
405 */
406 void onUnavailable();
407 }
408
409 /**
410 * Request a tethered interface in tethering mode.
411 *
412 * <p>When this method is called and there is at least one ethernet interface available, the
413 * system will designate one to act as a tethered interface. If there is already a tethered
414 * interface, the existing interface will be used.
415 * @param callback A callback to be called once the request has been fulfilled.
416 */
Remi NGUYEN VAN11f39242020-03-09 13:56:18 +0900417 @RequiresPermission(anyOf = {
418 android.Manifest.permission.NETWORK_STACK,
419 android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK
420 })
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900421 @NonNull
markchienc8e7d752020-02-26 20:54:55 +0800422 public TetheredInterfaceRequest requestTetheredInterface(@NonNull final Executor executor,
423 @NonNull final TetheredInterfaceCallback callback) {
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900424 Objects.requireNonNull(callback, "Callback must be non-null");
markchienc8e7d752020-02-26 20:54:55 +0800425 Objects.requireNonNull(executor, "Executor must be non-null");
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900426 final ITetheredInterfaceCallback cbInternal = new ITetheredInterfaceCallback.Stub() {
427 @Override
428 public void onAvailable(String iface) {
markchienc8e7d752020-02-26 20:54:55 +0800429 executor.execute(() -> callback.onAvailable(iface));
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900430 }
431
432 @Override
433 public void onUnavailable() {
markchienc8e7d752020-02-26 20:54:55 +0800434 executor.execute(() -> callback.onUnavailable());
Lorenzo Colitti19b8b882020-01-24 19:29:17 +0900435 }
436 };
437
438 try {
439 mService.requestTetheredInterface(cbInternal);
440 } catch (RemoteException e) {
441 throw e.rethrowFromSystemServer();
442 }
443 return new TetheredInterfaceRequest(mService, cbInternal);
444 }
James Mattis407ea1d2021-12-14 18:23:30 -0800445
446 private static final class InternalNetworkManagementListener
James Mattis1ecadfa2022-01-28 13:42:38 -0800447 extends IEthernetNetworkManagementListener.Stub {
James Mattis407ea1d2021-12-14 18:23:30 -0800448 @NonNull
449 private final Executor mExecutor;
450 @NonNull
James Mattis1ecadfa2022-01-28 13:42:38 -0800451 private final BiConsumer<Network, EthernetNetworkManagementException> mListener;
James Mattis407ea1d2021-12-14 18:23:30 -0800452
453 InternalNetworkManagementListener(
454 @NonNull final Executor executor,
James Mattis1ecadfa2022-01-28 13:42:38 -0800455 @NonNull final BiConsumer<Network, EthernetNetworkManagementException> listener) {
James Mattis407ea1d2021-12-14 18:23:30 -0800456 Objects.requireNonNull(executor, "Pass a non-null executor");
457 Objects.requireNonNull(listener, "Pass a non-null listener");
458 mExecutor = executor;
459 mListener = listener;
460 }
461
462 @Override
463 public void onComplete(
464 @Nullable final Network network,
James Mattis1ecadfa2022-01-28 13:42:38 -0800465 @Nullable final EthernetNetworkManagementException e) {
James Mattis407ea1d2021-12-14 18:23:30 -0800466 mExecutor.execute(() -> mListener.accept(network, e));
467 }
468 }
469
470 private InternalNetworkManagementListener getInternalNetworkManagementListener(
471 @Nullable final Executor executor,
James Mattis1ecadfa2022-01-28 13:42:38 -0800472 @Nullable final BiConsumer<Network, EthernetNetworkManagementException> listener) {
James Mattis407ea1d2021-12-14 18:23:30 -0800473 if (null != listener) {
474 Objects.requireNonNull(executor, "Pass a non-null executor, or a null listener");
475 }
476 final InternalNetworkManagementListener proxy;
477 if (null == listener) {
478 proxy = null;
479 } else {
480 proxy = new InternalNetworkManagementListener(executor, listener);
481 }
482 return proxy;
483 }
484
James Mattis28547372022-02-02 14:32:40 -0800485 /**
486 * Updates the configuration of an automotive device's ethernet network.
487 *
488 * The {@link EthernetNetworkUpdateRequest} {@code request} argument describes how to update the
489 * configuration for this network.
490 * Use {@link StaticIpConfiguration.Builder} to build a {@code StaticIpConfiguration} object for
491 * this network to put inside the {@code request}.
492 * Similarly, use {@link NetworkCapabilities.Builder} to build a {@code NetworkCapabilities}
493 * object for this network to put inside the {@code request}.
494 *
495 * If non-null, the listener will be called exactly once after this is called, unless
496 * a synchronous exception was thrown.
497 *
498 * @param iface the name of the interface to act upon.
499 * @param request the {@link EthernetNetworkUpdateRequest} used to set an ethernet network's
500 * {@link StaticIpConfiguration} and {@link NetworkCapabilities} values.
501 * @param executor an {@link Executor} to execute the listener on. Optional if listener is null.
502 * @param listener an optional {@link BiConsumer} to listen for completion of the operation.
503 * @throws SecurityException if the process doesn't hold
504 * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
505 * @throws UnsupportedOperationException if called on a non-automotive device or on an
506 * unsupported interface.
507 * @hide
508 */
509 @SystemApi
510 @RequiresPermission(anyOf = {
511 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
512 android.Manifest.permission.NETWORK_STACK,
513 android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
James Mattis28547372022-02-02 14:32:40 -0800514 public void updateConfiguration(
James Mattis407ea1d2021-12-14 18:23:30 -0800515 @NonNull String iface,
James Mattis1ecadfa2022-01-28 13:42:38 -0800516 @NonNull EthernetNetworkUpdateRequest request,
James Mattis407ea1d2021-12-14 18:23:30 -0800517 @Nullable @CallbackExecutor Executor executor,
James Mattis1ecadfa2022-01-28 13:42:38 -0800518 @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
James Mattis28547372022-02-02 14:32:40 -0800519 Objects.requireNonNull(iface, "iface must be non-null");
520 Objects.requireNonNull(request, "request must be non-null");
James Mattis407ea1d2021-12-14 18:23:30 -0800521 final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
522 executor, listener);
523 try {
524 mService.updateConfiguration(iface, request, proxy);
525 } catch (RemoteException e) {
526 throw e.rethrowFromSystemServer();
527 }
528 }
529
James Mattis28547372022-02-02 14:32:40 -0800530 /**
531 * Set an ethernet network's link state up.
532 *
533 * When the link is successfully turned up, the listener will be called with the resulting
534 * network. If any error or unexpected condition happens while the system tries to turn the
535 * interface up, the listener will be called with an appropriate exception.
536 * The listener is guaranteed to be called exactly once for each call to this method, but this
537 * may take an unbounded amount of time depending on the actual network conditions.
538 *
539 * @param iface the name of the interface to act upon.
540 * @param executor an {@link Executor} to execute the listener on. Optional if listener is null.
541 * @param listener an optional {@link BiConsumer} to listen for completion of the operation.
542 * @throws SecurityException if the process doesn't hold
543 * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
544 * @throws UnsupportedOperationException if called on a non-automotive device.
545 * @hide
546 */
547 @SystemApi
548 @RequiresPermission(anyOf = {
549 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
550 android.Manifest.permission.NETWORK_STACK,
551 android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
552 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
553 public void connectNetwork(
James Mattis407ea1d2021-12-14 18:23:30 -0800554 @NonNull String iface,
555 @Nullable @CallbackExecutor Executor executor,
James Mattis1ecadfa2022-01-28 13:42:38 -0800556 @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
James Mattis28547372022-02-02 14:32:40 -0800557 Objects.requireNonNull(iface, "iface must be non-null");
James Mattis407ea1d2021-12-14 18:23:30 -0800558 final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
559 executor, listener);
560 try {
561 mService.connectNetwork(iface, proxy);
562 } catch (RemoteException e) {
563 throw e.rethrowFromSystemServer();
564 }
565 }
566
James Mattis28547372022-02-02 14:32:40 -0800567 /**
568 * Set an ethernet network's link state down.
569 *
570 * When the link is successfully turned down, the listener will be called with the network that
571 * was torn down, if any. If any error or unexpected condition happens while the system tries to
572 * turn the interface down, the listener will be called with an appropriate exception.
573 * The listener is guaranteed to be called exactly once for each call to this method.
574 *
575 * @param iface the name of the interface to act upon.
576 * @param executor an {@link Executor} to execute the listener on. Optional if listener is null.
577 * @param listener an optional {@link BiConsumer} to listen for completion of the operation.
578 * @throws SecurityException if the process doesn't hold
579 * {@link android.Manifest.permission.MANAGE_ETHERNET_NETWORKS}.
580 * @throws UnsupportedOperationException if called on a non-automotive device.
581 * @hide
582 */
583 @SystemApi
584 @RequiresPermission(anyOf = {
585 NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
586 android.Manifest.permission.NETWORK_STACK,
587 android.Manifest.permission.MANAGE_ETHERNET_NETWORKS})
588 @RequiresFeature(PackageManager.FEATURE_AUTOMOTIVE)
589 public void disconnectNetwork(
James Mattis407ea1d2021-12-14 18:23:30 -0800590 @NonNull String iface,
591 @Nullable @CallbackExecutor Executor executor,
James Mattis1ecadfa2022-01-28 13:42:38 -0800592 @Nullable BiConsumer<Network, EthernetNetworkManagementException> listener) {
James Mattis28547372022-02-02 14:32:40 -0800593 Objects.requireNonNull(iface, "iface must be non-null");
James Mattis407ea1d2021-12-14 18:23:30 -0800594 final InternalNetworkManagementListener proxy = getInternalNetworkManagementListener(
595 executor, listener);
596 try {
597 mService.disconnectNetwork(iface, proxy);
598 } catch (RemoteException e) {
599 throw e.rethrowFromSystemServer();
600 }
601 }
Lorenzo Colitti2edad7a2014-05-21 16:23:43 -0700602}